创建标记并进行本地更改,然后对公共分支进行重新绑定

时间:2013-12-11 20:37:07

标签: git version-control merge

我们有一种情况(对于这个例子)我们有一条直线的开发准备发布:

A --> B --> C --> D
                  ^ HEAD

我们认为提交CD过于思考,我们希望从B发布。我们有一个工具可以返回并标记B作为我们的发布版本,比如说product-1.0.0,然后将许多版本控制文件更新为1.1.0,或者下一个版本。< / p>

问题是标签的创建,以及文件的调整,都是原子操作。我们可以改变这一点,但这有点麻烦。

因此,虽然标记需要指向B,但我们希望将文件更改弹出到新的提交中。我们现在有什么:

      v detached, tagged, with local changes
      |
A --> B --> C --> D
                  ^ HEAD

但是,如果我们从目前的观点出发,我们最终会:

       /--> E (a 'lost' commit)
      /
A --> B --> C --> D
      ^ tag       ^ HEAD

最简单的方法是,从“与本地更改分离”或“丢失提交”点,将我们的本地更改或新提交合并到公共分支,使其看起来像:

A --> B --> C --> D --> E
      ^ tag             ^ NEW HEAD

提交CD以及整个分支都是公开的 - 因此我们无法真正在E和{{1}之间注入提交B }}。如果这些提交(CC)作为我们发布的产品的“更新”D版本存在,那也没关系,我们只想在当前创建一个新提交1.0.0

有没有比存储更好的方法,查看HEAD,然后弹出并提交?

2 个答案:

答案 0 :(得分:1)

此答案显示了一个工作流程,它使用本地分支作为存储机制的替代方法。这是我喜欢的方法。

我将假设:

  • 您的公共分支负责人称为master
  • 此“原子操作”是用于发布的脚本。
  • 发布标记(product-1.0.0)最终需要指向B.
  • EC之后,需要将发布提交(D)“添加”到主提示。
  • 您已master签出,工作树干净。

历史记录最初看起来像这样(origin遥控器代表公开的内容,HEAD指向您当前签出的分支机构负责人:

(A)<--(B)<--(C)<--(D)
                  ^ ^
                 /   \
           master     orgin/master
                ^
                |
             HEAD

您需要自己查看此图表。我通常使用像这样的git别名(g表示“graph”):

git config --global alias.g "log --decorate --oneline --graph"

然后您可以通过调用以下内容获取上述图片:

git g master origin/master

(显示从master和/或origin/master可以到达的所有内容。使用git g --all显示每个人。)

首先创建一个名为temp的本地临时分支头,指向B,然后将其检出。

git branch temp <SHA1 of B>
git checkout temp

提交图现在看起来像这样:

       HEAD
       |
       v
       temp
       |
       v
(A)<--(B)<--(C)<--(D)
                  ^ ^
                 /   \
           master     orgin/master

运行发布脚本,该脚本标记当前提交,进行更改(可能会增加版本号或其他内容),然后提交更改。

<magic release script>

如果我正确理解了您的发布脚本,那么结果图应如下所示:

                        HEAD
                        |
                        v
                        temp
                        |
                        v
 tag: product-1.0.0    (E)
                   \   /
                    v v
              (A)<--(B)<--(C)<--(D)
                                ^ ^
                               /   \
                         master     orgin/master

现在是时候回到master并“继承”E提交:

git checkout master
git cherry-pick <SHA1 of E>

cherry-pick命令将单个提交视为补丁。 “补丁”包含B处的树快照与E处的快照之间的差异。然后将此“补丁”应用于您签出的任何分支头 - 在本例中为master。修补程序中的更改将生成一个具有相同消息的新提交(F),并将作者作为原始提交(E)。

                        temp
                        |
                        v
 tag: product-1.0.0    (E)
                   \   /
                    v v
              (A)<--(B)<--(C)<--(D)<--(F)
                                 ^     ^
                                 |     |
                     origin/master     master
                                       ^
                                       |
                                       HEAD

请注意,F提交与E提交不同!它只是“在精神上是一样的”,即它引入了相同的逻辑变化。

在此之后,请检查最终状态,您应该准备好将新的master州推送到origin以使其公开。

git push origin master:master

您现在可以删除临时temp分支头:

git branch -D temp

您通常使用-d选项删除分支,但git不允许您在此处使用它。原因是您将丢失E提交。在这种情况下,可以使用E“保存”cherry-pick。由于git认为EF是不同的提交,因此无法知道E的精神仍然存在于F中,并且不会提供任何信息丢失。您需要告诉git您已使用-D代替-d确保知道自己在做什么。

最后你应该:

    tag: product-1.0.0
                     |
                     v
              (A)<--(B)<--(C)<--(D)<--(F)
                                      ^ ^
                                     /   \
                        origin/master     master
                                          ^
                                          |
                                          HEAD

答案 1 :(得分:0)

在你的标签处分支并将E放在该分支上并将branch_E合并回你的主分支,或者只是在D之后将主要分支上的提交E提交回来。