Matthieu Vergne's Homepage

Last update: 06/01/2022 17:50:20

How to Safely Rewrite Git Commits?

Context

You want to improve your Git commits history, but you feel unsafe. What may happen if you mess up something? That is a good mindset: improving a Git history is rather simple, but as much as messing it up.

Question

How to safely rewrite Git commits?

Method

Delay the replacement of the original branch

Various commands offer similar capabilities. There is not a single way to do in Git. If you happen to use commands that touch your original branch, you may prefer to replace them by others and move the branch only at the end (or when necessary).

For example, git reset move your current branch to another commit. You may prefer git checkout to move to this commit while keeping your original branch where it is. Don't forget, however, that commands expecting this move must be changed too. You may use the commit ID instead of the branch that was supposed to point to it. At the end, don't forget to move your branch to the rewritten commits with git reset --hard or git branch --force.

Adapting the Git commands is not an easy task if you don't know them well enough. If you prefer to keep your procedure, prefer to rely on the backup describe below.

Use a Backup

Before to rewrite the commits of a branch, checkout and ensure it is in a satisfying state. Then, create your backup variables:


BACKUP_BRANCH=$(git rev-parse --abbrev-ref HEAD) # Current branch
BACKUP_COMMIT=$(git rev-parse ${BACKUP_BRANCH})  # Current commit of the branch

You can also push the branch on a remote to have a remote backup. It will help for the worst, paranoid cases.

If you think that rewriting your history went OK, you can compare your current state with the backup:


git diff ${BACKUP_COMMIT}

If you only rewrite the commits, the diff should be empty. Otherwise, you should only see expected changes.

If something goes wrong and you are lost, unable to retrieve a clean state, just reset everything:


git rebase --abort                # Stop any running rebase
git cherry-pick --abort           # Stop any running cherry-pick
git reset --hard                  # Remove any uncommitted change
git checkout ${BACKUP_BRANCH}     # Ensure that we are on the right branch
git reset --hard ${BACKUP_COMMIT} # Ensure that this branch is on its initial commit

If you messed up your local environment, including variables, you can git reset --hard on the remote backup. In the worst case, you can just delete the complete repository (format your computer, etc.), clone again the remote and checkout from the remote branch.

You can now restart from the beginning. Just avoid doing the same mistakes again.

Answer

To safely rewrite a Git history, you can either:

  • adapt the commands to apply the rewrite at the end if everything is OK ;
  • maintain a backup, like environment variables pointing to the original branches and commits, to reset to if something goes wrong.

Adapting the procedure helps when you know enough the commands ot the procedure and their equivalents. If you don't feel safe enough with that, prefer the backup solution. For a greater level of safety, prepare a remote backup that you can checkout/clone again if even your local environment explodes.

Bibliography