Czy mogę używać git diff na nieśledzonych plikach?


270

Czy można poprosić git diff o dołączenie nieśledzonych plików do wyjścia diff? A może najlepiej jest dodać nowe pliki, które utworzyłem, i istniejące pliki, które edytowałem i których używam

git diff --cached

?

Odpowiedzi:


267

Dzięki najnowszym wersjom git możesz utworzyć git add -Nplik (lub --intent-to-add), który dodaje do indeksu w tym miejscu obiekt blob o zerowej długości. Wynikiem jest to, że plik „nieśledzony” staje się teraz modyfikacją dodającą całą zawartość do tego pliku o zerowej długości, co pojawia się na wyjściu „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

Niestety, jak wskazano, nie można, git stashdopóki --intent-to-addplik jest w toku. Chociaż jeśli chcesz ukryć, po prostu dodajesz nowe pliki, a następnie przechowujesz je. Lub możesz użyć obejścia emulacji:

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

(konfigurowanie aliasu jest tutaj Twoim przyjacielem).


Okazuje się, że moja kopia Gita nie jest wystarczająco aktualna, aby dodać -N, ale to odpowiada na moje pytanie.
— Andrew Grimm

1
Możesz emulować „git add -N new.txt” za pomocą „git update-index --add --cacheinfo 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 new.txt” (jak udało mi się umieścić to na złą odpowiedź?)
— araqnid


1
co jeśli masz dużo nowych plików, czy istnieje prosty sposób na dodanie ich wszystkich, a następnie na różnicę?
— Vic

1
@Vicgit add -N .
— Nathan

92

Sądzę, że możesz różnicować pliki w indeksie i pliki nieśledzone, podając po prostu ścieżkę do obu plików.

git diff --no-index tracked_file untracked_file

3
Czy to działa, jeśli masz więcej niż jeden nieśledzony plik, który utworzyłeś od ostatniego zatwierdzenia?
— Andrew Grimm

12
Tak, idealna odpowiedź! Mogę wtedy użyć git diff --no-index untracked_file_1 untracked_file_2, aby uzyskać git diffkolorowanie składni itp na dyferencjału ... piękne.
— Colin D Bennett

40
Nie rozumiem, dlaczego porównujesz plik śledzony z niepowiązanym plikiem nieśledzonym. Jeśli po prostu chciał dostać diff wyjście do pliku nieśledzonej, można po prostu użyć /dev/nullzamiast: git diff --no-index -- /dev/null <untracked_file>.

4
Lub po prostu cat untracked_file_1, a może printf '\e[1;32m%s\e[0m\n' "$(cat untracked_file_1)"naprawdę potrzebujesz zielonej produkcji. :) (Chociaż bardziej poważnie, pamiętaj, że podstawienie polecenia usunie końcowe znaki nowego wiersza z pliku.)
— Wildcard,

8
To powinna być zaakceptowana odpowiedź - nie wymaga zmiany indeksu gita; co, jak mówi oryginalny autor, ma swoją wadę
— DIMMSum

38

Moje interaktywne codzienne gitowanie (gdzie cały czas różnicuję działające drzewo w stosunku do HEAD i chciałbym mieć w pliku diff nieuwzględnione pliki), add -N/--intent-to-addjest bezużyteczne, ponieważ pęka git stash .

Oto mój git diffzamiennik. To nie jest szczególnie czyste rozwiązanie, ale ponieważ naprawdę używam go tylko interaktywnie, jestem w porządku z hackiem:

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
}

Wpisywanie po prostu dbędzie zawierać niezrackowane pliki w diff (to jest to, na czym mi zależy w moim przepływie pracy) i d args...będzie się zachowywać jak normalne git diff.

Uwagi:

  • Używamy tutaj faktu, że git difftak naprawdę są to tylko poszczególne różnice skonkatenowane, więc nie jest możliwe dodróżnienie wyniku od „prawdziwego porównania” - z wyjątkiem faktu, że wszystkie nieśledzone pliki są sortowane na końcu.
  • Jedynym problemem związanym z tą funkcją jest to, że dane wyjściowe są pokolorowane, nawet po przekierowaniu; ale nie mogę zawracać sobie głowy dodaniem do tego logiki.
  • Nie mogłem znaleźć żadnego sposobu na włączenie nieśledzonych plików, po prostu tworząc zręczną listę argumentów git diff. Jeśli ktoś wymyśli, jak to zrobić, lub jeśli gitw przyszłości zostanie dodana funkcja , zostaw tutaj notatkę!

4
Jak na ironię, moje git update-index --add --cacheinfo 100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 new.txtobejście, które zasugerowałem dla starszych gitów , działa git stash, zakładając, że masz już e69de29bb w db, np. Próbując użyć add -Nwcześniej. Najwyraźniej więc nie jest to git add -Nw jakiś sposób równoważne: nie jestem pewien, jak to zrobić.
— araqnid

2
Nawiasem testmówiąc, wykonujesz porównanie ciągów zamiast numerycznej kontroli równości za pomocą polecenia. Nie powinno to wpływać na nic, ale test "$#" -eq 0dokładniej jest zgodne z przeznaczeniem.
— Wildcard,

1
Tak, nadal wygląda na to, że musisz to zrobić parami ... ale możesz sfałszować go w jeden, lesswięc nie musisz naciskać qdla każdego pliku i wydaje się dokładnie tak git diff, usuwając paginację dla poszczególnych plików ( -P), dodając go później ( | less), zachowując kolor ( --color=always) i interpretując go jako kolor ( less -rlub less -R). Tak więc w sumie jest to:do git -P diff --color=always -- /dev/null "$i"; done | less -r
— hyperpallium

