Anton Haglund 2020-11-17 Switching branches in git ------------------------- When working in a big git repository containing ~100000 files, your project might figure out that dividing into several smaller repositories is a good idea. These smaller repositories are added as submodules with the same path as they where before. This is not a bad idea, but one consequence is that switching branches might now be a bit troublesome. Assume that the project forked a release-branch before splitting the repository, let's call this branch 'release_1_0'. Now you have to backport a patch to release_1_0 due to an issue found by a user. When switching from master to release_1_0 we stumble across the following error. -> git checkout release_1_0 error: The following untracked working tree files would be overwritten by checkout .. The project has here decided to minimize the impact on the build system by putting the submodules at the exact same place in the directory structure with the same name as the old directory, this is why we get the warning about files beeing overwritten. Git can't figure out how to solve this inconsitency between the different branches of what is a submodule or not. -> git checkout -f release_1_0 The first step is to forcefully checkout the branch. -> git status This leaves us with a bunch of untracked files, which we don't want. -> git clean -dfx Cleanup all the untracked files. -> git submodule update Update submodules. -> git status Git status is reporting that some of the submodules have untracked content, we should aim for git status to have a clean report we can consider done with the exercise. Here are two implementations of a shell script which help you if you have lots of submodules. tcsh: foreach i ( `git status | grep "untracked content" | awk '{print $2}' ` ) foreach? pushd $i foreach? git clean -dfx foreach? popd foreach? end bash: for i in $(git status | grep 'untracked content' | awk '{print $2}' ) > do > pushd $i > git clean -dfx > popd > done -> git status Git status is now reporting a clean repository. We are now done with switching branch from master to release_1_0. When we have backported our patch to release_1_0 we probably want to go back to master again. -> git checkout master Going back to the master branch again will give us another mess. -> git clean -dfx -> git submodule update --init -> rm -rf path/to/file0 -> rm -rf path/to/file1 -> rm -rf path/to/file2 Remove untracked files manually because git clean is skipping them. -> git status Git status is reporting that some of the submodules have modified content this time. tcsh: foreach i ( `git status | grep "(modified content)" | awk '{print $2}' ` ) foreach? pushd $i ; git reset --hard origin/master ; popd foreach? end bash: for i in $(git status | grep "(modified content)" | awk '{print $2}' ) > do > pushd $i ; git reset --hard origin/master ; popd > done -> git submodule update Restore the submodules in order to get a clean git status -> git status On branch master Your branch is up-to-date with 'origin/master'. nothing to commit, working tree clean Now we should be back to the normal state again for master.