562

I commit to a git repository for the first time; I then regret the commit and want to revert it. I try

# git reset --hard HEAD~1

I get this message:

fatal: ambiguous argument 'HEAD~1': unknown revision or path not in the working tree.

This commit is the first commit of the repository. Any idea how to undo git's initial commit?

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Chau Chee Yang
  • 18,422
  • 16
  • 68
  • 132

11 Answers11

887

You just need to delete the branch you are on. You can't use git branch -D as this has a safety check against doing this. You can use update-ref to do this.

git update-ref -d HEAD

Do not use rm -rf .git or anything like this as this will completely wipe your entire repository including all other branches as well as the branch that you are trying to reset.

CB Bailey
  • 755,051
  • 104
  • 632
  • 656
  • 1
    Tried this while in a rebase -- wanted to split the very first commit -- then did `git status`, and to my surprise, git said `fatal: Not a git repository (or any parent up to mount point ...)` ! – Matt Fenwick Nov 21 '13 at 19:52
  • 1
    this didn't work for me. Make files including some that should be ignored but no `.gitignore`. `git add .`, `git commit -m "initial commit"`, `git update-ref -D HEAD`, create a `.gitignore`, notice that git still is seeing the files it added earlier that should ignored. In other words `git update-ref -d HEAD` did not take me back to the state before the initial commit. – gman Nov 20 '14 at 22:39
  • @gman: `.gitignore` has not effect on files that are already tracked (i.e. added to the index) – CB Bailey Nov 21 '14 at 07:49
  • 2
    But that's the point of the original question. Going back to the state just before the initial commit. – gman Nov 21 '14 at 08:08
  • 1
    @gman: No, this question is about _reverting_ the initial commit. Your question is a different question and should be asked as such, not as a comment on a 3 year old answer (where it gets almost zero visibility). – CB Bailey Nov 21 '14 at 08:09
  • 2
    `git reset --hard HEAD~1` would remove added files for all other commits. Clearly the question is how to get to the same state as that command works in all other cases. See this gist for proof your solution doesn't work https://gist.github.com/greggman/522fa69a21d6cfb3ff0b – gman Nov 21 '14 at 08:34
  • 30
    In case anyone gets confused by gman's comments: `git update-ref -d HEAD` **does** actually revert the initial commit, but keeps all previously commited changes added to the index. If you want to also remove those changes, just execute a following `git reset --hard`. Even if incomplete, this answer is indeed the best one, so avoid using `rm -fr .git` (unless you know what you are doing). – rsenna Aug 02 '15 at 17:21
  • 1
    Magic! Exactly what I needed. – Liran H Feb 21 '19 at 19:45
  • Regarding the use case of going back to the state just before the initial commit for the purpose of adding items to `.gitignore` (@gman's comments), do the following after running the `git update-ref -d HEAD` command: 1. Add the files to `.gitignore` if they are not already there. 2. Use `git rm --cached ...` to unstage the files you want to be untracked. 3. Then, when running `git status` again, you'll see that the files are ignored. – acetone Dec 27 '20 at 23:15
  • @MattFenwick see https://stackoverflow.com/questions/3695675/splitting-the-first-commit-in-git for splitting the first commit in a rebase. In short, `git rm --cached -r .` and `git commit --amend` did the trick for me. – mdcq Jan 02 '21 at 23:35
  • When I did this I ended up with all my current files added to the index, and had to remove them with `git diff --name-only --cached | while IFS= read f; do git rm --cached "${f}"; done` to really get a clean slate. – David Moles Jul 27 '21 at 14:49
  • As [DanK comments](https://stackoverflow.com/questions/6632191/how-to-revert-initial-git-commit/6632203?noredirect=1#comment77583063_36496818), `git update-ref -d HEAD` just deletes a reference to the last commit. It doesn't actually delete any commits. See [Git Objects](https://git-scm.com/book/en/v2/Git-Internals-Git-Objects) and [Git References](https://git-scm.com/book/en/v2/Git-Internals-Git-References). – ma11hew28 Jan 13 '22 at 16:45
  • @rsenna this deleted my files. – onlycparra Jun 21 '22 at 03:17
  • @onlycparra what do you mean by "this"? Again, `git update-ref -d HEAD` reverts the commit, without changing your local files. `git reset --hard` removes your local changes (hence potentially deleting your local files, if new files were added). – rsenna Jun 21 '22 at 10:05
  • @rsenna yes, the `git reset --hard` part. I do know that in normal circumstances that resets the directory tree to its state at "the previous commit". In this case there is no such thing as a previous commit. I assumed files would be left in there, but no, *some* of them were deleted, some of them remained in there. I haven't read the manual, but the behavior looks quite unexpected/arbitrary to me. Given that this is an edge case (no previous commit), and there is no turning back, shouldn't it take a more conservative approach? (I backed-up before trying stuff in git, so I didn't lose data) – onlycparra Jun 22 '22 at 00:48
114

You can delete the HEAD and restore your repository to a new state, where you can create a new initial commit:

git update-ref -d HEAD

After you create a new commit, if you have already pushed to remote, you will need to force it to the remote in order to overwrite the previous initial commit:

git push --force origin
frazras
  • 5,928
  • 4
  • 30
  • 40
  • 3
    Worth noting... this is the correct command but it doesn't delete the HEAD... it deletes the ref (located under .git\refs\heads) that the .git\HEAD file has checked out. After running this command you can still find the HEAD file pointing to refs/heads/ file that you deleted but if you follow that path you will see that the heads ref no longer exists. –  Jul 25 '17 at 17:54
  • It deleted my local branch and detaches HEAD. After running this started getting (HEAD detached at origin/master). Which wasted couple of hours later had to take fresh code. – Pankaj Prakash Oct 02 '22 at 04:52
33

This question was linked from this blog post and an alternative solution was proposed for the newer versions of Git:

git branch -m master old_master
git checkout --orphan master
git branch -D old_master

This solution assumes that:

  1. You have only one commit on your master branch
  2. There is no branch called old_master so I'm free to use that name

It will rename the existing branch to old_master and create a new, orphaned, branch master (like it is created for new repositories) after which you can freely delete old_master... or not. Up to you.

Note: Moving or copying a git branch preserves its reflog (see this code) while deleting and then creating a new branch destroys it. Since you want to get back to the original state with no history you probably want to delete the branch, but others may want to consider this small note.

nonsensickle
  • 4,438
  • 2
  • 34
  • 61
  • As opposed to what is (currently) stated, this solution actually does _not_ assume that there's only one commit on the original branch: it will simply replace the existing `master` branch with a new, empty one, regardless of the existing branch's state. – Tom Oct 23 '21 at 20:19
22

Under the conditions stipulated in the question:

  • The commit is the first commit in the repository.
  • Which means there have been very few commands executed:
    • a git init,
    • presumably some git add operations,
    • and a git commit,
    • and that's all!

If those preconditions are met, then the simplest way to undo the initial commit would be:

rm -fr .git

from the directory where you did git init. You can then redo the git init to recreate the Git repository, and redo the additions with whatever changes are sensible that you regretted not making the first time, and redo the initial commit.

DANGER! This removes the Git repository directory.

It removes the Git repository directory permanently and irrecoverably, unless you've got backups somewhere. Under the preconditions, you've nothing you want to keep in the repository, so you're not losing anything. All the files you added are still available in the working directories, assuming you have not modified them yet and have not deleted them, etc. However, doing this is safe only if you have nothing else in your repository at all. Under the circumstances described in the question 'commit repository first time — then regret it', it is safe. Very often, though, it is not safe.

It's also safe to do this to remove an unwanted cloned repository; it does no damage to the repository that it was cloned from. It throws away anything you've done in your copy, but doesn't affect the original repository otherwise.

Be careful, but it is safe and effective when the preconditions are met.

If you've done other things with your repository that you want preserved, then this is not the appropriate technique — your repository no longer meets the preconditions for this to be appropriate.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • 10
    This is bad advice. What if there's other stuff in the repo which you don't want to lose? – Matt Fenwick Jun 16 '14 at 17:44
  • 8
    Then it wouldn't be the initial commit, would it. There's only one initial commit. – Jonathan Leffler Jul 20 '14 at 04:43
  • 10
    "Then it wouldn't be the initial commit" -- actually, yes it would. You're neglecting the very common case of multiple branches. See Charles' answer. – Matt Fenwick Jul 21 '14 at 14:18
  • 2
    Helpful, however should come with a warning. – Simon Bengtsson Sep 04 '14 at 21:49
  • 5
    This actually works. The accepted answer does not. See comment – gman Nov 20 '14 at 22:39
  • This command DELETES the .git repo folder. So, if you created a branch that you wanted to use, it will be gone. OP *should* have stated *what* the command does, so you are warned of the consequences, and can take precautions before using it, and loosing info you may have wanted to keep. (In my case, the branch name - I could have copied it first). A great workaround, once you if/how it will affect you. – SherylHohman Dec 30 '18 at 23:00
  • It is dangerous, It removes *all* repo data, including configuration and stashes – Krypt Jan 29 '21 at 10:58
15

To revert the initial commit, use the command below.

git update-ref -d HEAD

Once done, the uncommitted files are now in the staging area. You can confirm this staging status by the git status command and you'll get a result similar to the one in the screenshot linked below.

My uncommitted files in the staging area are in yellow color

Git suggests the syntax of the command to unstage the files in question (see the image above). In short use the command below:

git rm --cached . -r

The dot(.) in the command represents the current location/dir while the flag -r unstages the files recursively without prompting confirmation for each file.

You can now perform a quick git status to confirm that the the staging area is now empty.

If you had already pushed your files to a remote repo, the next step is pushing these changes to the remote repo to restore parity between the two (local & remote).

However, before pushing, create a .gitignore file and populate it with the unnecessary files. Read how to create a .gitignore file here.

At this juncture, the next best logical solution is pushing the changes to remote either with git push or git push -f (However, always remember force pushing is dangerous - read here.).

However, both of these push commands could return an error, that may require one to pull and resolve merge conflicts. So in my bid to avoid this trouble, you might just have to delete the entire remote repo (On GitHub with these instructions), then recreate it with the same name.

In addition:

  • Delete the local git repo using the rm -rf .git,
  • re-initialize it with git init,
  • add all the current files to the staging area with git add -A,
  • commit them with git commit -m "<commit message>",
  • add the remote origin URL with git remote add origin <repo url>,
  • and finally, push the local files once more with git push -u origin main.

PS:

There are many reasons to revert the first commit. However, I think one of the most common reasons that equally affected me is forgetting to add a .gitignore file that excludes unnecessary files from a commit. In my case, this mistake meant that I unintentionally pushed node_modules directory to the remote repository.

After further research, I found a technical article explaining a simpler method of Ignoring a Previously Committed File, that does away with the need to undergo the tedious process of uncommitting and having to delete the remote repo.

Curiousone
  • 321
  • 3
  • 5
7

I will throw in what worked for me in the end. I needed to remove the initial commit on a repository as quarantined data had been misplaced, the commit had already been pushed.

Make sure you are are currently on the right branch.

git checkout master

git update-ref -d HEAD

git commit -m "Initial commit

git push -u origin master

This was able to resolve the problem.

Important

This was on an internal repository which was not publicly accessible, if your repository was publicly accessible please assume anything you need to revert has already been pulled down by someone else.

edward
  • 142
  • 1
  • 6
  • For this, I got `error: failed to push some refs to... hint: Updates were rejected because the tip of your current branch is behind hint: its remote counterpart. Integrate the remote changes (e.g. hint: 'git pull ...') before pushing again.` How would I fix that? – Manpreet Aug 18 '22 at 00:55
7

One option is to delete the repository and create a new one:

rm -rf .git
git init
ma11hew28
  • 121,420
  • 116
  • 450
  • 651
4

I wonder why "amend" is not suggest and have been crossed out by @damkrat, as amend appears to me as just the right way to resolve the most efficiently the underlying problem of fixing the wrong commit since there is no purpose of having no initial commit. As some stressed out you should only modify "public" branch like master if no one has clone your repo...

git add <your different stuff>
git commit --amend --author="author name <author.name@email.com>"-m "new message"
Richard
  • 721
  • 5
  • 16
4

For me:

git update-ref -d HEAD
git rm --cached . -r

First line was as suggested by CB Bailey (not sure why the second line was necessary, but git didn't uncommit the files until I did that - I could tell by running git status before and after the second line above)

stevec
  • 41,291
  • 27
  • 223
  • 311
1

Technically, to revert the initial commit, you'd do:

git revert HEAD

But since that records a new commit that reverses the effects of the last commit, you might as well just make a new commit yourself that fixes the issues introduced by your initial commit. That way, you'd keep your initial commit (Ie, you'd keep your history unchanged.) which you might want to do (especially if, eg, you've already pushed to a shared repository). Otherwise, you might prefer to just start over. Ie, delete the repository and create a new one.

ma11hew28
  • 121,420
  • 116
  • 450
  • 651
abdallah Nofal
  • 1,077
  • 8
  • 13
0

git reset --hard make changes, then do

git add -A
git commit --amend --no-edit 

or

git add -A
git commit --amend -m "commit_message"

and then

git push origin master --force

--force will rewrite that commit you've reseted to in the first step.

Don't do this, because you're about to go against the whole idea of VCS systems and git in particular. The only good method is to create new and delete unneeded branch. See git help branch for info.

Parham
  • 3,157
  • 4
  • 31
  • 44
damkrat
  • 355
  • 3
  • 6