将整个开发分支基于新的主分支进行变基

9
我正在处理一个代码库,理论上应该遵循Gitflow工作流程(参见Vincent Driessen的A successful git branching model)。然而,代码库的初始提交是在develop分支上进行的,看不到master分支。现在即将发布,我需要创建一个反映项目生产就绪状态的master分支,这个分支应该从一开始就存在。请注意,develop分支有多个特性分支。代码库完全本地,没有被推送过。
我的想法是创建一个孤立分支master,并将develop分支变基到它上面,但我不知道该如何操作。
那么,我该如何创建master分支,就好像从一开始就创建了一样?
更新:在我的情况下,develop 上的第一次提交并不适合用作生产环境的初始 master 提交,因此这样做是不明智的。项目处于这种状态的原因是当决定使用 Git 时,它最初没有使用版本控制系统。

那么,仅拥有一个主分支是否足够,还是实际上需要一个伪造的初始提交并设置过去的日期? - JSelser
@JSelser 如果初始提交具有正确的日期,那将是很好的,但只要存储库有效地运行,主分支代表着项目的生产就绪状态,那么它就解决了我的问题。 - Parker Hoyes
1
“develop” 分支是否反映了正确的生产就绪历史记录?只需运行 git branch master develop 命令即可。在 Git 中,不存在固有的分支基础,只有两个历史记录分叉的位置。 - jthill
如果develop分支不反映您想要的历史记录,则变基它不会有所帮助。绘制您拥有的提交图,记住每个提交都是项目状态的完整快照,并添加任何新的提交,以反映生产快照。重要的是图表,而不是您在端点上悬挂的标签。您将如何生成第一个生产就绪状态的提交? - jthill
@jthill 该仓库应遵循Gitflow工作流程,为此必须在新的孤立分支'master'上进行初始提交,然后将'develop'分支合并到该分支上。请参见下面的回答。 - Parker Hoyes
显示剩余2条评论
3个回答

8
经过一些尝试,我想到了这个方案。这是一个更简单的手动方法,用于VonC's answer
重新定位整个开发分支
假设您有一个分支develop,其中包含存储库的初始提交,并且您希望重写历史记录,使master分支包含新的初始提交。
首先,如果您的develop分支上的初始提交适合作为新的master分支上的初始提交,则可以在那里创建master分支,然后就完成了:
$ git branch master <sha1-of-initial-commit-on-develop>

如果您没有这种奢侈的条件,那么您需要创建一个新的空提交作为master的初始提交。
# Create the new master branch
$ git checkout --orphan master
# Clear the working directory (we want the initial commit to be empty)
$ git rm -rf .
# Create the initial commit on master
$ git commit --allow-empty -m "Initial commit"
# Rebase the entire develop branch onto the new master branch
$ git rebase --onto master --root develop

如果有任何分支从develop分支上分出来,它们会被“严重搞乱”。这是因为那些分支(我们称之为主题分支)仍然指向重置前的旧develop分支。如果没有分支从develop分支上分出来,那么你就完成了。
每个主题分支都需要重置到新的develop分支。为此,我们将按照另一个问题中概述的步骤进行操作(Git:如何重置到特定的提交?)。对于每个主题分支,请按照以下步骤操作。
用新创建的develop分支上的提交的sha1替换<common-ancestor>
$ git branch temp <common-ancestor>
$ git checkout <topic-branch>
$ git rebase temp
$ git branch -d temp

就是这样!请记住,不要在与他人合作的分支上进行变基。


3

理想情况下,您需要通过在开头添加提交来重写dev的完整历史记录:添加一次提交

# remember the first dev commit (before rebase)
git branch tmp  $(git rev-list --max-parents=0 HEAD)

# first you need a new empty branch
git checkout --orphan master
git rm -rf .

# then you apply the same steps
git commit --allow-empty -m 'root commit master'
git rebase --preserve-merges --onto master --root dev

然而,正如"将一个分支及其所有子分支进行变基"中所示,这将使得所有的feature分支指向它们旧的dev源(在变基之前)。
git branch --contains tmp | \
xargs -n 1 \
git rebase --committer-date-is-author-date --preserve-merges --onto master tmp^

即:旧的dev第一个提交(tmp)可以访问的任何分支都需要在master上进行rebase操作:已经在master上进行过rebase操作的任何公共提交都不会重复。这将从新(经过rebase操作的)dev分支重新创建feature分支的提交。

原始回答:

您可以简单地从dev分支的第一个提交创建master分支。

git branch $(git rev-list --max-parents=0 HEAD) master

(请查看 "如何引用最初的提交?")

这意味着在 dev 上进行的第一次提交也被认为是 master 的一部分,尽管这并不完全准确,但比重写整个 dev 的历史要容易。


这可能是一个可行的解决方案,但在我的情况下,develop 上的初始提交不应被视为项目的生产就绪状态。请参见我的更新问题。 - Parker Hoyes
这个方法确实将develop上的初始提交指向了master上的初始提交,但是在变基之后,特性分支不再指向正确的提交。 - Parker Hoyes
您更新后的解决方案仍然得到了相同的结果。特性分支指向旧的develop提交,而不是重新定位的提交。 - Parker Hoyes
@ParkerHoyes 不,我没有。你能试试只用其中一个特性分支的最后一部分:git rebase --committer-date-is-author-date --preserve-merges --onto master tmp^ aFeatureBranch,看看那个特性分支是否被正确地重定位了吗? - VonC
我想出了一个更简单的解决方案来解决我的问题。请看我的答案。通常这只是需要应用一次的修复,因此手动完成工作不应该是什么大问题。 - Parker Hoyes
显示剩余3条评论

0

来自Git filter-branch文档

要将一个提交(通常位于另一个历史记录的顶部)设置为当前初始提交的父提交,以便将其他历史记录粘贴到当前历史记录后面:

git filter-branch --parent-filter 'sed "s/^\$/-p <graft-id>/"' HEAD

(如果父字符串为空-这种情况发生在处理初始提交时-将graftcommit添加为父级)。请注意,这假定具有单个根的历史记录(即,没有发生没有共同祖先的合并)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接