0

I have a bare repository. I have a non-bare repository. In my bare repository I have the following:

git --work-tree=/C:/user/gitlab/data diff-tree --name-status -r master develop

Here we have master and develop branch inside the non-bare repository This works fine when I run it in the work-tree (non-bare repository)

When I put this inside my bare repository (/user/gitlab/shared.git/hooks) in post-receive it doesn't work.

I tried what is above. I don't know how exactly to compare my master branch and my develop branch with each other and show it's status.

while read oldrev newrev ref
do 
      git --work-tree=/C:/user/gitlab/data/ diff-tree --name-status -r master develop
done

Is it possible to compare two branches in your bare repository when pushing to it on you non-bare repository? (This is after committing your files)

Woods
  • 81
  • 1
  • 2
  • 8

1 Answers1

0

Given that you are working with hooks in bare repositories, you need to be aware that you never actually compare two branches. This is true regardless of which definition you use for the word branch (see What exactly do we mean by "branch"?). What you really compare here, with git diff-tree, is two commits.1

Fundamentally, a name like master—which is really refs/heads/master—or v2.1, which is really refs/tags/v2.1, just holds a commit hash ID. That's a hash ID, as in one, single, lonely hash ID. See the linked question for how that one hash ID can represent more than one commit.

Commands like those in the git diff family that want to look at a commit will translate the name into a raw hash ID, then proceed as if you had typed in the raw hash ID. Hence if you run:

git rev-parse master

and it prints 7c20df84bd21ec0215358381844274fa10515017, you could write the big ugly hash ID wherever you wrote master. What's special about branch names is that they move, and do so automatically—but when you're in pre- and post-receive hooks, you must be extra-careful about this, because the times when they move are tricky. That's why you are supposed to use loops like:

while read oldrev newrev ref; do ...; done

These loops read in three items: two hash IDs and a full reference name. The two hash IDs are the previous value of the reference—the hash that used to be how the full reference name would resolve—and the new value, the hash ID that the reference will represent soon. The last item is the full name: refs/heads/master, refs/tags/v2.1, and so on. The front part of the name tells you what kind of name it is, and the rest of the name, after stripping off the front part, is the branch or tag or other name.

In a pre-receive or update hook, the name itself has not yet changed at all, so the name should resolve to the old hash. Your hook's job is to verify whether these proposed updates should be allowed. In a post-receive hook, the name itself has changed. You are supposed to use the hash ID, not resolve the name to a hash ID now, because another change may be pending or have occurred as well, depending on how slow your post-receive hook itself is.

Any output you generate in a pre-receive or update hook will be copied to whoever is going the git push operation that triggered the hook to run. (This output will be prefixed with the word remote: and it will not appear until you send a complete line.) Any output you generate in a post-receive hook will be discarded! If you want it saved on the server, you must send it to a log file or logging service or similar.

There's no need for your --work-tree argument (and it's probably unwise to use one), but you will probably need to do your work in a pre-receive or update hook, and use the raw hash IDs as appropriate. It's up to you to figure out whether you want the updated values of both refs/heads/master and refs/heads/develop, if those two names are proposed to be updated, or not. It's also up to you whether to print the result of a git diff-tree if neither refs/heads/master nor refs/heads/develop are proposed to be updated.


1You can compare trees directly, and there are forms of git diff-tree that produce a combined diff of more than two trees, but using master develop here you're pretty clearly selecting the tip commits of master and develop.

torek
  • 448,244
  • 59
  • 642
  • 775
  • This helps a lot! Thank you! – Woods Aug 20 '19 at 19:01
  • So in the end I cannot go to my bare repository inside post-receive and compare the two commits from master and feature branch? (As it's not the best way?) – Woods Aug 20 '19 at 19:02
  • It just doesn't make sense as formulated. Your post-receive hook is invoked *because* some name(s) were updated. Read standard input (all lines) to find out which names, and what their old and new hash IDs were. You can use those to generate email or some other off-line type output and send it somewhere, but you can't send it directly to the person running `git push`. – torek Aug 20 '19 at 21:51
  • You are right. I was confused. This makes sense now. Thanks you! – Woods Aug 21 '19 at 03:21