web-dev-qa-db-fra.com

Comment décomposer un grand nombre de fichiers sans supprimer le contenu

J'ai accidentellement ajouté beaucoup de fichiers temporaires en utilisant git add -A

J'ai réussi à décomposer les fichiers à l'aide des commandes suivantes et à supprimer l'index modifié.

git ls-files -z | xargs -0 rm -f
git diff --name-only --diff-filter=D -z | xargs -0 git rm --cached

Les commandes ci-dessus sont répertoriées dans le git help rm. Mais malheureusement, mes fichiers ont également été supprimés lors de l’exécution, même si j’avais donné l’option cache. Comment puis-je effacer l'index sans perdre le contenu?

De plus, il serait utile que quelqu'un puisse expliquer le fonctionnement de cette opération.

416
sarat

git reset

Si tout ce que vous voulez, c'est annuler une course trop zélée "git add":

git reset

Vos modifications seront décomposées et prêtes à être rajoutées à votre guise.


NE PAS EXECUTER git reset --hard.

Cela annulera non seulement les fichiers ajoutés, mais annulera également les modifications apportées à votre répertoire de travail. Si vous avez créé de nouveaux fichiers dans le répertoire de travail, il les supprime ne le fera pas.

908
Ian Maddox

Si vous avez un dépôt vierge (ou HEAD n'est pas défini) [1] vous pourriez simplement

rm .git/index

Bien sûr, cela vous obligera à rajouter les fichiers que vous avez voulez ajouter.


[1] Remarque (comme expliqué dans les commentaires), cela ne se produit généralement que lorsque le repo est tout neuf ("vierge") ou si aucune validation n'a été effectuée. Plus techniquement, lorsqu'il n'y a pas de caisse ou d'arbre de travail.

Juste pour être plus clair :)

33
sehe

Utilisez git reset HEAD pour réinitialiser l'index sans supprimer de fichiers. (Si vous souhaitez uniquement réinitialiser un fichier particulier dans l'index, vous pouvez utiliser git reset HEAD -- /path/to/file pour le faire.)

L'opérateur de canal, dans un shell, prend la stdout du processus à gauche et le transmet sous la forme stdin au processus à droite. C'est essentiellement l'équivalent de:

$ proc1 > proc1.out
$ proc2 < proc1.out
$ rm proc1.out

mais à la place, c'est $ proc1 | proc2, le deuxième processus peut commencer à obtenir des données avant que le premier soit terminé, et aucun fichier n'est impliqué.

15
Amber

Si HEAD n'est pas défini, vous pouvez également faire

git rm -rf --cached .

tout défaire. C'est en fait la même chose que la solution de sehe, mais cela évite de gâcher avec les internes de Git.

8
jjlin
git stash && git stash pop
8
Bijan

Attention: n'utilisez pas la commande suivante à moins que vous ne vouliez perdre du travail non souscrit!

L'utilisation de git reset a été expliquée, mais vous avez également demandé une explication des commandes redirigées.

git ls-files -z | xargs -0 rm -f
git diff --name-only --diff-filter=D -z | xargs -0 git rm --cached

La commande git ls-files répertorie tous les fichiers connus de git. L'option -z leur impose un format spécifique, le format attendu par xargs -0, qui y invoque ensuite rm -f, ce qui signifie de les supprimer sans vérification de votre approbation.

En d’autres termes, "liste tous les fichiers que git connaît et supprime votre copie locale".

Ensuite, nous arrivons à git diff, qui montre les changements entre les différentes versions des éléments que git connaît. Celles-ci peuvent être des changements entre différentes arborescences, des différences entre les copies locales et des copies distantes, etc.
Tel qu’utilisé ici, il montre les changements non mis en scène; les fichiers que vous avez modifiés mais que vous n'avez pas encore engagés. L'option --name-only signifie que vous voulez uniquement les noms de fichiers (complets) et --diff-filter=D signifie que vous êtes intéressé uniquement par les fichiers supprimés. (Hé, n'avons-nous pas simplement supprimé un tas de choses?) Ceci est ensuite transféré dans le xargs -0 que nous avons vu auparavant, qui invoque git rm --cached sur eux, ce qui signifie qu'ils sont supprimés du cache, tandis que l'arborescence de travail doit être laissée seule - sauf que vous venez de supprimer tous les fichiers de votre arborescence de travail. Maintenant, ils sont également supprimés de votre index.

En d'autres termes, tous les changements, programmés ou non, ont disparu et votre arbre de travail est vide. Faites un cri, récupérez vos fichiers d'origine ou distants et refaites votre travail. Maudit le sadique qui a écrit ces lignes infernales; Je ne sais absolument pas pourquoi quelqu'un voudrait faire cela.


TL; DR: vous venez de tout arroser; recommencez et utilisez git reset à partir de maintenant.

5
SQB

Je crains que la première de ces lignes de commande ne supprime inconditionnellement de la copie de travail tous les fichiers qui se trouvent dans la zone de transfert de git. Le second a libéré tous les fichiers suivis mais maintenant supprimés. Malheureusement, cela signifie que vous aurez perdu toutes les modifications non validées apportées à ces fichiers.

Si vous souhaitez obtenir votre copie de travail et l'indexation sur leur état d'origine lors de la dernière validation , vous pouvez (avec soin) utilisez la commande suivante:

git reset --hard

Je dis "soigneusement" depuis git reset --hardeffacera les modifications non validées de votre copie de travail et index. Cependant, dans cette situation, il semble que vous souhaitiez simplement revenir à l'état lors de votre dernier commit, et les modifications non validées ont été perdues de toute façon.

Mise à jour: vos commentaires sur la réponse d'Amber semblent indiquer que vous n'avez pas encore créé de commits (car HEAD ne peut pas être résolu), cela ne vous aidera donc pas. 'ai peur.

En ce qui concerne le fonctionnement de ces canaux: git ls-files -z et git diff --name-only --diff-filter=D -z produisent tous deux une liste de noms de fichiers séparés par l'octet 0. (Ceci est utile car, contrairement aux nouvelles lignes, 0 octets sont garantis ne pas apparaître dans les noms de fichiers sur les systèmes de type Unix.) Le programme xargs construit essentiellement des lignes de commande à partir de son entrée standard, par défaut en prenant lignes de l'entrée standard et en les ajoutant à la fin de la ligne de commande. L'option -0 indique qu'il faut s'attendre à une entrée standard séparée par 0 octets. xargs peut appeler la commande plusieurs fois pour utiliser tous les paramètres de l'entrée standard, en s'assurant que la ligne de commande ne devient jamais trop longue.

Par exemple, si vous avez un fichier appelé test.txt avec le contenu suivant:

hello
goodbye
hello again

... alors la commande xargs echo whatever < test.txt appellera la commande:

echo whatever hello goodbye hello again
2
Mark Longair

Si vous souhaitez annuler toutes les modifications, utilisez la commande ci-dessous,

git reset --soft HEAD

Dans le cas où vous souhaitez annuler la mise en scène des modifications et les revenir du répertoire de travail,

git reset --hard HEAD
1
027