Let's say I created a subtree like this:
git subtree --add --prefix=subdir <path_to_remote> <remote_branch> --squash
Then I wanted to move/rename subdir, so I do this:
git mv subdir dir2/subdir
Now when I try to pull that subtree to a new prefix:
git subtree --pull --prefix=dir2/subdir <path_to_remote> <remote_branch> --squash
git says:
Can't squash-merge: 'dir2/subdir' was never added.
How can I do it properly?
The git subtree
command knows about your subtree, because it stores the name in the first commit when you add
a subtree:
Add 'subdir/' from commit 'c7fbc973614eced220dcef1663d43dad90676e00'
git-subtree-dir: subdir
git-subtree-mainline: c166dc69165f6678d3c409df344c4ed9577a2e11
git-subtree-split: c7fbc973614eced220dcef1663d43dad90676e00
git subtree pull
with the --squash
option looks for a commit containing git-subtree-dir
to find the most-recent commit from the remote repository and hence the point from which to apply and squash all commits.
In many cases a git subtree split --rejoin
operation will be successful:
$ git subtree split --rejoin --prefix=dir2/subdir HEAD
Merge made by the 'ours' strategy.
25070c483647f8136655d0e0c6c3d62f469177aa
The resulting commit looks like:
Split 'dir2/subdir/' into commit '25070c483647f8136655d0e0c6c3d62f469177aa'
git-subtree-dir: dir2/subdir
git-subtree-mainline: 59cc3c770e78dbc30bdfe36a6b4e14ce83b38f6c
git-subtree-split: 25070c483647f8136655d0e0c6c3d62f469177aa
This commit will be found and the next git subtree pull --squash
will succeed in most cases. Be aware that sometimes subtree operations fail and leave you with a branch of the subtree in your working copy of your repo. Make sure you delete any residual temporary branches to start with a clean slate.
Sometimes the above operation does not succeed, but I never found the reason why. In those cases you can rebase to the commit that added the subtree and change the directory name manually by amending the commit message. This operation will corrupt your whole history for everybody else, though.