Bisakah saya menggunakan git diff pada file yang tidak dilacak?

270

Apakah mungkin untuk meminta git diff untuk memasukkan file yang tidak terlacak dalam output diffnya? Atau taruhan terbaik saya untuk menambahkan file baru yang saya buat dan file yang sudah saya edit, dan gunakan

git diff --cached

?

Andrew Grimm
sumber

Jawaban:

267

Dengan versi git terbaru Anda dapat git add -Nfile (atau --intent-to-add), yang menambahkan gumpalan panjang nol ke indeks di lokasi itu. Hasilnya adalah bahwa file Anda "tidak terlacak" sekarang menjadi modifikasi untuk menambahkan semua konten ke file panjang nol ini, dan itu muncul dalam output "git diff".

git diff

echo "this is a new file" > new.txt
git diff

git add -N new.txt
git diff
diff --git a/new.txt b/new.txt
index e69de29..3b2aed8 100644
--- a/new.txt
+++ b/new.txt
@@ -0,0 +1 @@
+this is a new file

Sayangnya, seperti yang ditunjukkan, Anda tidak dapat git stashsementara Anda memiliki --intent-to-addfile yang tertunda seperti ini. Meskipun jika Anda perlu menyimpan, Anda cukup menambahkan file baru dan menyimpannya. Atau Anda dapat menggunakan solusi emulasi:

git update-index --add --cacheinfo \
100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 new.txt

(menyiapkan alias adalah teman Anda di sini).

araqnid
sumber
Ternyata salinan Git saya tidak cukup baru untuk ditambahkan -N, tetapi ini menjawab pertanyaan saya.
Andrew Grimm
1
Anda dapat meniru "git add -N new.txt" dengan "git update-index --add --cacheinfo 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 new.txt" (bagaimana saya bisa mengatur ini pada jawaban yang salah?)
araqnid
1
bagaimana jika Anda memiliki banyak file baru, adakah cara mudah untuk menambahkan semuanya lalu berbeda?
Vic
1
@Vicgit add -N .
Nathan
92

Saya percaya Anda bisa berbeda terhadap file dalam indeks Anda dan file yang tidak terlacak dengan hanya menyediakan path ke kedua file.

git diff --no-index tracked_file untracked_file
Harold
sumber
3
Apakah itu berfungsi jika Anda memiliki lebih dari satu file yang tidak terlacak yang Anda buat sejak komit terakhir?
Andrew Grimm
12
Ya, jawaban sempurna! Saya kemudian dapat menggunakan git diff --no-index untracked_file_1 untracked_file_2untuk mendapatkan git diffpewarnaan sintaks dll di diffs ... indah.
Colin D Bennett
40
Saya tidak mengerti mengapa Anda membandingkan file yang dilacak dengan file yang tidak dilacak yang tidak terkait. Jika Anda hanya ingin mendapatkan output diff untuk file tidak terlacak, Anda hanya dapat menggunakan /dev/nullgantinya: git diff --no-index -- /dev/null <untracked_file>.
4
Atau adil cat untracked_file_1, atau mungkin printf '\e[1;32m%s\e[0m\n' "$(cat untracked_file_1)"jika Anda benar-benar membutuhkan keluaran ramah lingkungan. :) (Meskipun pada catatan yang lebih serius, harap perhatikan bahwa penggantian perintah akan menghapus baris baru dari file Anda.)
Wildcard
8
Ini harus menjadi jawaban yang diterima - tidak perlu mengubah indeks git; yang seperti yang dikatakan penulis asli, memiliki sisi buruknya
DIMMSum
38

Untuk gitting interaktif saya sehari-hari (di mana saya melakukan diff pohon kerja terhadap HEAD sepanjang waktu, dan ingin agar file yang tidak terlacak dimasukkan ke dalam diff), add -N/--intent-to-addtidak dapat digunakan, karena rusak git stash .

Jadi, inilah git diffpengganti saya . Ini bukan solusi yang sangat bersih, tetapi karena saya benar-benar hanya menggunakannya secara interaktif, saya setuju dengan peretasan:

d() {
    if test "$#" = 0; then
        (
            git diff --color
            git ls-files --others --exclude-standard |
                while read -r i; do git diff --color -- /dev/null "$i"; done
        ) | `git config --get core.pager`
    else
        git diff "$@"
    fi
}

