İki taahhüt arasındaki değişiklikleri, arada olmayan taahhütler nasıl görebilirim?


642

git diffAradaki diğer taahhütler hariç olmak üzere, yalnızca iki taahhüt arasındaki farkı nasıl gösterebilirsiniz?


15
"git diff" her zaman iki işlem arasındaki farkı gösterir (veya commit ve working directory, vb.).
Jakub Narębski

21
@ JakubNarębski, bir komutun getirdiği değişiklikler ile başka bir işlemin getirdiği değişiklikler arasındaki farkı nasıl göreceğini soruyor. Başka bir deyişle, diffs veya interdiff farkı.
psusi

1
ve diff komutuna --dirstat = files parametresi eklerseniz, değiştirilen projelerin ve dosyaların değişiklik yüzdesiyle birlikte bir değişim yüzdesi ile ilgili çok güzel bir ekran görüntüsü alacaksınız. Bunun gibi: git diff [işlem numarası] [işlem numarası] --dirstat = dosya
Ibáñez Fernández

Yanıtlar:


605

git farkına 2 taahhüdü geçebilirsiniz:

-> git diff 0da94be  59ff30c > my.patch
-> git apply my.patch

1
Bu benim için çalıştı, ama şimdi, my.patchDiğer şubeye nasıl başvurabilirim ?
nacho4d

2
@ nacho4d: git checkout diğer şube && git uygula my.patch && git add. && git commit -am "Mesaj"
Felix Rabe

1
Git Apply vs. patch kullanmanın avantajı, git'e özgü yeniden adlandırmalar ve diğer bazı değişiklikleri dahil edebilmenizdir. Git format-patch ve git am kullanmayı seviyorum.
Russell

58
Bu cevap soruyu tamamen ele almıyor, bu yüzden neden bu kadar çok oyu olduğu hakkında hiçbir fikrim yok. OP, ilk komutu verdiğinizi nasıl alacağınızı soruyor ve ikincisinin hiçbir şeyle ilgisi yok.
psusi

3
Bu cevap hiçbir şeye cevap vermiyor. Mükemmel çalışıyor. Söz konusu iki taahhüdün sonrasından ayrılırsanız, bu farkı yeni şubeye uygularsanız, aralıklı taahhütlerin baş ağrısı olmadan iki taahhüt arasındaki değişiklikleri göreceksiniz.
Craig Labenz

142

Aradaki taahhütleri dahil etmeden / iki / iki komisyon arasındaki farkı sormak çok az mantıklıdır. Taahhütler sadece deponun içeriğinin anlık görüntüleridir; ikisi arasındaki farkı sormak zorunlu olarak onları içerir. O zaman soru şu ki, gerçekten ne arıyorsun?

William'ın önerdiği gibi, kiraz toplama, bir diğerinin üstüne yeniden yerleştirilmiş tek bir taahhüdün deltasını verebilir. Yani:

$ git checkout 012345
$ git cherry-pick -n abcdef
$ git diff --cached

Bu, 'abcdef' taahhüdünü alır, onu doğrudan atalarıyla karşılaştırır, ardından bu farkı '012345' üzerine uygular . Bu yeni fark daha sonra gösterilir - tek değişiklik, bağlamın 'abcdef'in yakın atalarından ziyade' 012345'ten gelmesidir. Tabii ki, çatışmalar vb. Alabilirsiniz, bu yüzden çoğu durumda çok yararlı bir süreç değildir.

Sadece abcdef ile ilgileniyorsanız, şunları yapabilirsiniz:

$ git log -u -1 abcdef

Bu, abcdef'i tek başına doğrudan atasıyla karşılaştırır ve genellikle istediğiniz şeydir.

Ve tabi ki

$ git diff 012345..abcdef

size bu iki taahhüt arasındaki tüm farklılıkları verir.

Neyi başarmaya çalıştığınız hakkında daha iyi bir fikir edinmenize yardımcı olabilir - bahsettiğim gibi, aralarında olmayan iki komisyon arasındaki farkı istemek aslında mantıklı değil.


41
Genel olarak, iki taahhüdü karşılaştırmanın pek mantıklı olmadığını kabul edeceğim. Ama git size nasıl düşünmeniz gerektiğini söylememede çok iyidir. Her biri aynı dosya kümelerinde aynı değişiklikleri yapıyormuş gibi görünen farklı taahhütlere sahip iki dalınız olduğunu varsayalım. Git bu iki yamanın aynı olup olmadığını gözlerime güvenmek zorunda kalmadan söylemek için kullanabilirsiniz. Sanırım bu konuda fayda var.
Chris Cleeland

