Làm thế nào để nem git hiển thị một cam kết hợp nhất với đầu ra khác biệt kết hợp ngay cả khi mọi tệp thay đổi đồng ý với một trong các phụ huynh?


184

Sau khi thực hiện hợp nhất "đơn giản" (không có xung đột), git showthường chỉ hiển thị nội dung như

commit 0e1329e551a5700614a2a34d8101e92fd9f2cad6 (HEAD, master)
Merge: fc17405 ee2de56
Author: Tilman Vogel <email@email>
Date:   Tue Feb 22 00:27:17 2011 +0100

Merge branch 'testing' into master

Điều này là do, để hợp nhất, git showsử dụng định dạng diff kết hợp mà bỏ qua các tệp đồng ý với một trong hai phiên bản gốc.

Có cách nào để buộc git vẫn hiển thị tất cả sự khác biệt trong chế độ khác biệt kết hợp không?

Việc thực hiện git show -msẽ cho thấy sự khác biệt (sử dụng khác biệt cặp đôi giữa phiên bản mới và tất cả các phiên bản gốc tương ứng) nhưng tôi thích có sự khác biệt được đánh dấu bởi +/- trong các cột tương ứng như trong chế độ kết hợp.


1
@ Tilman Vogel: vui lòng xem lại câu trả lời được chấp nhận - Có vẻ như có câu trả lời tốt hơn
Jayan

1
@Jaya Mặc dù các câu trả lời khác phổ biến hơn vì chúng chứa các gợi ý hữu ích, nhưng thực tế chúng không tiến gần hơn đến vấn đề của tôi khi chỉ thực hiện các khác biệt hai chiều. Tôi đã tìm kiếm một khác biệt ba chiều.
Tilman Vogel

Câu trả lời:


-3

Không, không có cách nào để làm điều này với git show. Nhưng đôi khi nó chắc chắn sẽ tốt và có thể tương đối dễ thực hiện trong mã nguồn git (sau tất cả, bạn chỉ cần bảo nó không cắt bỏ những gì nó nghĩ là đầu ra không liên quan), vì vậy bản vá phải làm như vậy có lẽ sẽ được chấp nhận bởi những người duy trì git.

Hãy cẩn thận những gì bạn muốn, mặc dù; hợp nhất một chi nhánh với một thay đổi một dòng đã được chia rẽ ba tháng trước vẫn sẽ có một sự khác biệt lớn so với dòng chính, và do đó, một sự khác biệt đầy đủ như vậy sẽ gần như hoàn toàn không có ích. Đó là lý do tại sao git không hiển thị nó.


12
Xin đừng nói "không có cách nào để làm điều này" rõ ràng là có thể - xem các câu trả lời khác. Điều này là rất sai lầm để nói.
kgadek

1
git hiển thị ĐẦU ^ ... ĐẦU; Giải pháp # per @ hesham_EE.
Michael Dimmitt

git hiển thị ĐẦU ~ 1 ... ĐẦU ~ 0 - chỉ tên; # cú pháp tốt hơn. Đối với pr lặp đi lặp lại.
Michael Dimmitt

255

Nhìn vào thông điệp cam kết:

commit 0e1329e551a5700614a2a34d8101e92fd9f2cad6 (HEAD, master)
Merge: fc17405 ee2de56
Author: Tilman Vogel <email@email>
Date:   Tue Feb 22 00:27:17 2011 +0100

Merge branch 'testing' into master

chú ý dòng:

Merge: fc17405 ee2de56

lấy hai id id đó và đảo ngược chúng. Vì vậy, để có được sự khác biệt mà bạn muốn, bạn sẽ làm:

git diff ee2de56..fc17405

để chỉ hiển thị tên của các tệp đã thay đổi:

git diff --name-only ee2de56..fc17405

và để giải nén chúng, bạn có thể thêm phần này vào gitconfig của bạn:

exportfiles = !sh -c 'git diff $0 --name-only | "while read files; do mkdir -p \"$1/$(dirname $files)\"; cp -vf $files $1/$(dirname $files); done"'

sau đó sử dụng nó bằng cách làm:

git exportfiles ee2de56..fc17405 /c/temp/myproject

Cảm ơn lời đề nghị nhưng tôi nghĩ nó không giải quyết được vấn đề của tôi. Do đánh dấu và định dạng bình luận hạn chế, tôi đã thêm nhận xét của mình vào câu trả lời của bạn. Xin lỗi vì điều đó! Cần phải được xem xét lại cho đến khi nhìn thấy.
Tilman Vogel

