Jak wystawić tylko część nowego pliku za pomocą git?

221

Ja kocham git dodać --interactive . Jest to teraz część mojego codziennego przepływu pracy.

Problem wydaje się, że nie działa z nieśledzonymi plikami. Chcę śledzić nowy plik, ale tylko dodać jego część, tzn. Niektóre części tego nowego pliku nie są jeszcze gotowe do przygotowania.

Na przykład, dzięki git add -i, mogę wybrać opcję łatki, a nawet edytować poszczególne porcje, aby wyeksponować części nowego kodu, pozostawiając komentarze kodu debugowania niestabilne. Uwielbiam pracować w ten sposób, ponieważ pokazuje, które miejsca mega łatki, nad którymi obecnie pracuję, nadal wymagają pracy.

Niestety nie wydaje mi się, że mogę zrobić to samo z nieśledzonym plikiem. Albo sfotografuję cały plik, albo nic. Obejściem, którego używałem, jest przemieszczanie lub nawet zatwierdzanie nowego pliku, gdy jest on pusty, a następnie stopniowanie poszczególnych zmian w zwykły sposób. Ale to rozwiązanie wydaje się brudnym hackem, a kiedy zapomnę lub zmienię zdanie, stwarza więcej problemów niż powinno być.

Pytanie brzmi zatem: w jaki sposób ustawić tylko część nowego pliku, aby ten nowy plik był śledzony, a cała scena lub jej część nie była wystawiana na scenę?

sierpień
źródło

Odpowiedzi:

415

Whoa, to wszystko update-indexi hash-objectinteresy wydają się zbyt skomplikowane. A może zamiast tego:

git add -N new_file
git add -i

Od git help add:

-N, --intent-to-add
    Record only the fact that the path will be added later.  An entry
    for the path is placed in the index with no content.  This is useful
    for, among other things, showing the unstaged content of such files
    with git diff and committing them with git commit -a.
Richard Hansen
źródło
9
++ 1! należny kredyt. Trochę za bardzo ufam, że znam te strony…</shame>
patrz
1
Dobrze znalezione Powinienem był przewinąć stronę podręcznika nieco dalej. Być może powinienem zwrócić odznakę Git Pro.
dave1010
3
Zastanawiam się, dlaczego git-gui nie używa tego wewnętrznie, aby móc wyrównywać linie z nowego pliku.
Deiwin,
6
Cudowne -Nodkrycie, dzięki! -pW tym przypadku wolałbym jednak to połączyć . gid add -N the_file& git add -p. Należy dodać, że -Nwspółpracuje również z-A
Cyrylem CHAPONEM
@Deiwin - możesz dodać [guitool] do swojego .gitconfig, aby zrobić „git add -N $ FILENAME”: [guitool ”Add with intent”] cmd = „git add -N $ FILENAME” needfile = tak noconsole = tak
Steve Folly,
7

Najłatwiejszym sposobem na to (i ogólnie interaktywną inscenizację imho) jest git gui. Jest dostarczany w pakiecie z git i powinien działać na prawie wszystkich platformach obsługiwanych przez git.

Po prostu uruchom, git guia otworzy się GUI, które pozwala na pomostowe i nieetapowe porcje, a nawet pojedyncze linie śledzonych i nie śledzonych plików.

Zrzut ekranu Git Gui

Chronial
źródło
To twórcza odpowiedź, a czasem bardzo, bardzo przydatna.
Pablo Olmos de Aguilera C.
3
Tylko uwaga, że ​​nie wszystkie dystrybucje git obejmują git gui. Na przykład w Debianie znajduje się w osobnym pakiecie o nazwie „git-gui”.
cristoper
Szukałem (nie dość mocno) tej funkcji od lat, to jest zmiana życia
austinmarton
2
Dla mnie inscenizacja pojedynczych wierszy nie śledzonych plików git guinigdy nie działała. W rzeczywistości wyłącza te opcje menu .
Deiwin,
2
@ Deiwin Musiałem faktycznie przegapić to w pytaniu - mój zrzut ekranu pokazuje już śledzony plik. Jeśli chcesz użyć git guinowego pliku, musisz git add -N new_filenajpierw uruchomić - patrz odpowiedź Richarda Hansena.
Chronial
6
git update-index --add --cacheinfo 100644 $(git hash-object -w /dev/null) newfile
git add --interactive newfile

