The Three Trees of Git (Part 2)
Interacting With Git’s Working Directory, Index and HEAD Mechanisms to Undo
July 30, 2020
Photo by Franck V. on Unsplash
checkout
Checkout the <filename> in the state it was in the last commit and permanently undo any changes that have been made to the <filename> since the last commit.
git checkout -- <filename>The two hyphens in between checkout and the <filename> are used to indicate that the name represented by <filename> is an actual file as opposed to a branch or an available command option that can be used with `git checkout`. If <filename> doesn’t match a branch name, or match an available option, or match a filename that starts with a hyphen, then you can omit the hyphens.
Checkout <filename> in the state it was in <n> commits prior.
git checkout HEAD~<n> <filename>If you perform this action and then stage and commit the file it will permanently undo any changes you made to <filename> after the corresponding commit you checked out.
This behaves the same as the command above but uses the <commit> instead of the HEAD to target and checkout <filename> in the state it was in at <commit>.
git checkout <commit> <filename>If you perform this action and then stage and commit the file it will permanently undo any changes you made to <filename> after the corresponding commit you checked out.
rm (remove)
Permanently remove an unmodified file from the Git repository and delete it from your computer.
git rm <filename>By “unmodified” I mean a file that has previously been tracked and committed but hasn’t been changed since the last commit or since being added to the Index. To remove “modified” files see examples below that use the `--force` option.
Permanently remove a modified file your repository and delete it from your computer.
git rm -f <filename>(-f is a shortcut for --force)As a safety precaution Git ordinarily doesn’t allow you to remove a modified file (a file that has been tracked and committed but has unsaved changes) but the `--force` option is what allows you to override this.
Unstage an unmodified file from the Index and stop tracking that file but keep the file in the Working Directory as an untracked file.
git rm --cached <filename>`--cached` is what allows you to keep a file in the Working Directory after you remove it from the Index and stop tracking it.
Same as above but target a folder that contains sub-directories and files.
git rm -r --cached <folder_name>This one is particularly helpful if you ever forgot to add your `node_modules` folder to your `.gitignore` file. For example, if you forget and accidentally push your `node_modules` to your remote repository you can add `node_modules` to your `.gitignore` file, run `git rm -r --cached node_modules` and then after you commit and push, `node_modules` will be removed from your remote repo and Git will no longer track it.
Unstage a modified file from the Index, stop tracking that file but keep any file modifications and keep the file in the Working Directory as an untracked file.
git rm --cached -f <filename>clean
Remove the untracked <filename> from the Working Tree and permanently delete it from your computer.
git clean -f <filename> (-f is a shortcut for --force)Same as above but it operates on all untracked files in the current directory.
git clean -fIf you want to first check to see what file would be removed you can use `git clean -n` (`-n` is a shortcut for `--dry-run`)
Same as the commands above but the addition of the `-d` option will also recursively remove all untracked sub-directories and/or any untracked files within those directories.
git clean -fdSimilar to the command above, you can use `git clean -nd` to see which files and sub-directories would be removed. If a sub-directory you attempt to clean has both tracked and untracked files then only the untracked files will be removed and the sub-directory will be kept in place.
reset
Unstage all modified files from the Index and move them back into the Working Directory with the modifications intact and move the HEAD and branch to the prior commit. The Index now matches the state of the prior commit.
git reset (shorthand for git reset HEAD --mixed)For all reset commands where you don’t specify a specific commit, Git will assume you want to target the HEAD, which is typically going to be the most recent commit.
Unstage a specific file from the Index with the modifications intact. This is basically the opposite of using `git add` to stage a file to the Index.
git reset <filename>Move the HEAD and branch to the specified commit but leave the Index and Working Directory intact.
git reset --soft <commit>Similar to the `git commit --amend` command, this will allow you to edit and add changes to a commit, but instead of only working on the most recent commit it will allow you first undo any commits that come after the target commit.
Move the Index, Working Directory, HEAD and branch to the prior commit. This will delete any modifications you’ve made to tracked files since the last commit (any untracked files will still exist).
git reset --hardSame as above but this will also delete any commits you made after the target commit.
git reset --hard <commit>revert
Create a new commit with the changes introduced by <commit> undone but keep <commit> and any commits that occurred after it in the history.
git revert <commit>Git will automatically initialize a new commit but by default it will enter VIM to allow you to enter a custom message. If you don’t care about customizing the message you can add the `--no-edit` option. Also, if you don’t want Git to automatically initialize a commit you can add the `-n` option (shorctut for` --no-commit`) and Git will apply the necessary changes from the reverted commit but will just add them to the Working Directory and Index so you can include additional updates in the next commit.
Same as above but target the <n>th most recent commit (e.g. git revert HEAD~2 will target the 3rd most recent commit).
git revert HEAD~<n>Amending Commits
Edit the commit message for the prior commit. Also, if you’ve staged any new changes before running the `amend` command then those changes will also be included in the amended commit.
git commit --amend -m “<your revised commit message>”