Mengetik hanya dakan memasukkan file yang tidak terlacak dalam diff (yang merupakan hal yang saya pedulikan dalam alur kerja saya), dan d args...akan berperilaku seperti biasa git diff.

Catatan:

  • Kami menggunakan fakta di sini yang git diffbenar-benar hanya perbedaan individual yang disatukan, jadi tidak mungkin untuk mengetahui dkeluaran dari "perbedaan nyata" - kecuali fakta bahwa semua file yang tidak terlacak disortir terakhir.
  • Satu-satunya masalah dengan fungsi ini adalah bahwa output berwarna bahkan ketika dialihkan; tapi saya tidak bisa repot-repot menambahkan logika untuk itu.
  • Saya tidak dapat menemukan cara untuk memasukkan file yang tidak terlacak dengan hanya mengumpulkan daftar argumen yang licin git diff. Jika seseorang mengetahui cara melakukan ini, atau jika mungkin suatu fitur ditambahkan gitpada suatu saat nanti, silakan tinggalkan catatan di sini!
Jo Liss
sumber
4
Ironisnya, git update-index --add --cacheinfo 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 new.txtsolusi saya yang saya sarankan untuk git yang lebih tua tidak berhasil git stash, dengan asumsi Anda sudah mendapatkan e69de29bb di db Anda, misalnya dengan mencoba menggunakan add -Nsebelumnya. Jadi rupanya itu tidak persis setara dengan git add -Ncara tertentu: tbh saya tidak yakin bagaimana caranya.
araqnid
2
Ngomong test-ngomong, Anda melakukan perbandingan string alih-alih kesetaraan numerik dengan perintah Anda . Seharusnya tidak mempengaruhi apa pun, tetapi test "$#" -eq 0lebih tepatnya apa yang dimaksudkan.
Wildcard
1
Ya, masih terlihat seperti Anda perlu melakukannya berpasangan ... tetapi dapat memalsunya menjadi satu lesssehingga Anda tidak perlu menekan quntuk setiap file dan rasanya persis seperti git diff, dengan menghapus pagination per file ( -P), menambahkannya kembali setelah itu ( | less), menjaga warna ( --color=always) dan menafsirkannya sebagai warna ( less -ratau less -R). Jadi semuanya:do git -P diff --color=always -- /dev/null "$i"; done | less -r
hyperpallium
Jika Anda ingin diganggu di masa depan, test -t 1(jadi mis. if [ -t 1 ]; then color_arg=--color; fiAtau sesuatu) adalah cara bagi shell untuk memeriksa apakah outputnya adalah terminal, yang merupakan cara yang berguna untuk memutuskan pewarnaan. Dan xargsmungkin memberi cara untuk menyingkirkan loop sementara. Anda masih membutuhkannya -n 1, jadi masih akan meluncurkan git beberapa kali, dan masih harus berpasangan seperti itu, tapi ... itu menghilangkan whiledan read, jadi mungkin itu lebih baik?!? Saya serahkan itu pada pembaca.
lindes
28

Tidak 100% to the point, tetapi jika karena alasan tertentu Anda tidak ingin menambahkan file Anda ke indeks seperti yang disarankan oleh jawaban yang diterima, berikut adalah pilihan lain:

Jika file tidak dilacak, jelas diff adalah keseluruhan file, jadi Anda bisa melihatnya dengan sedikit:

less $(git ls-files --others --exclude-standard)

Menavigasi di antara mereka dengan :ndan :puntuk selanjutnya dan sebelumnya ..

Perbarui dari komentar: Jika Anda memerlukan format tambalan Anda juga dapat menggabungkannya dengan git diff:

git ls-files --others --exclude-standard | xargs -n 1 git --no-pager diff /dev/null | less

Anda juga dapat mengarahkan output ke file atau menggunakan perintah diff lain dalam kasus ini.

pengguna1587520
sumber
6
Anda juga dapat menjalankan git diff /dev/null <untracked_tile>dan mendapatkan tambalan dalam format tambalan alih-alih "hanya" sebuah file
SimSimY
2
jawaban ini dikombinasikan dengan git diff adalah solusi sempurna.
iwind
22
git add -A
git diff HEAD

Hasilkan tambalan jika diperlukan, dan kemudian:

git reset HEAD
Amol Pujari
sumber
Ini berpotensi kehilangan pekerjaan sebelum (pra), dengan menambahkan semuanya. Terutama kasus jika seseorang menggunakan git add -psangat sering (yang biasanya saya sarankan, omong-omong) ... Ini memang memberikan cara melakukan hal dasar, itu hanya ... harus dicatat bahwa ia memiliki potensi untuk sisi yang tidak diinginkan efek.
lindes
13

