Làm thế nào tôi có thể có được một sự khác biệt bên cạnh khi tôi làm điều đó?


163

Khi tôi gõ "git diff", tôi muốn thấy một khác biệt bên cạnh, như với "diff -y" hoặc muốn hiển thị diff trong một công cụ tìm khác biệt tương tác như "kdiff3". Điều này có thể giải quyết như thế nào?



Lưu ý: bạn có một khác biệt bên cạnh trên GitHub .
VonC

Câu trả lời:


89

Mặc dù Git có triển khai nội bộ của diff, thay vào đó bạn có thể thiết lập một công cụ bên ngoài.

Có hai cách khác nhau để chỉ định một công cụ tìm khác biệt bên ngoài:

  1. thiết lập GIT_EXTERNAL_DIFFvà các GIT_DIFF_OPTSbiến môi trường.
  2. cấu hình công cụ tìm khác biệt bên ngoài thông qua git config

Xem thêm:

Khi thực hiện git diff, Git kiểm tra cả cài đặt của các biến môi trường trên và .gitconfigtệp của nó .

Theo mặc định, Git chuyển bảy đối số sau đây cho chương trình diff:

path  old-file  old-hex old-mode  new-file  new-hex new-mode

Bạn thường chỉ cần các tham số tệp cũ và tệp mới. Tất nhiên hầu hết các công cụ diff chỉ lấy hai tên tệp làm đối số. Điều này có nghĩa là bạn cần phải viết một tập lệnh bao bọc nhỏ, lấy các đối số mà Git cung cấp cho tập lệnh và đưa chúng vào chương trình git bên ngoài mà bạn chọn.

Giả sử bạn đặt tập lệnh bao bọc của bạn bên dưới ~/scripts/my_diff.sh:

#!/bin/bash
# un-comment one diff tool you'd like to use

# side-by-side diff with custom options:
# /usr/bin/sdiff -w200 -l "$2" "$5" 

# using kdiff3 as the side-by-side diff:
# /usr/bin/kdiff3 "$2" "$5"

# using Meld 
/usr/bin/meld "$2" "$5"

# using VIM
# /usr/bin/vim -d "$2" "$5"

sau đó bạn cần phải thực hiện tập lệnh đó:

chmod a+x ~/scripts/my_diff.sh

sau đó bạn cần cho Git biết cách và nơi để tìm tập lệnh trình bao khác biệt tùy chỉnh của bạn. Bạn có ba lựa chọn để làm điều đó: (Tôi thích chỉnh sửa tệp .gitconfig)

  1. Sử dụng GIT_EXTERNAL_DIFF,GIT_DIFF_OPTS

    ví dụ: trong tệp .bashrc hoặc .bash_profile bạn có thể đặt:

    GIT_EXTERNAL_DIFF=$HOME/scripts/my_diff.sh
    export GIT_EXTERNAL_DIFF
    
  2. Sử dụng git config

    sử dụng "git config" để xác định nơi có thể tìm thấy tập lệnh trình bao bọc của bạn:

    git config --global diff.external ~/scripts/my_diff.sh
    
  3. Chỉnh sửa ~/.gitconfigtập tin của bạn

    bạn có thể chỉnh sửa ~/.gitconfigtệp của mình để thêm các dòng này:

    [diff]
      external = ~/scripts/my_diff.sh
    

Ghi chú:

Tương tự như việc cài đặt công cụ tìm khác biệt tùy chỉnh của bạn, bạn cũng có thể cài đặt một công cụ hợp nhất tùy chỉnh, có thể là một công cụ hợp nhất trực quan để giúp trực quan hóa việc hợp nhất tốt hơn. (xem trang progit.org)

Xem: http://fredpalma.com/518/visual-diff-and-merge-tool/https://git-scm.com/book/en/v2/Customizing-Git-Git-Configuration


1
Điều này có giữ lại màu thiết bị đầu cuối git?
Sridhar Sarnobat

3
Điều này thật tuyệt, nhưng nó khởi chạy một trình xem mới cho mọi tệp. Bất kỳ cách nào để tạo ra một khác biệt hợp nhất trong, nói , meld?
HRJ

2
@Tilo Tôi đang gặp lỗi cho vim là im: Cảnh báo: Đầu ra không phải là thiết bị đầu cuối
lập trình viên đã chết vào

Có thể meldphiên bản được cấu hình để làm một diff thư mục, nơi tôi có thể chọn (s) tập tin Tôi muốn nhìn thấy các diff cho? Hiện tại nó chạy một meldlệnh riêng cho mỗi tệp và tôi phải thoát meldđể xem tệp tiếp theo. Tôi muốn meldcho tôi xem một danh sách các thư mục thay đổi như nó hoạt động khi meldđược sử dụng từ Mercurial.
kasperd

163

Hãy thử git Difftool

Sử dụng git difftoolthay vì git diff. Bạn sẽ không bao giờ quay trở lại.

CẬP NHẬT để thêm một ví dụ sử dụng:

Đây là một liên kết đến một stackoverflow khác nói về git difftool: Làm cách nào để tôi xem đầu ra 'git diff' với công cụ / trình xem khác nhau ưa thích của tôi?

Đối với các phiên bản mới hơn git, difftoollệnh hỗ trợ nhiều công cụ tìm khác biệt bên ngoài. Ví dụ: vimdiffđược hỗ trợ tự động và có thể được mở từ dòng lệnh bằng cách:

cd /path/to/git/repo
git difftool --tool=vimdiff

Các công cụ khác ngoài được hỗ trợ khác được liệt kê qua git difftool --tool-helpđây là một ví dụ đầu ra:

'git difftool --tool=<tool>' may be set to one of the following:
        araxis
        kompare
        vimdiff
        vimdiff2

The following tools are valid, but not currently available:
        bc3
        codecompare
        deltawalker
        diffuse
        ecmerge
        emerge
        gvimdiff
        gvimdiff2
        kdiff3
        meld
        opendiff
        tkdiff
        xxdiff

34
Hoặc có thể bạn sẽ quay trở lại nếu bạn nhận được This message is displayed because 'diff.tool' is not configured.. Có lẽ cập nhật câu trả lời với cách cấu hình tối thiểu thứ này, để nó hiển thị các khác biệt cạnh nhau trong thiết bị đầu cuối, đó là những gì OP yêu cầu? Các công cụ GUI khá vô dụng trên máy chủ từ xa nơi bạn kết nối bằng ssh.
Petr

1
Điểm thú vị, mặc dù tôi không nghĩ rằng cá nhân tôi đã từng cần sử dụng git trong khi SSH. Một trong những điều tốt đẹp về DVCS là phần Phân tán: ít nhất trong môi trường của tôi, sẽ không bao giờ gặp rắc rối khi sao chép cục bộ bất cứ repo nào tôi muốn chọc vào.
Matt Ball

1
Ít nhất là trong cấu hình của tôi, git difftoolvới vimdiffkhông phải lúc nào xếp hàng hai tập tin / bộ đệm một cách chính xác.
Rohmer

1
Thật tuyệt, và dưới đây trong danh sách câu trả lời: Sử dụng OI git difftool -yđể ngăn chặn dấu nhắc của
tkdiff

Liên quan: làm cho bạn kết hợp git difftooltrong Windows & Linux: stackoverflow.com/a/48979939/4561887
Gabriel Staples

55

Bạn cũng có thể thử git diff --word-diff. Nó không chính xác cạnh nhau, nhưng bằng cách nào đó tốt hơn, vì vậy bạn có thể thích nó hơn nhu cầu bên cạnh thực tế của mình.


12
Đây là cách dễ dàng nhất. Điều tuyệt vời hơn nữa làgit diff --word-diff=color
Rolf

@Rolf --word-diff=colorcho tôi một lỗi tùy chọn không hợp lệ. Phiên bản nào đã được giới thiệu?
Holloway

@Trengot Tôi chạy git 1.7.9, từ ngày 02/2012
Rolf

4
@Rolf phiên bản cài đặt mặc định ở đây là 1.7.1. Có thể giải thích sự khác biệt. git diff --color-wordslàm việc.
Holloway

4
Vâng, git diff --color-wordslà cách để đi trên các phiên bản git hiện đại.
VasiliNovikov

41

ydiff

Trước đây được gọi cdiff, công cụ này có thể hiển thị cạnh nhau , tăng dần và khác biệt đầy màu sắc .

Thay vì làm git diff, hãy làm:

ydiff -s -w0

Điều này sẽ khởi chạy ydiffở chế độ hiển thị song song cho mỗi tệp có sự khác biệt.

Cài đặt với:

python3 -m pip install --user ydiff

-hoặc là-

brew install ydiff

Đối với git log, bạn có thể sử dụng:

ydiff -ls -w0

