git非快进更新。怎么克服?

时间:2010-12-09 14:49:12

标签: git

为双重帖子道歉,但我在之前的问题中没有得到任何进一步的回复,所以我想我的运气会更好地解释它......

我已经设置了我的git工作结构如下(感谢另一个问题中的建议git : Small project work

 /live/website
       |
       |
/path/to/staging (bare)
  |          |
  |          |
dev1        dev2

目前,dev1和dev2都将项目推送到/path/to/staging repo。我在/ path / to / staging中有一个钩子,它会自动从我的/ path /到/ staging触发cd /live/website && git pull。这样,我就有了所有文件的工作副本。所以真的dev1,dev2和/ live / website都是/ path / to / staging的git克隆。

Rudi,建议通过以下方式查明path/to/staging上的receive.denyNonFastforwards是否设置为true:

cd path/to/staging/ && git config --get-all receive.denyNonFastforwards

不幸的是,它被设置为真。例如,如果我在/ live / website服务器上执行git reset --hard <SHA-1>,它就会成功。但是,当我尝试将我的更改从/ live / website推送到/ path / to / staging时:

error: failed to push some refs to '/path/to/staging/' To prevent you from losing history, non-fast-forward updates were rejected. Merge the remote changes before pushing again. See the 'non-fast-forward'

可能,当我在dev1或dev2中进行更改并尝试将更改推送到/ path / to / staging时,我遇到了同样的问题。

我希望有一种主重置,我可以登录/path/to/staging/live/website并逐步降级到稳定版本,而不是找出哪个开发人员进行了更改然后执行了git重置。可以这样做吗?如果我选择这样做,我基本上希望能够逐步降级到不同版本的文件......

1 个答案:

答案 0 :(得分:1)

根据您的其他问题,我猜您的情况看起来像下图中的第1行。

    current workflow:
                     /live/website    /path/to/staging     dev
1   now              1-2-3-F          1-2-3-F              1-2-3-F
2   reko             1-2-3(-F rm) ->  1-2-3                1-2-3-F
3   hack hack hack   1-2-3            1-2-3                1-2-3-F-5-6-7
4   dev push         1-2-3            1-2-3-F-5-6-7 <-     1-2-3-F-5-6-7
5   auto update      1-2-3-F-5-6-7 <- 1-2-3-F-5-6-7        1-2-3-F-5-6-7

6   revert workflow:
7   now              1-2-3-F          1-2-3-F              1-2-3-F
8   backout          1-2-3-F-~F   ->  1-2-3-F-~F           1-2-3-F
9   hack hack hack   1-2-3-F-~F       1-2-3-F-~F           1-2-3-F-5-6-7
10  dev try push     1-2-3-F-~F       1-2-3-F-~F           1-2-3-F-5-6-7
11  dev pull         1-2-3-F-~F       1-2-3-F-~F       ->  1-2-3-F-5-6-7-8
                                                                \-~F--/

12  dev push         1-2-3-F-~F       1-2-3-F-5-6-7-8  <-  1-2-3-F-5-6-7-8
                                             \-~F--/              \-~F--/

13  auto update      1-2-3-F-5-6-7-8  1-2-3-F-5-6-7-8  <-  1-2-3-F-5-6-7-8
                            \-~F--/          \-~F--/              \-~F--/

在当前的工作流程中,您有一个缺陷顶部提交(F),您使用rebase或reset删除(2),然后将此删除的提交推送到中央存储库。当引入F的开发人员在F之上做了其他提交(4)(这是git中的默认行为)时,出现了这个工作流程的问题,然后再次推动这项工作。由于F提交仅从中央仓库中剥离,开发人员不知道F不应该在那里,因此F再次出现(4)。由于您在中央仓库上设置了一个自动更新/live/website的挂钩,这意味着在此推送之后,故障也会重新出现在网络上。现在情况更糟了,因为F现在不再是HEAD了,所以你不能轻易删除F(你现在可以自行修改,但F生活在开发者仓库中的问题仍然存在)。

在恢复工作流程中,您告诉git revert F(8),这会导致git创建一个撤消提交F的提交,这里称为~F。您的工作副本现在处于看起来好像F从未发生过的状态,您可以安全地将~F推送到中央存储库。现在,当其他开发人员已完成新工作并想要推送(10)时,git将拒绝此推送,因为中央存储库中的~F提交不是开发人员存储库中任何提交的祖先,而git现在强制开发人员从中央存储库(11)中拉出~F。然后开发人员必须将~F合并(或重新绑定)到他的分支(12),然后再将新的更改推送到中央仓库(13)。

关于/live/website repo的一句话:由于/path/to/staging中有一个钩子会在推送时自动更新此回购,因此在/live/website中进行更改不是一个好主意。主要问题是,如果您在那里有本地更改的文件,或者导致合并冲突的提交,/path/to/staging中的推送可能会失败并使/live/website处于非常丑陋的状态。在具有自动更新的场景中,最好将目录的所有权直接赋予更新机制,这意味着那里的所有文件更改应该仅来自git pull,而不是来自那里的直接编辑/提交。您可以在/live/website的克隆中进行更正,然后将这些更改推送到/path/to/staging,然后将更改分发回/live/website(但不要推入/live/website [这会导致git搞砸你的索引],也不会在那里拉你的克隆变化,因为那时你可能需要合并你的克隆和/path/to/staging/live/website的不同开发历史,这绝对不是什么你想要的。)