git合并具有不同目录结构的分支

Jmerkow

我对git有点陌生,我已经使用了几个月,而且Im可以轻松完成大多数基本任务。所以...我认为现在该承担一些更复杂的任务了。在我的工作中,我们有一些人在处理较旧的代码以对其进行更新,这涉及实际的代码工作以及将目录结构更新为更具模块化的方式。我的问题是,这两件事可以在并行分支中完成,然后合并还是重新建立基础。我的直觉说不,因为dir重组是一个重命名,而git是通过添加新文件并删除旧文件来重命名的(至少这是我的理解)。但是我想确定。
这是场景:父分支看起来像:

├── a.txt
├── b.txt
├── c.txt

然后我们分支两个说,branchA和branchB。在branchB中,我们修改结构:

├── lib
│   ├── a.txt
│   └── b.txt
└── test
    └── c.txt

然后在branchA中更新a,b和c。

是否有某种方式可以将branchA中所做的更改与branchB中的新结构合并?想到了rebase,但是,我不认为git mv之后lib / a.txt实际上连接到a.txt。

詹姆森

周二

首先,请注意:您可以随时尝试合并,然后将其退出,以查看其作用:

$ git checkout master
Switched to branch 'master'
$ git status

(确保它是干净的—在发生更改时退出失败的合并并不好玩)

$ git merge feature

如果合并失败:

$ git merge --abort

如果自动合并成功,但是您不想保留它:

$ git reset --hard HEAD^

(请记住,这HEAD^是当前提交的第一个父级,并且合并的第一个父级是“合并之前的内容”。因此,如果合并有效,HEAD^则是合并之前的提交。)


这是一个简单的配方,用于查找git merge将自动检测到的重命名

  1. 确保diff.renamelimit10diff.renamestrue

    $ git config --get diff.renamelimit
    0
    $ git config --get diff.renames
    true
    

    如果尚未通过这种方式进行设置,请进行设置。(这会影响diff下面步骤。)

  2. 选择您要合并的分支,以及您要合并的分支。就是说,您将要做一些类似的事情git checkout master; git merge feature我们需要在这里知道这两个名字。找到它们之间的合并基础:

    $ into=master from=feature
    $ base=$(git merge-base $into $from); echo $base
    

    您应该会看到一些40个字符的SHA-1,就像ae47361...这里的或类似的东西。(随意打出来master,并feature取代$into$from无处不在这里。我现在用的变量,所以,这是一个“处方”,而不是“例子”。)

  3. 比较两者的合并基础$into$from以查看哪些文件被检测为“重命名”:

    $ git diff --name-status $base $into
    R100    fileB   fileB.renamed
    $ git diff --name-status $base $from
    R100    fileC   fileD
    

(您可能希望将这些差异运行,并将输出保存到两个文件中,然后在以后仔细阅读这些文件。旁注:您可以使用特殊语法获得第三个差异的效果master...feature:此处的三个点表示“查找合并基础“。)

两个输出部分有文件的列表Added,Deleted,Modified,Renamed,等等(例子中只有两个重命名,用100%匹配)。

自从$into以来master,第一个列表就是git认为已经在master(这些是合并时git“希望保留”的更改feature。)

同时,$fromfeature,因此第二个列表是git认为发生在的内容feature(这些是git希望master在合并时“现在添加到中的更改。)

在这一点上,必须做很多工作:

  • 标记为Rgit的文件将被检测为已重命名。
  • 如果R两个分支中的两个列表相同,则可能一切都很好(但还是请继续阅读)。如果R第一个列表中s,而第二个列表中没有...,请参见下文。
  • 当您运行git checkout master; git merge feature(或git checkout $into; git merge $from)git时,将执行第二个列表中所示的重命名,以便将这些更改“添加”到中master
  • 无论如何,将其与您希望git检测为重命名的文件进行比较查找DA输入你有显示为R条目:这些发生时,在其中一个分支,你不仅重命名的文件,而且还这么多,混帐不再检测到重命名改变的内容。

如果第二个列表没有显示您想要看到的所有内容,则需要帮助git out。请参阅下面的详细说明。

如果第一个列表的重命名不在第二个列表中,则这可能是完全无害的,或者可能导致“不必要的”合并冲突和错过真正合并的机会。Git是要假设你打算保留此重命名,并且也期待在合并,从发生了什么分支($fromfeature在这种情况下)。如果原始文件在此处被修改,则git将尝试将此处的更改引入重命名的文件中。那可能就是你想要的。如果原始文件在此处修改,则git没有任何内容可放入,并且将保留该文件。那可能也是您想要的。同样,“不良”情况是未检测到的重命名:git认为原始文件在分支删除feature,并创建了一个其他名称的新文件。

