"Whoops I didn't mean to commit that file."
This happens to me way too often. You commit a file, or find a new mistake and you don't want to clutter your commit history with quick fixes (even on a feature branch). Which is why git --amend is amazing and a really simple git trick that I don't think developers use enough.
Let's start with an example. We're writing our beautiful and extremely useful hello_world.py program. It looks like this
def hello_world(): return "Hello world!"
And our repo's log looks like this
~/Code/hello jordanhoover$ git log commit e8f9d04f1322b1a217d5d549c061793f498ad6c1 (HEAD -> master) Author: jordan Date: Mon Nov 11 17:58:44 2019 -0600 Initial commit.
Sweet. Turns out, though, we're actually in Hawaii, so we need this code to say "Aloha world" and we've already committed. No problem. Let's update the code first.
def hello_world(): # Is it goodbye or hello?! We'll never know return "Aloha world!"
Okay. Now we do our normal git process.
~/Code/hello jordanhoover$ git status On branch master Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: hello_world.py no changes added to commit (use "git add" and/or "git commit -a") ~/Code/hello jordanhoover$ git add hello_world.py ~/Code/hello jordanhoover$ git status On branch master Changes to be committed: (use "git reset HEAD <file>..." to unstage) modified: hello_world.py
We also commit just like normal, but add the --amend flag. We can add --no-edit to keep our previous message.
~/Code/hello jordanhoover$ git commit --amend --no-edit [master 380c861] Initial commit. Date: Mon Nov 11 17:58:44 2019 -0600 1 file changed, 2 insertions(+) create mode 100644 hello_world.py
Taking a look a the logs, our history still looks the same (except for our commit hash, which I'll get to here in a minute). Perfect.
~/Code/hello jordanhoover$ git log commit 380c86132b2f2d3ed0ee06e00880b66628ead952 (HEAD -> master) Author: jordan Date: Mon Nov 11 17:58:44 2019 -0600 Initial commit.
If we want to change the message, we can do that too. Just pass the -m flag per usual. You can also update the author or anything else you'd like with other commit flags.
~/Code/hello jordanhoover$ git commit --amend -m "Brand new commit message." [master 6c4ae9d] Brand new commit message. Date: Mon Nov 11 17:58:44 2019 -0600 1 file changed, 2 insertions(+) create mode 100644 hello_world.py ~/Code/hello jordanhoover$ git log commit 6c4ae9d45635be4856135d6202e569c5af40d07d (HEAD -> master) Author: jordan Date: Mon Nov 11 17:58:44 2019 -0600 Brand new commit message.
So this all sounds great, but how does this work with our remote branch? Well, lets check our status.
~/Code/hello jordanhoover$ git status On branch master Your branch and 'origin/master' have diverged, and have 1 and 1 different commits each, respectively. (use "git pull" to merge the remote branch into yours) nothing to commit, working tree clean
Git is telling us that our commits have diverged, because an amend completely overwrites the previous commit with the new replacement commit. This is why we had a new commit hash after our amend.
To reconcile our repos, we'll we have to do a force push, which tells Git to overwrite the remote branch's current history with the local one. Because this action is so encompassing and final, remember to be cautious. If you're working on a team or major project this should be done on your own feature branch and never on master. For the purposes of our demo, force pushing to master is fine.
To push we use our normal git push command, but with an -f flag.
~/Code/hello jordanhoover$ git push -f origin master Enumerating objects: 3, done. Counting objects: 100% (3/3), done. Writing objects: 100% (3/3), 269 bytes | 269.00 KiB/s, done. Total 3 (delta 0), reused 0 (delta 0) To github.com:jhoover4/hello-world.git + 6c4ae9d...2b707e7 master -> master (forced update)