【问题标题】:Git head via post-update通过更新后的 Git 头
【发布时间】:2014-09-12 20:30:15
【问题描述】:

我有一个本地开发服务器,我在其中进行所有更改,我们称之为local。 我在webserver 的 git 文件夹中有一个 git repo 设置,我们称之为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

【问题讨论】:

    标签: git githooks git-reset post-update


    【解决方案1】:

    您可能也不想更改服务器中的任何 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 版本。

    【讨论】:

    • 我没有裸仓库。在服务器上,我有 git 目录,远程设置如下所示:un@domain.tld:~/home/git/project.git 当我导航到project.git 并运行您的命令时,我收到错误:fatal: this operation must be run in a work tree
    • 啊,好吧,这也适用于非裸仓库(尽管您在更新当前分支时遇到了所有常见的问题,而不是在非裸仓库中工作的人)。这个错误有点令人费解:使用--work-tree=GIT_WORK_TREE= 你会强制git 使用另一个路径作为工作树。该路径必须存在,否则更新挂钩将不起作用。
    • 感谢您对修复错误提交的编辑。对我来说,情况并非如此。我更新了很多 Wordpress 插件,将它们推送到服务器,然后意识到它们不兼容。我无法取消更新它们,从那时起我已经做了很多提交。所以我试图在进行任何更新之前恢复到提交,修复服务器问题,然后返回到最近的提交。
    • 啊,好吧,在这种情况下,只提取旧的想法是有道理的。我想下一个问题是,推送是否以其他具有不同权限在活动树上写入的用户 ID 运行?
    • 你的保存分支是一个绝妙的主意,我可以看到它会在哪里起作用。我将您的答案标记为正确答案,因为我的解决方案似乎有点 hacky。我所做的是先备份local 目录,然后硬重置为更新前提交。将其推送到服务器。然后我修复了更改,并且能够通过进入备份找到提交 ID,使用 git log,复制提交 #,然后返回到 local 并将 git 重置为该 ID。为我工作。但它可能会变坏。
    猜你喜欢
    • 2019-08-05
    • 1970-01-01
    • 2019-02-07
    • 2012-01-28
    • 2012-07-09
    • 2021-10-08
    • 2015-05-08
    • 2018-12-01
    • 1970-01-01
    相关资源
    最近更新 更多