Proste demo:

mkdir /tmp/demo
cd /tmp/demo
git init .

echo hello > newfile
git update-index --add --cacheinfo 100644 $(git hash-object -w /dev/null) newfile
  • Wskazówka Jeśli masz pewność, że „pusty” obiekt blob już istnieje w bazie danych obiektów git, możesz e69de29bb2d1d6434b8b29ae775ad8c2e48c5391zamiast tego zakodować na stałe skrót . Nie polecam tego robić_
  • Wskazówka Jeśli korzystasz z systemu Windows, prawdopodobnie możesz po prostu użyć NUL:zamiast /dev/null. W przeciwnym razie użyj czegoś takiegoecho -n '' | git hash-object --stdin -w

Teraz indeks będzie zawierał newfilejako pusty obiekt blob, a pusty obiekt został wprowadzony do bazy danych obiektów, jeśli jeszcze nie istniał:

$ find .git/objects/ -type f 
.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391

$ git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
#   (use "git rm --cached <file>..." to unstage)
#
#   new file:   newfile
#
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   newfile
#

$ git diff
diff --git a/newfile b/newfile
index e69de29..ce01362 100644
--- a/newfile
+++ b/newfile
@@ -0,0 +1 @@
+hello

To powinno być dokładnie to, czego chcesz. Czy mogę również polecić zbiegłą wtyczkę vima do bardzo inteligentnego zarządzania indeksami (zobacz Lepsze dodawanie git -p? )

sehe
źródło
1
To wydaje się działać dobrze. Skalowałem go do „stage-empty-file”, ponieważ jest to trochę skomplikowane do zapamiętania.
dave1010
@ dave1010: Cieszę się, że to pomogło! Tak, myślałem o dodaniu aliasu, ale nie wiedziałem, w jaki sposób można oczekiwać obsługi np. Symboli wieloznacznych lub wielu argumentów nazw plików. Więc zdecydowałem się nie
widzieć
2

Edycja: wydaje się, że teraz nie działa. Jestem pewien, że było to wcześniej (na git 1.7.1). W przypadku, gdy to nie działa, sugeruję inscenizację, /dev/nulljak sugeruje to powyżej:

git update-index --add --cacheinfo 100644 $(git hash-object -w /dev/null) newfile

Jeśli korzystasz z systemu Windows (bez /dev/null), możesz zastąpić go ścieżką do pustego pliku.

Oryginalna odpowiedź

Chcesz

git add -p # (or --patch)

To dodaje do mnie nieśledzone pliki. Ze strony podręcznika:

Interaktywnie wybierz fragmenty łaty między indeksem a drzewem pracy i dodaj je do indeksu. Daje to użytkownikowi możliwość sprawdzenia różnicy przed dodaniem zmodyfikowanej zawartości do indeksu.

To skutecznie uruchamia add --interactive, ale omija menu poleceń początkowych i bezpośrednio przeskakuje do komendy łatki. Szczegółowe informacje zawiera „Tryb interaktywny”.

dave1010
źródło
2
Jakkolwiek interesujące, to nie działa dla mnie (git 1.7.4); git add -p newfilew ogóle nie działa (efekt nu), a git add --interactive„[a] ddracked” ma taki efekt git add newfile; Edycja sprawdzona również za pomocą git 1.7.5.3; bez kości
patrz
Dobra wskazówka dla systemu Windows, dodano do tego wskazówki w mojej odpowiedzi. Thx
sehe
-3

Dla przypomnienia innej możliwości: używam

git add -N file
git add -p file

Następnie możesz wystawić przystojniaków lub edytować je na miejscu.

Pedro Adame Vergara
źródło
1
Ta odpowiedź mówi to samo co odpowiedź zaakceptowana, która pochodzi z 2011 roku.
Stanislav Pankevich
Akceptowana odpowiedź łączy się add -Nz add -i. Właśnie dodałem, że add -pzamiast add -idziała.
Pedro Adame Vergara