Rewording/deleting commits
- imagine we want to change a commit message from 2 commits ago, or imagine we want to delete it altogether
- We can run git rebase -i HEAD~2
- meaning "I want to operate on the last 2 commits"
 
- vim will open and will list all of the commits that we have asked to change.
- change the command from picktoreword(ordropto delete) of the relevant commit, then save and close the file.
- change the message, save and close.
 
Changing contents of commit/Splitting commits
- run git rebase -i HEAD~n, wherenis the commit immediately preceding the commit we want to edit.
- change the rebase command of the commit we want to edit from picktoedit
- run git reset --mixed HEAD^, which leaves the working directory unchanged, but reverses the commit
- HEAD^is the parent of our current commit
 
- do our normal operations, adding files, deleting files, or modifying them as we please. git addthem,committhem as per normal workflow.
- run git rebase --continue
Reverting commits
- think of git revertas an inverse operation togit commit. Effectively, this command creates a new commit that undoes all of the changes introduced by a certain commit.
- Imagine we made a commit that simply changed which port our app connects to. Later on down the line, imagine that we want to "undo" that, and go back to the original port. We could change that port in the code and commit it, or we could simply run git revert <SHA>to make a new commit, known as arevert commitwhose sole purpose is to reverse the changes that that particular commit actually made.
Squashing commits
- Imagine we made 3 commits that should logically only be one.
- run git rebase -i HEAD~3
- leave the commit that everything will get squished into alone, but change the commits that will be thrown away from picktofixup
- listed by oldest to newest
- fixup and squish are similar, but fixup will discard the commit messages of the discarded commits.
- if we want to retain the commit messages, then use squashinstead offixup
 
 
- If we compare the git logs before and after, we will notice that the SHA of the commit with the same message will be different, showing that we are in fact rewriting history
Splitting commits
- Imagine we have made a commit that realistically should actually be split into 2 commits ("add navbar and fix bug")
- run git rebase -i HEAD~2
- change the commit we want to split from rebase operation picktoedit
- after saving the file, git will put us onto a special rebasing branch
- unstage all files that were added during that commit by running git reset HEAD^
- perform normal workflow, by adding commit1 changes and committing, then adding commit2 changes and committing
- run git rebase --continue
 
Undoing Work
- this will discard everything permanently
Restoring to the state of the last commit
- if just a single file, we can simply run git checkout HEAD <file>to blow away all changes, and restore the file to what it was in the most recent commit.
- if we want to blow away all changes and get the exact state of the last commit, we can run git reset --hard HEAD
- This tells Git to replace the files in your working copy with the "HEAD" revision
- we can replace HEAD with any SHA to go back to that previous version.
- note: this will not produce any new commits (like revert), nor will it delete any old ones. Instead, it works by resetting your current HEAD branch to an older revision (also called "rolling back" to that older revision)
- note2: since this doesn't rewrite history, the commits we "erased" are still available