将文件及其历史记录移动到新分支

时间:2017-12-14 17:52:31

标签: git github version-control gitlab branching-and-merging

我在一个分支中做了很多不同的更改,现在我想将一些更改移动到一个新分支,以便我的pull请求更具体。

现在我知道我可以这样做:git checkout <branchname> -- filename 但问题是我想保留文件历史记录。

目前我的git知识有限,我只能想到两种方法:

  1. 创建一个新的分支并编写包含我需要的文件的所有提交,然后逐个将它们重新提交到我的新分支。

  2. 从当前分支创建一个新分支,然后对我不想要的所有提交执行恢复提交。

  3. 自上次提取请求以来,我有超过50次提交,并且逐个提交/恢复提交是一个繁琐的过程。

    是否有一种简单的方法可以将文件移动到新分支,同时保留其历史记录?

4 个答案:

答案 0 :(得分:1)

您没有什么特别的,因为在Git中,文件不具有历史记录。 (也就是说,您只需重命名该文件,例如使用git mvmv后跟git add -u,并提交。)

相反,Git的提交历史。如果您想阅读历史记录,请阅读提交。

Git提供git log --follow

当您提出要求时,Git将通过读取提交历史记录并在每次提交时查看该文件来合成文件历史记录。如果该文件与父提交中相同文件的版本相比,相同,则Git根本不会显示提交。结果似乎是文件的历史记录,但它不是:它只是&#34;文件与提交的父提交中存储的版本不同的提交&#34; 1

这是发生不匹配的地方:如果&#34;那个特定文件&#34;表示path/to/file.ext,在某些时候,名义上相同的文件有不同的名称,例如p2/othername.otherext,好吧,现在Git的合成文件历史记录制作者正在寻找错误的名字。

Git提供的解决方法是git log --follow--follow的实际实现是粗暴的攻击:Git仍然只是一次查找一个名称。 --follow做的是让Git注意到,在某些提交中,&#34;之前的提交&#34;反对&#34;这个提交&#34;导致差异显示&#34;将p2/othername.otherext重命名为path/to/file.ext&#34;。所以,从那时起到现在为止,Git不再寻找path/to/file.ext而是开始寻找p2/othername.otherext

......并不总是有效

这种粗糙的hack在大多数情况下运行良好,但无法在fork-and-re-merge的提交链中跟踪两个不同的名称:

          o--o--o
         /       \
...--o--o         *--o--...
         \       /
          o--o--o

当Git从右向左工作(较新的提交给较旧的提交)遇到合并提交*时,它必须及时跟随两个父母,沿着顶线并沿着底线。它实际上是一次提交一个,或者,在一些非常常见的情况下 - 使用Git所谓的历史简化 - 只需完全删除其中一个分支,只需 提交的顶部或底部。

默认情况下,在查看特定路径名时会启用历史记录简化。由于git log --follow查看一个路径名,因此Git会查看特定的路径名​​,因此会启用历史记录简化。这可以帮助它执行--follow代码,因为它无法记住这两个名称(它不是那么聪明)。如果您使用各种git log选项关闭历史记录简化,则--follow代码会发生故障:它会更改单个要遵循的名称,而您却看不到合适的名称无论如何,合成历史。

1 这个概念在合并提交时变得更加棘手。如果path/to/file.ext与父提交的 one 中的相同文件相同,但与其他父提交中的同一文件不同,是否会更改?这也是历史简化的用武之地。组合diff 仅列出文件与所有父项中的版本不同的文件,历史简化程序通常仅遵循执行的提交更改文件。

如果你查看git log -p输出(有或没有--follow),那就是一个相关的棘手的位,这是git log没有打印< / em>默认情况下组合差异。您必须添加-c--cc,或使用-m拆分合并,以便在此处查看差异。

答案 1 :(得分:1)

工作流程应与您列出的类似。但是有一些命令可以使工作流程高效:

  1. 获取更改指定文件的提交列表

    假设您希望获得更改*.cs*.txttest.sh的提交,然后您可以通过

    获取更改任何文件的提交
    git log --grep=*.cs --format="%h  %cd" && git log --grep=*.txt --format="%h  %cd" && git log --grep=test.sh --format="%h  %cd"
    
  2. 创建新分支

    您可以从初始提交创建分支,以便新分支上的提交历史记录将记录指定文件更改为步骤列表的视图:

    git checkout -b newbranch <commit id for the initial commit>
    
  3. 樱桃选择步骤1中列出的提交从旧到新

    Cherry-根据提交日期从步骤1中选择从旧到新的提交。您还可以通过脚本挑选提交列表。

  4. 还原或删除master分支

    中的提交列表

    您可以使用git revert <commit>逐个恢复步骤1中列出的提交。但它会增加master分支的提交历史。

    另一种方法是通过交互式rebase删除master分支中的提交。在master分支中,您可以使用git rebase -i master~49(假设您在master分支上有50个提交)。

    然后在交互式窗口中,在您要删除的提交之前将pick更改为drop。交互式窗口应如下所示:

    pick <second commit>
    pick <third commit>
    ...
    drop <m-th commit>
    ...
    drop <n-th commit>
    ...
    pick <50th commit>
    

答案 2 :(得分:0)

你可以尝试,

一次创建补丁,

find . -name "00*" | sort | xargs git am 

在新分支中应用补丁

cy.ready()

答案 3 :(得分:0)

你必须将一个分支合并到另一个分支

命令是 - git merge [你要合并的分支名称]