簡體   English   中英

Git 合並分支時混合兩個函數

[英]Git mixing two functions when merging branches

我有一個反復出現的問題,當我合並兩個 PHP 類時,有時會發生這種情況,其中兩個分支都向這個 class 添加了一個 function。假設我有這種情況:

分支機構A

class MyClass {
   /* ... previous content ... */

   public function newFunctionA() {
      /* ... Content for function A ... */
   }
}

B分行

class MyClass {
   /* ... previous content ... */

   public function newFunctionB() {
      /* ... Content for function B ... */
   }
}

當我將B分支合並到 A 分支時,我得到以下信息:

class MyClass {
   /* ... previous content ... */

   <<<<<<< HEAD
   public function newFunctionA() {
      /* ... Content for function A ... */
   =======
   public function newFunctionB() {
      /* ... Content for function B ... */
   }

   >>>>>>> branchB
}

它包括兩個函數,但出於某種原因,它省略了第一個 function 的右大括號 ( } )。我知道它很容易解決,但接受這兩個內容並自己插入大括號,但我想知道有什么我可以改變的我的編碼風格可以促進 git 的合並過程並防止這些沖突?

答案可能是否定的,但也許是的

我們無法確定,因為您沒有向我們展示某些內容(Git 也沒有向展示)。 具體來說,您在這里缺少第三個輸入,即合並基礎提交。

如果我們能看到實際的沖突,我們可以肯定地說更多。 要查看實際沖突,如果將merge.conflictStyle設置為diff3 ,我們需要查看文件中顯示的內容。

這是怎么回事

當 Git 組合工作時,它不僅僅查看兩個分支提示提交。 也就是說,它不是在比較:

class MyClass {
   /* ... previous content ... */

   public function newFunctionA() {
      /* ... Content for function A ... */
   }
}

對比

class MyClass {
   /* ... previous content ... */

   public function newFunctionB() {
      /* ... Content for function B ... */
   }
}

相反,它產生了兩個差異 一比較:

class MyClass {
   /* ... previous content ... */
}

到:

class MyClass {
   /* ... previous content ... */

   public function newFunctionA() {
      /* ... Content for function A ... */
   }
}

這兩者之間的區別是,例如,形式的指令:

  • 在第 42 行,添加一個空行
  • 在第 43 行,添加public function newFunctionA() {
  • 在第 44 行,添加一個空行
  • 在第 45 行,添加...
  • 在第 52 行,添加}

由於 Git 的差異格式,所有“添加行”塊都聚集在一起,但是兩個輸入文件中的任何匹配行(例如空白行)可能會導致第二個“添加一些內容”塊。

然后,分別比較 Git:

class MyClass {
   /* ... previous content ... */
}

(這是第一次比較中左側文件的相同版本)到:

class MyClass {
   /* ... previous content ... */

   public function newFunctionB() {
      /* ... Content for function B ... */
   }
}

這也將生成一系列更改說明。 任何在左側(原始)與右側(新的東西)匹配的線都可以被認為是“相同的”。

Git 然后嘗試組合這兩組指令。

我們需要看到的是兩組指令,而不是沖突本身。 特別是,如果指令非常相似——就像你的情況一樣——默認情況下,Git 會繼續並合並它可以合並的部分,並且只在它不能合並的部分周圍留下沖突標記。 所以我們不知道沖突真正開始和結束的地方。

當使用diff3作為沖突樣式時,Git 在完全沖突中留下,顯示介於兩者之間的合並基礎版本。

更多信息和一些示例

Git 2.11 為git diff添加了一個新的啟發式算法。 (在我看來,這種啟發式從未被git merge在內部使用過;如果是,我認為你更有可能得到你想要的東西。但我不能確定這一點。)請參閱VonC 的這個答案. 有關詳細信息,請參閱 Git 源代碼中的提交433860f3d0beb0c6f205290bd16cda413148f098

TL;DR 摘要是啟發式將git diff output 更改為:

--- a/9c572b21dd090a1e5c5bb397053bf8043ffe7fb4:git-send-email.perl
+++ b/6dcfa306f2b67b733a7eb2d7ded1bc9987809edb:git-send-email.perl
@@ -231,6 +231,9 @@ if (!defined $initial_reply_to && $prompting) {
 }

 if (!$smtp_server) {
+       $smtp_server = $repo->config('sendemail.smtpserver');
+}
+if (!$smtp_server) {
        foreach (qw( /usr/sbin/sendmail /usr/lib/sendmail )) {
                if (-x $_) {
                        $smtp_server = $_;

(注意差異如何在“錯誤的”行集上同步)到:

--- a/9c572b21dd090a1e5c5bb397053bf8043ffe7fb4:git-send-email.perl
+++ b/6dcfa306f2b67b733a7eb2d7ded1bc9987809edb:git-send-email.perl
@@ -230,6 +230,9 @@ if (!defined $initial_reply_to && $prompting) {
        $initial_reply_to =~ s/(^\s+|\s+$)//g;
 }

+if (!$smtp_server) {
+       $smtp_server = $repo->config('sendemail.smtpserver');
+}
 if (!$smtp_server) {
        foreach (qw( /usr/sbin/sendmail /usr/lib/sendmail )) {
                if (-x $_) {

(請注意它現在如何位於“正確”的一組線上,對人眼而言)。 對文件所做的更改而言,這兩個差異是等效的,但我們更喜歡第二個差異。 此外,如果git merge正在合並更改,我們更希望git merge看到第二個。

請注意,這只是一種啟發式方法,因此它是否適用於您的特定更改對是另一個問題。 自己運行兩個git diff操作(啟用啟發式,因為它在現代 Git 中默認設置,並使用--no-indent-heuristic關閉它)會告訴你是否這樣做。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM