I’m working on updating several WordPress sites. Part of each site’s update includes converting the WordPress core and all frequently used plugins to Git submodules. While many recommend staying away from submodules all together, I’ve been using them for a while now and never had any issues, that is, until today. Luckily, it’s nothing severe, and in my case, pretty straight forward to fix (once you know the solution), but because the error didn’t make any sense, I’ve decided to document it here.
The main problem is that I’m unable to checkout the
master branch after adding the submodules on the
develop branch. Git complains with the following error:
error: The following untracked working tree files would be overwritten by checkout
That said, let’s look at the problem in detail and how we can solve it.
Let me setup the problem for you, in detail, using an example:
- You’re working on the
- You removed the
- You committed the changes
- You added
akismetback as a submodule
- You committed the changes
Attempt to checkout master branch
At this point, we’re on the
develop branch and trying to checkout the
master branch, but we’re greeted with this error:
# git checkout master error: The following untracked working tree files would be overwritten by checkout: wp-content/plugins/akismet/admin.php wp-content/plugins/akismet/akismet.css wp-content/plugins/akismet/akismet.gif wp-content/plugins/akismet/akismet.js wp-content/plugins/akismet/akismet.php wp-content/plugins/akismet/index.php wp-content/plugins/akismet/legacy.php wp-content/plugins/akismet/readme.txt wp-content/plugins/akismet/widget.php Aborting
For some reason, Git doesn’t recognize that those files have already been added and committed within the
akismet submodule, so it’s aborting the checkout to prevent them from being overwritten.
Review Git status
If there were truly untracked files, running a
git status would reveal them, but there aren’t any:
# git status On branch develop Your branch is up-to-date with 'origin/develop'. nothing to commit, working directory clean
Checkout master branch
Since we can’t checkout the
master branch the regular way, we’ll force it:
# git checkout master -f warning: unable to rmdir wp-content/plugins/akismet: Directory not empty Checking out files: 100% (1993/1993), done. Switched to branch 'master' Your branch is up-to-date with 'origin/master'.
Git displays a warning that it couldn’t remove our
akismet directory, which doesn’t make any sense, because it also exists on the
master branch, just not as a submodule.
Review Git status
We check the status again, just to find an untracked image directory:
# git status On branch master Your branch is up-to-date with 'origin/master'. Untracked files: (use "git add <file>..." to include in what will be committed) wp-content/plugins/akismet/img/ nothing added to commit but untracked files present (use "git add" to track)
To avoid tumbling down the rabbit hole deeper and deeper, let’s switch back to the
Checkout develop branch
It seems that everything is back to normal, but after a closer look, all submodule directories are either empty or incomplete. Running another
git status reveals that Git does recognize that something changed:
# git status On branch develop Your branch is up-to-date with 'origin/develop'. Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) (commit or discard the untracked or modified content in submodules) modified: wp-content/plugins/akismet (modified content) no changes added to commit (use "git add" and/or "git commit -a")
But to avoid any more confusion, let’s just reset all submodules.
We’ll go inside the
akismet directory and hard reset it:
# cd wp-content/plugins/akismet # git reset --hard HEAD is now at 645e807 Version 2.5.9
We’re basically back to square one, and to save you all from hours of trial and error, let’s look at the solution.
The only reason I wanted to checkout the
master branch in the first place, was to merge in the
develop branch and apply my updates. So let’s go ahead and do that.
1. Remove submodules
First, we’re going to remove the submodules that caused the conflict:
rm -rf wp-content/plugins/akismet
Note that we’re removing it without Git (
git rm); the goal here is just to get the problem directories out of the way. A
git status should display this:
# git status On branch develop Your branch is up-to-date with 'origin/develop'. Changes not staged for commit: (use "git add/rm <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) deleted: wp-content/plugins/akismet no changes added to commit (use "git add" and/or "git commit -a")
# git status On branch develop Your branch is up-to-date with 'origin/develop'. Changes to be committed: (use "git reset HEAD <file>..." to unstage) modified: .gitmodules deleted: wp-content/plugins/akismet
2. Checkout master branch
Second, we’ll checkout the
# git checkout master Checking out files: 100% (1993/1993), done. Switched to branch 'master' Your branch is up-to-date with 'origin/master'.
As you can see, without having to force it, we didn’t get the error we got before.
3. Merge develop into master branch
Third, we’ll merge our
develop branch into the
# git merge develop Updating 957cfdc..f3b9cfd Fast-forward ... wp-content/plugins/akismet | 1 + wp-content/plugins/akismet/admin.php | 850 --- wp-content/plugins/akismet/akismet.css | 12 - wp-content/plugins/akismet/akismet.gif | Bin 2777 -> 0 bytes wp-content/plugins/akismet/akismet.js | 112 - wp-content/plugins/akismet/akismet.php | 608 -- wp-content/plugins/akismet/index.php | 2 - wp-content/plugins/akismet/legacy.php | 396 -- wp-content/plugins/akismet/readme.txt | 153 - wp-content/plugins/akismet/widget.php | 108 - ... create mode 160000 wp-content/plugins/akismet delete mode 100644 wp-content/plugins/akismet/admin.php delete mode 100644 wp-content/plugins/akismet/akismet.css delete mode 100644 wp-content/plugins/akismet/akismet.gif delete mode 100644 wp-content/plugins/akismet/akismet.js delete mode 100644 wp-content/plugins/akismet/akismet.php delete mode 100644 wp-content/plugins/akismet/index.php delete mode 100644 wp-content/plugins/akismet/legacy.php delete mode 100644 wp-content/plugins/akismet/readme.txt delete mode 100644 wp-content/plugins/akismet/widget.php ...
You’ll notice that our
akismet directory is now empty, but that’s because the files for the submodule weren’t actually part of the
develop branch, so this is expected.
4. Fetch and update submodules
Lastly, we’ll fetch and update our submodules:
git submodule foreach git fetch --tags git submodule update --init --recursive
Which will checkout the very versions we chose on the
# git submodule update --init --recursive Submodule path 'wp-content/plugins/akismet': checked out '645e80750a543e2682b2369adfc77814d284b6f3'
That’s it. You’re now on the
master branch with all the changes you’ve made on the
Granted, this is not the most elegant way to accomplish the task, but it does, nevertheless, fix the problem… and with just a few commands:
rm -rf wp-content/plugins/akismet git checkout master git merge develop git submodule foreach git fetch --tags git submodule update --init --recursive
If you have any thoughts, questions or problems, let me know in the comments.