9
@ChrisCleeland, interdiff yardımcı programı bu durumda kullanışlı olabilir. Her bir taahhüdün farkını hemen üst ebeveyne göre almak için git diff kullanın, sonra farkları karşılaştırmak için interdiff kullanın.
bdonlan

3
@ChrisCleeland, git yamaları saklamaz. Dosya içeriğini depolar. Delta kullanan bir sıkıştırma şemasına sahiptir, ancak delta kaynaklarının dosyaların gerçek geçmişi ile ilintili olması gerekmez.
bdonlan

11
Kendi dallarındaki diğer taahhütler hariç olmak üzere iki taahhüt arasındaki fark mükemmel bir anlam ifade eder: bir taahhüt diğerinden kiraz seçildi, ancak bazı ince farklılıklar olabilir. İki dal arasında farklı olan tüm diğer ilgisiz saçmalıklar ile darmadağın olmadan ne olduklarını görmek istersiniz.
psusi

2
Veya ana öğeyi bir özellik dalına yeniden oluşturduğunuzu ve çakışmaları çözmeniz gerektiğini söyleyin. Daha sonra karşılaştırmak origin/featurebranch#HEAD, local/featurebranch#HEADçatışma çözümü sırasında hiçbir şeyi kaçırmamanıza yardımcı olabilir.
lefnire

91

12345 ve abcdef iki düzeltme ekini yama olarak karşılaştırmak için diff komutunu aşağıdaki gibi kullanabilirsiniz:

diff <(git show 123456) <(git show abcdef)

8
Neden git ile GNU diff kullanıyorsunuz?
OneOfOne

7
@OneOfOne git diff <(git show 123456) <(git show abcdef)çalışmıyor; diff <(...) <(...)yapar. (Sadece denedim).
Menachem

@Menachem git diff 123456 abcdef.
OneOfOne

15
@OneOfOne Bu aynı şeyi yapmaz. Önerdiğiniz şey , her bir taahhüdün ağaçlarını tek bir yama göstererek karşılaştırır . Ben (ve @plexoos) ne yaptığımız , her biri ayrı taahhütlerle tanıtılan iki yamayı , diğer bir deyişle diffçıktıyı iki diffs'den karşılaştırıyor. Bu, iki giriş akışının okunmasını ve karşılaştırılmasını içerir. diff(GNU veya Unix diff) bunu git diffyapabilirken yapamaz. Bazıları bunu neden yapmak isteyebilir. Şu anda bunu yapmanın tam ortasındayım, kötü giden bir birleşmeyi temizliyorum.
Menachem

1
git farkındaki tüm meta verilerin gnu farkını içermeyecek mi?
joelb

61
git diff <a-commit> <another-commit> path

Misal:

git diff commit1 commit2 config/routes.rb

Bu dosyadaki taahhütler arasındaki farkı gösterir.


24

Tüm değişiklikleri kontrol etmek için:

  git diff <commit_Id_1> <commit_Id_2>

Yalnızca değiştirilen / eklenen / silinen dosyaları kontrol etmek için:

  git diff <commit_Id_1> <commit_Id_2> --name-only

NOT : Aralarında kesinti olmadan fark kontrolü için, taahhüt kimliklerini girmenize gerek yoktur.


20

Diyelim ki buna sahipsin

A
|
B    A0
|    |
C    D
\   /
  |
 ...

Ve bununla Aaynı olduğundan emin olmak istiyorsun A0.

Bu hile yapacak:

$ git diff B A > B-A.diff
$ git diff D A0 > D-A0.diff
$ diff B-A.diff D-A0.diff

3
@Plexoos'un yanıtı gibi tek astar olarak da kısaltılabilir : diff <(git diff B A) <(git diff D A0)(git show ile aynı sonuç)
pogosama

14

012345 ve abcdef komutları arasındaki farkı görmek istediğinizi varsayalım. Aşağıdakiler istediğinizi yapmalıdır:

$ git ödeme 012345
$ git cherry-pick -n Instagram Hesabındaki Resim ve Videoları abcdef
$ git diff --cached

Teşekkürler, ezme işleminden sonra sonucunuzu kontrol etmek iyi bir fikirdir. Örneğin, şubenizi ezilmemiş taahhütlerle kontrol edebilir ve kiraz, ezilmiş taahhüdünüzü etkileşimli rebase ile her şeyin pürüzsüz olup olmadığını görmek için seçebilirsiniz. Ayrıca usta dalın önüne geçtiğinde.
akostadinov

10

Peki buna ne dersin:

