Git:如何在不进行分支或 git revert 的情况下用先前的提交替换当前的工作目录?

rkp*_*rkp 7 git

有没有一种简单的方法可以使用 git 进行以下操作?

提交复制粘贴图

基本上我想在我的提交历史记录的顶部创建一个新的提交,它相当于我的历史记录中的先前提交(例如,将项目恢复到先前的状态)。

我不想使用分支,因为我正在向以前从未使用过 git 的人教授这个,并且我希望尽可能保持“线性”。(我的大多数观众只需要备份内容,查看项目历史,并在必要时将项目恢复到以前的状态,但没有其他任何远程幻想。)

我不想使用,git revert --no-commit 49a732c..HEAD因为如果碰巧之后发生合并,这会给出错误消息49a732c(我承认这在我的观众中不太可能,但有时确实会通过疯狂尝试使错误消息消失而发生)。

我也不想删除/重写历史记录。

基本上,有没有更简单的方法来做到这一点?

# make sure on master and working directory clean
me@laptop:~/Desktop/proj$ git status
On branch master
nothing to commit, working directory clean

# check out commit to restore
me@laptop:~/Desktop/proj$ git checkout 49a732c
Note: checking out '49a732c'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b <new-branch-name>

HEAD is now at 49a732c... Fix bugs.

# copy project checked out at 49a732c to temp folder
me@laptop:~/Desktop/proj$ cp -r . ../temp

# check out master again
me@laptop:~/Desktop/proj$ git checkout master
Previous HEAD position was 49a732c... Fix bugs.
Switched to branch 'master'

# remove everything except .git
me@laptop:~/Desktop/proj$ rm -rfv !(".git")
rm: refusing to remove '.' or '..' directory: skipping '.'
rm: refusing to remove '.' or '..' directory: skipping '..'
removed 'file_1.py'
removed 'file_2.py'

# copy everything except .git from temp (checked out at 49a732c) into working directory
# (so working directory is identical to project at commit 49a732c)
me@laptop:~/Desktop/proj$ cp -nr ../temp/* ./

# make new commit identical to project state at 49a732c
me@laptop:~/Desktop/proj$ git add *
me@laptop:~/Desktop/proj$ git add -u
me@laptop:~/Desktop/proj$ git commit -m “Restore project to commit 49a732c.”
[master 2b6416c] Restore project to commit 49a732c.
 3 files changed, 18 deletions(-)

# remove temp
me@laptop:~/Desktop/proj$ rm -rf ../temp

# new commit 2b6416c is now identical to 49a732c
Run Code Online (Sandbox Code Playgroud)

或者,如果分支是执行此操作的最佳方法,是否有一系列命令始终有效并且不会产生任何合并冲突或告诉您使用 git stash(假设当前工作目录是干净的)?

Von*_*onC 10

要创建新提交,恢复旧提交的内容,您可以:

  • 首先,标记分支的当前 HEAD(假设master在这里):我们需要移动该 HEAD而不修改master,因此让我们创建一个名为“ tmp”的新临时分支where masteris。

    git checkout master
    git checkout -b tmp
    
    Run Code Online (Sandbox Code Playgroud)

(是的,这与问题的“无分支”相反,但您很快就会删除该 tmp 分支)

这会将索引(和工作树)重置为正确的内容,但这也会移动 HEAD。但是,这会移动tmpHEAD,而不是masterHEAD。

现在一个普通的git push就足够了,任何合作者都可以像往常一样简单地拉动,仍然可以获得旧的重置内容。

git push
Run Code Online (Sandbox Code Playgroud)

  • 刚刚测试过这个,它有效。正是我正在寻找的东西。另请注意,“gitbranch -M tmp master”会让您留在 master 上并删除 tmp,因此可以跳过接下来的两行。非常感谢。 (3认同)

Ald*_*ath 6

假设您从一个干净的工作树开始,您可以这样做:

cd <root_directory_of_your_repo>
git checkout master
git checkout 49a732c -- .
Run Code Online (Sandbox Code Playgroud)

当您指定一个文件(在本例中.为(存储库的根目录))作为 的参数时git checkout,签出将不会切换分支(存储库HEAD将保持不变)。它只会更新索引以使该文件与指定提交中的该文件的版本匹配。由于您指定了存储库的根目录,索引中的所有文件都将更新以匹配指定的提交49a732c

  • @Alderath“当您指定一个文件(在本例中为“.”(存储库的根目录))作为“git checkout”的参数时,结帐将不会切换分支(存储库“HEAD”将保持不变) ”。谢谢,这正是我所需要的——在我偶然发现这个之前,我一直在到处寻找(并且在这个过程中多次搞乱了我的仓库。我想知道为什么更多的人不推荐这个...... (2认同)