I had to change some of my Git history because I had used the wrong Github user to push some changes to personal projects.
I just needed to change the user that committed the code without changing any of the other history. I don’t use rebase very often so here are my notes on this.
It’s ok to make changes like this to master/main branch on personal projects because you’re the only person using the repository.
But you probably don’t want to do this on anything other than a feature branch when you’re working in repo with many other users. You could really mess up some of your colleagues work. It’s most likely that your master branch is locked against making destructive changes anyway.
Rebase changes your Git history. This is destructive and you want to be able to revert it if you’re not happy at the end.
I highly recommend creating a “restore point” tag to go back to if you need it. You wont need this for every rebase but it’s really handy for tricky ones.
git tag REBASERESTORE_20210320_DARRAGH
Now you can undo the rebase later with
git reset --hard REBASERESTORE_20210320_DARRAGH
There is a default tag called
ORIG_HEAD that points to the tag before you started a destructive action but it is controlled by Git. You can use this to reset to the current state of your repo but I prefer to have a tag that I know will not change before I need it.
## Find the last commit that was good Find the hash of the commit that was ok. This is the commit just before the one(s) you need to change. If you need to rebase from the first commit use `git rebase -i --root` ## Start the rebase by using interactive ```shell git rebase -i f56f4c6c370d6c80ce35d1300fb8fde7b7a442f1
Output from Git interactive below. Using the defaults Git will open a text editor in the console showing you the commits that can be changed.
You will edit the lines in the file describing the changes you want to make and then save the file.
GNU nano 2.0.6 File: ...ordan-com/.git/rebase-merge/git-rebase-todo pick d6a295d change date pick 1464991 migrate to gatsby v3 # Rebase 17c9b0e..1464991 onto 17c9b0e (2 commands) # # Commands: # p, pick <commit> = use commit # r, reword <commit> = use commit, but edit the commit message # e, edit <commit> = use commit, but stop for amending # s, squash <commit> = use commit, but meld into previous commit # f, fixup <commit> = like "squash", but discard this commit's log message # x, exec <command> = run command (the rest of the line) using shell # b, break = stop here (continue rebase later with 'git rebase --continue') # d, drop <commit> = remove commit # l, label <label> = label current HEAD with a name # t, reset <label> = reset HEAD to a label # m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
To delete a commit completely just comment out the line with
GNU nano 2.0.6 File: ...ordan-com/.git/rebase-merge/git-rebase-todo # pick d6a295d change date pick 1464991 migrate to gatsby v3
Git will delete this commit. Make sure you really want this. The code is gone.
To change the author you must set the commit to edit (or
GNU nano 2.0.6 File: ...ordan-com/.git/rebase-merge/git-rebase-todo e d6a295d change date pick 1464991 migrate to gatsby v3
To combine the commit with the previous commit you use rebase (or
r). This can be useful if you need to edit the name on many commits because you can just combine them into one first. Then do another rebase afterwards to change the author of one commit.
GNU nano 2.0.6 File: ...ordan-com/.git/rebase-merge/git-rebase-todo r d6a295d change date r 1464991 migrate to gatsby v3
You need to save the file. In nano use
ctrl-o and use the name Git suggests by just pressing
enter. Then press
ctrl-x to exit the editor. This might be different for you depending on operating system or your settings.
Rebase interactive will start running through each of your requests one-by-one.
For each commit that you chose to edit (
e) Git will ask you what changes you want to make. To change the author use
git commit --amend --author="Darragh O'Riordan <email@example.com>" --no-edit
--no-edit here. This is important. If you don’t use
--no-edit then Git will create a NEW commit with your changes. We don’t want this. We just want to edit the existing commit.
Now Git will suggest you move on to the next commit you asked to edit so we ask it to continue
git rebase --continue
Keep going until the rebase command finishes. Git will print a message when it’s done.
Successfully rebased and updated refs/heads/master.
So you’re all done. Now you might need to update the origin.
Make sure you know that it’s safe to push these changes to your origin.
It’s probably safe if you’re on a feature branch only you have worked on or if it’s a personal project that only you commit to. Just push with —force.
git push --force
You can abort in the interactive stage with
git rebase --abort
OK so this will vary depending on what you’ve done.
If you have created a restore point you can go back to that
git reset --hard REBASERESTORE_20210320_DARRAGH
If you just realized you did something wrong right after seeing
Successfully rebased and updated refs/heads/master then you can probably use a restore point that Git automatically creates for us at
git reset --hard ORIG_HEAD
Please note that running this again will go back to the next ORIG_HEAD before the last
merge so be careful.
If you don’t have either of those available then you might be in trouble.
If you get an error like
warning: could not read '.git/rebase-merge/head-name': No such file or directory
Then you can completely quit the messed up rebase with