Jeśli chcesz się martwić w przyszłości test -t 1(np. Czy if [ -t 1 ]; then color_arg=--color; ficoś w tym rodzaju), to sposób, w jaki powłoka sprawdza, czy jej wyjściem jest terminal, co jest przydatnym sposobem na wybór koloru. I xargsmoże dać sposób na pozbycie się pętli while. Nadal będziesz tego potrzebować -n 1, więc nadal będzie uruchamiał git kilka razy i nadal musi być w ten sposób parami, ale ... pozbywa się whilei read, więc może lepiej?!? Pozostawiam to czytelnikowi.
— Lindes

28

Nie w 100% do rzeczy, ale jeśli z jakiegoś powodu nie chcesz dodawać plików do indeksu, jak sugeruje zaakceptowana odpowiedź, oto inna opcja:

Jeśli pliki nie są śledzone, oczywiście różnicą jest cały plik, więc możesz po prostu wyświetlić je z mniejszą liczbą:

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

Nawiguj między nimi za pomocą :ni, :paby przejść do następnego i poprzedniego

Aktualizacja z komentarzy: Jeśli potrzebujesz formatu łatki, możesz także połączyć go z git diff:

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

W tym przypadku możesz również przekierować dane wyjściowe do pliku lub użyć innego polecenia diff.


6
możesz także uruchomić git diff /dev/null <untracked_tile>i pobrać łatkę w formacie łatki zamiast „tylko” pliku
— SimSimY

2
ta odpowiedź w połączeniu z git diff jest idealnym rozwiązaniem.
— iwind

22
git add -A
git diff HEAD

W razie potrzeby wygeneruj poprawkę, a następnie:

git reset HEAD

Może to spowodować utratę wcześniejszej (wstępnej) pracy przez dodanie wszystkiego. Zwłaszcza w przypadku, gdy ktoś korzysta z tego git add -pbardzo często (co zresztą ogólnie polecam) ... To daje sposób na zrobienie podstawowej rzeczy, po prostu ... należy zauważyć, że ma potencjał niepożądanej strony efekty.
— Lindes

13

to działa dla mnie:

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

Ostatni krok jest opcjonalny, pozostawi plik w poprzednim stanie (bez śledzenia)

przydatne, jeśli tworzysz również łatkę:

  git diff --cached my_file.txt > my_file-patch.patch

Specyfika tej pary dodawania / resetowania stanowi niezły kontrast z podejściem shotgun z stackoverflow.com/a/50486906/313756 ... dzięki za to.
— Lindes

9

Zmiany działają podczas przemieszczania i przemieszczania za pomocą tego polecenia. Nowe pliki działają podczas przemieszczania:

$ git diff HEAD

Jeśli nie są one ustawione, widoczne będą tylko różnice plików.


26
HEADjest wartością domyślną , więc jest to ta sama wartość , git diffktóra nie rozwiązuje problemu.
— Iulian Onofrei,

4
Wymaga to git addod każdego
— nieśledzonego

Jeśli edytujesz tę odpowiedź, aby uwzględnić git add, najprostszym jest, jeśli twoim przypadkiem użycia jest sprawdzenie, co właśnie dodałeś / chcesz dodać
— KCD

8

Dla jednego pliku:

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

Dla wszystkich nowych plików:

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

Jako alias:

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

Dla wszystkich zmodyfikowanych i nowych plików połączonych jako jedno polecenie:

{ git --no-pager diff; gdnew }

2

zwykle kiedy pracuję z zespołami zdalnymi, ważne jest dla mnie, aby mieć wcześniejszą wiedzę o zmianach dokonanych przez inne zespoły w tym samym pliku, zanim przejdę do etapów git bez śledzenia -> etapowe -> zatwierdzenie, napisałem skrypt bash, który pomóż mi uniknąć niepotrzebnego rozwiązania konfliktu scalania ze zdalnym zespołem lub załóż nowy oddział lokalny oraz porównaj i połącz w głównym oddziale

#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

w powyższym skrypcie pobieram zdalną gałąź główną (niekoniecznie jej gałąź główną) do FETCH_HEAD, robią one listę tylko mojego zmodyfikowanego pliku i porównują zmodyfikowane pliki do git difftool

tutaj wiele difftooli obsługiwanych przez git, konfiguruję Meld Diff Viewer dla dobrego porównania GUI.


-9

Zakładając, że nie masz lokalnych zatwierdzeń,

git diff origin/master

8
Pytanie wymaga git diffpolecenia zawierającego nieśledzone pliki. To polecenie ich nie obejmuje. To, czy istnieją lokalne zatwierdzenia, nie ma absolutnie nic wspólnego z tym pytaniem.
— toon81

JFTR, I git merge --squash mybranch, i git diff masterpokazałem mi zmiany w nieśledzonych plikach.
— muammar

2
To niemożliwe. Wygląda na to, że jesteś zdezorientowany, co znaczy „nieśledzony”. Untracked nie oznacza, że ​​plik jest śledzony w jednej gałęzi, a nie w innej, oznacza to, że nie jest w żaden sposób „w Git”. To, czy zgniatasz, czy nie, nie ma znaczenia. git diffnie pokazuje różnic w nieśledzonych plikach: ponieważ nie są śledzone, z definicji nigdy nie ma żadnych różnic do pokazania. Tak działa Git. :)
— toon81
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.