Merge git fork changes with unrelated histories

If the history of a Git repository has been rewritten, but someone has forked the repository before the history was rewritten, they will be unable to merge due to the unrelated history. This method corrects the history in their forked branches to match the original repository.

In this synthetic example:

  • Original Git repository: github.com/username/coolprog main branch develop
  • Forked Git repository: github.com/jane/coolprog
  • A colleague, Jane, with GitHub username jane, has created a branch from develop named feature1. However, scivision changed the history of develop after the fork.

The “easy” way can reduce the risk of compromising months or years of work compared to the “Pure Git” way.

Easy way

If the “Pure Git” way was attempted first, avoid using that directory. Instead, git clone the forked repository again.

Clone the forked repository into a temporary directory:

cd ${TMPDIR}
git clone https://github.invalid/jane/coolprog

cd coolprog
git switch feature1

Create a branch jane-feature1 in the original repository to copy the forked changes:

cd ~/code/coolprog

git switch -c jane-feature1

Manually merge the changes made in the feature1 branch using compare folders.

Note that the repository will likely have many files that are not in the fork due to .gitignore.

For any new files that need to be tracked by Git: git add filename

When satisfied with the manual merge, commit the changes in jane-feature1 to give proper credit to jane:

GIT_COMMITTER_NAME="Jane" GIT_COMMITTER_EMAIL="jane@users.noreply.github.com" git commit --author="Jane <jane@users.noreply.github.com>"

Note that Jane’s real-life email is not used to avoid exposing it to spammers. Verify the commit with git log.

Upload the changes to the Git repository:

git push -u origin jane-feature1

Merge changes into main branch

To incorporate these new features into the develop branch:

git switch develop

git merge jane-feature1

git push

Jane should create a new fork of the repository, deleting the old fork with the incorrect history to avoid repeating this process for future changes.

Reforking current repository

Jane should refork from the original GitHub repository with the corrected history to clean up the “unrelated changes” issue.

To do this, assuming no further changes have been made:

  1. Delete the coolprog directory on the local machine.
  2. “Delete repository” at the bottom of https://github.invalid/jane/coolprog/settings.
  3. Fork the original repository again from https://github.invalid/scivision/coolprog#fork-destination-box.

This procedure is typically unnecessary and is only required when Git history has been rewritten before the fork.

Pure Git

This method requires Jane to force push and execute these commands (or grant write access to the forked repository). It is risky, so the “Easy” way is recommended.

Clone the forked repository into a temporary directory:

cd ${TMPDIR}
git clone https://github.invalid/jane/coolprog

cd coolprog
git switch develop

Add the original repository as upstream of the fork:

git remote add upstream https://github.invalid/scivision/coolprog
git fetch upstream

git rebase upstream/develop

git switch feature1
git rebase develop

If these changes are successful and the Git history is confirmed to be correct, a git push -f can be performed. Ensure secure, independent copies of the GitHub repository are available, as force-pushing overwrites Git history and may erase work.

Sometimes for Git repos with a long, complicated history this doesn’t work, and would be time consuming to fix. In that case, let’s try the “easy” way.