6
Có vẻ, chỉnh sửa của tôi đã bị từ chối. Tóm lại: Khác biệt của bạn không hiển thị bổ sung đến từ chi nhánh nào. Và bạn không thể phân biệt được những thay đổi đã được thêm vào trong lần thứ hai hoặc bị xóa trong nhánh đầu tiên.
Tilman Vogel

45
Một giải pháp tốt hơn là git diff fc17405...ee2de56- điều này sẽ hiển thị tất cả các thay đổi trên ee2de56 có thể truy cập được từ các cam kết trên fc17405, mà tôi tin là những gì bạn muốn. Lưu ý 3 chấm thay vì hai.
Kris Nuttycombe

1
@KrisNuttycombe 3 chấm và thứ tự. Và bình luận của bạn là những gì tôi đang tìm kiếm, mà tôi nghĩ giống với những gì OP muốn.
Izkata

@KrisNuttycombe Điều này bằng cách nào đó không hoạt động git log, mà vẫn hiển thị tất cả các cam kết, như ..biến thể. .....làm tương tự cho log, nhưng vì diffchúng khác nhau!? Làm thế nào để tôi có được một danh sách các cam kết đã được sáp nhập vào chi nhánh này?
Rudie

77

Một giải pháp tốt hơn (được đề cập bởi @KrisNuttycombe):

git diff fc17405...ee2de56

cho cam kết hợp nhất:

commit 0e1329e551a5700614a2a34d8101e92fd9f2cad6 (HEAD, master)
Merge: fc17405 ee2de56
Author: Tilman Vogel <email@email>
Date:   Tue Feb 22 00:27:17 2011 +0100

để hiển thị tất cả các thay đổi ee2de56có thể truy cập được từ các cam kết trên fc17405. Lưu ý thứ tự của các giá trị băm cam kết - nó giống như được hiển thị trong thông tin hợp nhất:Merge: fc17405 ee2de56

Cũng lưu ý 3 chấm ...thay vì hai !

Để biết danh sách các tập tin đã thay đổi, bạn có thể sử dụng:

git diff fc17405...ee2de56 --name-only

Đây chính xác là những gì tôi đã có sau +1.
geedoubleya

Điều này thực sự cho thấy kết quả của một cuộc xung đột hợp nhất, trong khi câu trả lời khác thì không.
Pod

12

Bạn có thể tạo nhánh với ĐẦU được đặt thành một cam kết trước khi hợp nhất. Sau đó, bạn có thể làm:

git merge --squash testing

Điều này sẽ hợp nhất, nhưng không cam kết. Sau đó:

git diff

5

Có vẻ như đã trả lời ở đây: https://public-inbox.org/git/7vd392ezhx.fsf@alter.siamese.dyndns.org/

Theo cách tương tự, chạy

$ git diff --cc $ M $ M ^ 1 $ M ^ 2 $ (git merge-base $ M ^ 1 $ M ^ 2)

sẽ hiển thị một bản vá kết hợp giải thích trạng thái ở mức $ M so với các trạng thái được ghi trong cha mẹ của nó và cơ sở hợp nhất.


Bạn có biết liệu có công cụ nào có thể được cấu hình để hiển thị một sự khác biệt như vậy theo cách song song, có khả năng trong một vài cột (như trong cửa sổ giải quyết xung đột hợp nhất IntelliJ) không? Câu trả lời của bạn chính xác là tôi đang tìm kiếm
Max

@Max Không tôi sợ tôi không. Googling "n-way visual diff" cung cấp một số liên kết, vì vậy tôi đã thử chúng.
max630

4

Tôi nghĩ bạn chỉ cần 'git show -c $ ref'. Thử điều này trên kho git trên a8e4a59 cho thấy một khác biệt kết hợp (cộng / trừ ký tự trong một trong 2 cột). Như hướng dẫn sử dụng git-show đề cập, khá nhiều đại biểu tham gia 'git diff-tree' để các tùy chọn đó trông hữu ích.


3
Không, đối với hợp nhất "đơn giản", git show -c $refhiển thị cùng một đầu ra như tôi đã trích dẫn, tức là không có sự khác biệt. -cchọn một chế độ khác được kết hợp rất giống với chế độ mặc định cho các cam kết hợp nhất là '--cc', xem git help showgit help diff-tree. Cả hai hoàn toàn bỏ qua các tệp đồng ý với một trong hai phiên bản gốc của tệp đó.
Tilman Vogel

a8e4a59thực sự không thuộc danh mục hợp nhất, ý tôi là vậy. Cam kết hợp nhất này thực sự chứa một tệp khác với cả hai phiên bản mẹ của nó. Documentation/git-fast-import.txtcó một số thứ được thêm vào từ cha mẹ này và một số từ người khác. Điều này dẫn đến đầu ra không trống từ git diff-tree --cc. Tuy nhiên, chỉ những thay đổi trong trường hợp "xung đột" này được hiển thị. Tất cả các kết quả hợp nhất "sạch", nhìn vào git show -m a8e4a59, hoàn toàn không được hiển thị.
Tilman Vogel

