Search code examples
linuxgitversion-controlgitg

Git: Commits that stick-out of master without being in a branch


I've been working on a project for some time using a git local repository for version control.

I have two branches in the repository: master and "other" (not its real name).

When I run git branch I get this list:

  other
* master

Looking at my repository graph with gitg (a Gnome GUI for git), selecting "all branches" from the branches drop-down list, I get this graph:

enter image description here

I see the two branches, but there are also two commits, tagged "v1.2y" and "v1.2s", that stick out of the master branch and don't seem to merge back into it. They seem to be hanging there like non-merged-back branches, but they are not actual branches. At least neither git nor gitg list them as being branches.

Can someone explain to me the reason they stick out of the master branch if they are not branches themselves?

Please don't just simply tell me what to do to make it normal but, most importantly, the reason why this happened to begin with.

EDIT: I have never made a rebase or force push.


Solution

  • First of all, you can read about the difference between tags and branches here: How is a tag different from a branch? Which should I use, here?

    Suppose you do the following:

    git checkout master                      //go to branch master, say at commit x
    git checkout -b newbranch                //create a new branch called newbranch that also points to x
    git commit -a -m some_branch_commit_1    //add a commit to newbranch
    git tag tagged_my_commit                 //tag your commit
    git checkout master                      //go back to master
    git commit -a -m "Something"             //add a commit, say y to master 
    git checkout newbranch                   //go back to newbranch
    git rebase master                        //create a copy of the commits on newbranch so that they now split of from y instead of x
    

    In this case, a new copy of commit some_branch_commit_1 will be created. However, the old one still exists (it was tagged tagged_my_commit) so it will never disappear. Basically, you now have two copies of the same commit, one of them is not on a branch with a particular name.

    Suppose however you didn't tag that commit, then in principle it could be removed by git. However, deleting such commits (garbage collection) only happens from time to time. This can explain why commits that shouldn't keep on existing still are in your repostiroy. If you want to read more, see https://git-scm.com/docs/git-gc

    As noted in the comments, this does not only happen with rebases. Any form of rewriting (e.g., amending commits, changing the pointer of a branch, ...) can lead you to this situation.

    EDIT as requested: another example

    git checkout master                  //go to master, say at commit x
    git commit -a -m "I did something"   //create a commit, say y1
    git tag tagit                        //tag your commit
    

    your history now looks like this

    y1  = master  =  tagit
    |
    x
    

    Now do the following //edit some file
    git commit -a -m "I did something (more)" --amend //change commit y1 such that it now also takes changes to the other file into account, say this is y2

    In that case your history looks like this

    y1=tagit  y2=master
    |         /
    |        /
    |       /
    |      /
    |     /
    |    /
    |   /
    |  /
    x
    

    which seems to be like in your situation