在这种“坏”情况下,git会给您合并冲突。例如,它可能会说:

CONFLICT (rename/delete): newname deleted in feature and renamed in HEAD.
Version HEAD of newname left in tree.
Automatic merge failed; fix conflicts and then commit the result.

这里的问题不是混帐保留了文件在其新名称master(我们probalby那); 这是因为git可能错过了合并在branch中所做更改的机会feature

更糟的是-这可能可以归类为错误-如果新名称出现在merge-from分支中feature,但是git认为它是那里的新文件,则git在工作树中仅留下文件的merge-into版本。发出的消息是相同的。在这里,我对进行了一些更改,master以重命名fileBfileE,并在上feature确保git不会将更改检测为重命名:

$ git diff --name-status $base master
R100    fileB   fileE
$ git diff --name-status $base feature
D       fileB
R100    fileC   fileD
A       fileE
$ git checkout master; git merge feature
CONFLICT (rename/delete): fileE deleted in feature and renamed in HEAD.
Version HEAD of fileE left in tree.
Automatic merge failed; fix conflicts and then commit the result.

请注意可能引起误导的消息fileE deleted in featureGit正在打印名称(名称的master版本);那是它相信您“想要”看到的名称。但这是fileB被“删除”的文件,被feature一个全新的文件所代替fileE

git-imerge下面提到的,也许可以处理这种特殊情况。)


1可以单独设置merge.renameLimitlimit在源代码中拼写为小写,但这些配置变量不区分大小写)。将这些设置为0会告诉git使用“适当的默认值”,随着CPU的速度越来越快,这些默认值多年来已经发生了变化。如果未设置单独的合并重命名限制,则git使用diff重命名限制,如果未设置或为0,则再次使用合适的默认值。如果设置不同,则merge和diff将在不同情况下检测重命名。

您现在还可以设置与递归合并“重命名门槛” -Xrename-threshold=,例如-Xrename-threshold=50%此处的用法与git diff-M选项相同此选项首先出现在git 1.7.4中。


假设您在分支机构上master,而您则是git merge 12345467git merge otherbranch这是git的作用:

  1. 找到merge-base:git merge-base master 1234567git merge-base master otherbranch

    这将产生一个提交ID。我们将该ID称为B“ Base”。Git现在具有三个特定的提交ID:B合并基础;当前分支的尖端的提交ID master; 以及您提供的提交ID1234567或branch的提示otherbranch为了完整起见,我们只用提交图来绘制这些内容。假设它看起来像这样:

    A - B - C - D - E       <-- master
          \
            F - G - H - I   <-- otherbranch
    

    如果一切顺利,git将产生一个具有EI作为其两个父对象的合并提交,但我们想将注意力集中在生成的工作树上,而不是提交图上。

  2. 给定这三个提交(B EI),git会计算两个差异,即la git diff

    git diff B E
    git diff B I
    

    在这种情况下,第一个是对所做的更改集,branch第二个是对进行的更改集otherbranch

    如果您git diff手动运行,则可以设置“相似性阈值”以用于重命名检测-M(请参见上文,以在合并期间进行设置)。Git的默认合并将自动重命名检测设置为50%,这是您没有-M选择并diff.renames设置为的结果true

如果文件“足够相似”(并且“完全相同”就足够了),则git将检测到重命名:

    $ git diff B otherbranch  # I tagged the merge-base `B`
    diff --git a/fileB b/fileB.txt
    similarity index 71%
    rename from fileB
    rename to fileB.txt
    index cfe0655..478b6c5 100644
    --- a/fileB
    +++ b/fileB.txt
    @@ -1,3 +1,4 @@
     file B contains
     several lines of
     stuff.
    +changeandrename

(在这种情况下,我只是将名称从改名为fileBfileB.txt但是检测也可以跨目录使用。)让我们注意,这很方便地由git diff --name-status输出表示

    $ git diff --name-status B otherbranch
    R071    fileB   fileB.txt

(我还要在这里注意,我已经在全局git config中diff.renames设置了truediff.renamelimit = 0。)

  1. Git的现在试图改变从结合BI(上otherbranch)从进入改变BE(上branch)。

如果git能够检测lib/a.txta.txt,则它将连接它们。(并且您可以通过执行预览来预览它git diff。)在这种情况下,自动合并结果可能是您想要的或足够接近的结果。

如果不是,它将不会。

当自动重命名检测失败时,有一种方法可以逐步分解提交(或者可能已经被充分分解)。例如,假设序列中F G H I提交,一个步骤(也许G)简单地重命名a.txtlib/a.txt,等步骤(FH和/或I)作出许多其他变化a.txt(以任何名义)以欺骗的git到没有意识到该文件是重命名。您可以在此处执行的操作是增加合并次数,以便git可以“查看”重命名。让我们假设为简单起见,这F不会改变a.txtG重命名它,使DIFF从BG节目重命名。我们可以做的是先合并提交G

