为双重帖子道歉,但我在之前的问题中没有得到任何进一步的回复,所以我想我的运气会更好地解释它......
我已经设置了我的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重置。可以这样做吗?如果我选择这样做,我基本上希望能够逐步降级到不同版本的文件......
答案 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
的不同开发历史,这绝对不是什么你想要的。)