63

I am working on a git repository with a master branch and another the topic branch. I have switched to topic branch and modified a file. Now, if I switched to the master branch, that same file is shown as modified.

For example:

git status in git-build branch:

# On branch git-build
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       modified:   cvsup_current
#

Switch to master branch

[root@redbull builder_scripts (git-build)]# git co master
M       builder_scripts/cvsup_current
Switched to branch "master"

git status in master branch

[root@redbull builder_scripts (master)]# git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       modified:   cvsup_current
#

Why is that the file is shown as modified in the master branch even though it was modified in git-build branch?

My understanding was that the branches are independent of each other and when I change from one branch to another the changes do not "spill over" from one branch to another. So I am obviously missing something here.

Has anyone got a clue stick?

Timothy G.
  • 6,335
  • 7
  • 30
  • 46
Rajkumar S
  • 2,471
  • 5
  • 23
  • 28

6 Answers6

71

Why is that the file is shown as modified in master branch even though it was modified in git-build branch?

The key to remember is that the file was not modified in the git-build branch. It was only modified in your working copy.

Only when you commit are the changes put back into whichever branch you have checked out

Gareth
  • 133,157
  • 36
  • 148
  • 157
  • Thanks, the answers combined have made this much clear for me! – Rajkumar S Oct 29 '08 at 10:09
  • I just realized, coming from an SVN mindset, committing in a branch isn't actually committing it to your "SVN" server, it's more of a "save my changes to this branch". I'm still trying to adjust. –  Mar 24 '11 at 10:53
  • 4
    "It was only modified in your working copy" <-- no, it was also modified in the index, i.e. the change had been staged – Mark Longair Mar 26 '11 at 07:04
  • But how does git do this? What happens if I modified a file on a branch and then checkout a different branch where that file has changes, i.e. the files don't share the same base anymore. How is this different from rebasing? If I have modified some files git doesn't allow me to rebase until I commit those changes. – Milad Aug 16 '16 at 14:15
  • I've had this pollution problem with Git on windows. Files from a committed change are left in the filesystem after switching to another branch. – StingyJack Feb 18 '17 at 20:40
44

If you want to temporarily store your changes to one branch while you go off to do work on another, you can use the git stash command. It's one of the amazing little unsung perks of using git. Example workflow:

git stash #work saved
git checkout master
#edit files
git commit
git checkout git-build
git stash apply #restore earlier work

git stash stores a stack of changes, so you can safely store multiple checkpoints. You can also give them names/descriptions. Full usage info here.

Peter Burns
  • 44,401
  • 7
  • 38
  • 56
  • 1
    Although this doesn't directly answer the why part, this answer best fits the intention of what the OP was trying to do. This is exactly what I was looking for – Carl Pritchett Aug 23 '15 at 20:44
  • 1
    git stash won't secure the new files. It stashes only the already tracked files. So if one has created new files, even after stashing, those new files will be available in other folders. – raghu Aug 28 '18 at 13:27
15

This is the default behaviour of git.

You can use -f flag to checkout to do "clean checkout" if you like.

Marko
  • 30,263
  • 18
  • 74
  • 108
  • 16
    Be aware that this doesn't keep the changes on top of the branch you're leaving or anything. This will throw away the uncommitted changes (except if the file is untracked). – webmat Oct 30 '08 at 00:00
  • 12
    It is the very rare case where you want to use `git checkout -f` as it will instantly, irrevocably, and without prompting throw away any uncommitted changes. There's a reason git checkout works the way it does, I advise reading Gareth's comment below. – Peter Burns Oct 05 '11 at 00:01
10

The modified files are not put in the repository until you add and commit them. If you switch back to your topic branch and commit the file, then it won't appear on the master branch.

Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285
3
  • It is not like git branches are dependent on each other but also they do not have a complete code base separately for each branch either.
  • For each commit, Git stores an object that contains a pointer to the changes. So each branch points to its own latest commit and HEAD points to the branch currently you are in.
  • When you switch the branch, the HEAD pointer points to that particular commit of the branch. So if there are modified files, the default behavior is to copy over them.

You can do the following things to overcome this issue.

  1. Use -f option to ignore the changes.

If you want to save the changes:

  1. Commit the changes locally in the same branch and then switch the branch.
  2. Use git stash, switch the branch, do your work, switch back to the original branch and do git stash apply.
Raviteja
  • 1,892
  • 3
  • 15
  • 12
1

In my experience this "spillover" problem arises because git does not protect "untracked" files from git checkout (only tracked but uncommitted files would be protected, i.e. user would be forced to git commit them before a git checkout is allowed to another branch).

If you switch back to the original branch that created these files (and "untracks" them), these files become "untracked" again and can be git add'ed or git rm'ed.

For me it looks like a bug: even "untracked" files should be protected from git checkout.

mirekphd
  • 4,799
  • 3
  • 38
  • 59