Làm thế nào để tìm một cam kết với cha mẹ của nó?


460

Ngoài việc viết một bí danh hoặc tập lệnh, có một lệnh ngắn hơn để nhận khác biệt cho một cam kết cụ thể không?

git diff 15dc8^..15dc8

Nếu bạn chỉ cung cấp id xác nhận duy nhất git diff 15dc8, nó sẽ khác với cam kết đó.


Điều thú vị nhất về điều này là nó sẽ hoạt động với "git Difftool", sử dụng các công cụ để hiển thị diff.
orip

Để tham khảo, câu trả lời cho câu hỏi khác này minh họa cách bạn có thể thiết lập bí danh được cung cấp bởi bash để đơn giản hóa phần trên: stackoverflow.com/questions/3321492/ Lỗi
Nick

Câu trả lời:


641

Sử dụng git show $COMMIT. Nó sẽ hiển thị cho bạn thông điệp tường trình cho cam kết và khác biệt của cam kết cụ thể đó.


45
Quá tệ, nó không thể sử dụng Difftool :(
orip

1
@orip bạn luôn có thể đặt GIT_EXTERNAL_DIFF thành một tập lệnh thực hiện điều tương tự như Difftool của bạn.
Slacy

7
Tôi thích câu trả lời của JakubNarebski, vì biểu thức cam kết được đưa ra sẽ hoạt động trong nhiều ngữ cảnh: stackoverflow.com/a/449128/992887
RichVel

1
Nếu không có khác biệt được hiển thị, có thể không có thay đổi thực tế, như đối với một cam kết hợp nhất
Devin G Rhode

6
@PTWithy: Câu hỏi là "Có lệnh nào ngắn hơn để nhận khác biệt cho một cam kết cụ thể không?", Câu hỏi này trả lời.
mipadi

439

Sử dụng:

git diff 15dc8^!

như được mô tả trong đoạn sau của trang git-rev-parse (1) (hoặc trong trang gitrevutions hiện đại (7) ):

Hai cách viết tắt khác để đặt tên cho một tập hợp được hình thành bởi một cam kết và các cam kết mẹ của nó tồn tại. Ký hiệu r1 ^ @ có nghĩa là tất cả cha mẹ của r1. r1 ^! bao gồm cam kết r1 nhưng không bao gồm tất cả cha mẹ của nó.

Điều này có nghĩa là bạn có thể sử dụng 15dc8^!như một tốc ký cho 15dc8^..15dc8bất cứ nơi nào trong git nơi cần sửa đổi. Đối với lệnh diff , git diff 15dc8^..15dc8được hiểu là git diff 15dc8^ 15dc8, có nghĩa là sự khác biệt giữa cha mẹ của commit ( 15dc8^) và commit ( 15dc8).

Lưu ý : phần mô tả trong git-rev-parse(1)manpage nói về phạm vi sửa đổi , nơi nó cũng cần hoạt động cho các cam kết hợp nhất, với nhiều hơn một phụ huynh. Sau đó r1^!là " r1 --not r1^@" tức là " r1 ^r1^1 ^r1^2 ..."


Ngoài ra, bạn có thể sử dụng git show COMMITđể có được mô tả cam kết và khác biệt cho một cam kết. Nếu bạn chỉ muốn khác, bạn có thể sử dụnggit diff-tree -p COMMIT


7
Đây phải là câu trả lời được chấp nhận, nó gọn gàng hơn nhiều. Tuy nhiên, câu cuối cùng của trích xuất git-rev-parse khá khó hiểu - có vẻ như nó có nghĩa là 'phạm vi từ cha mẹ của cam kết này đến cam kết này'.
RichVel

1
@RichVel: hơi khó hiểu vì nó cũng cố gắng mô tả tình huống trong đó cam kết có nhiều hơn một cha mẹ (là một cam kết hợp nhất). r1 ^! Làm việc như mong đợi cũng vậy.
Jakub Narębski

@ JakubNarębski: điểm tốt, có lẽ bạn có thể chỉnh sửa câu trả lời của mình để tóm tắt sự hiểu biết của bạn về các trường hợp cha mẹ đơn thân và nhiều phụ huynh - mỗi câu có thể dễ hiểu hơn.
RichVel

1
@ JakubNarębski: vâng, tốt hơn nhiều! Bây giờ tôi sử dụng phím tắt này mọi lúc - cảm ơn.
RichVel

1
Các ^!ký hiệu viết tắt cha mẹ làm việc đúng với difftool cho các cam kết bình thường nhưng diff được đảo ngược cho các cam kết hợp nhất. Tại sao như vậy?
hIpPy

56

Nếu bạn biết khoảng cách bao xa, bạn có thể thử một cái gì đó như:

# Current branch vs. parent
git diff HEAD^ HEAD

# Current branch, diff between commits 2 and 3 times back
git diff HEAD~3 HEAD~2

Cam kết trước làm việc như thế này:

# Parent of HEAD
git show HEAD^1

# Grandparent
git show HEAD^2

Có rất nhiều cách bạn có thể chỉ định các cam kết:

# Great grandparent
git show HEAD~3

Xem trang này để biết chi tiết .


2
TRƯỚC ^ 2 không phải là ông bà, nếu TRƯỚC ^ 1 là bố, thì TRƯỚC ^ 2 là mẹ. Sử dụng ĐẦU ~ 2 cho bố của bố.
Binary

11

Như @mipadi chỉ ra, bạn có thể sử dụng git show $COMMIT, nhưng điều này cũng hiển thị một số tiêu đề và thông báo cam kết. Nếu bạn muốn một khác biệt thẳng, sử dụng git show --pretty=format:%b $COMMIT.

Đây rõ ràng không phải là một bàn tay quá ngắn, vì vậy tôi đang giữ bí danh này trong .gitconfig của mình

    [alias]
      sd = show --pretty=format:%b

Điều này cho phép tôi sử dụng git sd $COMMITđể hiển thị khác .


1
Bí danh này có thể bao gồm --color giúp dễ đọc hơn: sd = show --color --pretty = format:% b
RichVel

@RichVel Thật vậy! Điểm rất tốt. Nếu bạn có màu được bật theo mặc định trong git, bạn sẽ không cần công tắc này. Đó là những gì tôi thường làm.
Øystein Steimler

5

Nhiều ví dụ được đề cập (ví dụ: git diff 15dc8^!hoặc git diff 15dc8^..15dc8) không hoạt động nếu bạn đang sử dụng zsh và có extendedglobtùy chọn được đặt. Bạn có thể sửa nó bằng một trong ba cách sau:

  1. unsetopt extendedglob (và / hoặc xóa nó khỏi .zshrc)

  2. setopt NO_NOMATCH (và / hoặc đặt nó trong .zshrc)

  3. thoát khỏi dấu mũ và đập mỗi lần bằng dấu gạch chéo ngược, vd git diff 15dc8\^\!



2

Giải pháp của Paul ở trên đã làm những gì tôi đã hy vọng nó sẽ.

$ git diff HEAD^1

Ngoài ra, rất hữu ích khi thêm các bí danh như hobs đã đề cập, nếu bạn đặt phần sau vào phần [bí danh] trong tệp ~ / .gitconfig thì bạn có thể sử dụng tay ngắn để xem khác biệt giữa đầu và trước đó.

[alias]
    diff-last = diff HEAD^1

Sau đó, chạy $ git diff-last sẽ giúp bạn có kết quả. Lưu ý rằng điều này cũng sẽ bao gồm bất kỳ thay đổi nào bạn chưa cam kết cũng như khác biệt giữa các lần xác nhận. Nếu bạn muốn bỏ qua các thay đổi mà bạn chưa cam kết, thì bạn có thể sử dụng diff để so sánh trực tiếp với CHÍNH với cha mẹ của nó:

$ git diff HEAD^1 HEAD

0

Sử dụng bí danh, vì vậy không trả lời chính xác câu hỏi của bạn nhưng tôi thấy chúng hữu ích cho việc thực hiện những gì bạn dự định ...

alias gitdiff-1="git log --reverse|grep commit|cut -d ' ' -f2|tail -n 2|head -n 2|xargs echo|sed -e 's/\s/../'|xargs -n 1 git diff"
alias gitdiff-2="git log --reverse|grep commit|cut -d ' ' -f2|tail -n 3|head -n 2|xargs echo|sed -e 's/\s/../'|xargs -n 1 git diff"
alias gitdiff-3="git log --reverse|grep commit|cut -d ' ' -f2|tail -n 4|head -n 2|xargs echo|sed -e 's/\s/../'|xargs -n 1 git diff"

alias gitlog-1="git log --reverse|grep commit|cut -d ' ' -f2|tail -n 2|head -n 2|xargs echo|sed -e 's/\s/../'|xargs -n 1 git log --summary"
alias gitlog-2="git log --reverse|grep commit|cut -d ' ' -f2|tail -n 3|head -n 2|xargs echo|sed -e 's/\s/../'|xargs -n 1 git log --summary"
alias gitlog-3="git log --reverse|grep commit|cut -d ' ' -f2|tail -n 4|head -n 2|xargs echo|sed -e 's/\s/../'|xargs -n 1 git log --summary"
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.