Git 4: Correcting Mistakes
Correcting Mistakes
Note: I’m doing this in Ubuntu 18.04.
A useful Git tool to have in your back pocket is git stash. Let’s start by making a clean repository as follows:
mkdir my_cool_app
cd my_cool_app
git init
Initialized empty Git repository in ~/my_cool_app/.git/
Open a file a called killer_app.py in your favorite editor and type:
print("My killer app")
then save the file. Then stage and commit by:
git add killer_app.py
git commit -m "Initial commit"
which yields:
[master (root-commit) 4c62075] Initial commit
1 file changed, 1 insertion(+)
create mode 100644 killer_app.py
Pro Tip: you must have at least one commit to stash.
Now add a line to your killer_app.py script:
print("Isn't it cool?")
Next close your editor (this is important later). Then enter the following at the shell prompt:
git stash push -m "Saving work"
which should yield:
Saved working directory and index state On master: Saving work
This has pushed the working directory onto a data structure called a stack. Don’t believe me? Try entering:
git stash list
at the prompt. It should result in something like:
stash@{0}: On master: Saving work
(END)
being output to the terminal. When you are done type ‘q’ to get back to your shell. Now reopen your editor and you should see the last line has been removed. Close your editor one more time, then enter:
git stash pop
which results in:
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: killer_app.py
no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (f8c6f24796935e696f5aa51148b85a86be52820b)
What’s just happened is that Git has popped the last entry off of the stash stack. Reopen your editor and you will see the last line has reappeared.
Amending, Unstaging, and Unmodifying
These come from the Git book.
Amending
You can also amend a commit, meaning you can undo a mistake one commit back. As an example, if you commit and then realize you forgot to stage the changes in a file you wanted to add to this commit, you can do something like this:
git commit -m 'Initial commit'
git add forgotten_file
git commit --amend
You end up with a single commit — the second commit replaces the results of the first.
Only amend commits that are still local and have not been pushed somewhere! Amending previously pushed commits and force pushing the branch will cause problems for your collaborators. For more on what happens when you do this and how to recover if you’re on the receiving end read The Perils of Rebasing.
Unstaging
The next two sections demonstrate how to work with your staging area and working directory changes. The nice part is that the command you use to determine the state of those two areas also reminds you how to undo changes to them. For example, let’s say you’ve changed two files and want to commit them as two separate changes, but you accidentally type git add *
and stage them both. How can you unstage one of the two? The git status
command reminds you:
git add *
git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)renamed: README.md -> README
modified: CONTRIBUTING.md
Right below the “Changes to be committed” text, it says use git reset HEAD <file>...
to unstage. So, let’s use that advice to unstage the CONTRIBUTING.md
file:
git reset HEAD CONTRIBUTING.md
Unstaged changes after reset:
M CONTRIBUTING.md
git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)renamed: README.md -> README
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: CONTRIBUTING.md
The command is a bit strange, but it works. The CONTRIBUTING.md
file is modified but once again unstaged.
For now this magic invocation is all you need to know about the git reset
command. We’ll go into much more detail about what reset
does and how to master it to do really interesting things in Reset Demystified.
Unmodifying
What if you realize that you don’t want to keep your changes to the CONTRIBUTING.md file? How can you easily unmodify it — revert it back to what it looked like when you last committed (or initially cloned, or however you got it into your working directory)? Luckily, git status tells you how to do that, too. In the last example output, the unstaged area looks like this:
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: CONTRIBUTING.md
It tells you pretty explicitly how to discard the changes you’ve made. Let’s do what it says:
git checkout -- CONTRIBUTING.md
git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)renamed: README.md -> README
You can see that the changes have been reverted.
Important! It’s important to understand that
git checkout -- <file>
is a dangerous command! Any local changes you made to that file are gone — Git just replaced that file with the most recently-committed version. Don’t ever use this command unless you absolutely know that you don’t want those unsaved local changes!
Git Restore
Git restore is relatively new and I haven’t used it much. It is covered here.
Git Diff & Git Difftool
There is a diff tool provided in Git. Others have documented it. There is a Git difftool as well.
git mv and Git Rm
Also provided out of the box with Git are git mv and git rm. Be very careful with git rm and be sure you actually are deleting what you think you are deleting!
Next:
Next time we’ll get into the weeds a bit and explore some of how Git works under the hood.
If you are not interested in getting in to the details as much, I suggest you skip to this page.
Credits
https://linuxfromanoobie.wordpress.com/2018/04/21/git-undoing/
https://www.freecodecamp.org/news/useful-tricks-you-might-not-know-about-git-stash-e8a9490f0a1a/
https://stackoverflow.com/questions/10725729/see-whats-in-a-stash-without-applying-it
https://www.git-tower.com/learn/git/ebook/en/command-line/advanced-topics/diffs/#start
https://www.toolsqa.com/git/git-diff/
https://stackoverflow.com/questions/255202/how-do-i-view-git-diff-output-with-my-preferred-diff-tool-viewer