我可以覆盖请求请求的目标文件吗?

时间:2019-07-01 14:32:08

标签: git azure-repos

我有2个存储库(A)和(B)。 (B)是(A)的Fork,并且已收到文件目录重命名。 (B)中的许多文件只是具有不同的父文件夹名称。现在,我正在尝试将(A)的请求拉入(B),但是Azure Repos表示目标文件已删除。

是否有一种方法可以手动覆盖拉取请求,以便在(A)的文件映射到(B)的文件的地方可以发生从(A)到(B)的映射文件?同样,它们是相同的文件,只是父文件夹不同。如果可以的话,我想避免更改(A)的文件夹结构。

1 个答案:

答案 0 :(得分:1)

简短的回答是“否”,但是问题本身有点问题。如果您问 right 问题,答案可能是“是”。

首先,“拉取请求”不是Git的东西,而是各种Web服务(例如GitHub或Bitbucket或(如果您是)Azure)提供的附加组件。 Git真正具有的功能是 fetch 提交-从其他Git存储库中获取完整的提交-并合并

当您获取其他人的提交时,您得到的实际上就是他们的 提交。 Universe中的每个提交都有自己独特的,唯一的哈希ID。哈希ID是提交过程中所有内容的加密校验和:快照中的所有文件,提交人员的名称和电子邮件地址,其日志消息,尤其是用于Git-导致目前为止的所有历史。也就是说,为了将 this 提交放入您的存储库,您还必须将所有导致导致提交的提交及其快照,作者和日志消息等。 / em>此提交。

现在您的存储库中有他们的提交,您就有了他们的提交。现在由您决定要使用这些提交的内容。您可以按原样保留它们,也可以在复制过程中(提交副本之前)对它们进行拷贝并进行更改。这些副本可以具有您喜欢的任何差异:请记住,副本将具有与原始副本不同的 哈希ID。只有原始提交才能使用原始哈希ID。

