1

I have been trying to set-up repository with gitlab CE, as a part of the set-up created a repo and been playing around with it, when I encountered, that after I make some modification to files and switch branch using checkout, I'm allowed to switch even though I have unstaged files, which was different from my previous experience that I was not allowed to checkout until I either did a commit or stash.

This experience beats the purpose of seamlessly switching branches without having to worry about unintended creeping in.

The steps are highlighted below.

somasundaram.s@user  /d/projects/repositories/newrepo (master)
$ ls -ltr
total 1
-rw-r--r-- 1 somasundaram.s 1049089 13 Apr  4 16:28 README
-rw-r--r-- 1 somasundaram.s 1049089  0 Apr  4 16:31 hi

somasundaram.s@user  /d/projects/repositories/newrepo (master)
$ git branch new-branch

somasundaram.s@user  /d/projects/repositories/newrepo (master)
$ git checkout new-branch
Switched to branch 'new-branch'

somasundaram.s@user  /d/projects/repositories/newrepo (new-branch)
$ touch newfile

somasundaram.s@user  /d/projects/repositories/newrepo (new-branch)
$ ls -ltr
total 1
-rw-r--r-- 1 somasundaram.s 1049089 13 Apr  4 16:28 README
-rw-r--r-- 1 somasundaram.s 1049089  0 Apr  4 16:31 hi
-rw-r--r-- 1 somasundaram.s 1049089  0 Apr  4 16:37 newfile 
somasundaram.s@user  /d/projects/repositories/newrepo (new-branch)
$ git checkout master
Switched to branch 'master'

somasundaram.s@user  /d/projects/repositories/newrepo (master)
$ ls -ltr
total 1
-rw-r--r-- 1 somasundaram.s 1049089 13 Apr  4 16:28 README
-rw-r--r-- 1 somasundaram.s 1049089  0 Apr  4 16:31 hi
-rw-r--r-- 1 somasundaram.s 1049089  0 Apr  4 16:37 newfile
Somasundaram Sekar
  • 5,244
  • 6
  • 43
  • 85

3 Answers3

4

git checkout carries unstaged files to the new branch

Its not a bug.

The is how git behave.


enter image description here

In the following diagram you can see the 3 states.

Git has three main states that your files can reside in:

  • committed
  • modified
  • staged

They are all shared between your branches. but when you checkout branch you change the HEAD so you end up with the staging area && working directory shared between your repository even when you checkout branches.


How to checkout different branch with clean working directory and stage area?

If you wish to checkout clean branch without any "leftovers" in your working directory and staging are you can create a new worktree which will result in shared view of your repository (all the content is shared) but with a different working directory and staging area.


From git v2.5

git worktree add <new_path>

Now do whatever you want in any of your branches. It will create 2 separate working folders separated from each other while pointing to the same repository.

Using wortree you don't have to do any clear or reset in order to remove all your staged and untracked content.

Here is demo of how to do it:

enter image description here


Community
  • 1
  • 1
CodeWizard
  • 128,036
  • 21
  • 144
  • 167
  • Thanks, but what beats me is this flow explained in the youtube link(pointed at the time of explanation) https://youtu.be/ZDR433b0HJY?t=1414 – Somasundaram Sekar Apr 04 '16 at 12:14
  • I guess it is not unstaged files, but also unstaged modifications, as I have observed. – Somasundaram Sekar Apr 04 '16 at 12:20
  • yes. and again read this to understand it better. Once you commit and checkout different branch your HEAD is changed but all all other changes (working dir+stage area) are moving along with you. http://stackoverflow.com/questions/34519665/how-to-move-head-back-to-a-previous-location/34519716#34519716 – CodeWizard Apr 04 '16 at 12:23
3

That's a feature, not a bug, and has been that way ever since, as far as I know. If git thinks that it can safely carry along your local modifications, it does so.

If you want to get rid of them, git reset --hard.

AnoE
  • 8,048
  • 1
  • 21
  • 36
  • Have tried this last week and I was not allowed to switch until I staged the files or stashed them, which makes me think I have broken some configuration or may have to do some configuration – Somasundaram Sekar Apr 04 '16 at 11:21
  • Yup. Surprised me when I first noticed, but absolutely correct. – Erick G. Hagstrom Apr 04 '16 at 11:21
  • @SomasundaramSekar It only does this if the files didn't change between the two versions. If any of the files that you have changed locally also changed between the version you have checked out and the one that you're trying to check out, you'll get the behavior you describe. – Erick G. Hagstrom Apr 04 '16 at 11:23
  • I think it's wrong since `newfile` is not tracked by Git. – Plouff Apr 04 '16 at 11:25
1

Git won't change files that are not currently tracked in the repository. In your example, you only created an untracked file (newfile).

So the Git's behavior is absolutely normal.

If you git add newfile without commiting the changes, Git won't allow you to switch to master branch.

For example, this will be handled by Git:

$ git branch new-branch
$ git checkout new-branch
Switched to branch 'new-branch'
$ echo "test" > newfile
$ git add newfile
$ git checkout master
A       newfile
Switched to branch 'master'

For in depth explanations: https://stackoverflow.com/a/8526610/882697

Community
  • 1
  • 1
Plouff
  • 3,290
  • 2
  • 27
  • 45
  • 1
    Changes in the tracked files were also carried forward, which I believe is not normal. – Somasundaram Sekar Apr 04 '16 at 11:24
  • @SomasundaramSekar: Changes in which files? – Plouff Apr 04 '16 at 11:28
  • That works too somasundaram.s@user /d/projects/repositories/newrepo (new-branch) $ echo "test" > newfile somasundaram.s@user /d/projects/repositories/newrepo (new-branch) $ git add newfile warning: LF will be replaced by CRLF in newfile. The file will have its original line endings in your working directory. somasundaram.s@user /d/projects/repositories/newrepo (new-branch) $ git checkout master M README A newfile Switched to branch 'master' somasundaram.s@user /d/projects/repositories/newrepo (master) $ vi newfile – Somasundaram Sekar Apr 04 '16 at 11:30
  • You are right, I thought Git would prevent the branch change. But actually, it does the change of branch and put newfile in the index. So no modifications are lost. – Plouff Apr 04 '16 at 11:34
  • @SomasundaramSekar: I added a link in my answer that should be helpful. Good luck with your tests! – Plouff Apr 04 '16 at 11:36