简体   繁体   中英

Commits count in local branch after Git rebase

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:

  1. master commit 4
  2. master commit 5
  3. dev commit 2(the new commit created on top of rebased master)
  4. dev commit 3(the new commit created on top of rebased master)

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM