Come mettere in scena solo una parte di un nuovo file con git?


222

Mi piace git aggiungere --interactive . Ora fa parte del mio flusso di lavoro quotidiano.

Il problema sembra non funzionare con file non monitorati. Quello che voglio fare è tenere traccia di un nuovo file, ma aggiungerne solo una parte, ovvero alcune parti di questo nuovo file non sono ancora pronte per essere messe in scena.

Ad esempio, con git add -i, posso scegliere l'opzione patch e persino modificare singoli hunk al fine di mettere in scena parti del nuovo codice, lasciando in scena i commenti del codice di debug. Adoro lavorare in questo modo perché è ovvio su quali luoghi della mega patch su cui sto attualmente lavorando hanno ancora bisogno di lavoro.

Sfortunatamente, non riesco a fare lo stesso con un file non tracciato. O metto in scena l'intero file o niente. La soluzione alternativa che ho utilizzato è la gestione temporanea o addirittura il commit di un nuovo file quando è vuoto, quindi la gestione temporanea delle singole modifiche nel solito modo. Ma questa soluzione sembra un trucco sporco e quando dimentico o cambio idea, crea più problemi di quanti dovrebbero esserci.

Quindi la domanda è: come mettere in scena solo una parte di un nuovo file, in modo che questo nuovo file venga tracciato ma lasciando l'intero o parti del suo contenuto in scena?

Risposte:


415

Whoa, tutto ciò update-indexe gli hash-objectaffari sembrano eccessivamente complicati. Che ne dici invece di questo:

git add -N new_file
git add -i

Da 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.

9
++ 1! credito dovuto. Mi fido un po 'troppo del fatto che conosco queste </shame>
pagine man

1
Ben trovato. Avrei dovuto scorrere ulteriormente la pagina man. Forse dovrei restituire il badge Git Pro.
dave1010,

3
Mi chiedo perché git-gui non lo usi internamente per essere in grado di mettere in scena le linee da un nuovo file.
Deiwin,

6
Splendida -Nscoperta, grazie! Anche se preferirei combinarlo con -pin quel caso. gid add -N the_file& git add -p. Si dovrebbe aggiungere che -Nfunziona anche con-A
Cyril CHAPON

@Deiwin - potresti aggiungere un [guitool] al tuo .gitconfig per fare un "git add -N $ FILENAME": [guitool "Aggiungi con intento"] cmd = "git add -N $ FILENAME" needsfile = yes noconsole = yes
Steve Folly,

7

Il modo più semplice per farlo (e imitare la stadiazione interattiva in generale) è git gui. Viene fornito in bundle con git e dovrebbe funzionare su quasi tutte le piattaforme supportate da git.

Basta eseguire git guie si aprirà una GUI che consente di mettere in scena hunk non staging e anche singole righe di file tracciati e non tracciati.

Screenshot di Git Gui


Questa è una risposta creativa e talvolta è molto, molto utile.
Pablo Olmos de Aguilera C.

3
Solo una nota che non tutte le distribuzioni git includono git gui. In Debian, ad esempio, si trova in un pacchetto separato chiamato 'git-gui'.
cristoper,

Ho cercato (non abbastanza difficile) questa funzione per anni, questo è un cambio di vita
austinmarton,

2
Per me la messa in scena di singole righe di file git guinon tracciati non ha mai funzionato. In effetti, disabilita queste opzioni di menu .
Deiwin,

2
@Deiwin Devo averlo perso nella domanda - il mio screenshot mostra un file già tracciato. Se si desidera utilizzare git guiper un nuovo file, è necessario eseguire git add -N new_fileprima - vedere la risposta di Richard Hansen.
Cronologia,

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

Demo semplice:

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

echo hello > newfile
git update-index --add --cacheinfo 100644 $(git hash-object -w /dev/null) newfile
  • Suggerimento Se sei sicuro che il BLOB "vuoto" esiste già nel database degli oggetti git, puoi e69de29bb2d1d6434b8b29ae775ad8c2e48c5391invece codificare l'hash . Non consiglio di farlo_
  • Suggerimento Se sei su Windows, probabilmente puoi semplicemente usare NUL:invece di /dev/null. Altrimenti, usa qualcosa di simileecho -n '' | git hash-object --stdin -w

Ora l'indice conterrà newfilecome BLOB vuoto e il BLOB vuoto è stato inserito nel database degli oggetti se non esisteva ancora:

$ 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

Questo dovrebbe essere esattamente quello che vuoi. Posso anche raccomandare il plug-in fuggitivo vim per una gestione degli indici molto intelligente (vedi Better git add -p? )


1
Questo sembra funzionare bene. L'ho modificato in "stage-empty-file" in quanto è un po 'complesso da ricordare.
dave1010,

@ dave1010: Sono contento che abbia aiutato! Sì, ho pensato di aggiungere un alias, ma non sapevo come ti aspetteresti di gestire, ad esempio, caratteri jolly o argomenti con più nomi di file in generale. Quindi ho deciso di non farlo
sehe

2

Modifica: questo non sembra funzionare ora. Sono sicuro che lo era prima (su git 1.7.1). Nel caso in cui non funzioni, suggerisco la messa /dev/nullin scena come suggerisce sopra:

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

Se sei su Windows (senza /dev/null), puoi sostituirlo con il percorso di un file vuoto.

Risposta originale

Tu vuoi

git add -p # (or --patch)

Questo aggiunge file non tracciati per me. Dalla pagina man:

Scegli in modo interattivo blocchi di patch tra l'indice e l'albero di lavoro e aggiungili all'indice. Ciò offre all'utente la possibilità di rivedere la differenza prima di aggiungere contenuti modificati all'indice.

Questo esegue effettivamente add --interactive, ma ignora il menu di comando iniziale e passa direttamente al sottocomando patch. Vedere "Modalità interattiva" per i dettagli.


2
Per quanto interessante, non funziona per me (git 1.7.4); git add -p newfilenon funziona affatto (effetto nu) e git add --interactive'[a] dd untracked' ha l'effetto che git add newfileha; Modifica anche controllato con git 1.7.5.3; no dice
vedi il

Buon suggerimento per Windows, aggiunto suggerimenti per quello nella mia risposta. Thx
sehe

-2

Solo per la cronaca di un'altra possibilità: io uso

git add -N file
git add -p file

E poi puoi mettere in scena hunk o modificarli in posizione.


1
Questa risposta dice la stessa della risposta accettata, che risale al 2011. Downvote.
Stanislav Pankevich,

La risposta accettata si combina add -Ncon add -i. Ho appena aggiunto anche questo add -pinvece che add -ifunziona.
Pedro Adame Vergara,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.