git checkout branch after git add, seems not update index and working area

Here is my situation:

  1. create a file 2.md in branch dev, and git add this file, then I can see this file is added into index through git ls-files
  2. switch to branch master by git checkout master, but ls and git ls-files still shows this file exists in working tree and index. Why git checkout doesn’t update working tree and index according to master’s last commit?
    Here is the description of git checkout in git manual:

To prepare for working on <branch>, switch to it by updating the index and the files in the working tree, and by pointing HEAD at the branch. Local modifications to the files in the working tree are kept, so that they can be committed to the <branch>.

  1. git commit this file in branch master, then git checkout dev, I find this file disappears from both working tree and index of branch dev, which also confuse me

Below is my operation and output:

(base) [root@zjmhost hello-github]# git checkout dev
Switched to branch 'dev'
(base) [root@zjmhost hello-github]# touch 2.md
(base) [root@zjmhost hello-github]# ls
2.md  copy.md  README.md  test.md
(base) [root@zjmhost hello-github]# git ls-files
.ipynb_checkpoints/README-checkpoint.md
README.md
copy.md
test.md
(base) [root@zjmhost hello-github]# git add 2.md 
(base) [root@zjmhost hello-github]# git ls-files
.ipynb_checkpoints/README-checkpoint.md
2.md
README.md
copy.md
test.md
(base) [root@zjmhost hello-github]# git checkout master
A       2.md
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 12 commits.
  (use "git push" to publish your local commits)
(base) [root@zjmhost hello-github]# ls
1.md  2.md  copy.md  README.md  test.md
(base) [root@zjmhost hello-github]# git ls-files
.ipynb_checkpoints/README-checkpoint.md
1.md
2.md
README.md
copy.md
test.md
(base) [root@zjmhost hello-github]# git commit -m "commit 2.md in master branch"
[master 005f0c2] 2.md do the same with 1.md
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 2.md
(base) [root@zjmhost hello-github]# git ls-files
.ipynb_checkpoints/README-checkpoint.md
1.md
2.md
README.md
copy.md
test.md
(base) [root@zjmhost hello-github]# git checkout dev
Switched to branch 'dev'
(base) [root@zjmhost hello-github]# ls
copy.md  README.md  test.md
(base) [root@zjmhost hello-github]# git ls-files
.ipynb_checkpoints/README-checkpoint.md
README.md
copy.md
test.md

n your scenario, there are some details about how Git handles uncommitted changes when switching between branches that are important to understand. Here’s a breakdown of what’s happening:

1. Switching from dev to master without committing the new file

When you created the file 2.md on the dev branch and added it to the index, the file was staged but not yet committed. Then, you switched to the master branch without committing the changes on dev.

Why does the file still show up in the working tree after switching to master?

Git doesn’t discard uncommitted changes in your working directory by default when you switch branches. Since 2.md was added but not committed in dev, it remains in your working tree (and index) when you switch to master. This behavior is intended to allow users to carry over their uncommitted changes between branches.

In this case, since 2.md wasn’t yet committed to dev, it appears in your working directory after you switch to master, allowing you to either commit it in master or stash/discard it.

2. Committing the file on master

Once you commit 2.md on the master branch, the file becomes part of the master branch’s history. So now, 2.md is tracked and committed in master.

3. Switching back to dev after committing in master

When you switch back to the dev branch, the file 2.md disappears from both the working tree and the index. This happens because 2.md was never committed to the dev branch. On dev, your commit history doesn’t include that file, so Git removes it from your working directory to align with the state of dev.

Key Points:

  • Uncommitted changes in your working directory (like new files or changes to existing files) are not discarded when switching branches.
  • If a file exists in one branch (e.g., master) and not in another (e.g., dev), Git will remove it from the working directory when you switch back to the branch where the file does not exist.
  • If you want to avoid carrying over uncommitted changes when switching branches, you can either commit the changes or stash them with git stash before switching branches.

Commands for handling such situations:

  • To stash uncommitted changes:
git stash

To pop the stash and apply the changes after switching branches:

git stash pop

To commit changes before switching branches:

git commit -m "your message"
git checkout <other-branch>

Let me know if this clears things up or if you have any more questions!