ingydotnet / git-subrepo

MIT License
3.18k stars 263 forks source link

git subrepo pull after squashing #578

Open ehrencrona opened 1 year ago

ehrencrona commented 1 year ago

I'm getting the error message Local repository does not contain <A> ("A" being a specific commit ID) when running git subrepo pull. This is because I had rebased the history of the subrepo to squash some commits and clean up the history.

The equivalent, squashed commit (that is part of the history of main) has commit ID "B".

I tried to go into the .gitrepo and replace the commit= line with "B", but when I do that and rerun git subrepo pull I am still getting the same error message referring to commit "A". I have grep'ed through the entire repo and there is no reference to commit "A" anywhere.

How can I recover from this situation?

xzchaoo commented 1 year ago

Helo @ehrencrona . I also encountered this problem. Here is my workaround.

Hope the official can have a more elegant solution.

If there is no new local commits after your last git subrepo push, run git subrepo clone $remote $subrepo_dir -b $branch --force. It will force set the local subrepo dir content to the remote version.

Now the last three commit histories of your branch will be:

commit 1 ... git subrepo clone --branch=$your_branch --force $your_remote subrepo_dir 9 minutes ago
commit 2 ... git subrepo push --remote=$your_remote --branch=$your_branch subrepo_dir 13 minutes ago
commit 3 ... normal commit message

I think this commit history is not clean enough, so I will fix it using:

git rebase --soft commit3
git commit -m "new comment message".
git push -f
git subrepo push -r $your_remote -b $your_branch --force

If after git subrepo push you continue to make some commits on the branch of main repo and want to keep those commits.

current_branch=...

# make sure your workspace is clean

git checkout -b temp_branch `main repo commit id when last subrepo push`

git subrepo clone $your_remote $subrepo_dir -b $your_branch --force

git checkout $current_branch

git rebase temp_branch

# Maybe need to fix conflicts. When encountering a .gitrepo conflict, just keep any file on one side. I'll fix it later.
# It's great if there are no conflicts.

git reset --soft $temp_branch

# rollback .gitrepo
git checkout HEAD ${subrepo_dir}/.gitrepo

git commit -m "Here I squash multiple commits after last 'subrepo push' into one. Write some messages"

git branch -D temp

git push -f
git subrepo push -r $your_remote -b $your_branch --force

If you want to keep the original commit messages after your last 'subrepo push' instead squashing them into one commit. This is a little more complicated.

You need to modify the above code, start with git rebase temp_branch.

git rebase -i temp_branch
# pick all normal commits
# drop all commits generated by subrepo

git branch -D temp
git push -f
git subrepo push -r $your_remote -b $your_branch --force