将分支移动到历史记录中的另一个点

phl*_*psy 5 git branch

我们有以下历史

start         master  public
|                 |   |
v                 v   v
o---o-- ... --o---o---o
Run Code Online (Sandbox Code Playgroud)

不幸的是,我们在master包含一些敏感数据的分支中做了一些提交.我们在一个名为public的独立分支中进行了修改.现在我们想要"切断" public分支,以获得一个完整而干净的"状态",public但没有妥协的历史部分仍然包含在内master.换句话说,我们想要以下新历史:

start         master
|                 |
v                 v
o---o-- ... --o---o
 \
  o <- public
Run Code Online (Sandbox Code Playgroud)

现在退房public将导致与原始情况相同的工作树,但没有合理的历史细节.然后我们将旧分支停止master:将其重命名为unsafe并从新master分支中精心设计一个新public分支.通过这种方式,我们保留了旧的历史,unsafe并且能够public毫无后顾之忧地将分支机构推向公众:

start         unsafe
|                 |
v                 v
o---o-- ... --o---o
 \
  o---o-- ... --o <-- public
   \           /
    o-- .. --o-- ... --o <-- master
Run Code Online (Sandbox Code Playgroud)

有什么正确的git命令来实现这一目标?

PS:当然我们可以结账start,建立一个新的分支并在那里提交分支的整个工作树public.但必须有一种不同的,更加迷人的git方式!

Rei*_*fer 4

将所有公共提交合并为一个提交(即将多个提交合并为一个提交,或完全删除单个提交等)的正确方法是使用git rebase -i. 所以你要做的是(假设第一次提交有一个标签,start如你的图表所示):

git checkout public
git rebase -i start
Run Code Online (Sandbox Code Playgroud)

将出现一个编辑器窗口,您可以在其中编辑所有补丁的顺序,只需用于squash所有补丁。保存该文件并关闭编辑器后,git将根据要求重新组合您的补丁历史记录。当然,master分支根本不会改变它的历史。

要将您当前的 master 重命名为不安全并开始公开进行所有进一步的开发,我会这样做:

git checkout -b unsafe master # <- creates a new branch "unsafe"
git checkout master
git reset --hard public    # <- forces master branch to point to public
Run Code Online (Sandbox Code Playgroud)

如果您不创建unsafe分支,硬重置将丢失 master 中的所有提交,并且您将无法(轻松)再访问它们。因此,请确保您确实创建了该分支。

另一种方法是重命名masterunsafe创建一个新的 master 分支:

git branch -m master unsafe  # renames master to unsafe
git checkout -b master public  # creates new branch master as a copy of public
Run Code Online (Sandbox Code Playgroud)

两者都应该产生完全相同的分支结构。(当然,第二个没有失去历史的危险......)