0

我有一个本地开发服务器,我在其中进行所有更改,我们将其称为local. 我在我的 git 文件夹中有一个 git repo 设置webserver,我们称之为gitfolder. 然后我有我的实时文件,每次我 git push 时都会从 gitfolder 推送,我们称之为live.

我的工作流程。

编辑文件,提交更改,推送到webserver. 然后更新后接管以下内容:

#!/bin/sh
export GIT_WORK_TREE=/path/to/live
git checkout -f

这完美地工作。然而,这是我的问题。我想恢复 git 更改,我通常会通过git reset --hard commit- 但如果我导航到live,显然那不是 git repo。

当我继续gitfolder运行相同的命令git reset --hard commit时,它不会更新live并且我收到错误“致命:此操作必须在工作树中运行”

采取的步骤?现在,我已经复制了我的local文件夹并进行了local2- 然后local2我恢复了更改,然后将其推送到live,所以我的原始local文件夹仍然具有所有更改。

我不想恢复local- 就在live

4

1 回答 1

3

您可能也不想更改服务器中的任何引用(git reset可能会将任何分支HEAD点移动到master,但您说您不想恢复或重置本地系统,因此基于此,我假设您不这样做'也不想恢复或重置您的裸存储库)。

在这种情况下,只需登录到服务器、cd裸存储库,然后运行:

git checkout --work-tree=/path/to/live checkout -f <commit-ID>

或者:

GIT_WORK_TREE=/path/to/live git checkout -f <commit-ID>

换句话说,您只是在做更新钩子所做的事情,但是使用原始提交 ID 来提取该特定版本,而无需更改存储库本身中的任何分支。


虽然我认为这是对您问题的字面回答,但我想指出其他一点:如果您git revert在自己的本地存储库中提交了错误的提交,您将获得一个新的提交,该提交取消了错误提交的影响,但是错误的提交还在里面。然后,您可以按通常的方式将结果推送到服务器:

... - o - X - o - U   <-- master, origin/master

X错误的提交在哪里,并且U是“取消”所做的提交X。只是为了说明,我o在它们之间也包含了一个无趣的提交。

现在您可以简单地还原您的还原,以便您的本地回购以再次重播“错误”提交结束:

... - o - X - o - U       <-- origin/master
                    \
                      X'  <-- master

哪里X'是错误提交的副本,它“取消”了U所做的撤消。您现在可以修复它,在 top or 上再次提交git commit --amend,等等,当一切正常时,git push将结果再次发送到服务器。这将是处理该问题的更典型的方式。


根据评论,这是另一个选项,它可能适合也可能不适合,更好等:与其在本地重置或恢复,不如创建一个新的本地分支或标签(让我们在这里使用分支)指向您要恢复的提交服务器。您可能还需要服务器上的名称,这样它就不会垃圾收集提交(这意味着您以后必须再次通过网络发送它们)。

例如,假设上面的树local看起来像这样,画了一个扭结,这样我就可以添加一个标签:

... - o - R
            \
              X - o - o -...- o   <-- HEAD=master, origin/master

R是您希望服务器重置为的提交,而X其他提交是更新 Wordpress 插件的提交等。(我假设您正在处理分支master;根据需要进行更改。)

同时,在服务器上,情况如下所示:

... - o - R
            \
              X - o - o -...- o   <-- HEAD=master

如果你想保留服务器上的所有提交,我们应该给最终o提交一个新的分支名称,因为我们必须在那里强制更新master。等等local,我们可能会运行这个:

$ git push origin master:save

这将在服务器上创建一个名为 的新分支save,因此它现在看起来像这样:

... - o - R
            \
              X - o - o -...- o   <-- HEAD=master, save

钩子将update执行通常的git checkout -f,它检查HEAD分支(因为没有指定分支),在这种情况下是master,所以服务器被更新到最后一次o提交(毫无意义,它已经在那里)。但接下来,我们再次这样做local

$ git branch for-server <commit-ID-for-R>

这会将设置更改local为如下所示:

... - o - R                       <-- for-server
            \
              X - o - o -...- o   <-- HEAD=master, origin/master

还不是很有趣,但是接下来:

$ git push --force origin for-server:master

这(带--force)告诉服务器强制更新其master指向 commit R,之后它有这个:

... - o - R                       <-- HEAD=master
            \
              X - o - o -...- o   <-- save

save标签将剩余的提交保存在服务器上的存储库中。同时,post-update钩子运行并执行 a git checkout -f,其中使用HEAD,指向master,指向提交R。所以现在 Web 服务器应该已经R部署了提交。

回来local,您只需要记住遥控器上的for-server映射即可。master(如果您愿意,您可以重命名所有本地分支以匹配服务器上的命名:例如更改mastersave和更改for-servermaster。这完全独立于此。)

请注意,服务器上唯一要做save的就是保持提交X和所有后续os。如果您想直接在服务器上工作,或者不想通过网络发回这些提交,那就太好了。但是,如果在服务器上(它有一个工作目录,因为它不是一个裸仓库),你git checkout save将更HEAD改为指向save并且下次post-update运行钩子时,它将部署save版本,而不是master版本.

于 2014-09-12T20:43:29.443 回答