-w0tự động phát hiện chiều rộng thiết bị đầu cuối của bạn. Xem ydiff trang kho lưu trữ GitHub để biết chi tiết và bản demo.

Đã thử nghiệm trong Git 2.18.0, ydiff 1.1.


@RyneEverett: Bạn có thể giải thích cách làm tương đương git diff | cdiff -svới icdiff không?
einpoklum

Chỉ cần chạy ydiff -stừ không gian làm việc git / svn / hg, bạn không cần phải tham gia.
ymattw

nếu bạn muốn giới hạn độ lệch cho một tệp cụ thể trong lịch sử của Git, cd <git repo>rồi chạyydiff -ls <path/to/file>
slm

22

Bạn có thể thực hiện song song diffbằng cách sử dụng sdiffnhư sau:

$ git difftool -y -x sdiff  HEAD^ | less

đâu HEAD^là một ví dụ mà bạn nên thay thế bằng bất cứ thứ gì bạn muốn khác.

Tôi tìm thấy giải pháp này ở đây , nơi có một vài gợi ý khác. Tuy nhiên, câu trả lời này là câu hỏi của OP ngắn gọn và rõ ràng.

Xem người đàn ông git-Difftool để được giải thích về các đối số.


Lấy ý kiến ​​trên tàu, bạn có thể tạo một git sdifflệnh tiện dụng bằng cách viết tập lệnh thực thi sau:

#!/bin/sh
git difftool -y -x "sdiff -w $(tput cols)" "${@}" | less

Lưu nó như /usr/bin/git-sdiffchmod -xnó. Sau đó, bạn sẽ có thể làm điều này:

$ git sdiff HEAD^

Tôi thường làm "$ git Difftool -x 'sdiff -s -w 240'" (hoặc bất kỳ chiều rộng màn hình nào) nếu / khi tôi muốn triệt tiêu cùng một dòng và chỉ có một tệp (khác tôi làm vimdiff)
HidekiAI

1
@HidekiAI Tôi cảm thấy khó khăn khi gõ chiều rộng thiết bị đầu cuối mỗi lần, vì vậy tôi sử dụng tput colsthay thế, ví dụ : git difftool -x "sdiff -s -w $(tput cols)".
jaume

nó có thể làm nổi bật những thay đổi trong màu sắc? Ngay bây giờ có vẻ như chúng ta phải sử dụng đôi mắt của mình để phát hiện ra những thay đổi thực sự là gì
phân cực

Thay thế sdiff bằng icdiff để có được màn hình màu đẹp.
Greg

10
export GIT_EXTERNAL_DIFF='meld $2 $5; echo >/dev/null'

sau đó chỉ đơn giản là:

git diff

1
'meld.' làm việc quá Và nó hiển thị tất cả các thay đổi trong một cửa sổ hợp nhất.
HRJ

@HRJ hoạt động hoàn hảo! Thật đơn giản và thực tế :)
waldyrious

9

Nếu bạn muốn thấy sự khác biệt song song trong trình duyệt mà không liên quan đến GitHub, bạn có thể thưởng thức git webdiff , một sự thay thế thả xuống cho git diff:

$ pip install webdiff
$ git webdiff

Điều này cung cấp một số lợi thế so với các khác biệt GUI truyền thống như tkdiffở chỗ nó có thể cung cấp cho bạn tô sáng cú pháp và hiển thị các khác biệt hình ảnh.

Đọc thêm về nó ở đây .


7

Tôi sử dụng colordiff .

Trên Mac OS X, cài đặt nó với

$ sudo port install colordiff

Trên Linux có thể apt get install colordiffhoặc một cái gì đó tương tự, tùy thuộc vào bản phân phối của bạn.

Sau đó:

$ git difftool --extcmd="colordiff -ydw" HEAD^ HEAD

Hoặc tạo bí danh

$ git alias diffy "difftool --extcmd=\"colordiff -ydw\""

Sau đó, bạn có thể sử dụng nó

$ git diffy HEAD^ HEAD

Tôi gọi nó là "diffy" bởi vì diff -ykhác biệt bên cạnh trong unix. Colordiff cũng thêm màu sắc, đó là đẹp hơn. Trong tùy chọn -ydw, ydành cho bên cạnh, wlà bỏ qua các khoảng trắng và dlà để tạo ra độ lệch tối thiểu (thường bạn sẽ có kết quả tốt hơn là diff)


thêm -yđể bỏ qua Launch 'colordiff' [Y/n]:lời nhắc.
Beni Cherniavsky-Paskin