1
@TilmanVogel: Cảm ơn bạn đã chỉ ra rằng việc hợp nhất tệp "không thú vị" bị loại khỏi git show -cđầu ra. ( man git-diff-treecó nói "Hơn nữa, nó chỉ liệt kê các tệp đã được sửa đổi từ tất cả các bậc cha mẹ." nhưng tôi chắc chắn đã phát hiện ra điều đó.)
Paul Whittaker

3

trong trường hợp của bạn, bạn chỉ cần

git diff HEAD^ HEAD^2

hoặc chỉ băm cho bạn cam kết:

git diff 0e1329e55^ 0e1329e55^2

4
Không, điều này chỉ khác biệt hai chiều giữa hai cha mẹ. Những gì tôi đã yêu cầu là một chế độ đồng thời hiển thị sự khác biệt giữa git merge-base HEAD^ HEAD^2HEAD^HEAD^2trong cùng một kiểu như được thực hiện cho các tệp được hợp nhất với xung đột.
Tilman Vogel

3

Nếu cam kết hợp nhất của bạn là cam kết 0e1329e5, như trên, bạn có thể nhận được khác biệt được chứa trong hợp nhất này bằng cách:

git diff 0e1329e5^..0e1329e5

Tôi hi vọng cái này giúp được!


3

Nếu bạn đang ngồi ở cam kết hợp nhất thì điều này sẽ hiển thị các khác biệt:

git diff HEAD~1..HEAD

Nếu bạn không ở cam kết hợp nhất thì chỉ cần thay thế CHÍNH bằng cam kết hợp nhất. Phương pháp này có vẻ như đơn giản và trực quan nhất.


1
Đây không phải là đầu ra "khác biệt kết hợp". Nhận khác biệt giữa mỗi cặp cha mẹ và ĐẦU không phải là một vấn đề ở đây.
Tilman Vogel

2

Bạn có thể sử dụng lệnh diff-tree với cờ -c. Lệnh này cho bạn thấy những tập tin đã thay đổi trong cam kết hợp nhất.

git diff-tree -c {merged_commit_sha}

Tôi đã nhận được mô tả cờ -c từ Git-Scm :

Cờ này thay đổi cách hiển thị một cam kết hợp nhất (có nghĩa là nó chỉ hữu ích khi lệnh được đưa ra một, hoặc --stdin). Nó cho thấy sự khác biệt giữa từng cha mẹ với kết quả hợp nhất đồng thời thay vì hiển thị khác nhau theo cặp giữa cha mẹ và kết quả cùng một lúc (đó là những gì tùy chọn -m làm). Hơn nữa, nó chỉ liệt kê các tệp đã được sửa đổi từ tất cả các bậc cha mẹ.


2
Có vẻ như một bài viết hay về chủ đề này: haacked.com/archive/2014/02/21/reviewing-merge-commits và có lẽ điều này cũng vậy: longair.net/blog/2009/04/16/git-fetch-and-merge
Devin G Rhode

1

Tôi đã xây dựng một cách tiếp cận mục đích chung để thực hiện các hoạt động khác nhau trên các cam kết của hợp nhất.

Bước một : Thêm bí danh cho git bằng cách chỉnh sửa ~/.gitconfig:

[alias]
  range = "!. ~/.githelpers && run_on_merge_range"

Bước hai : Trong ~/.githelpers, xác định hàm bash:

run_on_merge_range() {
  cmd=$1; shift
  commit=$1; shift
  range=$(git show $commit | grep Merge: | awk '{print $2 "..." $3}')
  echo "git $cmd $range $@"
  if [ -z $range ]; then
    echo "No merge detected"
    exit 1
  fi
  git $cmd $range $@
}

Bước ba : Lợi nhuận!

git range log <merge SHA> --oneline
git range diff <merge SHA> --reverse -p
git range diff <merge SHA> --name-only

Có lẽ có rất nhiều phòng để cải thiện ở đây, tôi chỉ cần đánh nó với nhau để vượt qua một tình huống khó chịu. Vui lòng chế giễu cú pháp bash và / hoặc logic của tôi.


Lưu ý rằng bạn có thể muốn thay đổi "..." thành ".." trong bit "awk", tùy thuộc vào những gì bạn cần và lệnh nào bạn đang chạy: stackoverflow.com/questions/462974/
Thẻ
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.