0

In the online version of the Pro Git book, I find the sentence "The HEAD in Git is the pointer to the current branch reference, which is in turn a pointer to the last commit you made or the last commit that was checked out into your working directory.". When reading about branching, I read that a branch is created from current HEAD, e.g. here. In my naivety, I conclude that creating a branch carries over anything that is committed (as it is part of HEAD) and nothing more (i.e. also not what is part of the index via staging). However, I find that staged changes from the parent branch are also part of the newly created child branch. Isn't that counterintuitive since my branch should contain the HEAD which in turn is the latest commit in the parent branch?

Example

A repo with one committed file "testfile" in only existing branch master. I add a line to this file echo "test a new line" >> testfile, stage it via git add .. Now I decide to do something else but need a new branch for that. I create git branch testbranch. Now I like to switch to the new branch (actually I would expect that git won't let me switch since I have staged but uncommitted changes on master but it will) git checkout testbranch. Now git status tells me I have changes to be committed in my testbranch. Why? I created the testbranch to do other things and expected it to contain what was in the HEAD of its parent branch (master).

Triamus
  • 2,415
  • 5
  • 27
  • 37
  • 1
    What you are describing is not a problem with the branch creation. testbranch is created poiting to the last revision of master (where HEAD was in the first place). The fact that "changes are carried over with you if you checkout a different branch" is related to how "checkout" works. If you would like those (uncommitted) changes to not be carried over if you switch to a different branch then you should stash them. – eftshift0 Apr 24 '17 at 13:26
  • I see. That seems to make sense. And why it sometimes let's you switch even with uncommitted changes is (rather longishely) explained in [git-checkout-another-branch-when-there-are-uncommitted-changes-on-the-current](http://stackoverflow.com/questions/22053757/git-checkout-another-branch-when-there-are-uncommitted-changes-on-the-current) – Triamus Apr 24 '17 at 13:38
  • @Edmundo you may post the answer If you like me to accept. thanks! – Triamus Apr 24 '17 at 13:39

1 Answers1

1

While the answer in the comments seems to have satisfied your curiosity, there is a bit more that should be said.

There's some conceptual confusion that comes through when you say that the staged changes are "carried over to the new branch". Branches are a concept of the database. There can be any number of them, as reflected in .git/refs/heads and/or the packed-refs file. There is only one index, and it is not part of (or really related to) any branch. It is more a part of your checked out state.

As Edmundo notes, you can use git stash to do what you want. When you create a stash, really you're creating up to two temporary commits (one representing any staged changes, one representing any unstaged changes) with a special ref (stash - which is moved and tracked using the reflog to support a "stack" of stashes if you need more than one). These changes are parented to your HEAD commit, but can still be applied/popped anywhere. That's as close to a branch-specific index as you can get.

Mark Adelsberger
  • 42,148
  • 4
  • 35
  • 52
  • Thanks! I believe I have understood the issue. Your point "There is only one index, and it is not part of (or really related to) any branch" is helpful. My main misconception was that I assumed the observed behavior to be caused by ```git branch``` when really it's a feature of ```git checkout```. I also just tried with ```git stash``` and it works as expected. – Triamus Apr 24 '17 at 14:07
  • To add one more observation, ```git checkout``` worked on the new branch despite having uncommitted changes in ```master```. However, it does not seem to work on another, already existing branch. Then git gives error. – Triamus Apr 24 '17 at 15:37
  • 1
    The error I believe you're referring to has to do with a checkout operation that would overwrite an uncommitted change. When you're checking out a branch that's pointing to the same commit as `HEAD`, there's generally not a reason that would happen, so git lets it go. – Mark Adelsberger Apr 24 '17 at 16:52