bạn có chắc git alias diffy "difftool --extcmd=\"colordiff -ydw\""không Có nên không git config --global alias.diffy "difftool --extcmd=\"colordiff -ydw\""?
phân cực

6

Đối với unix, kết hợp chỉ gitvà tích hợp diff:

git show HEAD:path/to/file | diff -y - path/to/file

Tất nhiên, bạn có thể thay thế HEAD bằng bất kỳ tham chiếu git nào khác và có lẽ bạn muốn thêm một cái gì đó giống như -W 170vào lệnh diff.

Điều này giả định rằng bạn chỉ đang so sánh nội dung thư mục của bạn với một cam kết trong quá khứ. So sánh giữa hai cam kết phức tạp hơn. Nếu vỏ của bạn là bashbạn có thể sử dụng "quá trình thay thế":

diff -y -W 170 <(git show REF1:path/to/file) <(git show REF2:path/to/file)

trong đó REF1REF2là các tham chiếu git - thẻ, nhánh hoặc băm.


Cảm ơn - lệnh của bạn 'git show HEAD: path / to / file' là những gì tôi cần để đưa ra giải pháp của riêng mình, 'vimdfiff <(git show HEAD: path / to / file) path / to / file'. Các bit vẫn không được xếp chính xác, nhưng đó là giải pháp tốt nhất tôi có ngay bây giờ.
Talexb

5

Cá nhân tôi thực sự thích icdiff !

Nếu bạn đang ở Mac OS Xvới HomeBrew, chỉ cần làm brew install icdiff.

Để có được nhãn tệp chính xác, cộng với các tính năng thú vị khác, tôi có trong ~/.gitconfig:

[pager]
    difftool = true
[diff]
    tool = icdiff
[difftool "icdiff"]
    cmd = icdiff --head=5000 --highlight --line-numbers -L \"$BASE\" -L \"$REMOTE\" \"$LOCAL\" \"$REMOTE\"

Và tôi sử dụng nó như: git difftool


3

Câu hỏi này xuất hiện khi tôi đang tìm kiếm một cách nhanh chóng để sử dụng cách tích hợp git để xác định vị trí khác biệt. Tiêu chí giải pháp của tôi:

  • Khởi động nhanh, tùy chọn dựng sẵn cần thiết
  • Có thể xử lý nhiều định dạng dễ dàng, xml, các ngôn ngữ lập trình khác nhau
  • Nhanh chóng xác định các thay đổi mã nhỏ trong tệp văn bản lớn

Tôi tìm thấy câu trả lời này để có được màu trong git.

Để có được sự khác biệt bên cạnh thay vì dòng khác nhau, tôi đã điều chỉnh câu trả lời tuyệt vời của mb14 cho câu hỏi này với các tham số sau:

$ git diff --word-diff-regex="[A-Za-z0-9. ]|[^[:space:]]"

