Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does the `..` mean in git branch reference?

Tags:

git

git log origin/master git log origin/master.. 

What is the exact difference with the above? I'm trying to understand what exactly the .. notation does. I thought it was a range, but in this case it does something different.

like image 787
Coocoo4Cocoa Avatar asked May 12 '09 00:05

Coocoo4Cocoa


People also ask

What is branch reference in Git?

The branch is a type of a referencegit/refs/heads directory and contains the hash of a commit that the master branch points to. 1. cat ./. git/refs/heads/master.

What does tilde mean in Git?

Git HEAD. HEAD is used to represent the current snapshot of a branch. For a new repository, Git will by default point HEAD to the master branch. Changing where HEAD is pointing will update your current active branch. The ~(tilde) and ^(caret) symbols are used to point to a position relative to a specific commit.

What is Ref tag in Git?

A ref is anything pointing to a commit, for example, branches (heads), tags, and remote branches. You should see heads, remotes, and tags in your . git/refs directory, assuming you have all three types of refs in your repository. refs/heads/0.58 specifies a branch named 0.58.

What is ref heads in Git?

git/refs/ . In Git, a head is a ref that points to the tip (latest commit) of a branch. You can view your repository's heads in the path . git/refs/heads/ . In this path you will find one file for each branch, and the content in each file will be the commit ID of the tip (most recent commit) of that branch.


2 Answers

With git log (and all the other Git commands that take a similar argument set), it's a specification of how to find a range of revisions, yes. Remember that in Git's general world, that means some subgraph of the revision graph--- to most people, it generally means just a range of revisions in a list. (And if you don't do much if any branching, it simplifies to that in Git too).

The revision specification contains a set of positive references (starting points) and negative references (stopping points) and additional filters (limit number of revisions, grep commit text, etc.). Git starts with the positive references and goes back through the revision history, stopping when it encounters revisions that are reachable from the negative references (not necessarily just when it reaches one of the negative references themselves).

It's perhaps rather confusing that there are various shorthand notations that have evolved, that aim to make this all easier to use and yet somehow also manage to confuse- I had to spend quite a while figuring out just what "master..maint", "maint..master", etc. meant and when to use which.

When you just say "origin/master", then that means "origin/master" is a positive reference and there are no negative references. So Git starts at origin/master and walks back through all the revisions available-- you get the complete history of origin/master.

"origin/master.." is shorthand for "origin/master..HEAD" which looks kind of like it means "from origin/master up to HEAD". Which it does, effectively. It can be rewritten as "HEAD ^origin/master" or "HEAD --not origin/master". In this case, HEAD is a positive reference and "origin/master" is a negative reference. So Git starts at HEAD and walks back through the graph until it encounters a revision that is reachable from origin/master. It is likely that it will encounter origin/master itself, in fact. Note that all the references are inclusive-- the positive references themselves are output and the negative references aren't (unless you give --boundary, and then they're flagged). That means that "origin/master..HEAD" outputs nothing if HEAD and origin/master are the same revision.

So if you have made a couple of local commits on top of the upstream version you have this kind of situation:

steve@monolith:~/src/git <master>$ git log --pretty=oneline --abbrev-commit --decorate -n 4 ea3107d (refs/heads/master) Add another dummy comment 869c260 Add dummy comment 6345d7a (refs/remotes/origin/master, refs/remotes/origin/HEAD) Merge branch 'maint' be427d7 allow -t abbreviation for --track in git branch 

And now "git log origin/master.." means git will start at HEAD (ea3107d), which isn't reachable from origin/master, so it prints that. Then it walks back to HEAD's parent (869c260), which still isn't, so prints that. Then the next parent is 6345d7a, which is origin/master so it stops.

Note that "git log ..origin/master" does the opposite-- tries to walk back from origin/master to HEAD. In this case, it won't print anything. But if I checked out "origin/maint", it would print the revisions on origin/master that were not on origin/maint: so in general, try to think of "A..B" as "revisions in B that are not in A", and remember that omitting A or B means "HEAD".

Just for extra super duper confusion, there is also a notation "A...B". So remember to count the number of dots! In the case of A and B being in a line of revisions, there is no real difference. But what "A...B" means is the revisions in either A or B that are not in any of the merge bases for A and B. So if A and B are on divergent branches, it shows all the commits made on either since they diverged.

The "long form" for a revision range ("B --not A") allows you to specify things like "all revisions on local branches that are not on any remote-tracking branch" ("--branches --not --remotes"). This argument list is parsed by many Git commands ("git rev-list" being the core one), including gitk. So you can do "gitk --branches --not --remotes" to see your local changes graphically.

And finally for mega-bonus confusion, commands like "git diff" accept the same sort of shorthand syntax, but it doesn't mean (quite) the same thing. git diff actually takes two revisions and compares them, which is not the same as a range-- remember that a revision range in Git is a subgraph, not just a list. "git diff A..B" is equivalent to "git diff A B". "git diff A...B" means "show the changes in B since it diverged from A". Confusing? Just a bit: for example, "git log A...B" and "git log B...A" mean the same thing, but "git diff A...B" and "git diff B...A" don't.

like image 178
araqnid Avatar answered Sep 19 '22 18:09

araqnid


git log origin/master 

Would be like (fake command):

git log INITIAL..origin/master 

While:

git log origin/master.. 

Is:

git log origin/master..HEAD 
like image 37
FelipeC Avatar answered Sep 19 '22 18:09

FelipeC