Converge Divergent Git Repositories
In GitHub we clone a repository, make changes and issue pull requests. Often the pull request is not fully merged into the upstream repository. There can be several reasons for this:
- The upstream maintainer rejects or ignores my commits.
- The upstream maintainer cherry picks some commits and rejects others.
- The upstream maintainer manually updates their repository with selected commits.
The result is that the two repositories do not have the same commit history. My repository contains commits that are not in the upstream repository. This may be fine and desirable if I want the code bases to diverge. The problem comes if I really just want to keep collaborating on the same code base. So I make further modifications and issue a pull request against the upstream repository. All the older commits that were not merged will appear as part of the pull request. This makes it confusing for the remote maintainer. I have to say something like "pull in the last two commits but ignore the rest". And it happens for every pull request.
If my old commits are not going upstream I may decide to reverse them so that future pull requests are more concise. I can converge with the upstream repository in two ways.
- The safe way is to make new commits that reverse all the unwanted commits. That will cause the actual repository content to converge. If I examine a pull request I can see the commit list and use this to build my list of converging commits. The downside to this approach is that it involves manually reverting each commit.
- The second approach is useful if you are the only one using the repository and it hasn't been cloned. The commit history can be rewritten to match the upstream repository.
git rebase -i HEAD~to review and remove the commits that weren't merged upstream.
git push -fto force your repo to accept the rewritten history.
The upside of this is that it is quick and easy to accomplish. The downside is that it is only appropriate for commits that haven't been shared.