views:

105

answers:

3

I am confused about a behavior of git checkout. The documentation of git checkout says:

--merge

When switching branches, if you have local modifications to one or more files that are different between the current branch and the branch to which you are switching, the command refuses to switch branches in order to preserve your modifications in context. However, with this option, a three-way merge between the current branch, your working tree contents, and the new branch is done, and you will be on the new branch.

But, I have done a small test which is not behaving as said in the bold part. That is:

  1. I create a git repo
  2. create a directory and a file with some conent and commit it in master branch.
  3. Create another branch "testbranch"
  4. change the content of the file in master. But did not commit.
  5. switched to "testbranch".
  6. Now the changed and uncommitted changes from master branch come to testbranch!

Wasn't it supposed to fail, if I have some local changes and wanted to switch to a branch?

Below is the list of commands to reproduce this behavior:

sabya@SABYA-PC e:/test/merge_test
$ git init
Initialized empty Git repository in E:/test/merge_test/.git/

sabya@SABYA-PC e:/test/merge_test (master)
$ mkdir src

sabya@SABYA-PC e:/test/merge_test (master)
$ echo "Hello World" > src/a.txt

sabya@SABYA-PC e:/test/merge_test (master)
$ cat src/a.txt
Hello World

sabya@SABYA-PC e:/test/merge_test (master)
$ git add src

sabya@SABYA-PC e:/test/merge_test (master)
$ git commit -m "say hello"
[master (root-commit) 939f6e0] say hello
 1 files changed, 1 insertions(+), 0 deletions(-)
 create mode 100644 src/a.txt

sabya@SABYA-PC e:/test/merge_test (master)
$ git branch testbranch

sabya@SABYA-PC e:/test/merge_test (master)
$ echo "Changed content" > src/a.txt

sabya@SABYA-PC e:/test/merge_test (master)
$ git status
# On branch master
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       modified:   src/a.txt
#
no changes added to commit (use "git add" and/or "git commit -a")

sabya@SABYA-PC e:/test/merge_test (master)
$ git checkout testbranch
M       src/a.txt
Switched to branch 'testbranch'

sabya@SABYA-PC e:/test/merge_test (testbranch)
$ cat src/a.txt
Changed content

Can anyone explain this?

Below is my git version output:

sabya@SABYA-PC e:/test/merge_test (testbranch)
$ git --version
git version 1.7.0.2.msysgit.0
A: 

I'm thinking that you shouldn't be switching out to another branch without commiting your changes first, otherwise you get into an 'unclean' state. What version of git are you using?

Pydroid
+2  A: 

You haven't commited the changed file to master, so when you checkout the new branch it get's moved along with it to the new branch. The key is in this line

sabya@SABYA-PC e:/test/merge_test (master)
$ git checkout testbranch
M       src/a.txt
Switched to branch 'testbranch'

Notice how it says M src/a.txt? The M stands for modified file.

Commit the changes to master before checking out another branch.

Josh K
Exactly that is why I thought `git checkout testbranch` would fail with error similar to: Could not switch to testbranch. local changes detected which would be overwritten.Even the documentation says so.
Sabya
@Sabya: it only fails if local changes are detected in files which are different between the branch you're on and the branch you're switching to. In your case, the committed version of `src/a.txt` contains the text "Hello World" on _both_ the `master` branch and the `testbranch` branch. It's the same content, so git does not have a problem with switching.
David Zaslavsky
@Sabya: It also won't let you change branches if the changes are "staged" meaning you said `git add .` or similar.
Josh K
+3  A: 

The key is "that are different between the current branch and the branch to which you are switching"

If you change the file in the branch, commit it, checkout another branch, start modifying the same file in there, and checkout first branch again, without comming the file, checkout will fail.

Example

git init
vim file
# hack hack hack
git add .
git commit -m "1"
git checkout -b branch
vim file
# hack hack hack
git commit -a -m "2"
git checkout master
vim file
# hack hack hack
git checkout branch

Here you must have an error.

d.m