如何解决与远程git repo的冲突?

Joh*_*ver 2 git merge conflict

所以,首先,我是一个完全新手的git.

我们的工作流程是克隆远程仓库,做工作,提交等等,直到我们开心,然后推送到原点/分支.然后做一个拉取请求.(这可能是疯了,它似乎容易出现问题,但我对这些东西一无所知,只是盲目地遵循程序:-))我这样做......并且与其他人编辑的文件存在冲突我克隆了主人后合并的分支.我的提交使该文件多余,所以我想要的快速答案是,如何让git只是破坏这个文件?但更长远的是,每当发生冲突时,这显然不是正确的答案:-)但是我向Google提出的所有内容似乎都假设我正在直接从有问题的回购中解决.像"git status"这样的东西告诉他们一切都很好,因为它正在查看我的repo克隆.我无法找到我如何解决这是一个远程存储库.

tor*_*rek 9

在其他任何事情之前,让我这样说(这有点简化,但就其而言足够准确):git pull只是一个便利脚本,它执行两个底层的git命令,git fetch然后是git merge.如果你用而不是(获取+合并)来思考它们会更有意义.fetchpull

你确实不能用git在"远程存储库"上工作.一切都是本地的.当您获取或推送时,您的本地git联系远程 - 将其视为通过Internet电话呼叫其他人 - 以及您的git和他们的git交换信息,之后您要给他们东西(git push)或者他们给你东西(git fetch).

当他们给你东西时,你的git会记下他们拥有的分支,并更新你对"遥控器上的东西如何"的想法.这些进入你的(本地!)"远程分支",例如origin/masterorigin/develop,或者他们使用的任何分支名称:你的git坚持origin/在前面,因为你正在做git fetch origin.1 这个分支重命名技巧非常重要.这尤其意味着无论您正在处理哪些本地分支,它始终都是安全的git fetch,因为它只会更新您的"远程分支".(这也是本地的 - 他们在你的.git目录中,而不是遥控器.你只需在他们的git在互联网电话上调用他们的git时添加,更改和删除你的副本就可以同步它们.)

但是当你给他们的东西时,没有重命名.当你这样做时git push origin master,你的git说,无论你是谁,你都会打电话origin:"嘿,我建议你们改变你们master给我的新承诺." 他们是否接受这一点取决于他们.一般来说,他们(无论他们是谁)接受"快速前锋"但不接受"非快速前锋".对于(更多)关于这一点,请看这个更长的答案.

当使用拉请求(并与用户发起推动相结合),你通常会推动你提交到每个用户的位置:例如,而不是从你推mastermaster遥控器上,你可能会推到to-everyone/from-JohnOliver/master.或者,您可能会推送到只有您推送的存储库,但其他人都可以看到.这里的想法是你在这里做的推动永远不会与其他任何人发生冲突,只是让你的提交可见,之后你发出"拉动请求"告诉别人去看看那些提交.如果他们(无论他们是谁)喜欢他们,他们会将它们添加到master遥控器上.如果没有,他们会让你重写它们.

请注意,如果您重写提交,您将获得一个新的,不同的提交.每个提交都有一个很难看的SHA-1 ID,作为其完整的"真实姓名".此ID是提交的全部内容的加密校验和:所涉及的所有文件,您的姓名和电子邮件,日期/时间戳以及您的提交的父提交.如果你改变任何东西,你会得到一个新的不同的提交.(您的新提交可以使用与旧提交相同的父ID,以及相同的用户名和电子邮件.如果您足够快[可以在一秒钟内完成多少次提交?:-)],或者钻井时间,你甚至可以得到相同的时间戳.但是如果文件不同,您将获得不同的commit-ID.那没关系:这就是我们想要的.如果你得到相同的 commit-ID,那么所有文件都是相同的,你的名字和时间也是如此,所以它毕竟是旧的提交.)


现在,回到你的问题......

我做[拉] ...并且与我们自己的分支中编辑的文件发生冲突,这个文件在我克隆了master之后被合并了.我的提交使该文件多余,所以我想要的快速答案是,如何让git只是破坏这个文件?

