0

Situation

  • I have a local Git repo.

enter image description here

  • I have only on branch: master.

  • I used to have another branch but I merged it into master and then deleted it.

  • Such merged and deleted branch bifurcated from fe6263e.

  • 0c81926 was an --amend of c79dc19

  • There is no tag nor any other comming pointing to c79dc19. I understand that if some object was pointing to an ammended commit, such commit would continue to show in the history. But this is not the case.

Questions

  • Why didn't the history line flattened?

  • Why is still c79dc19 showing?

  • How did it happen?

As I mentioned nothing points to it and I did a git -gc to clean up any hanging commit.

Tulains Córdova
  • 2,559
  • 2
  • 20
  • 33
  • 1
    Related: http://stackoverflow.com/questions/26050327/how-does-git-commit-amend-work-exactly – jub0bs Nov 09 '16 at 18:38

3 Answers3

2

There is no tag nor any other [commit] pointing to c79dc19

That's not what the history shows.

Try running git show HEAD - it'll show what the two parents of the merge are. It looks from your graph like one is the c79dc19, and that's why it shows up in your history.

Most likely, either the branch really started at c79dc19 (so that was already on master), or the branch was merged to master as a fast-forward when c79dc19 was its head.


Worked illustration:

  1. initial state

    fe62 <=master <=HEAD
    
  2. new commit

    fe62 <- c79d <=master <=HEAD
    
  3. checkout new branch

    fe62 <- c79d <=master <=branch <=HEAD
    
  4. amend (on branch) gives a new commit 0c81 which replaces c79d on that branch but doesn't change master

    fe62 <- c79d <=master
         \- 0c81 <=branch <=HEAD
    
Useless
  • 64,155
  • 6
  • 88
  • 132
  • I think this is the most likely situation. Branched off of `c79dc19` and then amended on the branch. So when the merge happened, it saw the base as `fe6263e` (the parent commit of the branch point) instead of `c79dc19`. – Holden Lewis Nov 09 '16 at 19:57
  • They do - when you amend c79, you create an alternate version of it with the same parent. So, the original c79 and the amended 0c8 show as branches from their common ancestor. – Useless Nov 10 '16 at 12:07
  • When I do `git show HEAD` if shows `Merge: c79dc19 f6429eb`. – Tulains Córdova Nov 10 '16 at 12:39
  • so HEAD is pointing directly to c79 as one of its two parents, as I said. – Useless Nov 10 '16 at 13:36
2

You created new branch from master at c79 so master continued to point there. Then from the new branch you committed the amendment, hence master and new branch have diverged histories.

One thing to note is that an amendment doesn't actually modify the commit. Commits are immutable. An amendment creates a new commit based on another.

If you want to flatten it, then point master to the previous commit and merge to the tip.

git checkout -b temp
git branch -f master fe6263e
git checkout master
git merge f6429eb
Jeff Puckett
  • 37,464
  • 17
  • 118
  • 167
  • 1
    +1 because I flattened the tree running the commands one by one. But I'm afraid I'll have to accept @Useless' answer because he explained what happened in a way I could clearly understand. – Tulains Córdova Nov 10 '16 at 12:50
1

It's hard to be 100% sure, but this happens often so this is probably the correct answer.

You mention that you have only one branch, named master. I believe you! But you don't have only one repository—or more precisely, you have your clone, and then there is some other clone, probably on a remote you call origin on some central server such as GitHub or a corporate server. You send commits to the server, and get commits from the server.

You also mentioned using git commit --amend. See How does git commit --amend work, exactly? (as in Jubobs' comment) for details, but in short, this doesn't change the commit, it just shoves it aside in favor of the new replacement commit. Presumably, though, you had already pushed the original commit—so now it was in the master branch in the other repository.

So you now had 0c81926 as the tip of your master, while they (origin) had c79dc19. You then made new commit f6429eb, so that your master pointed to that.

Then, I bet you ran git pull (and most likely you have not configured or instructed your git pull to do git rebase). This ran git fetch followed by git merge. The git fetch checked with your remote, origin, and found that its master pointed to commit c79dc19. The git merge that git pull ran merged their branch with your branch, producing merge commit 706b1ef.

In the end, what this means is that you did have two different branches: master, and master. It's just that one of them is your master, and one of them is someone else's master.

Note that you can get rid of commit c79dc19 and the merge, e.g., using git rebase -i fe6263e (the point just before the mess starts): delete the unwanted extra commit, and let git rebase flatten the remaining history and omit the merge. (Or, use the method in Jeff Puckett II's answer.) Once you do this, though, your history will be divergent from the history on origin: they have a commit (that same c79dc19 you are trying to get rid of) that you don't. So you won't be able to push without forcing the push (optionally, "force with lease", expecting their master to be c79dc19, to make sure they have not gotten even more commits since the last time you checked).

Community
  • 1
  • 1
torek
  • 448,244
  • 59
  • 642
  • 775
  • Very good answer but I'm afraid I have never made a fetch or a pull in that repo. I've only done local work from beginning to end. – Tulains Córdova Nov 10 '16 at 11:21
  • Ah. Some of the helpful items were obscured in your graphic (in particular the "merge branch ..." had the branch name and details pixelated away). It looks like the accepted answer is the right one in this case. – torek Nov 10 '16 at 13:40