将整个开发分支重新定位到新的主分支

Rebase entire development branch onto new master branch

我正在使用理论上应该遵循 Gitflow 工作流程的存储库(请参阅 Vincent Driessen 的 A successful git branching model)。但是,存储库的初始提交是在 develop 分支上进行的,并且看不到 master 分支。临近发布时间,我需要创建一个 master 分支来反映项目的生产就绪状态,这应该从一开始就存在。请记住 develop 分支有多个功能分支。存储库完全是本地的,没有被推送。

我的想法是创建一个孤立分支 master 并将 develop 分支变基到它上面,但我不知道该怎么做。

那么,如何创建 master 分支,就好像它是从一开始就创建的一样?

更新: 在我的例子中,develop 上的第一个提交不是一个应该被认为适合生产的提交,所以使用它作为初始 master commit 是不明智的。项目之所以会是这个状态是因为当初决定使用Git.

的时候没有使用VCS

理想情况下,您需要通过 adding a commit at the start:

重写 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

然而,如“Rebasing a branch including all its children”所示,这将使所有 feature 分支指向其旧的 dev 原点(在变基之前)。

git branch --contains tmp | \
xargs -n 1 \
git rebase --committer-date-is-author-date --preserve-merges --onto master tmp^

即:任何可从旧 dev 第一次提交 (tmp) 访问的分支都需要重新基于 master:任何已经重新基于 master 的公共提交都不会'不再重复。这将重新创建 feature 分支的提交,从新的(重新设置的)dev 分支。


原回答:

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

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

(参见“How to reference the initial commit?”)

这意味着在 dev 上完成的第一次提交也被认为是 master 的一部分,这并不完全准确,但比重写 整个 dev.

的历史

经过一番摆弄,这就是我想出的。这是 .

的一种更简单的手动方法

重新构建整个开发分支

假设您有一个分支 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 分支有任何分支,它们应该是 "majorly messed up"。这是因为那些分支(我们称它们为主题分支)仍然指向旧的 develop 分支,然后才重新设置基线。如果 develop 分支没有分支,那么你就完成了。

每个主题分支都必须重新定位到新的 develop 分支。为此,我们将按照另一个问题 (Git: How to rebase to a specific commit?) 中概述的步骤进行操作。对于每个主题分支,请执行以下步骤。

<common-ancestor> 替换为新创建的 develop 分支上的提交的 sha1,主题分支应从该分支分支。

$ git branch temp <common-ancestor>
$ git checkout <topic-branch>
$ git rebase temp
$ git branch -d temp

就是这样!请记住,您不应在与其他人合作的分支上变基。

来自Git filter-branch documentation.

To set a commit (which typically is at the tip of another history) to be the parent of the current initial commit, in order to paste the other history behind the current history:

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

(if the parent string is empty - which happens when we are dealing with the initial commit - add graftcommit as a parent). Note that this assumes history with a single root (that is, no merge without common ancestors happened).