Rewriting History#

Golden Rule: Don’t rewrite public history.

To undo local commits, use:

# Undoing comiits
git reset --soft # Removes the commit only
git reset --mixed # Removes commit and unstages files
git reset --hard # removes commit, unstages changes, discards local changes
# to undo the last commit
git reset --hard HEAD~1 # hard revert to commit previous to current head
position, i.e undo last commit.

git reset --(option) HEAD~3..HEAD # reverts the commits between the 4th last
and the head. Any similar combination of start..stop settings can be used.

To undo/change shared/published commits, use:

git revert <commitRef>   # Reverts a specific commit
git revert HEAD~3..HEAD  # TReverts the last three commits
git revert HEAD~3..     # HEAD is the default end and can be left out
git revert --no-commit HEAD~3.. # Doesn't make a seperate commit for each
revert and instad the are combined
git revert --abort # to cancel the revert
git revert --continue # to commit the revert

Recover lost Commits#

In case you accidentally removed some commits.

git reflog
git reset --hard HEAD@{X} # where X is the number of the head pointer you wish
to recover.

To see the history of other commit pointers, use:

git reflog show <branchName> # show history of <branchName> pointer.

Amending the Last Commit#

If you’ve committed and then realised there’s a typo, we shouldn’t do another commit. Instead we should amend that last commit.

We correct our typo, git add it and then:

git commit --amend  # We can add a new message or leave blank and accept the
orginal message from the previous commit.

If we want to include a file in the last commit. We make our changes, then add the file to the staging area and then commit using:

git commit --amend

If we want to remove a file form the last commit:

git reset --mixed HEAD~!
git status -s
git clean -fd # remove untracked files from working directory
git add .
git commit -m "New commit messages"

Amend an Earlier Commit#

We are going to use interactive rebasing. Identify the parent commit reference to where you wish to start the rebase.

The begin interactive rebasing.

git rebase -i <parentCommitref>

Edit the rebase plan. Select the key word of the commit you wish to change and replace them with the appropriate keyword from the included documentation. Make the changes and add, and commit them.

If you mess up:

git rebase --abort

If you’re happy with the changes:

git rebase --continue  # look at the logs to see the changes.

Dropping Commits#

To remove or drop commits we use:

git rebase -i <commitRefOfParent>
# We can use the parent refence, the refernce it self with ^ or the refernce
git rebase -i oiu76532^
git rebase -i oiu76532~1

In the rebase window, remove the reference to the commit we wish to drop. Save. This may generate conflicts. Use

git mergetool

to resolve commits.

git rebase --continue  # If you screw up, git rebase --abort takes us back to
the state before we started.

Rewording Commit Messages#

To reword we use

git rebase -i <parentRefernce>

Edit the rebase window to replace pick with reword. (Do not change the commit messages here). After saving, git will run through the list of commits, pause, and allow us to edit the commit messages for the commits we selected for rewording.

Reordering Commits#

git rebase -i <parentRefernce> # of oldest commit to reorder.

In the rebase window reorder the commits. In order to avoid multiple and difficult merge conflicts, try reordering on commit at a time.

Squashing Commits#

To combine related batches of work, logically parts of the same unit of work.

git rebase -i <parentRef>

Edit the rebase window to replace pick with squash. After saving, git will run through the list of commits, pause, and allow us to edit the commit messages for the combined/squashed commit. Edit as required and save.

To avoid editing the commit messages, we can instead choose to ignore the commit messages of some commits using fixup in place of squash.

Split a Commit#

To separate into multiple commits a previous commit that contains more than one logical units of change.

git rebase -i <parentRef>

In the rebase window we change the keyword from pick to edit on the commit we wish to split. Save.

The HEAD is now at the commit, and we can reset and make changes here.

git rebase -i <parentRef>
# pick -> edit. The save
git reset --soft Head~1 # the changes will remain as staged
# or
git reset --mixed Head~1 # the changes will be in the working
                         # directory

Make the appropriate commits reflecting logical units of change and once we’re done.

git rebase --continue