您可能也不想更改服务器中的任何 refs(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 提交。
现在您可以简单地还原您的还原,以便您的本地 repo 以再次重放“错误”提交结束:
... - o - X - o - U <-- origin/master
\
X' <-- master
其中X' 是错误提交的副本,它“取消”了U 所做的撤消操作。您现在可以修复它,在顶部或git commit --amend 等上再次提交,当一切正常时,git push 再次将结果发送到服务器。这将是一种更典型的处理问题的方式。
基于 cmets,这是另一个选项,它可能适合也可能不适合、更好等:与其在本地重置或还原,不如创建一个新的本地分支或标签(让我们在这里使用分支)指向您的提交想在服务器上恢复。您可能还想在服务器上设置一个名称,这样它就不会垃圾收集提交(这意味着您以后必须再次通过网络发送它们)。
例如,假设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,所以服务器更新到最后一个@ 987654354@ commit(毫无意义,它已经存在了)。但接下来,我们再次在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指向提交R,之后它有这个:
... - o - R <-- HEAD=master
\
X - o - o -...- o <-- save
save 标签将剩余的提交保存在服务器的存储库中。同时post-update钩子运行并执行git checkout -f,它使用HEAD,它指向master,它指向提交R。所以现在 Web 服务器应该已经部署了提交 R。
回到local,您只需要记住for-server 映射到遥控器上的master。 (如果您愿意,您可以重命名所有本地分支以匹配服务器上的命名:例如,将master 更改为save 并将for-server 更改为master。这完全独立于此。)
请注意,save 在服务器上所做的唯一事情是保持提交X 和所有后续os。如果您想直接在服务器上工作,或者不想通过网络发回这些提交,那就太好了。但是,如果在服务器上(它有一个工作目录,因为它不是一个裸仓库),你是一个 git checkout save,你将更改 HEAD 以指向 save 并且下一次是 post-update 钩子运行时,它将部署save 版本,而不是master 版本。