¿Cómo representar solo una parte de un nuevo archivo con git?

222

Me encanta git add --interactive . Ahora es parte de mi flujo de trabajo diario.

El problema parece que no funciona con archivos sin seguimiento. Lo que quiero hacer es rastrear un nuevo archivo, pero solo agregar parte de él, es decir, algunas partes de este nuevo archivo aún no están listas para su puesta en escena.

Por ejemplo, con git add -i, puedo elegir la opción de parche e incluso editar trozos individuales para organizar partes del nuevo código, dejando sin comentarios los comentarios del código de depuración. Me encanta trabajar de esta manera porque hace obvio en qué lugares del mega parche en el que estoy trabajando todavía necesitan trabajar.

Desafortunadamente, parece que no puedo hacer lo mismo con un archivo sin seguimiento. O pongo en escena todo el archivo o nada. La solución que he estado usando es organizar o incluso confirmar un nuevo archivo cuando está vacío, y luego organizar cambios individuales de la manera habitual. Pero esta solución se siente como un truco sucio y cuando olvido, o cambio de opinión, crea más problemas de los que debería haber.

Entonces, la pregunta es: ¿Cómo organizar solo una parte de un nuevo archivo, para que este nuevo archivo sea rastreado pero dejando todo o parte de su contenido sin clasificar?

augustin
fuente

Respuestas:

415

Whoa, todo eso update-indexy los hash-objectnegocios parecen demasiado complicados. ¿Qué tal esto en su lugar:

git add -N new_file
git add -i

De 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
fuente
99
++ 1! debido crédito Confío un poco demasiado que sé estas páginas de manual por ahora ....</shame>
sehe
1
Bien encontrado Debería haber desplazado la página del manual un poco más. Quizás debería devolver la insignia de Git Pro.
dave1010
3
Me pregunto por qué git-gui no usa esto internamente para poder trazar líneas desde un nuevo archivo.
Deiwin
66
Maravilloso -Ndescubrimiento, gracias! Aunque preferiría combinarlo -pen ese caso. gid add -N the_file& git add -p. Cabe agregar que -Ntambién funciona con-A
Cyril CHAPON
@Deiwin: puede agregar un [guitool] a su .gitconfig para hacer un "git add -N $ FILENAME": [guitool "Agregar con intención"] cmd = "git add -N $ FILENAME" needsfile = yes noconsole = yes
Steve Folly
7

La forma más fácil de hacer esto (y la puesta en escena interactiva de IMHO en general) es git gui. Viene incluido con git y debería funcionar en casi todas las plataformas compatibles con git.

Simplemente ejecute git guiy se abrirá una interfaz gráfica de usuario que permite colocar trozos en escena y sin escena e incluso líneas individuales de archivos rastreados y no rastreados.

Captura de pantalla de Git Gui

Crónica
fuente
Esta es una respuesta creativa y, a veces, es muy, muy útil.
Pablo Olmos de Aguilera C.
3
Solo una nota que no todas las distribuciones de git incluyen git gui. En Debian, por ejemplo, está en un paquete separado llamado 'git-gui'.
cristoper 01 de
He estado buscando (no lo suficiente) esta característica durante años, esto cambia la vida
austinmarton
2
Para mí, la puesta en escena de líneas individuales de archivos sin seguimiento git guinunca ha funcionado. De hecho, deshabilita estas opciones de menú .
Deiwin
2
@Deiwin Debo haber pasado esto por alto en la pregunta: mi captura de pantalla muestra un archivo ya rastreado. Si desea utilizar git guipara un nuevo archivo, git add -N new_fileprimero debe ejecutarlo ; consulte la respuesta de Richard Hansen.
Crónica del
6
git update-index --add --cacheinfo 100644 $(git hash-object -w /dev/null) newfile
git add --interactive newfile

Demo simple:

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

echo hello > newfile
git update-index --add --cacheinfo 100644 $(git hash-object -w /dev/null) newfile
  • Sugerencia Si está seguro de que el blob 'vacío' ya existe en su base de datos de objetos git, puede codificar el hash en su e69de29bb2d1d6434b8b29ae775ad8c2e48c5391lugar. No recomiendo hacer eso_
  • Sugerencia Si está en Windows, probablemente pueda usar en NUL:lugar de /dev/null. De lo contrario, use algo comoecho -n '' | git hash-object --stdin -w

Ahora el índice contendrá newfilecomo el blob vacío, y el blob vacío se ha ingresado en la base de datos de objetos si aún no existía:

$ 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

Esto debería ser precisamente lo que quieres. ¿Puedo recomendar también el complemento fugitivo vim para una gestión de índice muy inteligente (ver Better git add -p? )

sehe
fuente
1
Esto parece funcionar bien. Lo he alias "stage-empty-file" ya que es un poco complejo de recordar.
dave1010
@ dave1010: ¡Me alegra que haya ayudado! Sí, pensé en agregar un alias, pero no sabía cómo esperarías manejar, por ejemplo, comodines o múltiples argumentos de nombre de archivo en general. Así que opté por no hacerlo
sehe
2

Editar: esto no parece estar funcionando ahora. Estoy seguro de que era antes (en git 1.7.1). En caso de que no funcione, sugiero la puesta /dev/nullen escena como sehe sugiere arriba:

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

Si está en Windows (sin /dev/null), puede reemplazarlo con la ruta a un archivo vacío.

Respuesta original

Usted quiere

git add -p # (or --patch)

Esto agrega archivos sin seguimiento para mí. Desde la página del manual:

Elija interactivamente trozos de parche entre el índice y el árbol de trabajo y agréguelos al índice. Esto le da al usuario la oportunidad de revisar la diferencia antes de agregar contenido modificado al índice.

Esto ejecuta efectivamente add --interactive, pero omite el menú de comando inicial y salta directamente al subcomando patch. Consulte "Modo interactivo" para más detalles.

dave1010
fuente
2
Sin embargo interesante, no funciona para mí (git 1.7.4); git add -p newfileno funciona en absoluto (efecto nu) y git add --interactive'[a] dd sin seguimiento' tiene el efecto que git add newfiletiene; Editar también marcado con git 1.7.5.3; sin dados
sehe
Buena sugerencia para Windows, añadí sugerencias para eso en mi respuesta. Thx
sehe
-2

Solo para el registro de otra posibilidad: yo uso

git add -N file
git add -p file

Y luego puedes montar trozos o editarlos en su lugar.

Pedro Adame Vergara
fuente
1
Esta respuesta dice lo mismo que la respuesta aceptada, que se remonta a 2011. Voto negativo.
Stanislav Pankevich
La respuesta aceptada se combina add -Ncon add -i. Acabo de agregar eso en add -plugar de add -iobras, también.
Pedro Adame Vergara