Skip to content

Instantly share code, notes, and snippets.

@mbbx6spp
Last active January 2, 2022 09:09
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mbbx6spp/ad45953f8cfe0115bd6d245558e84b45 to your computer and use it in GitHub Desktop.
Save mbbx6spp/ad45953f8cfe0115bd6d245558e84b45 to your computer and use it in GitHub Desktop.

Rewriting Git history on feature branches

Assumes:

  • feature branch is feature/add_csv_file
  • mainline is deploy

If you want to rewrite Git history on your feature branch here is how to do it.

  1. Make sure you are on the branch you want to rewrite the history of:
git checkout feature/add_csv_file
  1. Next you want to make sure you have the latest changes pulled locally and rebase un-pushed commits on top of remote changes:
git pull --rebase feature/add_csv_file
  1. Now make sure you have the latest mainline (deploy) changes fetched locally:
git fetch origin deploy
  1. Now we will interactively rebase our feature branch changes on top of the mainline:
git rebase -i origin/deploy
  1. At this point git will ask you for the plan for your rebase with a list of commits in order which you can edit to tell Git how to reorder or squash your commits. When you want to squash one commit into the previous commit you will want to change the pick keyword for that commit to squash. The initial plan will look something like this:
pick d17582b Add instructions on safely rewriting history in Git feature branches
pick 2ed86d4 Add rebase plan example
You might decide to squash the last commit into the first one like so:
pick d17582b Add instructions on safely rewriting history in Git feature branches
squash 2ed86d4 Add rebase plan example

Other possible commit commands supported in the rebase plan are:

  • p or pick <commit> uses the commit
  • r or reword <commit> uses the commit, but allows you to edit the commit message
  • e or edit <commit> uses the commit, but stops for user to amend it
  • s or squash <commit> use commit, but meld into previous commit
  • f or fixup <commit> like squash, but discards this commit’s log message
  • x or exec <command> run command (the rest of the line) using the current shell
  • b or break stops at that point, forces a pause (to continue the rebase process later you would use ‘git rebase –continue’)
  • d or drop <commit> remove commit
  • l or label <label> labels current HEAD with a name
  • t or reset <label> resets HEAD to a label

Read more about these and other options in the git rebase manual pages or official documentation.

  1. Once Git has rebased based on the plan you gave it above, you'll want to check the history in Git is what you expect it should be. You can use tig or variations of git log.

  2. If you have rewritten history that was previously on the remote branch you will not be able to simply push as usual, so the following typical push command will fail git server checks:

git push origin feature/add_csv_file # this will not work

To rewrite the remote branch's history with your changes safely you can use the --force-with-lease flag which will ensure that your history rewriting was done with the latest remote branch history:

git push origin feature/add_csv_file --force-with-lease

If you get an error here you will want to start over since someone has pushed to the remote branch in the time it took you to rewrite your history. Go back to the first bullet above to restart.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment