我已经创建了一个简单的git repo来说明我的问题,可以在GitHub上找到:https://github.com/smileyborg/EvilMerge
这是回购历史的例证:
master A---B---D---E-----G-----I
\ / \ /
another_branch ----C \ /
\ /
another_branch2 F---H
Run Code Online (Sandbox Code Playgroud)
(在GitHub上的实际回购中,D是4a48c9,I是48349d.)
D是一个"简单"的邪恶合并,其中合并提交"正确"解决了合并冲突,但也产生了一个不相关的"邪恶"变化,这两个变化在父系统中都不存在.通过git show -c在此提交上使用,可以发现此合并的"邪恶"部分,因为输出包括++和--(而不是单个+和-)以指示父级中不存在的更改(请参阅上下文的答案).
I一种别样邪恶的合并,其中合并提交"正确"的解决合并冲突(从变化所引起F,以file.txt与变化相冲突G),也有"邪恶"丢弃到一个完全不同的文件中所做的更改file2.txt(有效撤消变化H).
你怎么知道这I是一个邪恶的合并?换句话说,您可以使用哪些命令来发现I不仅手动解决冲突,而且还无法合并应该具有的更改?
正如下面的RenéLink所指出的那样,很难(或许不可能)定义一套通用标准来识别"邪恶合并".然而,就像最高法院大法官斯图尔特所说的关于色情内容一样,当你看到邪恶的合并是你所知道的.
因此,或许更好的问题是:在合并提交中可以使用什么git命令来获得仅在合并提交本身中引入的所有新颖更改的diff输出.这种差异应包括:
D)I)这里的目标是能够让人类看看这个输出并知道合并是否成功或(意外或恶意)"邪恶",而 …
在git-config文档中有关pull.rebase的信息:
pull.rebase
如果为true,则rebase在获取的分支顶部分支,而不是在运行"git pull"时合并默认远程的默认分支.请参阅"branch..rebase"以在每个分支的基础上进行设置.
注意:这是一个可能危险的操作; 除非您了解其含义,否则不要使用它(有关详细信息,请参阅git-rebase(1)).
谁能详细描述一下"NOTE: this is a possibly dangerous operation; do not use it unless you understand the implications (see git-rebase(1) for details)"是什么意思?
当以交互方式 rebase 时,Git 将打开一个编辑器,其中包含可以使用的命令。其中三个命令与称为label.
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# . create a merge commit using the original merge commit's
# . message (or the oneline, if no original merge commit was
# . specified). Use -c <commit> to reword the commit message.
Run Code Online (Sandbox Code Playgroud)
这是什么label以及如何使用它?
在ClearCase中,当在两个不同版本的目录中找到两个具有相同名称的文件时,会发生恶意孪生,并且如果元素OID不同但名称相同.
在GIT中,SHA1 id始终是唯一的,具有相同名称的文件始终具有不同的SHA1 id.
我们没有Evil双胞胎的概念,但是有可能有两个或更多开发人员在同一目录中创建具有相同文件名的不同内容的文件.在合并期间,当两个文件完全不同时,开发人员有可能单独保留其更改并留下其他更改导致代码丢失.
任何人都可以告诉我,如果GIT中存在类似于ClearCase的问题或正弦,每个SHA1 id都是唯一的,GIT中不会有任何邪恶的双胞胎问题.
这是一个多年来被问过很多次的问题。我找到了很多答案,尤其是这个:
Git - 如何在所选文件上强制合并冲突和手动合并(@Dan Moulding)
此页面包含如何设置始终返回失败的合并驱动程序的详细指南,从而使手动合并成为可能。我试图为 Windows 调整该解决方案:
我将以下内容添加到我的%homepath%\.gitconfig:
[merge "verify"]
name = merge and verify driver
driver = %homepath%\\merge-and-verify-driver.bat %A %O %B
我把驱动改成了
cmd /K "echo Working > merge.log & git merge-file %1% %2% %3% & exit 1"
(echo Working > merge.log添加来检查驱动程序是否被调用)。
并且,在 repo 的根目录下,创建了一个.gitattributes包含以下行的文件:
*.txt merge=verify
不幸的是,它不起作用。我试图合并一个文件feature.txt,唉,合并成功完成。似乎根本没有调用驱动程序,因为没有创建 merge.log 文件。
我做错了什么吗?任何强制手动合并问题的解决方案都是最受欢迎的。
合并到分支与重新建立分支时的冲突数量有什么区别吗?这是为什么?
进行合并时,合并更改存储在合并提交本身(具有两个父级的提交)中。但是当进行变基时,合并存储在哪里?
谢谢,奥马尔
假设我正在合并一个pull请求,并且还希望在更改日志中使用一行来合并:
> git merge --no-ff otherguy/feature-x
> echo "Feature: X" >> changelog
> git commit -am "Changelog update"
> git push
Run Code Online (Sandbox Code Playgroud)
在单个提交中可能有类似的事情:
> git merge --no-ff --no-commit otherguy/feature-x
> echo "Feature: X" >> changelog
> git commit -am "Merge otherguy/feature-x + changelog"
> git push
Run Code Online (Sandbox Code Playgroud)
这样相同的提交将包含合并和文件更改.
授予我从下游存储库合并时始终更新更改日志,这是一个问题:
后一种方式是明智的做法,以及后来会出现意想不到的后果吗?
更新:至于为什么我需要一个单独的文件更改日志,当我已经有一个git日志时,文件中的那个更多被修剪(条目或每个合并,不是每次提交),有时更好的措辞和某种格式(例如debian) /变化).所以,这是外部使用.
在GitHub的一篇文章中,我阅读了以下内容:
在以下情况下,您无法自动在GitHub上进行重新绑定和合并:重新提交提交被认为是"不安全的",例如在没有合并冲突的情况下可能存在rebase但会产生与合并不同的结果.
我不清楚rebase如何产生与合并不同的结果.
任何人都可以解释它是如何可能的?
链接到原始文章:https: //help.github.com/articles/about-pull-request-merges/
我们今天在工作中发现了 GIT 的一个严重问题,我想知道这是一个错误还是设计使然,以及如何解决这个问题。
考虑以下事件序列:
结果:即使文件已在两个分支中进行编辑,也不会报告合并冲突,更糟糕的是,即使是最近的提交,步骤 3.2 中的还原也没有保留。
这是一个巨大的问题,从以下最近的示例中可以看出:我的一位同事对不同的分支进行了类似的更改,注意到这些更改的一部分是恶意的,因此在其中一个分支上手动还原了其中的一部分. 合并分支后,他惊讶地发现他的恢复没有通过合并。
我上传了一个最小的例子到谷歌驱动器来演示这个问题。您可以将 Master 合并到 test1 中,反之亦然,以自己查看。
https://drive.google.com/drive/folders/19a-QPwOQKsn9PywUPd2DRnvUOml03nZ-?usp=sharing
如果有任何问题,我将 TortoiseGIT 2.12.0.0 与 Git for Windows 2.32.0.2 一起使用。
我们称之为亚伦的一位同事被指派翻新一个网站的一个部分作为一个长期项目.他创建了一个名为的新Git分支aaron.他所有的改变都是在这个分支上进行的.在他工作的同时,我继续维护整个网站,对我做出改变master.
最终,亚伦将他的分支合并到了master.这以某种方式还原了我master在合并时和aaron首次创建分支之间所做的所有提交.如果我打字git show <hash of merge commit>,我可以看到当Aaron在他的分支上工作时我改变的每个文件的差异.这些差异显示了我所做的每一项改变的回归.如果Aaron手动将其分支上的每个文件的内容复制到master并提交更改,它看起来就像是这样.(他没有这样做.我只是想说明日志显示的内容.)
根据亚伦的说法,他没有做任何奇怪的事情.他说他刚跑了git pull origin/aaron.
可能是什么导致了这个?是否有可能git pull origin aaron将我的所有更改都还原为master?
此外,是否有一种简单的方法可以将我的更改恢复到master而不还原他的所有工作?
编辑1:
其中一个已更改但在master合并后还原的文件是foo.txt.所以我这样做了:
git checkout aaron
git log foo.txt
Run Code Online (Sandbox Code Playgroud)
日志并不能反映任何变化foo.txt的时刻之后aaron分支产生.我有点期待在aaron分支的日志中看到我的更改的恢复,但我没有.那么,这最终证明亚伦做了一些其他事情而不是他声称做过的简单拉动吗?
编辑2:
我曾经说过他打字origin/aaron,但他确实打字了origin aaron.我已经改变了它.
编辑3
根据下面的建议,我选择通过重写历史来解决这个问题.我在这一点上确信这个问题是由一个误导的解决冲突的企图造成的.
我有以下情况:
$ git --version
git version 2.7.3.windows.1
$ git log --graph --oneline
* 83e3254 version 1.1
* 34188af merge of feature into master
|\
| * 784ba31 awesome change
|/
* 6eec273 added file1
* 84d80a5 added version file
Run Code Online (Sandbox Code Playgroud)
要在新目录中重现此问题
rm -rf .git
git init
echo version 1.0 > version.txt
git add version.txt
git commit -m "added version file"
echo file1 > file1
git add file1
git commit -m "added file1"
git checkout -b feature
echo awesome change …Run Code Online (Sandbox Code Playgroud) 我从master分支创建了一个功能分支,然后(做了一些工作并且)不得不删除这个分支上的许多文件。现在,我想将更改合并回master,但不会丢失master我在功能分支上删除的文件。
简而言之,这是我所做的:
(master)> git checkout -b feature
# deleted many files
> git checkout master
> git merge ??? # how to merge back without losing files
Run Code Online (Sandbox Code Playgroud)
换句话说,当文件存在于功能分支上时,将其合并到 master 中。在 feature 分支上删除文件时,不要合并 master 上的删除操作,而是保留文件。
我怎样才能做到这一点?
我一直使用 git 进行合并。我对接下来发生的事情感到恼火,我想知道是否有更好的工作流程方法(我缺少的命令,另一种方法,等等)。
当我 git merge 到my/branchlike时git merge --no-ff --no-commit that/other-branch,我通常会解决冲突。现在这一切都完成了,我检查所有更改,以防自动合并出错(如果您想知道,因此是 --no-commit)。
上次,我发现了一个自动合并,你会笑的,我宁愿有一个冲突。事实上,自动合并会丢弃一些我不希望它丢弃的东西。
这里有一个简短的括号:我不是在讨论 git 的自动合并对于最新的公共基础来说是正确还是错误。我只是告诉你,好吧:我宁愿让 git 在大型合并的其他文件中重播该单个文件的游戏,并将其标记为冲突,以便我手动编辑。
所以,当前的设置是:
git merge --no-ff --no-commitgit diff HEADfoobar自动合并的文件的方式令我不满意。那么命令 #5 是什么:
foobar在步骤 #1 的大合并中间重放单个文件的合并,以强制将其标记为与三向差异友好文件冲突,即使用 <<<<<<< ======= >>>>>>> 而不是自动合并的结果。谢谢。
git ×13
merge ×4
git-merge ×3
git-branch ×2
git-rebase ×2
github ×2
rebase ×2
branch ×1
git-pull ×1
sha1 ×1