Ajouter tous les fichiers à un commit sauf un seul fichier?

571

J'ai un tas de fichiers dans un ensemble de modifications, mais je veux ignorer spécifiquement un seul fichier modifié. Ressemble à ceci après git status:

# modified:   main/dontcheckmein.txt
# deleted:    main/plzcheckmein.c
# deleted:    main/plzcheckmein2.c
...

Existe-t-il un moyen de le faire, git addmais d'ignorer le seul fichier texte que je ne veux pas toucher? Quelque chose comme:

git add -u -except main/dontcheckmein.txt
user291701
la source

Réponses:

851
git add -u
git reset -- main/dontcheckmein.txt
Ben Jackson
la source
28
comment exclure tout le dossier? - principal ou principal / ou principal / *?
Alan Coromano
8
@MariusKavansky Vous pouvez utiliser tous ces formulaires. Si vous utilisez, main/*il est nécessaire de l'ajouter --devant pour faire savoir à git qu'il s'agit d'un chemin. Les deux autres variantes fonctionnent sans inclure les deux tirets. (Testé dans l'invite de commande sur Windows 7 avec msysGit)
dennisschagt
2
Si vous souhaitez exclure certains dossiers contenant une énorme quantité de fichiers ou d'autres dossiers: ajoutez-les temporairement à votre gitignore. effectuer un git resetpour ces dossiers par la suite fonctionnera toujours, mais il faudra du temps pour ajouter les gros dossiers.
Michael Trouw
2
Donc, il n'y a pas de doublure?
BroVic
5
@Ben Jackson serait bien de commenter chaque ligne, vous ne pensez pas?
ed1nh0
140

1) Pour commencer à ignorer les modifications apportées à un seul fichier déjà versionné

git update-index --assume-unchanged "main/dontcheckmein.txt"

et pour défaire ça git update-index --no-assume-unchanged "main/dontcheckmein.txt"

documents github pour ignorer les fichiers

2) Pour ignorer complètement un seul fichier spécifique empêchant sa création dans le référentiel

Tout d'abord, regardez ce post stackoverflow: Git global ignore ne fonctionne pas

Dans .gitignore, ajoutez le chemin d'accès relatif au fichier sans interligne ./.

Donc, si votre fichier est à MyProject/MyFolder/myfile.txt, (où se .gittrouve également dans le MyProjectdossier), ajoutez-le MyFolder/myfile.txtà votre .gitignorefichier at .

Vous pouvez confirmer les règles associées à ignorer via git check-ignore "MyFolder/myfile.txt"

À propos de Global Ignorer

Ce lien en parle ~/.gitignore_global, mais le fichier est lié à votre projet. Donc, si vous mettez le modèle ne comprennent pas MyFolder/myfile.txtdans ~/.gitignore_global, il ne fonctionnera mais ne fera pas beaucoup de sens ...

D'un autre côté, si vous configurez votre projet avec git config core.excludesfile .gitignore.gitignoreest situé MyProject, le fichier local sera prioritaire ~/.gitignore_global, ce qui peut avoir des règles très utiles ...

Donc, pour l' instant, je pense qu'il est préférable de faire un script pour mélanger votre .gitignoreavec ~/.gitignore_globalà .gitignore.

Un dernier avertissement
Si le fichier que vous souhaitez ignorer est déjà dans le référentiel, cette méthode ne fonctionnera que si vous le faites:, git rm "MyFolder/myfile.txt"mais sauvegardez-le d'abord, car il sera également supprimé localement! Vous pouvez le recopier plus tard ...

Puissance du Verseau
la source
5
Vous pouvez utiliser git rm --cached MyFolder/myyfile.txtpour supprimer le fichier du référentiel mais le conserver localement. Explication sur help.github.com
dennisschagt
87

Pour un fichier

git add -u
git reset -- main/dontcheckmein.txt

Pour un dossier

git add -u
git reset -- main/*
Rituraj ratan
la source
9
pourquoi le -u est-il nécessaire? pourquoi pas git add . && git reset -- main/*?
2
L'option -u met à jour l'index là où il a déjà une entrée correspondant à <pathspec>. Cela supprime et modifie les entrées d'index pour correspondre à l'arborescence de travail, mais n'ajoute aucun nouveau fichier. Si aucun <pathspec> n'est donné lorsque l'option -u est utilisée, tous les fichiers suivis dans l'arborescence de travail entière sont mis à jour (les anciennes versions de Git étaient utilisées pour limiter la mise à jour au répertoire actuel et à ses sous-répertoires).
Farhad Mammadli
6
Quelqu'un peut-il expliquer pourquoi le -u est nécessaire dans un langage que les pros non-git comprendront?
Patrick
2
-u est utilisé pour référencer votre branche actuelle vers laquelle vous faites pression. Vous n'aurez plus besoin de taper git push origin mastervotre prochain push, git pushet git saura que c'est dans la branche master. J'espère que cela aide.
Pepeng Hapon
69

gitPrend désormais en charge exclude certain paths and filespar pathspec magic :(exclude)et sa forme courte :!. Vous pouvez donc facilement y parvenir en utilisant la commande suivante.

git add --all -- :!main/dontcheckmein.txt
git add -- . :!main/dontcheckmein.txt

En fait, vous pouvez spécifier plus:

git add --all -- :!path/to/file1 :!path/to/file2 :!path/to/folder1/*
git add -- . :!path/to/file1 :!path/to/file2 :!path/to/folder1/*
yeux de chat
la source
1
La meilleure réponse, merci! Au moins, pour mon cas: j'avais juste besoin d'exclure un type de fichier.
Andre Polykanine
15
C'est excellent! Notez que sous Linux, vous devez citer les :!...clauses pour empêcher le shell de se plaindre. Ainsi, par exemple: git add --all -- ':!path/to/file1' ':!path/to/file2' ':!path/to/folder1/*'.
Martin_W
Y a-t-il quelque chose comme ça :!/path/to/(file1|file2)?
seeker_of_bacon
Cela entre en collision avec quelque chose dans zsh, ne fonctionne pas pour moi sur macOS et le dernier git.
Merlin
1
Quelqu'un peut-il indiquer où cela est officiellement documenté?
samurai_jane
20

Bien que Ben Jackson ait raison, j'ai pensé ajouter également comment j'utilisais cette solution. Vous trouverez ci-dessous un script très simple que j'utilise (que j'appelle gitadd) pour ajouter toutes les modifications, à l'exception de quelques-unes que je garde répertoriées dans un fichier appelé .gittrackignore(très similaire au fonctionnement de .gitignore).

#!/bin/bash
set -e

git add -A
git reset `cat .gittrackignore`

Et voici à quoi .gittrackignoreressemble mon courant .

project.properties

Je travaille sur un projet Android que je compile à partir de la ligne de commande lors du déploiement. Ce projet dépend de SherlockActionBar, il doit donc être référencé dans project.properties, mais cela gâche la compilation, alors maintenant je tape gitaddet j'ajoute toutes les modifications à git sans avoir à désajouter project.properties à chaque fois.

Anthony Naddeo
la source
Je ne savais pas ce qu'était --jusqu'à votre commentaire. Selon les pages de manuel, son optionnel et ne change pas le résultat de la commande (au moins dans ce cas). Cette question semble soutenir cela, stackoverflow.com/questions/17800994/… . Corrigez-moi si je me trompe, mais il semble que cela signifie "traiter quoi que ce soit après --comme des arguments, pas des options / commutateurs"
Anthony Naddeo
Belle utilisation de --dans que git checkoutje vois dans cette question. Je ne savais pas non plus ce qu'était le double tiret jusqu'à cet échange. Je me demande si l' git checkoutambiguïté entre les branches et les fichiers pourrait également affecter, sous cette forme ou sous une autre forme git reset.
Giulio Piancastelli
10

Pour conserver le changement dans le fichier mais pas pour valider, je l'ai fait

git add .

git reset -- main/dontcheckmein.txt

git commit -m "commit message"

pour vérifier que le fichier est exclu, faites

git status

gsumk
la source
4

Utilisez git add -Apour ajouter simultanément tous les fichiers modifiés et nouvellement ajoutés.

Exemple

git add -A
git reset -- main/dontcheckmein.txt
Dhanuka Nuwan
la source
4
git add .
git reset main/dontcheckmein.txt
Daniel Danielecki
la source
1

Pour le cas spécifique de la question, le moyen le plus simple serait d'ajouter tous les fichiers avec l' extension .c et de laisser de côté tout le reste:

git add *.c

De git-scm (ou / et man git add):

git add <pathspec>…

Fichiers pour ajouter du contenu. Des fichiers (par exemple * .c) peuvent être fournis pour ajouter tous les fichiers correspondants. <...>

Notez que cela signifie que vous pouvez également faire quelque chose comme:

git add **/main/*

pour ajouter tous les fichiers (qui ne sont pas ignorés) qui se trouvent dans le maindossier. Vous pouvez même vous déchaîner avec des motifs plus élaborés:

git add **/s?c/*Service*

Ce qui précède ajoutera tous les fichiers qui se trouvent dans le s(any char)cdossier et ontService quelque part dans leur nom de fichier.

De toute évidence, vous n'êtes pas limité à un modèle par commande. Autrement dit, vous pouvez demander à git d'ajouter tous les fichiers ayant une extension .c et .h :

git add *.c *.h

Ce lien pourrait vous donner d'autres idées de motifs globaux.

Je trouve cela particulièrement utile lorsque j'apporte de nombreux changements, mais je veux quand même que mes commits restent atomiques et reflètent un processus progressif plutôt qu'un mélange de changements sur lesquels je travaille à l'époque. Bien sûr, à un certain point, le coût de l'élaboration de modèles élaborés l'emporte sur le coût de l'ajout de fichiers avec des méthodes plus simples, ou même un fichier à la fois. Cependant, la plupart du temps, je peux facilement identifier les fichiers dont j'ai besoin avec un modèle simple et exclure tout le reste.

Au fait, vous devrez peut- être citer vos modèles globaux pour qu'ils fonctionnent, mais cela n'a jamais été le cas pour moi.

cegas
la source
0

J'utilise git add --patchun peu et je voulais quelque chose comme ça pour éviter d'avoir à frapper dtout le temps à travers les mêmes fichiers. J'ai concocté un couple d'alias git très hacky pour faire le travail:

[alias]
    HELPER-CHANGED-FILTERED = "!f() { git status --porcelain | cut -c4- | ( [[ \"$1\" ]] && egrep -v \"$1\" || cat ); }; f"
    ap                      = "!git add --patch -- $(git HELPER-CHANGED-FILTERED 'min.(js|css)$' || echo 'THIS_FILE_PROBABLY_DOESNT_EXIST' )"

Dans mon cas, je voulais juste ignorer tout le temps certains fichiers minifiés, mais vous pourriez lui faire utiliser une variable d'environnement comme $GIT_EXCLUDE_PATTERNpour un cas d'utilisation plus général.

Chris
la source
0

Modifications à valider: (utilisez "git reset HEAD ..." pour annuler la mise en scène)

colin rickels
la source
0

Vous pouvez essayer ceci: git add * && git reset main/dontcheckmein.txt

Rodrigo
la source