我怎样才能更好地处理在git中污染"封闭"分支的提交?

Ian*_* C. 3 git version-control git-branch

我们刚接触到我的公司git,从Subversion开始git,周末我们遇到了我们的存储库中有一个分支的情况,我们不希望在那里提交一个分支的公共版本.我们有:

A -> B
Run Code Online (Sandbox Code Playgroud)

然后得到了错误的提交将分支放在:

A -> B -> C -> D
Run Code Online (Sandbox Code Playgroud)

C和D永远不应该在那个分支上.问题是这个分支是"关闭" - 这是我们软件的发布版本,不应该有任何新的提交到这个分支.

在Subversion中,出现这种情况的唯一方法就是提交!D和!C,这样你最终得到:

A -> B -> C -> D -> !D -> !C
Run Code Online (Sandbox Code Playgroud)

这让我回到B但是让我继续前进分支的时间线,所以任何拥有远程分支的人都会与主存储库同步,然后让他们撤消,然后让他们撤消到最终的逻辑相似的版本B(但不是B - 称之为B').

我遇到了这个解决方案,用于恢复git中的提交,这似乎是理想的:它会将我们的公共存储库恢复原状A -> B.但这意味着在任何人的工作机器上任何克隆这个分支将是非常不正确的,每个人都需要重新克隆.我的修复相当于:

git checkout thebranch
git reset --hard <<commit # associated with commit B>>
git push --force
Run Code Online (Sandbox Code Playgroud)

我最终走上了上述链接的路线,引起了很大的轰动:

a)您可以使用这样的git在公共存储库中丢弃提交历史记录,从字面上重写提交现实;

b)每个人都必须重新克隆,这样他们就不会冒险重新注入C -> D分支机构(或我们想要创建的那个分支机构的新分支机构).

我想我应该这样做:

git revert HEAD~2
git commit
git push
Run Code Online (Sandbox Code Playgroud)

但是这会离开分支A -> B -> C -> D -> E,它真的不应该C -> D -> E在它上面,因为它应该被关闭.

我有三个问题:

  1. 我怎么能更好地处理清理工作?用revert而不是reset?这里的分支污染最好的做法是什么?
  2. push --force还原分支的确是否真的破坏了公共存储库的历史?或者git回滚到B但是保留了一个记录,C -> D并且在某些时候我已经回复到了B?它肯定不会在提交日志中显示恢复,但是我的操作记录可能会保留在其他位置?
  3. 你如何处理git中的"封闭"分支,以至于这些变化首先不可能在那里发生?我们确实在提交B处将一个标记应用于存储库,并且人们应该使用branch +标记来获取发布的源代码,但是如果更改显示在不应该具有的分支行上,这仍然是一件可怕的事情.在提交B之后对其进行更改.并且从分支机构分支以获取修补程序版本的人可能很容易错过标记并将其拉C -> D入其新分支.

idb*_*rii 5

您应该使用标记用于发布("封闭分支")和分支用于开发("开放分支").这是解决问题的替代解决方案(您可以只使用已发布代码的标记)以及将来防止此问题的方法.

在开发v3.1时,您可以使用v3.1分支.v3.1完成后,标记最后一次提交并将分支重命名为下一个开发分支(v3.2).记住:Git不是Svn!分支只是提交的指针.删除分支不会删除提交(但如果这些提交未包含在另一个分支中,它们将悬空,因此您应该在删除分支之前创建标记).

如果要开发v3.1(v3.1.1)的补丁,则在标记v3.1上创建分支:

git checkout -b v3.1.1 v3.1
Run Code Online (Sandbox Code Playgroud)

对于您的开发人员来说这将更加清晰(分支机构用于开发,标签用于发行版)并防止此问题再次出现.


恢复分支的推力是否真的破坏了公共存储库的历史?

不.如果您为提交D创建了标记或分支,那么该分支仍然可以.使用git reflog以了解最近的变化头部.那些承诺应该在那里.(或git fsck.)


有关不使用其他版本控制系统作为理解基础的git的良好讨论,请尝试使用PeepCode的Git Internals.这不是免费的,但我认为除了集中版本控制之外,理解git要好得多.(Git社区图书看起来是一个很好的免费替代品.)