How can I delete commits that are after the current HEAD?

In my Git repository, I created three commits in a row: commit1, commit2, and commit3.

I then realized I messed up in commit2 and commit3, and decided to go back to commit1. To do that, I ran

  • How to make composer to use an exact SHA1 value?
  • Jenkins jobs and GIT/maven structure
  • Partial sharing of git repositories
  • How do you NOT add untracked files in git?
  • GitBash generally slow
  • Where are the git commit ids stored?
  • git checkout commit1

    Now I am in commit1. How do I delete commit2 and commit3?

  • How do I change my author name on GitHub?
  • Cherry-pick to specific commit from other branch
  • Why is bundler not installing gems stored in get repo properly?
  • setting up git instaweb with nginx
  • gitlab SSH key project cloning issue
  • Entire git history of commits is doubled up
  • 4 Solutions collect form web for “How can I delete commits that are after the current HEAD?”

    Check your branch out and then reset it

    Based on your description and under the assumption you were on some branch called mybranch before checking out commit1 (C1 in my graphs below), you must be in the following situation:

    C1 [HEAD]
      C2 -- C3 [mybranch]

    Commits C2 and C3 still appear in the output of git log because they’re still reachable from the mybranch refererence. Also, note that HEAD is detached. What you should do is…

    1. Reattach HEAD to mybranch, by running

      git checkout mybranch

      This should put you in the following situation:

        C2 -- C3 [HEAD=mybranch]
    2. Reset the mybranch branch to its tip’s grandparent, by running

      git reset --hard mybranch~2

      That should put you in the following situation:

      C1 [HEAD=mybranch]

    Because commits C2 and C3 have now become unreachable (i.e. “deleted”), they’re not shown on this last graph.

    Why resetting without first reattaching the HEAD won’t work

    This may be a bit cheeky, but here is an explanation of why the other two answers won’t work. As correctly pointed out by cmbuckley in his comment,

    git reset resets the state of the current branch you’re on (so you’d need to be on the branch to do that). If you’ve checked out commit1, you’re probably not on a branch (detached HEAD state).

    Since the OP (Imray) is in detached HEAD state, running git-reset before reattaching HEAD to the branch will not move the branch reference in question. Here is a toy example illustrating this.

    # set things up
    $ mkdir test
    $ cd test
    $ git init
    Initialized empty Git repository in /Users/jubobs/Desktop/test/.git/
    # create a first commit
    $ touch README
    $ git add .
    $ git commit -m "add README"
    [master (root-commit) 85137ba] add README
     1 file changed, 0 insertions(+), 0 deletions(-)
     create mode 100644 README
    # create a second commit
    $ printf "foo\n" > README
    $ git commit -am "write 'foo' in README"
    [master 3948e84] write 'foo' in README
     1 file changed, 1 insertion(+)
    # inspect the log
    $ git log --graph --decorate --oneline --all
    * 3948e84 (HEAD, master) write 'foo' in README
    * 85137ba add README
    # check out the second commit (which detaches the HEAD)
    $ git checkout 3948e84
    Note: checking out '3948e84'.
    # (boilerplate stdout is omitted...)
    HEAD is now at 3948e84... write 'foo' in README
    # reset to the first commit (equivalent to 'git reset --hard 85137ba')
    $ git reset --hard HEAD^
    HEAD is now at 85137ba add README
    $ git log --graph --decorate --oneline --all
    * 3948e84 (master) write 'foo' in README
    * 85137ba (HEAD) add README

    Note that the git reset command moved HEAD to the initial commit, but did not move the master branch whatsoever. The second commit is not “deleted”, because it’s still reachable from master; it is therefore listed in the output of git log.

    I’m going to assume you’re in the master branch in your repo for naming purposes, but any branch will do. This can be thought of as simply a pointer to a commit object. You can also think of HEAD as another pointer, which you can move around with git checkout

    commit1  ->  commit2  ->  commit3

    If you want to change your master pointer to be at commit1, then you need to issue a git reset command, as others have indicated.

    git reset --hard commit1

    This moves the master pointer in the above diagram to same place as the commit1 object.

    Note, you aren’t actually deleting the commit2 and commit3 objects, it’s just that within git there’s no branches pointing to them, so git is free to clean them up if it wants to, or you can force it by running a garbage collect with something like:

    git gc --aggressive --prune

    Until it is actively cleared from your repo, you can still checkout both commit2 and commit3, so despite you moving the master pointer back to commit1 (with git reset), you have to be careful if (say) you accidentally commit passwords to the repository and are trying to revert back – they will still be in your local repo until pruned.

    Force Your Branch to Current HEAD and Checkout Branch

    git branch -f mybranch
    git checkout -

    Checkout Branch and Force Your Branch to Current HEAD

    git checkout -
    git reset --hard HEAD@{1}

    The second option is particular advantageous because you do not need to type the name of your branh or the identity of your current commit. You could even make it an alias.

    EDIT: This assumes that you have not been jumping around, and your most recent checkout was from your branch.

    You want to nuke commit commit3 (Assuming you are currently on commit3 – as HEAD). you can do following:

    git reset --hard HEAD~1

    The result is:

    commit1 -> commit2 

    You can follow similar process for moving back to commit1 (i.e. git reset --hard HEAD~2).

    Git Baby is a git and github fan, let's start git clone.