Your question is still full of odd-looking constructs like:
git branch contains older-branch --contains COMMITHASH
but I think I understand what you are doing and asking. (Note that a more-focused question could get a more-focused answer.) I think the answer you want is git branch -r --contains
. But in case it isn't....
The basic mistake you are making here is thinking that branch names actually mean anything to Git. :-) More specifically, you're assuming that your branch names get updated automatically when some other Git repository updates their branch names.
This is not the case.
When you run git fetch
, you have your Git call up some other Git repository somewhere. Typically you will have exactly one other Git repository, which you will call origin
. You can, however, list multiple different other Git repositories. You just have to make up a unique name for each one.
Now, suppose the Git repository over at origin
, which resides at some URL url
, has three branch names: master
, develop
, and feature
. When you run:
$ git clone <url>
you get a Git repository of your own. Your Git repository now knows of another Git repository—the one at url
—and has saved that URL under the name origin
:
$ git remote
origin
$ git remote show origin
* remote origin
Fetch URL: ...
... lots more stuff ...
The second git remote
command here actually called up that other Git to get information from it. Most commands, by far, in Git don't call up any other Git: they only look inside your Git repository.
At this point, your Git repository has only one branch name, almost certainly master
.1 If you run git branch
to list your branch names, you'll see that one branch.
Does this mean that branches develop
and feature
don't exist in your repository? The answer to that is both no and yes. The problem is determining what you mean by branch. See also What exactly do we mean by "branch"?
The commits you might care about here do exist. And in fact, some names you might want to use exist too! The names that don't exist are the branch names develop
and feature
.
If you run:
git branch --contains <hash-id>
you will definitely not see the name develop
, because you do not have the name develop
.
I did git fetch
to make sure I was up-to-date with upstream.
That is the—or a, at least—right thing to do.
... Confused, I did git checkout older-branch
and then [git branch --contains
worked for me]
This is because git checkout
will sometimes create a new branch name.
The key here is once again the ambiguous meaning of the word branch. If you mean branch name, you must have the name. But if you mean something else, well....
Besides branch names, your own Git repository has what I now call remote-tracking names. Git calls them remote-tracking branch names—but they are not branch names at all.
When you run git fetch origin
, or a git fetch
that uses origin
, your Git calls up the Git over at origin
. They have a conversation, and your Git will obtain any commits they have, that you don't, that your Git would like to take. Your Git will then update your remote-tracking names.
Your remote-tracking names in this case would be origin/master
, origin/develop
, and origin/feature
. Your Git creates one for every branch name your Git sees in their Git.
These remote-tracking names remember, for you / your Git, that their Git had branch names, and what commit hash IDs those branch names held. A git fetch
will update them. (If they've deleted some branch names, you can use git fetch --prune
to have your Git delete your corresponding remote-tracking names. Without a pruning option, your Git will hang on to extra remote-tracking names. This prune mode probably should be the default, but for historical reasons, isn't.)
Your branch names are just that: yours. Just because Fred has added, deleted, and changed some of his branch names, that doesn't mean your Git will change yours. If you connect your Git to a remote named fred
, your Git will update your fred/*
names automatically, because your Fred-tracking names, while yours, are meant for remembering Fred's. The same goes with your origin
-tracking names.
When you did git checkout older-branch
, though, your git checkout
command looked through your branch names. The name older-branch
wasn't in there. Rather than just giving up right away and saying: you don't have that branch, your Git went on to look at all of your remote-tracking names.
If you have one remote-tracking name that looks enough like the branch name you asked for, your Git now creates a branch name of your own, corresponding to that remote-tracking name. So if you have origin/older-branch
, well, now you do have older-branch
. The commit identified by older-branch
will be the same commit hash ID that origin/older-branch
identifies right now
Now that you do have a branch name, it's up to you to maintain it. It's probably wiser to delete it and use origin/older-branch
directly. The git branch
command won't list remote-tracking names by default, but with the -r
option, that's exactly what it will list. So git branch -r --contains
will list those remote-tracking names where the remote-tracking name's commit is a descendant of the commit hash you specify on the command line.
1The other Git gets to say which branch name you get by default, if you didn't get specific in your git clone
command about which branch your git clone
should create. But unless someone sets it up otherwise, the other Git says I recommend master
so that's what you usually get anyway.