There are many branches displayed in the graph view, however I'm unable to identify them. I only have one branch: main
. How can I identify them?
CodePudding user response:
Those are not branches. Instead, they are branches.
Think about that for a moment. It's obviously self-contradictory. Yet it's also true. What does that mean about the word branch?
Think about the word cleave, which, according to the dictionary, means:
cleave (1 of 2): intransitive verb: to adhere firmly and closely or loyally and unwaveringly ...
cleave (2 of 2): transitive verb: 1: to divide by or as if by a cutting blow: SPLIT
2: to separate into distinct parts ...
3: to subject to chemical cleavageintransitive verb: ...
So, "cleave" (often used with "to") means "stick together as one" and also (used without "to"), split apart. We must infer what someone means by context.
How this applies to the word "branch"
Suppose we have the following graph, where older commits are placed towards the left, and newer commits are placed towards the right:
I--J <-- branch1
/
...--G--H
\
K--L <-- branch2
Clearly branch1
and branch2
are branches—or more precisely, branch names that point to tip commits J
and L
respectively, with those two commits having parents I
and K
respectively. Commits I
and K
both have, as their (single) parent commit, commit H
, which has, as its single parent commit, commit G
.
Here's a trick question: which branch holds commits H
and G
and earlier commits?
The reason it's a trick question is simple: we know that there are at least two branches that hold these; there may be more, perhaps many more. Commits G
and H
are on both branches.
The word branch, in Git, therefore has at least two meanings:
- a branch name, e.g.,
main
; - a set of commits, e.g.,
I-J
.
Git also has a kind of name that Git calls a remote-tracking branch name. This adds at least a third kind of "branch", though some years ago I decided that the word branch in this phrase is useless and should ideally be dropped entirely, producing thee phrase remote-tracking name. I find this clearer (although still not entirely satisfactory).
Git uses the term tip commit—or sometimes branch head, although this phrase seems to have fallen into disuse—to talk about commits J
and L
as referred-to by branch names branch1
and branch2
respectively.
In the end, it's all pretty messy. We (humans) use words to communicate, but in this case the word branch results in a great deal of mis-communication. We must be careful when using it.
Let me re-draw the graph I drew above this way:
...--G--H--I--J <-- branch1
\
K--L <-- branch2
Here's a question to which I think different people will give different answers: Does this look like the same graph?
It is, in fact, the same graph. But I suspect it's mostly topologists (who are always dunking their coffee cups into their donuts) or computer scientists (who draw their trees upside down), who might say that they look the same.
This second drawing misleadingly implies that commits G-H
are only on branch1
when in fact they're on both branches.
Suppose we now run:
git switch branch1 && git merge branch2 && git branch -D branch2
and wind up with this as our graph:
I--J
/ \
...--G--H M <-- branch1
\ /
K--L
All the commits are now on branch1
(only, unless there are other branch names we can't see because I left them out of the drawing). This is fine in Git because in Git, we find commits by starting with some branch or tag or other name like branch1
, and then having Git work backwards. Commit M
points to both commits J
and L
and therefore finds both commits; these two commits find I
and K
; and these two commits find H
, where the history has merged together.
In other words, commit M
—a merge commit—causes the history to branch. The branch-point commit H
, which is not a merge commit at all, causes the history to merge.
(Does this mean we're using the wrong terms in Git? Maybe—but those are the terms we have, and aside from making small changes like dropping the word branch from the silly phrase remote-tracking branch name, we probably won't make a lot of headway in changing them.)
How this applies to your graph
Your graph has five colored lines: grey, blue, red, green, and ... I'm not sure what to call the remaining one (yellow? peach? orange?). You are calling them branches. Are they branches? Well, with how many meanings the word branch has, I suppose they are, if you want them to be.
But they don't have branch names that find them. The things that find the top-most blue-line commit include the branch name main
, and also the remote-tracking names origin/main
and origin/HEAD
.
That commit is itself a merge commit, with two parents. One of the parents is shown directly below it, as a blue dot on the same blue line, and the other parent is shown several lines later, following a red line to a red dot representing another merge commit (again with two parents—almost all merge commits have exactly two parents, though a Git merge can technically have two or more).
The red-dot merge commit, whose subject is rebase
, leads to both another red-dot-red-line commit th<character> squash
and a green-line green-dot commit Initial commit
. The green-line Initial commit
commit has, as its (single) parent, another commit whose subject is Initial commit
; your viewer has therefore displayed that as another green dot. It in turn has another parent, one of the vault backup
commits, which has another ordinary (non-merge) parent, which has a merge commit as its parent. This causes your graph-viewer to draw the second parent as that last line (yellow or peach or whatever color it is), which presumably leads down to yet another commit that's just not shown here.
It is your graph-drawing software that is choosing the colors and the method of drawing, here. These are not "branches" in terms of Git branch names, but they are "branches" in terms of being collections of commits strung together via parent/child relationships. When and whether you want to call that a branch, and how you wish to communicate this to some other human, are questions for you to decide. What Git has is the set of commits that form these parent/child relations (and thereby a Directed Acyclic Graph or DAG), plus the branch names, tag names, remote-tracking names, and other names that let you (and Git) find some particular starting-point commits from which to work backwards.
How can I identify them?
If, by the word them, you mean the commits—the things drawn as dots along those lines—Git's actual name for each commit is its commit hash ID. Your graph-drawing software has omitted these hash IDs, so that makes it difficult to name the commits directly, but if you use git log --decorate --oneline --graph
, Git's drawing will include the hash IDs (albeit abbreviated).