ini bekerja untuk saya:

git add my_file.txt
git diff --cached my_file.txt
git reset my_file.txt

Langkah terakhir adalah opsional, itu akan meninggalkan file dalam keadaan sebelumnya (tidak terlacak)

berguna jika Anda membuat tambalan juga:

  git diff --cached my_file.txt > my_file-patch.patch
Alejandro Moreno
sumber
Kekhasan pasangan add / reset ini sangat kontras dengan pendekatan shotgun dari stackoverflow.com/a/50486906/313756 ... terima kasih untuk itu.
lindes
9

Perubahan berfungsi saat dipentaskan dan tidak dipentaskan dengan perintah ini. File baru berfungsi saat dipentaskan:

$ git diff HEAD

Jika tidak dipentaskan, Anda hanya akan melihat perbedaan file.

alairock
sumber
26
HEADadalah nilai default , jadi ini sama dengan git diffyang tidak menyelesaikan masalah.
Iulian Onofrei
4
Ini memerlukan git adddari setiap file yang tidak dilacak
SilvioQ
Jika Anda mengedit jawaban ini untuk memasukkannya, git addini adalah yang paling sederhana jika use case Anda adalah untuk memeriksa apa yang baru saja Anda tambahkan / ingin tambahkan
KCD
8

Untuk satu file:

git diff --no-index /dev/null new_file

Untuk semua file baru:

for next in $( git ls-files --others --exclude-standard ) ; do git --no-pager diff --no-index /dev/null $next; done;

Sebagai alias:

alias gdnew="for next in \$( git ls-files --others --exclude-standard ) ; do git --no-pager diff --no-index /dev/null \$next; done;"

Untuk semua file yang dimodifikasi dan baru digabungkan sebagai satu perintah:

{ git --no-pager diff; gdnew }
radzimir
sumber
2

biasanya ketika saya bekerja dengan tim lokasi terpencil, penting bagi saya bahwa saya memiliki pengetahuan sebelumnya tentang perubahan yang dilakukan oleh tim lain dalam file yang sama, sebelum saya mengikuti tahapan git untrack -> bertahap -> komit untuk itu saya menulis skrip bash yang bantu saya untuk menghindari penyelesaian konflik merger yang tidak perlu dengan tim jarak jauh atau membuat cabang lokal baru dan membandingkan dan menggabungkan cabang utama

#set -x 
branchname=`git branch | grep -F '*' |  awk '{print $2}'`
echo $branchname
git fetch origin ${branchname}
for file in `git status | grep "modified" | awk "{print $2}" `
do
echo "PLEASE CHECK OUT GIT DIFF FOR "$file 
git difftool FETCH_HEAD $file ;
done

dalam skrip di atas saya mengambil cabang utama jarak jauh (tidak perlu cabang masternya) ke FETCH_HEAD mereka membuat daftar file yang dimodifikasi saja dan membandingkan file yang dimodifikasi dengan git difftool

di sini banyak difftool yang didukung oleh git, saya mengkonfigurasi 'Meld Diff Viewer' untuk perbandingan GUI yang baik.

adg
sumber
-9

Dengan asumsi Anda tidak memiliki komitmen lokal,

git diff origin/master
Pradhan
sumber
8
Pertanyaannya meminta git diffperintah yang menyertakan file yang tidak dilacak. Perintah ini tidak termasuk mereka. Juga, apakah komitmen lokal ada atau tidak sama sekali tidak ada hubungannya dengan pertanyaan.
toon81
JFTR, saya git merge --squash mybranch, dan git diff mastermenunjukkan kepada saya perubahan dalam file yang tidak terlacak.
muammar
2
Itu tidak mungkin. Anda tampaknya bingung tentang apa artinya "tidak terlacak". Tidak dilacak tidak berarti bahwa file dilacak di satu cabang dan bukan yang lain, itu berarti bahwa itu bukan "di Git" di mana pun dengan cara apa pun. Apakah Anda squash atau tidak, tidak ada bedanya. git difftidak menunjukkan perbedaan dalam file yang tidak terlacak: karena mereka tidak terlacak tidak pernah ada perbedaan untuk ditunjukkan, menurut definisi. Begitulah cara Git bekerja. :)
toon81