Comment mettre en scène seulement une partie d'un nouveau fichier avec git?


222

J'adore git ajouter --interactive . Cela fait maintenant partie de mon flux de travail quotidien.

Le problème semble qu'il ne fonctionne pas avec les fichiers non suivis. Ce que je veux faire, c'est suivre un nouveau fichier, mais n'en ajouter qu'une partie, c'est-à-dire que certaines parties de ce nouveau fichier ne sont pas encore prêtes à être mises en scène.

Par exemple, avec git add -i, je peux choisir l'option de patch et même éditer des morceaux individuels afin de mettre en scène des parties du nouveau code, en laissant les commentaires de code de débogage non organisés. J'adore travailler de cette façon car cela rend évident quels endroits du méga patch sur lesquels je travaille actuellement ont encore besoin de travail.

Malheureusement, je ne semble pas pouvoir faire de même avec un fichier non suivi. Soit je met en scène tout le dossier, soit rien. La solution de contournement que j'utilise consiste à mettre en scène ou même à valider un nouveau fichier lorsqu'il est vide, puis à mettre en scène les modifications individuelles de la manière habituelle. Mais cette solution ressemble à un hack sale et quand j'oublie ou change d'avis, cela crée plus de problèmes qu'il ne devrait y en avoir.

La question est donc la suivante: comment mettre en scène uniquement une partie d'un nouveau fichier, afin que ce nouveau fichier soit suivi mais en laissant tout ou partie de son contenu sans mise en scène?

Réponses:


415

Whoa, tout ça update-indexet les hash-objectaffaires semblent trop compliqués. Et à la place:

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.

9
++ 1! crédit dû. Je fais trop confiance que je connais ces pages de manuel maintenant ...</shame>
sehe

1
Bien trouvé. J'aurais dû faire défiler la page de manuel un peu plus loin. Je devrais peut-être retourner le badge Git Pro.
dave1010

3
Je me demande pourquoi git-gui ne l'utilise pas en interne pour pouvoir mettre en scène les lignes d'un nouveau fichier.
Deiwin

6
Merveilleuse -Ndécouverte, merci! Bien que je préfère le combiner avec -pdans ce cas. gid add -N the_file& git add -p. Il faut ajouter que ça -Nmarche aussi avec-A
Cyril CHAPON

@Deiwin - vous pouvez ajouter un [guitool] à votre .gitconfig pour faire un "git add -N $ FILENAME": [guitool "Add with intent"] cmd = "git add -N $ FILENAME" needsfile = yes noconsole = yes
Steve Folly

7

La façon la plus simple de le faire (et la mise en scène interactive à mon humble avis en général) est git gui. Il est fourni avec git et devrait fonctionner sur presque toutes les plates-formes prises en charge par git.

Exécutez simplement git guiet une interface graphique s'ouvrira qui permet de mettre en scène et de supprimer les mecs et même des lignes uniques de fichiers suivis et non suivis.

Capture d'écran de Git Gui


C'est une réponse créative et parfois c'est très, très utile.
Pablo Olmos de Aguilera C.

3
Juste une note que toutes les distributions git n'incluent pas git gui. Dans Debian, par exemple, il se trouve dans un paquet séparé appelé «git-gui».
cristoper

J'ai recherché (pas assez dur) cette fonctionnalité pendant des années, c'est un changeur de vie
austinmarton

2
Pour moi, la mise en scène de lignes uniques de fichiers non suivis git guin'a jamais fonctionné. En fait, il désactive ces options de menu .
Deiwin

2
@Deiwin Je dois avoir manqué cela dans la question - ma capture d'écran montre un fichier déjà suivi. Si vous souhaitez utiliser git guiun nouveau fichier, vous devez d' git add -N new_fileabord exécuter - voir la réponse de Richard Hansen.
Chronial

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

Démo 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
  • Astuce Si vous êtes sûr que le blob «vide» existe déjà dans votre base de données d'objets git, vous pouvez coder en dur le hachage à la e69de29bb2d1d6434b8b29ae775ad8c2e48c5391place. Je ne recommande pas de faire ça_
  • Astuce Si vous êtes sous Windows, vous pouvez probablement simplement utiliser à la NUL:place de /dev/null. Sinon, utilisez quelque chose commeecho -n '' | git hash-object --stdin -w

Maintenant, l'index contiendra en newfiletant que blob vide, et le blob vide a été entré dans la base de données d'objets s'il n'existait pas encore:

$ 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

Cela devrait être précisément ce que vous voulez. Puis-je également recommander le plugin fugitif vim pour une gestion d'index très intelligente (voir Better git add -p? )


1
Cela semble bien fonctionner. Je l'ai remplacé par "stage-empty-file" car c'est un peu complexe à retenir.
dave1010

@ dave1010: Heureux que cela ait aidé! Oui, j'ai pensé à ajouter un alias, mais je ne savais pas comment vous vous attendriez à gérer, par exemple, des caractères génériques ou plusieurs arguments de nom de fichier en général. Donc , je choisi de ne pas
sehe

2

Edit: cela ne semble pas fonctionner maintenant. Je suis sûr que c'était avant (sur git 1.7.1). Dans le cas où cela ne fonctionne pas, je suggère de mettre /dev/nullen scène comme le suggère ci-dessus:

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

Si vous êtes sous Windows (sans /dev/null), vous pouvez le remplacer par le chemin d'accès à un fichier vide.

Réponse originale

Tu veux

git add -p # (or --patch)

Cela ajoute des fichiers non suivis pour moi. Depuis la page de manuel:

Choisissez interactivement des morceaux de patch entre l'index et l'arborescence de travail et ajoutez-les à l'index. Cela permet à l'utilisateur de revoir la différence avant d'ajouter du contenu modifié à l'index.

Cela exécute efficacement add --interactive, mais contourne le menu de commandes initial et passe directement à la sous-commande patch. Voir «Mode interactif» pour plus de détails.


2
Cependant intéressant, cela ne fonctionne pas pour moi (git 1.7.4); git add -p newfilene fonctionne pas du tout (effet nu) et git add --interactive'[a] dd untracked' a l'effet qui git add newfilea; Modifier également vérifié avec git 1.7.5.3; pas dé
sehe

Bon indice pour Windows, ajout d'indices pour cela dans ma réponse. Thx
sehe

-2

Juste pour le compte rendu d'une autre possibilité: j'utilise

git add -N file
git add -p file

Et puis vous pouvez mettre en scène des mecs, ou les modifier sur place.


1
Cette réponse est identique à la réponse acceptée, qui remonte à 2011. Downvote.
Stanislav Pankevich

La réponse acceptée se combine add -Navec add -i. J'ai juste ajouté cela add -pau lieu de add -itravaux aussi.
Pedro Adame Vergara
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.