git checkout master; git merge otherbranch~2

一旦合并完成和Git已经从更名a.txtlib/a.txt树为新的合并提交的分支branch,我们做了第二次合并在提交带HI

git merge otherbranch

此两步合并使git“做正确的事”。

在最极端的情况下,一个增量的,逐个提交的合并序列(手动完成将非常痛苦)将拾取所有可以拾取的内容。幸运的是,已经有人为您编写了此“增量合并”程序:git-imerge我没有尝试过,但是对于困难的情况,这是显而易见的答案。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

git合并具有不同目录结构的分支

来自分类Dev

Git-Bash和WSL具有不同的目录结构

来自分类Dev

在git的2个不同分支中合并2个具有相同名称的文件

来自分类Dev

合并两个具有不同文件夹名称的git分支

来自分类Dev

使用合并策略根据目录更新具有原始项目的项目的当前Git分支

来自分类Dev

合并具有不同结构的两个表的结果

来自分类Dev

Git:显示与 master 相比具有不同提交的分支?

来自分类Dev

TFS具有具有不同文件夹结构的分支

来自分类Dev

git合并冲突期间访问不同的分支

来自分类Dev

Git PR合并和结果分支不同

来自分类Dev

Git分支:分支没有不同

来自分类Dev

具有不同主分支和发行分支的发行版本的Git标签

来自分类Dev

具有基准的Git分支

来自分类Dev

如何在不引发合并冲突集群的情况下将子分支分支为具有即将到来的提交和合并的不同开发分支****?

来自分类Dev

Git将功能分支合并到Master是否会有所不同

来自分类Dev

git-删除具有基于合并提交的标签的分支是否安全?

来自分类Dev

git-log:具有拓扑顺序的合并提交的祖先分支的输出顺序

来自分类Dev

如果我git删除了具有尚未合并到其分支的远程分支,该怎么办

来自分类Dev

合并来自不同分支/目录的特定文件

来自分类Dev

Git合并到所有分支

来自分类Dev

git 没有正确合并分支

来自分类Dev

现有分支中的新git分支,无需与master合并

来自分类Dev

将不同的条件选择查询合并为一个-具有结构

来自分类Dev

将一个git分支移到另一个具有不同Parent的分支?

来自分类Dev

如何git push到具有不同基本名称的远程跟踪分支?

来自分类Dev

git push分支到具有不同名称的新仓库

来自分类Dev

Git 推送到具有 2 个不同分支的 2 个遥控器

来自分类Dev

将Kafka与具有不同目录结构的aws s3同步

来自分类Dev

计算git分支与master有何不同?

Related 相关文章

  1. 1

    git合并具有不同目录结构的分支

  2. 2

    Git-Bash和WSL具有不同的目录结构

  3. 3

    在git的2个不同分支中合并2个具有相同名称的文件

  4. 4

    合并两个具有不同文件夹名称的git分支

  5. 5

    使用合并策略根据目录更新具有原始项目的项目的当前Git分支

  6. 6

    合并具有不同结构的两个表的结果

  7. 7

    Git:显示与 master 相比具有不同提交的分支?

  8. 8

    TFS具有具有不同文件夹结构的分支

  9. 9

    git合并冲突期间访问不同的分支

  10. 10

    Git PR合并和结果分支不同

  11. 11

    Git分支:分支没有不同

  12. 12

    具有不同主分支和发行分支的发行版本的Git标签

  13. 13

    具有基准的Git分支

  14. 14

    如何在不引发合并冲突集群的情况下将子分支分支为具有即将到来的提交和合并的不同开发分支****?

  15. 15

    Git将功能分支合并到Master是否会有所不同

  16. 16

    git-删除具有基于合并提交的标签的分支是否安全?

  17. 17

    git-log:具有拓扑顺序的合并提交的祖先分支的输出顺序

  18. 18

    如果我git删除了具有尚未合并到其分支的远程分支,该怎么办

  19. 19

    合并来自不同分支/目录的特定文件

  20. 20

    Git合并到所有分支

  21. 21

    git 没有正确合并分支

  22. 22

    现有分支中的新git分支,无需与master合并

  23. 23

    将不同的条件选择查询合并为一个-具有结构

  24. 24

    将一个git分支移到另一个具有不同Parent的分支?

  25. 25

    如何git push到具有不同基本名称的远程跟踪分支?

  26. 26

    git push分支到具有不同名称的新仓库

  27. 27

    Git 推送到具有 2 个不同分支的 2 个遥控器

  28. 28

    将Kafka与具有不同目录结构的aws s3同步

  29. 29

    计算git分支与master有何不同?

热门标签

归档