Don’t panic. Here’s how to un-do mistakes in Git
Overview
- Fork
- Git config
- Clone in account folder
- git checkout file
- New branch
- Editing
- git cherry-pick
- Status
- Committed but not pushed
- Local Clean
- Un-Add/Reset from Staging
- Commit - Amend Message
- Commit - Amend Contents
- Commit - Should Have Branched
- Commit - Revert
- Reset Local Commits
- Public revert push
- Un-Push tags
- Fallback to previous SHA
- Delete branch
- Cancel Pull Request
- Upstream Remove
- Pull reversal
- Un-Fetch my changes
- Merge abandon during merge
- Forgot to create a branch first
- Resources
- More
This presents ways to reverse or un-do common actions in Git.
Fork
If you didn’t mean to fork a repository, but you did anyway, erase the repo.
-
Click on Settings tab in GitHub.
-
Scroll down to the bottom of the page and click Delete this repository.
-
Type the name of the repo.
-
Click “I understand the consequences, delete this repository”.
-
Provide your password if it’s requested again.
-
For a list of your repos, click your avatar at the upper-right corner and select Your profile.
Git config
If you find a mis-spelling in your attribution, simply repeat the command with the information you want.
On a Mac, git config commands create entries in the ~/.git/config file:
[user] email = wilsonmar@gmail.com name = Wilson Mar user = wilsonmar
Edit the text file.
Clone in account folder
If you mistyped, remove a folder and all its contents with a rm -rf command. But be at the folder above the folder you want to remove.
pwd cd .. rm -rf gitclass
git checkout file
Mentioning a single [file] in the
git checkout
command overwrites whatever changes have been made to the file and replaces it with an old version of that file:git checkout -- [file]
-
As with several other git commands, two dashes goes before specification of a single file.
-
Git assumes you want to checkout HEAD, the last commit on the currently-checked-out branch.
-
Whatever exists are permanently gone because they were not committed.
Checking out an old commit from .git repo history makes the entire working directory match that commit. However, the “current” state of your project remains untouched in the master branch.
New branch
A branch can be deleted because they are just pointers to commits.
git branch -d branch name
Editing
NOTE: It doesn’t matter how many times a file is changed and saved if that file is unmanaged.
To see whether the file is managed:
git status
git cherry-pick
To “replay” changes specified in a specific commit onto files in the working directory:
git cherry-pick [commit SHA1]
[git-cherry-pick in SCM,VIDEO]
Status
The git status command details the status of changes to the repo.
Committed but not pushed
To get a list of commits but not yet pushed:
git log origin/master..HEAD --oneline
Local Clean
If you are overwhelmed by too many untracked files in your working directory, first enumerate what files will be cleared:
git clean -n
Nuke files from the folder using the clean command:
git clean -fdx
- -f removes files untracked. It’s required.
- -d removes untracked directories.
- -x removes files Git ignores due to mention in .gitignore.
Un-Add/Reset from Staging
To remove a specified [file] (such as README.md) just from the staging area (undo git add), but leave the working directory unchanged:
git reset [file]
Alternately, the Staging area is also called cache because the command to remove a file in Staging:
git rm --cached [file]
- Specifying git rm without –cached removes the file from both cached and working directory.
To remove every file from Git’s index/Staging, add -r . (with the dot representing all files and folders under the current folder):
git rm --cached -r .
Commit - Amend Message
Changes can be made to specific commits as long as they have not been pushed to others in GitHub. The following applies to such commits.
If the message text is all you want to undo, repeat the command with
--amend
added:git commit -m"#DAC-123 Update again for show" --amend
The above creates a new commit SHA in place of the previous commit.
The amend action is remembered by
git reflog
locally until purged.Commit - Amend Contents
To replace just the content text of a commit, git add the change then:
git commit --amend --no-edit
The above command means you lose the ability to fall-back to previous versions. So use it only to fix minor typos.
See [docs/git-commit]
Commit - Should Have Branched
If you made a commit to master and then realized (before pushing) that you would like to put changes in the lastest commit under a new branch:
-
-
Checkout a new branch named “my-new-branch”, which you change:
git checkout -b my-new-branch
-
Identify the SHA of the previous commit:
git log --oneline
In the example below, it would be “ee1a5c98”:
b10405ec (HEAD -> master, origin/master, origin/HEAD) whatever ee1a5c98 Update
-
Identify the specific date and time of a commit:
git show --no-patch --no-notes --pretty='%ci' ee1a5c98
The response is a sortable international date format such as this:
2019-08-29 10:36:37 -0400
-0400 is the time zone offset for the local time in New York City, West of Greenwich, England (UTC 0).
-
Position the branch to the SHA found:*, for example:
git branch -f master ee1a5c98
-
Confirm:
git log --oneline
Commit - Revert
To change a file with commits already pushed to others, use the
git revert
command for Git to figure out the opposite of all the change introduced by a particular commit. If the commit added some text, revert deletes that text.First figure out the specific commit id using the git log command (such as “5a34def”)
git log
Then supply that commit id in the command:
git revert [commit-SHA]
The creates a new commit which need to be pushed up to GitHub.
See this explanation and manual on the git revert command.
Reset Local Commits
To reset the .git repo history and the working tree (the “hard” part) back the way it was one commit (^) ago:
git reset --hard HEAD^
- PROTIP:
--hard
is recommended because it keeps the working tree the same as what’s in the .git repository. - This should only be for commits which have not been pushed public.
- HEAD~1 is same as HEAD^ to go back one commit.
- HEAD~2 or HEAD^^ to go back two commits.
- Do not specify just HEAD because the point of the command is to go back.
- PROTIP: You may prefer to completely clear out whatever files created are untracked in the working tree.
- The next step is usually a
git add
.
Public revert push
The preferred alternatively is a revert command can be issued, as described above.
But do it for each commit pushed, in reverse order.
Alternately, to undo the previous
git push
command (specified by HEAD^) which sent to a remote origin what has been committed for a specific branch:git push -f origin HEAD^:master
- VIDEO: Rewriting Git History - Amend, Reword, Delete, Reorder, Squash and Split by The Modern Coder
- Git Tutorial 5: Undoing/Reverting/Resetting code changes by codebasics
Un-Push tags
To delete a tag in the origin repo (on GitHub or GitLab), such as in branch released:
git tag released/201706
PROTIP: In GitHub, the colon character is what specifies delete, followed by “refs/tags” as in:
git push origin :refs/tags/released/201706
Fallback to previous SHA
I’ve had to do this with my github.io repository, which contains markdown text in the _posts folder that GitHub automatically converts into displayable HTML in the _source folder. GitHub sends emails out if it cannot do that. However, I didn’t read my email and several changes to markdown didn’t become visible to readers.
To fix it, I looked at GitHub online to identify the date and time stamp to the last good update so I can fall back all changes to that point in time.
PROTIP: This is a way to fall back if there are no merges in between the current HEAD and the hash one before the one that you want to go back to:
git revert --no-commit e05fced..HEAD
git commit
git push
Delete branch
Because branches are just markers within Git, once a feature branch is in GitHub, that branch can be deleted from the local repo
git branch -d feat1
and from GitHub (by specifying that colon in front of the branch name).
git push origin :feat1
NOTE: The colon is the secret special sauce. There is no “delete” command with this.
Cancel Pull Request
A pull request can be cancelled in the GitHub web GUI.
Upstream Remove
To remove a remote named “upstream”:
git remote remove upstream
Verify:
git remote -v
Pull reversal
Use the
ORIG_HEAD
created when the last checkout occurred:git reset --hard ORIG_HEAD
Alternately, specify a timeframes reported by
git log
:git reset --hard master@{"10 minutes ago"}
Un-Fetch my changes
To undo what has been fetched from a remote, remove the remote:
git remote remove upstream
Now add it again and fetch only single branch:
git remote add upstream https://github.com/wilsonmar/git-utilities git fetch upstream
Merge abandon during merge
Cancel a merge:
git merge --abort
Forgot to create a branch first
If you’ve been committing to the master branch and realize that you should have first created a branch, you can create that branch and reset the master to that as the HEAD. [This article describes the process.
Create a branch:
git branch mytopicbranch
Identify the SHA associated to the commit where HEAD should be by looking on-line or a git log command such as commits not yet pushed, such as “2f7efb32”.
Reset HEAD to that SHA, such as:
git reset 2f7efb32 --hard
- PROTIP:
Resources
This page combines the wisdom from these who came before me:
-
Git Out Of Trouble by GitHub
-
ohshitgit.com (@ohshitgit) by Katie Sylor-Miller
-
Git Pretty by Justin Hileman (@bobthecow)
-
https://github.com/blog/2019-how-to-undo-almost-anything-with-git
-
Git and the Terrible, Horrible, No Good, Very Bad Day [35:03] by Hector Alfaro, trainer at GitHub, at Git Merge 2017 https://github.com/hectorsector/git-and-the-bad-day how to detangle things by use of more advanced porcelain commands such as git bisect.
Serious problems are fixed by BFG and git filter-branch
-
https://marklodato.github.io/visual-git-guide/index-en.html
-
https://opensource.com/article/18/6/git-reset-revert-rebase-commands 19 Jun 2018
-
https://evilmartians.com/chronicles/git-push—force-and-how-to-deal-with-it
More
This is one of a series on Git and GitHub:
- Why Git? (file-based backups vs Git clone)
- Git basics (script)
- Git whoops (correct mistakes)
- Git command shortcuts
- Git interactive merge (imerge)
- Git patch
- Git utilities
- Git hooks
- GitHub data security
- GitHub actions for automation JavaScript
- GitHub REST API
- GitHub GraphQL API
- GitHub PowerShell API Programming
- GitHub GraphQL PowerShell Module