如果保留原件,则保留其文件结构。没有办法解决这个问题。具有唯一哈希ID的提交将一直冻结。没有人(不是您,不是他们,不是Git)可以更改该提交。您要么拥有它,要么那样,或者根本不拥有它。 (通过将这些提交填充到存储库中后,确定不喜欢它们,可以实现“完全不拥有”状态。您只需停止使用它们,并通过其哈希ID引用它们即可。 ,最终您的Git会丢弃它们。这里的引用和reflog有点棘手,但主要是删除所有引用并等待的问题。

如果您将这些原件复制到具有新文件结构的新提交中,那很好。无论是否保留原件,都可以保留副本。但是,您的副本就是您的副本-您的,无论他们是谁,它们都无法与它们将来的更新很好地结合在一起。如果您打算与其他人进行持续的工作,那可能不是一条好路。

现在让我们看第二个更有趣的部分:

  

是否有一种方法可以手动覆盖拉取请求,以便在(A)的文件映射到(B)的文件的地方可以发生从(A)到(B)的映射文件?同样,它们是相同的文件,只是父文件夹不同。如果可以的话,我想避免更改(A)的文件夹结构。

现在我们知道Git中没有拉取请求之类的东西了,我们可以将其变成正确的问题,即:

  

现在我已将其提交保存在存储库中,是否可以使用松散Git文件匹配规则的参数将其提交与提交合并?

问题的答案是。您可能需要使用命令行Git而不是精美的Web界面执行此操作-例如,GitHub的clicky按钮Web界面不具备此功能。

当Git执行合并时(如git merge otherbranch),此合并有三个输入。三个输入之一是您当前的提交-您所在分支的尖端或HEAD提交:这是同一提交的两个名称,其真实名称是其丑陋的哈希ID。输入之一是您指定的另一个提交-在这种情况下为otherbranch,但您也可以只提供原始哈希ID; Git只是将名称 otherbranch 转换为原始哈希ID,用于合并。

那是两个输入,那么第三个是什么?答案是它由图形暗示。请记住,在上面我曾说过,如果您从其他人那里进行了一次特定的提交,那么您还必须进行所有导致 的提交。我们可以以图形方式绘制这种情况:

...--o--o--*--o--o--L   <-- yourbranch (HEAD)
            \
             A--B--R   <-- theirbranch (or theirrepo/branch or whatever)

这里L代表您当前( L eft或 L ocal或--ours)提交,而R代表他们的( R ight或othe R 或从- R emote-Git或--theirs获得)提交。 AB代表您需要从它们中获取的提交的哈希ID以获取提交R,而*是的哈希ID您已经拥有的提交A的父级。 1

对于这些真正的合并案例,git merge的工作方式(您肯定会是这样的)是Git运行两个 git diff来找出您更改的内容更改的内容。实际上,第一个差异是:

git diff --find-renames <hash-of-*> <hash-of-L>

请注意此--find-renames参数。第二个差异等效于:

git diff --find-renames <hash-of-*> <hash-of-R>

如果您没有重命名文件夹,则在*L之间,而他们 did 重命名文件夹,则在*L之间,Git将在合并过程中尝试匹配*R中的文件,即使它们具有不同的名称。 此尝试取决于文件内容的相似性。

同时,如果 you *L之间重命名了一个文件夹,而他们没有重命名了该文件夹,则Git会执行一样。它尝试将*中的基本名称与L中的您的名称进行匹配。这种尝试取决于文件内容的相似性。

如果两个都重命名了文件夹,那也可以。 Git尝试根据提交*中与每个可能相同名称的每个新名称的 content content 相似性来查找原始文件。在两个分支提示中可能不是文件。

已将*L中的所有重命名文件配对,发现path/to/file.ext中的文件*现在位于{{1}中的path/different/file.ext },Git知道您对L所做的更改是通过将file.ext的原始*file.ext的新名称进行比较而获得的对于同一文件。它还知道您已重命名该文件。同样,将所有重命名从L配对到*之后,Git知道他们对R所做的更改是通过比较{{1 }}的原始file.ext*的同一文件的新名称。

在所有情况下,一旦Git正确识别了重命名的文件,合并便照常进行:Git尝试逐个文件地合并您的更改及其更改。它还尝试保留你们两个人所做的任何重命名。

这一切都可以通过几种方式出错:

  • 如果您重命名为file.ext,则Git不知道要保留哪个新名称。您将遇到R冲突,必须手动解决。这与您还必须自行解决的任何其他合并冲突是分开的。完成解析后,如有必要,file.ext将文件命名为您想要保留的名称,然后rename/rename将合并的更改以您想要保留的名称命名。

    < / li>
  • 如果谁更改了文件的名称也对内容进行了太多更改,Git将无法将旧文件与新文件配对。多少是太多了?好吧,Git具有相似性阈值的概念。当Git执行git mv操作的git add部分时,Git将针对似乎已从旧提交中被删除的每个文件,将已删除文件的内容与在新提交中似乎是从头开始创建的每个文件的内容。如果旧的--find-renames与新的git diff old-commit new-commit有30%的相似性,而新的file.ext与新的different.ext相似的有70%,则以70%相似的匹配为准。但是,如果没有文件达到“ 50%匹配”,则默认设置是确定该文件毕竟已删除。

    如果您自己运行other.ext,则可以添加重命名阈值因子,该因子默认为50%,但可以调整。根据需要向上或向下调整它,以使Git与 right 文件配对。 Git会在diff输出中告诉您相似度索引是什么。

    您可以在运行git diff --find-renames之前,在 之前手动运行这种git diff,并找到使Git匹配文件的适当相似性索引。然后,您可以运行git merge告诉git merge -X find-renames=number将其数字用于其两个git merge操作。

    当然,如果必须大幅度降低相似性阈值,则合并操作本身很有可能在此处发生冲突,因为这表明您已对文件进行了太多更改,以至于所有更改他们会冲突,可能会与您所做的更改冲突。但这可能足以自动处理合并的 more

因此,就像以前一样,这里是手动进行合并的方法。首先使用git diff --find-rename获得您打算合并的提交。然后,使用git fetch查找git merge-base --all将找到的共享的基于合并的提交。使用此共享的merge-base作为起点提交,运行git merge,并将您和/或他们的分支提示提交哈希ID或分支名称作为终点提交。将git diff --find-renames添加到此--name-status中仅获得有关哪些文件已配对并被发现修改的摘要,以及哪些文件被视为删除的摘要。调整重命名查找阈值(git diff;如果要使用短拼写,则调整--find-renames=number),直到获得最佳结果。然后将-Mnumbergit merge选项一起使用,以使-X rename-threshold=number将该相同的数字传递给两个基础差异。


1 您可能已经拥有git mergeA。使提交B如此重要的原因在于,这是您的分支机构及其分支上所有最佳共享提交: >最好的。从技术上讲,它是构成存储库的提交的有向无环图(DAG)中的两个选定提交中的最低公共祖先(LCA)提交。您可以使用以下命令找到此提交的哈希ID:

*

例如。有时根本没有公共提交,有时-很少-DAG中两次提交中的LCA不止一个,但是通常这只会产生一个哈希ID,这就是合并的基础。