I usually submit a list of commits for review. If I have the following commits:
HEAD
Commit3
Commit2
For me it was for removing some credentials from a repo. I tried rebasing and ran into a ton of seemingly unrelated conflicts along the way when trying to rebase --continue. Don't bother attempting to rebase yourself, use the tool called BFG (brew install bfg) on mac.
If you haven't already pushed the commits then you can go back to a previous commit using git reset HEAD^[1,2,3,4...]
For example
git commit <file1> -m "Updated files 1 and 2"
git commit <file3> -m "Updated file 3"
Oops, forgot to add file2 to the first commit...
git reset HEAD^1 // because I only need to go back 1 commit
git add <file2>
This will add file2 to the first commit.
Based on Documentation
Amending the message of older or multiple commit messages
git rebase -i HEAD~3
The above displays a list of the last 3 commits on the current branch, change 3 to something else if you want more. The list will look similar to the following:
pick e499d89 Delete CNAME
pick 0c39034 Better README
pick f7fde4a Change the commit message but push the same commit.
Replace pick with reword before each commit message you want to change. Let say you change the second commit in the list, your file will look like the following:
pick e499d89 Delete CNAME
reword 0c39034 Better README
pick f7fde4a Change the commit message but push the same commit.
Save and close the commit list file, this will pop up a new editer for you to change your commit message, change the commit message and save.
Finaly Force-push the amended commits.
git push --force
I just thought I'd share an alias that I'm using for this. It's based on non-interactive interactive rebase. To add it to your git, run this command (explanation given below):
git config --global alias.amend-to '!f() { SHA=`git rev-parse "$1"`; git commit --fixup "$SHA" && GIT_SEQUENCE_EDITOR=true git rebase --interactive --autosquash "$SHA^"; }; f'
Or, a version that can also handle unstaged files (by stashing and then un-stashing them):
git config --global alias.amend-to '!f() { SHA=`git rev-parse "$1"`; git stash -k && git commit --fixup "$SHA" && GIT_SEQUENCE_EDITOR=true git rebase --interactive --autosquash "$SHA^" && git stash pop; }; f'
The biggest advantage of this command is the fact that it's no-vim.
(1)given that there are no conflicts during rebase, of course
git amend-to <REV> # e.g.
git amend-to HEAD~1
git amend-to aaaa1111
The name amend-to
seems appropriate IMHO. Compare the flow with --amend
:
git add . && git commit --amend --no-edit
# vs
git add . && git amend-to <REV>
git config --global alias.<NAME> '!<COMMAND>'
- creates a global git alias named <NAME>
that will execute non-git command <COMMAND>
f() { <BODY> }; f
- an "anonymous" bash function.SHA=`git rev-parse "$1"`;
- converts the argument to git revision, and assigns the result to variable SHA
git commit --fixup "$SHA"
- fixup-commit for SHA
. See git-commit docsGIT_SEQUENCE_EDITOR=true git rebase --interactive --autosquash "$SHA^"
git rebase --interactive "$SHA^"
part has been covered by other answers.--autosquash
is what's used in conjunction with git commit --fixup
, see git-rebase docs for more infoGIT_SEQUENCE_EDITOR=true
is what makes the whole thing non-interactive. This hack I learned from this blog post.