I'm trying out Git rebase in my test project so as to learn how it works. May be I'm missing something trivial, but i'm not able to figure out how the commits count got the value it shows in the log.
I have 2 branches. Master and Dev. There are no pending commits in any branch, that are to be pushed to the remote branches. And this is how it looks before rebase: And now i do the rebase using the below set of commands:
C:\GitRepositories\boney_git_fun>git checkout dev
C:\GitRepositories\boney_git_fun>git rebase master
First, rewinding head to replay your work on top of it...
Applying: dev commit 2
Applying: dev commit 3
C:\GitRepositories\boney_git_fun>git status
On branch dev
Your branch and 'origin/dev' have diverged,
and have 6 and 2 different commits each, respectively.
(use "git pull" to merge the remote branch into yours)
nothing to commit, working directory clean
C:\GitRepositories\boney_git_fun>git push --force
Ok. I have pushed the changes to the remote repository and this is how it looks now.
And now my question. In the log below,
C:\\GitRepositories\\boney_git_fun>git status On branch dev Your branch and 'origin/dev' have diverged, and have 6 and 2 different commits each, respectively.
how did the local dev branch have 6 commits after rebase ? I could think only of 4 commits in the local dev branch, which are:
Could anyone please tell me about the missing 2 commits? Let me know if any more info is required.
The trick is to realize that some commits are on many branches. When you did the rebase, you changed the label dev
. Four existing commits that were , earlier, only on master
are now on both master
and dev
. Two other commits that were on dev
are no longer on dev
at all; instead, new commits—replacements for the two old ones; copies —are now on dev
.
Here are the two chains of commits (before and after, transcribed from your images) along with their hash IDs. 1 I have also added the branch labels. Note that a commit's hash ID is its "true name": this is the real identity of the commit. It's shortlog, eg, master commit 4
, is just a text string that can be copied to a new and different commit. In other words, those gobbledygook strings of hexadecimal characters c4ef678
and so on are the actual names to which you should pay attention.
1 This graph is not drawn the way git log --graph --oneline
would draw it, it's a literal transcription of your images. The --graph
option turns on topological sorting in git log
, which changes how the commits are clustered in the one-per-line output, and also attempts to draw first and second parents of merges in a particular way, neither of which is the case here.
before:
* c4ef678 dev commit 3 (dev)
| * 6d98d13 master commit 5 (master)
| * 531ae4f master commit 4
* | 1d1165d dev commit 2
| * 264c713 Merged dev into master
|/|
| * d3145f2 master commit 3
* | e855864 dev commit 1
|/
* e90a213 master commit 2
* abe2416 master branch commit
* 6685b20 README.md created online with Bitbucket
Note that commits c4ef678
and 1d1165d
are only on dev
; commits 6d98d13
and 531ae4f
and 264c713
and d3145f2
are only on master
; and e855864
and below are on both branches. To see this, start at the commit that bears the branch name label— c4ef678
for dev
, or 6d98d13
for master
—and follow the connecting lines from dot to dot (asterisk to asterisk in the text copies here). You can only move in the generally-downward direction, but at a merge like 264c713
, follow both lines downward.
after:
* e09e49b dev commit 3 (dev)
* 6a8c956 dev commit 2
* 6d98d13 master commit 5 (master)
* 531ae4f master commit 4
* 264c713 Merged dev into master
|\
* | d3145f2 master commit 3
| * e855864 dev commit 1
|/
* e90a213 master commit 2
* abe2416 master branch commit
* 6685b20 README.md created online with Bitbucket
This graph is much simpler to follow: commit e09e49b
is the tip of dev
, and it and its predecessor 6a8c956
are only on dev
. After—well, before , really ... before those, we have 6d98d13
, which is the tip of master
and is on both master
and dev
. Then we have 531ae4f
, which is likewise on both master
and dev
, and so on.
We can see, now, that what git rebase
did was to copy original commits c4ef678
and 1d1165d
to new commits e09e49b
and 6a8c956
respectively. The parent of 6a8c956
is 6d98d13
, which is the tip of master
. The parent of c4ef678
is of course 1d1165d
—which means the copying happened in the reverse order, ie, the older commit got copied first, then the newer one: "forward" order in Git is actually backwards, as Git starts with the tip-most commit as identified by a branch label, then moves back through previous commits by looking at each commit's parent. For a merge commit, which is distinguished by having two parents, 2 Git looks at both parents.
Since commits can be on more than one branch at a time, the act of copying the two dev
-only commits to two new commits that sit atop the existing commits that were , before, only on master
, has now changed things so that there are six commits on dev
that were not on dev
before: the copied two, and the four that had been only on master
. These are the six that are reported here:
Your branch and 'origin/dev' have diverged, and have 6 and 2 different commits each, respectively
The two that are only on origin/dev
—this is also your own label, in your repository; it's your repository's memory of what is or was on origin
—are the original two before the copying. That is, if we drew them in, we'd have this slightly more complicated graph:
* c4ef678 dev commit 3 (origin/dev)
* 1d1165d dev commit 2
| * e09e49b dev commit 3 (dev)
| * 6a8c956 dev commit 2
| * 6d98d13 master commit 5 (master)
| * 531ae4f master commit 4
| * 264c713 Merged dev into master
| |\
| | * d3145f2 master commit 3
|/ |
* | e855864 dev commit 1
| /
| /
|/
* e90a213 master commit 2
* abe2416 master branch commit
* 6685b20 README.md created online with Bitbucket
If you scan the connecting lines here, you can see which commits are the six on dev
that are not on origin/dev
, and which are the two that are on origin/dev
that are not on dev
.
2 A merge commit is actually any commit with two or more parents, but the "or more" case is a bit odd. These commits are called octopus merges and octopus merges are never actually required , so they are mostly for showing off. :-)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.