git diff abcdef 123456 | less

Anında birçok farklı diffs karşılaştırmak istiyorsanız sadece daha az boru ile kullanışlı.


6

Git 2.19'dan bu yana şunları kullanabilirsiniz:

git range-diff rev1...rev2 - ortak atalarından başlayarak iki taahhüt ağacını karşılaştırın

veya git range-diff rev1~..rev1 rev2~..rev2 - verilen 2 taahhüt tarafından getirilen değişikliklerin karşılaştırılması


4

Benim aliasayarlar ~/.bashrciçin dosyanın git diff:

alias gdca='git diff --cached' # diff between your staged file and the last commit
alias gdcc='git diff HEAD{,^}' # diff between your latest two commits

2

Benim aliasayarlar ~/.zshrciçin dosyanın git diff:

alias gdf='git diff HEAD{'^',}' # diff between your recent tow commits

Teşekkürler @Jinmiao Luo


git diff HEAD~2 HEAD

son 2. taahhüt ve akım arasında tam bir değişiklik.

HEAD uygun


1

Ben iki taahhüt arasında fark görüntüler, Ubuntu iyi çalışır bir senaryo yazdı.

https://gist.github.com/jacobabrahamb4/a60624d6274ece7a0bd2d141b53407bc

#!/usr/bin/env python
import sys, subprocess, os

TOOLS = ['bcompare', 'meld']

def getTool():
    for tool in TOOLS:
        try:
            out = subprocess.check_output(['which', tool]).strip()
            if tool in out:
                return tool
        except subprocess.CalledProcessError:
            pass
    return None

def printUsageAndExit():
    print 'Usage: python bdiff.py <project> <commit_one> <commit_two>'
    print 'Example: python bdiff.py <project> 0 1'
    print 'Example: python bdiff.py <project> fhejk7fe d78ewg9we'
    print 'Example: python bdiff.py <project> 0 d78ewg9we'
    sys.exit(0)

def getCommitIds(name, first, second):
    commit1 = None
    commit2 = None
    try:
        first_index = int(first) - 1
        second_index = int(second) - 1
        if int(first) < 0 or int(second) < 0:
            print "Cannot handle negative values: "
            sys.exit(0)
        logs = subprocess.check_output(['git', '-C', name, 'log', '--oneline', '--reverse']).split('\n')
        if first_index >= 0:
            commit1 = logs[first_index].split(' ')[0]
        if second_index >= 0:
            commit2 = logs[second_index].split(' ')[0]
    except ValueError:
        if first != '0':
            commit1 = first
        if second != '0':
            commit2 = second
    return commit1, commit2

def validateCommitIds(name, commit1, commit2):
    if commit1 == None and commit2 == None:
        print "Nothing to do, exit!"
        return False
    try:
        if commit1 != None:
            subprocess.check_output(['git', '-C', name, 'cat-file', '-t', commit1]).strip()
        if commit2 != None:
            subprocess.check_output(['git', '-C', name, 'cat-file', '-t', commit2]).strip()
    except subprocess.CalledProcessError:
        return False
    return True

def cleanup(commit1, commit2):
        subprocess.check_output(['rm', '-rf', '/tmp/'+(commit1 if commit1 != None else '0'), '/tmp/'+(commit2 if commit2 != None else '0')])

def checkoutCommit(name, commit):
    if commit != None:
        subprocess.check_output(['git', 'clone', name, '/tmp/'+commit])
        subprocess.check_output(['git', '-C', '/tmp/'+commit, 'checkout', commit])
    else:
        subprocess.check_output(['mkdir', '/tmp/0'])

def compare(tool, commit1, commit2):
        subprocess.check_output([tool, '/tmp/'+(commit1 if commit1 != None else '0'), '/tmp/'+(commit2 if commit2 != None else '0')])

if __name__=='__main__':
    tool = getTool()
    if tool == None:
        print "No GUI diff tools"
        sys.exit(0)
    if len(sys.argv) != 4:
        printUsageAndExit()

    name, first, second = None, 0, 0
    try:
        name, first, second = sys.argv[1], sys.argv[2], sys.argv[3]
    except IndexError:
        printUsageAndExit()

    commit1, commit2 = getCommitIds(name, first, second)

    if not validateCommitIds(name, commit1, commit2):
        sys.exit(0)

    cleanup(commit1, commit2)
    checkoutCommit(name, commit1)
    checkoutCommit(name, commit2)

    try:
        compare(tool, commit1, commit2)
    except KeyboardInterrupt:
        pass
    finally:
        cleanup(commit1, commit2)
    sys.exit(0)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.