我在GIT中有两个分支-分支A和分支B。分支A包含10个文件,分支B包含15个文件,其中10个文件是分支A中常见的文件。
当我合并分支A到分支B时,可以看到以下行为: 1.额外的5个不常见的文件正在被删除。2.删除B分支常用文件中多余的行。
当我将分支B合并到分支A时,可以看到以下行为: 1.额外的5个文件没有添加到分支A。
我已经在GIT bash和Tortoise GIT中尝试过了,并且可以看到相同的行为。你能建议我如何在不删除文件或丢失更改的情况下处理这种情况吗?
发布于 2020-02-14 10:56:49
当您合并两个分支时,Git会恰好查看三个点来考虑要合并的内容:两个头,以及称为合并基点的第三个位置,这通常是分支的分叉点。它在合并结果中产生的所有内容都是合并基和每个头之间更改的总和。换句话说,如果您在一侧进行了更改,而没有在另一侧进行更改,则产生的合并将包含该更改。
在您的示例中,在一个分支中您删除了文件,而在另一个分支中您没有对这些文件执行任何操作。由于删除文件算作更改,因此会将其合并到结果中。
如果您不想删除这些文件,请调整分支A,使其不会删除这些文件,然后执行合并。这是解决问题的最好、最简单的方法。
或者,你可以做所谓的邪恶合并,这是一个你篡改Git通常会产生的结果的合并。如果要执行此操作,请像往常一样执行合并,然后运行git checkout B -- file1 file2 file3 file4 file5,其中文件是已删除的路径。然后运行git commit --amend将更改压缩到合并提交中。
发布于 2020-02-14 11:07:02
分支名称在这里并不重要。重要的是提交。
诀窍是绘制您的提交并找到合并基础。合并基础是分支连接的地方。让我们画出你的实际分支。当然,我必须猜测您的提交是什么;您还没有向我们展示您的存储库及其提交。但它们可能看起来像这样:
I--J <-- BranchA
/
...--G--H
\
K--L <-- BranchB在这里,每个大写字母代表了一些实际的提交散列ID。使用git log --graph BranchA BranchB让Git为你绘制图表,垂直方向是新的提交数朝上,而不是我绘制的方式,水平方向是新的提交数向右。git log命令还将包含实际的散列ID(尽管略有缩写)。
请注意,在某些情况下,两个分支是如何连接在一起的。在我上面绘制的图表中,它们在提交H时连接在一起。此提交是合并基,合并基是合并的关键。
您正在做的是比较提交J和L的内容。其中一个提交的文件比另一个多五个文件。这并不重要。
重要的是你得到了什么如果你:
H和J。这会告诉你,在从J.H的一系列提交中,你-或任何人-改变了什么,比较H与L。这将告诉您在从H到L.的一系列提交过程中,您或任何人更改了哪些内容
Git将结合这两组更改。
一旦找到commit H (或者不管它的实际散列ID是什么),您会发现这两个比较中的一个是删除5个文件。这是Git正在合并的一系列变化之一。(根据您上面的描述,这是H-vs-J:删除发生在第一行。)
两个比较中的另一个说:“您根本不需要对这五个文件做任何操作”。很容易将这两条指令结合起来:“什么都不做”加上"delete“等于"delete”。所以git merge会删除这五个文件。
最好的方法是在分支A上进行新的提交,即将合并基础H或提交L中的这五个文件放回
I--J--M <-- BranchA
/
...--G--H
\
K--L <-- BranchB现在,比较一下H和M,我们建议不要对这五个文件做任何事情。比较H和L还表明,不要对这五个文件做任何事情。组合这两组指令很容易: Git将保留这五个文件,这五个文件在所有三个提交中都是相同的。
作为bk2204 answered while I was typing all this,你可以继续进行合并,然后修改它-或者你可以运行git merge --no-commit,这样Git实际上还不会进行最终提交,然后在提交之前修改它-这样合并结果就会保留这五个文件,尽管结果更自然。然后你就会得到:
I--J
/ \
...--G--H M
\ /
K--Lmerge commit M中的快照合并更改,但保留五个文件。(移动到M的分支名称取决于您在运行git merge之前对哪个分支执行git checkout。)
最后,如果有某些原因不在合并之前进行恢复提交-这通常是最佳实践-并且您不想进行需要重复此技巧的“邪恶合并”(如果您曾经使用过git rebase --rebase-merges ),则可以继续进行合并提交M,它将删除这五个文件,但随后将它们放回提交中。例如,假设您使用git checkout BranchA; git merge BranchB,因此您将获得:
I--J
/ \
...--G--H M <-- BranchA (HEAD)
\ /
K--L <-- BranchB现在,您可以再提交一次,只需将文件放回原处:
git checkout <hash-of-H> -- file1 file2 ... file5
git commit -m "restore five files that were erroneously deleted in commit <hash>"例如,这会导致:
I--J
/ \
...--G--H M--N <-- BranchA (HEAD)
\ /
K--L <-- BranchB在那里,commit N拿回了这五个文件。
(如果您想从commit L中获取这五个文件,请使用git checkout BranchB或git checkout hash-of-L,但如果没有修改/删除冲突,这意味着这五个文件在commit H和L中匹配。因此,使用哪个命令来获取这五个文件并不重要:使用任何最简单的命令。请注意,这里的名称BranchB只能正确工作,因为我们在BranchA上进行了合并,因此名称BranchB不会移动。如果我们使用git checkout BranchB; git merge BranchA,那么指向M的名称将是BranchB。)
https://stackoverflow.com/questions/60219219
复制相似问题