当你做的时候,pull你正在做一个fetch跟随的merge.在fetch带来了别人的承诺(或多个),这是现在发现,能对origin/master(或任何分支机构;我只是要承担master这里).

如果你已经完成了你的工作,那么你有自己的承诺,可以找到你的master.(如果你还没有提交,那么做一个可能不是一个好主意git merge.但是你上面的工作流程说你有.所以我们假设你有自己的工作.)让我们画出结果的"提交图",这只是写下(在白板上或作为ASCII艺术或其他任何东西)的一种奇特的方式,一些提交显示谁做了什么:

             A   <-- master <-- HEAD
           /
...* <-- *
           \
             B   <-- origin/master
Run Code Online (Sandbox Code Playgroud)

你的承诺,A就在你的承诺上master.他们的提交B是在你的origin/master(从他们复制master).双方AB具有相同的父提交,最右边的*图中的节点.这*指向其父母,依此类推.(/\线条确实应该是箭头指向*,但箭头只能在某些浏览器中使用.)

什么git merge是尝试将您的更改A与其中的更改结合起来B.只要git无法自己组合,就会出现合并冲突.

...我的提交使该文件冗余,所以我想要的快速答案是,如何使git只是破坏这个文件?但更长远的是,每当发生冲突时,这显然不是正确的答案:-)但是我向Google提出的所有内容似乎都假设我正在直接从有问题的回购中解决.像"git status"这样的东西告诉我一切都很好......

如果git status认为合并进展顺利,并git merge没有停下来,说有冲突,那么混帐没意识到有一个矛盾.它认为您的更改和更改都可以合并为"所有更改的总和".在merge随后还做出了新的承诺:

             A
           /   \
...* <-- *       M   <-- master <-- HEAD
           \   /
             B   <-- origin/master
Run Code Online (Sandbox Code Playgroud)

这里唯一的问题是与合并结果相关联的文件M错误的:如你所说,他们的更改(或整个文件本身)应该消失,但是git认为你的更改没有冲突,所以git保留了两者!

让我在这里重复一句话:

我在Google上发现的一切似乎都假设我正在直接处理有问题的回购.

.你在你的回购中工作.如果您git push或以其他方式邀请人们从您的回购中获取东西,您将分享您所做的事情,但在此之前,这一切都是您的. 在您发布之前它是私有的,这意味着您也可以更改它.

如果您确实有这样的虚假合并提交,那么要做的就是在发布之前删除或修复合并.(你当然可以在事后解决它,但以前其他人修复它会更好.)

在stackoverflow上讨论如何删除合并git reset,或者如何修改git commit --amend合并(你可以合并提交,如果你想保留合并本身,这是特别方便的).如果你删除了合并,你可以将你的提交"重新绑定"到你选择的新提交上,但在这里要小心:因为git在合并时没有检测到任何冲突,所以几乎肯定不会检测到冲突.重新定义,你也想要重做一个文件,特别是在你的提交不需要更改的时候(或者不需要整个文件).交互式rebase为您提供了执行此操作所需的所有工具,当然,在此过程中还有很多东西需要了解git.有关变基的更多stackoverflow答案.


最后,如果你确实遇到了冲突,但解决了它(可能是错误的)并且git commit结果仍然是,那么解决办法仍然与上述相同:删除或修复合并.如果要删除合并,然后重复它,但没有让git提交生成的文件,请使用git merge --no-commit.Git将尽最大努力自动合并所有内容,但随后停止而不提交.这为您提供了撤消其更改的位置,甚至:

git rm file.dat # no longer needed at all
Run Code Online (Sandbox Code Playgroud)

之后你可以git commit得到结果(作为合并提交).


1如果你正在做,git fetch batman那么你的git会命名它们batman/master,依此类推.基本上,遥控器只是"你的名字",他们的分支将这个名字推到前面,你的git以这种方式跟踪他们的分支.这就是为什么他们被称为"远程分支",或者有时候是稍长的短语"远程跟踪分支".

如果您只是在git fetch没有命名的情况下运行,origingit会计算出哪个遥控器可以自动使用; 通常这只是origin反正(但谁知道,batman如果你已经设置了,甚至brucewayne或其他什么).在任何情况下,适当的远程名称都会卡在"远程分支"的前面.