Nếu bạn không thích thêm [- hoặc {+ tùy chọn --word-diff=colorcó thể được sử dụng.

$ git diff --word-diff-regex="[A-Za-z0-9. ]|[^[:space:]]" --word-diff=color

Điều đó đã giúp có được sự so sánh phù hợp với cả mã json và xml và mã java.

Tóm lại, các --word-diff-regextùy chọn có khả năng hiển thị hữu ích cùng với cài đặt màu để có được trải nghiệm mã nguồn được tô màu cạnh nhau so với khác biệt dòng tiêu chuẩn, khi duyệt qua các tệp lớn có thay đổi dòng nhỏ.


3

Một số người khác đã đề cập đến cdiff cho git side-side diffing nhưng không ai đưa ra cách thực hiện đầy đủ.

Cài đặt cdiff:

git clone https://github.com/ymattw/cdiff.git
cd cdiff
ln -s `pwd`/cdiff ~/bin/cdiff
hash -r # refresh your PATH executable in bash (or 'rehash' if you use tcsh)
        # or just create a new terminal

Chỉnh sửa ~ / .gitconfig chèn các dòng này:

[pager]
        diff = false
        show = false

[diff]
        tool = cdiff
        external = "cdiff -s $2 $5 #"

[difftool "cdiff"]
        cmd = cdiff -s \"$LOCAL\" \"$REMOTE\"

[alias]
        showw = show --ext-dif

Máy nhắn tin tắt là cần thiết để cdiff hoạt động với Diff, dù sao nó cũng là máy nhắn tin nên điều này vẫn ổn. Difftool sẽ hoạt động bất kể các cài đặt này.

Bí danh hiển thị là cần thiết vì git show chỉ hỗ trợ các công cụ tìm khác biệt bên ngoài thông qua đối số.

'#' Ở cuối lệnh diff khác là quan trọng. Lệnh diff của Git nối thêm $ @ (tất cả các biến diff có sẵn) vào lệnh diff, nhưng chúng tôi chỉ muốn hai tên tệp. Vì vậy, chúng tôi gọi hai người đó một cách rõ ràng với $ 2 và $ 5, và sau đó ẩn $ @ đằng sau một nhận xét có thể gây nhầm lẫn cho sdiff. Kết quả là một lỗi trông giống như:

fatal: <FILENAME>: no such path in the working tree
Use 'git <command> -- <path>...' to specify paths that do not exist locally.

Các lệnh Git hiện tạo độ lệch cạnh nhau:

git diff <SHA1> <SHA2> 
git difftool <SHA1> <SHA2>
git showw <SHA>

Sử dụng Cdiff:

'SPACEBAR' - Advances the page of the current file.
'Q'        - Quits current file, thus advancing you to the next file.

Bây giờ bạn có diff khác nhau thông qua git diff và Difftool. Và bạn có mã nguồn python cdiff để tùy biến người dùng quyền lực nếu bạn cần nó.


2

Đây là một cách tiếp cận. Nếu bạn chuyển qua ít hơn, chiều rộng xterm được đặt thành 80, không quá nóng. Nhưng nếu bạn tiến hành lệnh với, ví dụ: COLS = 210, bạn có thể sử dụng xterm mở rộng của mình.

gitdiff()
{
    local width=${COLS:-$(tput cols)}
    GIT_EXTERNAL_DIFF="diff -yW$width \$2 \$5; echo >/dev/null" git diff "$@"
}

1
Buồn cười. Tôi đã ký tên bằng một bút danh nhưng điều đó đã bị bỏ qua ... Cảm ơn vì đã vượt qua tôi, Stack Overflow. :(
Thomas Mellman

2

Mở Intellij IDEA , chọn một hoặc nhiều cam kết trong cửa sổ công cụ "Kiểm soát phiên bản", duyệt các tệp đã thay đổi và nhấp đúp vào chúng để kiểm tra các thay đổi cạnh nhau cho mỗi tệp.

Với trình khởi chạy dòng lệnh kèm theo, bạn có thể mang IDEA lên bất cứ nơi nào một cách đơn giản idea some/path

xem kiểm soát phiên bản khác biệt


1

Có rất nhiều câu trả lời tốt về chủ đề này. Giải pháp của tôi cho vấn đề này là viết một kịch bản.

Đặt tên này là 'git-scriptname' (và làm cho nó có thể thực thi được và đặt nó vào PATH của bạn, giống như bất kỳ tập lệnh nào) và bạn có thể gọi nó như một lệnh git bình thường bằng cách chạy

$ git scriptname

Các chức năng thực tế chỉ là dòng cuối cùng. Đây là nguồn:

#!/usr/bin/env zsh
#
#   Show a side-by-side diff of a particular file how it currently exists between:
#       * the file system
#       * in HEAD (latest committed changes)

function usage() {
    cat <<-HERE
    USAGE

    $(basename $1) <file>

    Show a side-by-side diff of a particular file between the current versions:

        * on the file system (latest edited changes)
        * in HEAD (latest committed changes)

HERE
}

if [[ $# = 0 ]]; then
    usage $0
    exit
fi

file=$1
diff -y =(git show HEAD:$file) $file | pygmentize -g | less -R

1

Đây có thể là một giải pháp hơi hạn chế, nhưng thực hiện công việc bằng cách sử dụng difflệnh của hệ thống mà không cần các công cụ bên ngoài:

diff -y  <(git show from-rev:the/file/path) <(git show to-rev:the/file/path)
  • chỉ lọc các dòng thay đổi sử dụng --suppress-common-lines(nếu bạn diffhỗ trợ tùy chọn).
  • không có màu trong trường hợp này, chỉ là các diffdấu thông thường
  • có thể điều chỉnh độ rộng cột --width=term-width; trong Bash có thể lấy chiều rộng bằng $COLUMNShoặc tput cols.

Điều này có thể được gói vào một tập lệnh git helper để thuận tiện hơn, ví dụ, cách sử dụng như thế này:

git diffy the/file/path --from rev1 --to rev2
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.