Git: How do you replace your current working directory with a previous commit without branching or git revert?

后端 未结 3 1242
礼貌的吻别
礼貌的吻别 2020-12-18 08:35

Is there an easy way to the following with git?

Basically I want to create a new commit at the top of my commit history that is equivalent to a previous com

相关标签:
3条回答
  • 2020-12-18 08:50

    To create a new commit, restoring the content of an old commit, you can:

    • First, mark the current HEAD of your branch (assuming master here): we will need to move that HEAD without modifying master, so let's create a new temporary branch called 'tmp' where master is.

      git checkout master
      git checkout -b tmp
      

    (yes, that is against the "without branching" of the question, but you will delete that tmp branch soon)

    • Then we go back to an older commit with the right content.

      git reset --hard <old_commit>
      

    That resets the index (and working tree) to the right content, but that also moves HEAD. However, that moves tmp HEAD, not master HEAD.

    • move back tmp HEAD to where master is, but without modifying the index or the working tree (which are representing what we need for a new commit)

      git reset --soft master
      
    • make a new commit, on top of master/tmp HEAD, which represents the right content (the old commit).

      git commit -m "new commit, image of an old one"
      
    • Finally, force master to be where tmp is: one new commit later.

      git branch -M tmp master
      git checkout master
      git branch -d tmp
      

    Now a regular git push is enough, any collaborator can simply pull as usual, and still get the old reset content.

    git push
    
    0 讨论(0)
  • 2020-12-18 09:07

    In situation when you want to return to some state you do following:

    git reset --hard 49a732c

    This step put your master branch into desired state. If you want to save you previous branch state:

    git checkout 48ah14s -b archive/my-unrecognized-experiments

    You still can do it after reset because reset doesn't delete commits.

    PS Branching is essential part of git. It is better to teach branching then teach such complicated (in git) things as you pictured.

    EDIT If you want your master to stay consistent with remotes:

    git reset 49a732c # move HEAD back, all changes still in working tree
    git commit -am "My unrecognized experiments" # save all changes as one commit
    git reset --hard 48ah14s  # restore master HEAD
    git revert <hash of my unrecognized experiments> # apply reverted changes to master
    
    0 讨论(0)
  • 2020-12-18 09:09

    Assuming you start from a clean worktree, you could do:

    cd <root_directory_of_your_repo>
    git checkout master
    git checkout 49a732c -- .
    

    When you specify a file (in this case . (the root directory of your repo)) as an argument to git checkout, the checkout will not switch branch (the repo HEAD will remain the same). It will just update the index to make that file match the version of that file from the specified commit. Since you specified the root directory of the repo, all files in the index will be updated to match the specified commit 49a732c

    0 讨论(0)
提交回复
热议问题