1

在我们当前的工作流程中,我们有 2 个主要的 git 分支:

master- 稳定发布分支

testing- 每个人都测试他们的代码吗

现在每个开发人员都会为他们开发的每个功能创建新的分支。完成后,他们将其合并到testing,当我们的 QA 说可以进行时,他们将他们的分支合并到master部署到生产中。

随着时间的流逝,我们的testing分支被从未投入生产的提交污染。被遗弃的功能,被重写而不是固定的东西和其他东西。

为了保持mastertesting处于某种一致的状态,我们希望testing不时“重置”。现在,我们通过将testing其从master.

这里最大的问题是我们需要确保每个开发人员也删除他的本地testing分支并检查它的新副本。如果一位开发人员忘记这样做并再次推动测试,那么我们试图摆脱的所有脏提交都会回来。

有没有办法以分发给所有用户的方式重置服务器上的分支?

一个可接受的解决方案是将testing分支置于一个没有人可以在不进行本地重置的情况下再推送到它的状态。但我想不出一种方法来做到这一点。

master在和恢复提交之间创建差异testing不是一种选择,因为这会阻止这些提交中的每一个再次进入测试。

理想情况下,我有一个脚本可以定期执行此重置,并且git pull每个用户本地环境都不需要交互(除了 )。

4

4 回答 4

2

随着时间的流逝,我们的测试分支被从未投入生产的提交污染。被遗弃的功能,被重写而不是固定的东西和其他东西。

这怎么可能?显然,如果某个功能被放弃,那么您也应该将其从测试分支中删除,因为它似乎是您的看门人。基本上,如果您说您的测试分支随着时间的推移而受到污染,那么它就违背了测试分支的全部目的,因为现在您正在测试的东西并不代表您想要推送到生产环境的代码。

如果某些事情没有成功,那么开发人员应该恢复他的更改并将提交推送到测试分支,在那里更改也会被恢复。

在您的场景中,您应该全部或全部从测试合并到生产。

于 2015-02-25T00:46:20.887 回答
2

简短的回答是“不,你不能那样做”。

请记住,每个克隆都是一个完整的独立实体1,除了它的origin和(取决于克隆选项)一些初始分支状态之外,它与从中克隆它的源存储库几乎没有什么不同。2 一旦有人拿起一个名为testing并调用它的分支origin/testing

  • 他们有你让他们拥有的提交;和
  • 他们有一个引用(“远程跟踪分支”),命名为origin/testing他们的 git 将自动更新,甚至在他们连接到 remote 时修剪(删除)origin

到目前为止一切顺利,这个“自动修剪”动作听起来很棒。如果您可以说服他们设置remote.origin.prunetrue

$ git config remote.origin.prune true

然后,一旦您删除了名为分支testing它们 origin/testing将在下一个时自动消失git fetch origin

他们创建一个名为testing. 他们的 git不会删除这个分支,除非他们要求这样做。就他们的 git 而言,他们的私有分支就是他们的私有分支。你不能说服他们的 git 删除他们的 private ,testing就像你不能说服他们的 git 删除他们的 private 一样experiment-22。他们创造了它;这是他们的存储库;他们控制着它。

(请注意,他们还保持对自动修剪的控制,因为他们也可以随时将git config设置remote.origin.prune移开,或false设置为改变它的作用;它的初始默认设置是他们在运行时创建的。)remote.origin.fetchgit fetchgit clone

可以继续使用此模型,前提是您让所有开发人员自行控制删除或清理此分支标签。但这不是要走的路。相反,您应该使用另一种模型:为您的开发人员创建一个新的、不同的分支标签,用于您正在进行的新的(和不同的)开发线。

例如,您可能拥有dev-feature-X一个临时分支,您的开发人员都可以共享它来处理功能 X。当您完成它时,您可以随意保留或删除它,您的开发人员会自动选择删除(使用修剪设置)或不在他们的空闲时间。同时,您已经创建dev-feature-Y了一个临时分支,您的开发人员都可以共享它来处理功能 Y,等等。


1至少忽略不适用的“浅”克隆等特殊情况。

2如果您没有克隆--mirror,源的分支将成为您的远程分支,并且您根本没有本地分支,直到您签出一个(通常master,通常作为clone命令的最后一步)。另外,clone 看不到源的钩子,所以这些钩子没有被克隆。目录中也没有任何其他特殊状态.git,例如.git/info. 但是,这些都不会影响普通分支使用的原则。

于 2015-02-25T00:52:51.700 回答
1

如果一个开发人员忘记 [rebase] 并再次推送,那么我们试图摆脱的testing所有 [来自废弃提示] 的脏提交都会回来。testing

您无法控制其他人的存储库中发生了什么,但您可以控制他们推送给您的存储库的内容。

一个可接受的解决方案是将测试分支置于一个没有人可以在不进行本地重置的情况下再推送到它的状态。但我想不出一种方法来做到这一点。

这个预接收钩子将拒绝通过合并引入不需要的历史的推送:

#!/bin/sh
#  Do not permit merges from unwanted history
#set -x
err=0
while read old new ref; do              # for each pushed ref

        [[ ${old%[^0]*} = $old ]] && continue # new branches aren't checked.

        nomerge=$(git for-each-ref refs/do-not-merge --format='%(objectname)^!')

        if [[ $( git rev-list --count --ancestry-path --boundary $old..$new $nomerge
         ) != $( git rev-list --count --ancestry-path --boundary $old..$new ) ]]; then
                echo "$ref doesn't allow merges from outdated history"
                err=1
        fi
done
exit $err

# why it works:

# if adding nomerge commits' parents as ancestors has any effect, then the
# nomerge commits are reachable without going through $old, i.e. they're 
# in some merged history. So check whether adding the abandoned commits as
# explicit ancestors to the push makes them show up, and refuse it if so.

要标记不需要的提交,请参考它们refs/do-not-merge,例如

git config alias.no-further-merges-from \
  '!f() { git update-ref "refs/do-not-merge/$1-@`date +%Y-%m-%dT%H%M%S`" "$1"; }; f'

所以放弃的仪式testing

git no-further-merges-from testing
git checkout -B testing master

如果您想标记以前放弃的提示,您可以通过 sha 或任何其他表达方式引用它们,例如

git no-further-merges-from 'testing@{last october 31}'
于 2015-02-25T02:24:10.410 回答
1

一种选择是通过以特殊方式合并到主分支来重置开发分支的状态。

git checkout master
git checkout -b new_testing
git merge -s ours testing # this creates a merge commit, but
                          # its tree is that of the current work-tree
                          # which in our case is the same as master
git checkout testing
git merge ours_testing
git branch -d new_testing

我们需要创建临时new_testing分支,因为合并策略ours保留当前树而不是其他树,并且没有等效theirs策略。

在此之后,您将最终得到一个分支结构,例如

*         (testing) merge
|\
| *       (master) last commit on master
* |       last commit on testing
| |

但是测试的内容会和master的内容相匹配。

这样做的好处是,任何对之后发生的测试进行本地提交的人都可以像往常一样last commit on testing重新调整他们的更改。origin/testing

由于这不应该中断通常的开发流程,因此没有理由不能经常(每晚?)进行。

于 2015-02-25T01:10:06.053 回答