web-dev-qa-db-fra.com

Pourquoi existe-t-il deux manières de décomposer un fichier dans Git?

Parfois, git suggère git rm --cached pour décomposer un fichier, parfois git reset HEAD file. Quand devrais-je utiliser lequel?

MODIFIER:

D:\code\gt2>git init
Initialized empty Git repository in D:/code/gt2/.git/
D:\code\gt2>touch a

D:\code\gt2>git status
# On branch master
#
# Initial commit
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#       a
nothing added to commit but untracked files present (use "git add" to track)

D:\code\gt2>git add a

D:\code\gt2>git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
#   (use "git rm --cached <file>..." to unstage)
#
#       new file:   a
#
D:\code\gt2>git commit -m a
[master (root-commit) c271e05] a
 0 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 a

D:\code\gt2>touch b

D:\code\gt2>git status
# On branch master
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#       b
nothing added to commit but untracked files present (use "git add" to track)

D:\code\gt2>git add b

D:\code\gt2>git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       new file:   b
#
1048
Senthess

git rm --cached <filePath>ne décompose pas un fichier, il en fait procède à la suppression du (des) fichier (s) du repo (en supposant qu'il a déjà été validé auparavant) mais laisse la fichier dans votre arbre de travail (vous laissant avec un fichier non suivi).

git reset -- <filePath> va décompresser toutes les modifications planifiées pour le (s) fichier (s) donné (s).

Cela dit, si vous utilisiez git rm --cached sur un nouveau fichier mis en scène, vous auriez l’impression que vous l’aviez tout simplement désinstallé, car il n’avait jamais été commis auparavant.

1729
Ryan Stewart

git rm --cached est utilisé pour supprimer un fichier de l'index. Dans le cas où le fichier est déjà dans le référentiel, git rm --cached le supprimera de l'index, le laissant dans le répertoire de travail et une validation le supprimera également du référentiel. En gros, après la validation, vous auriez non versionné le fichier et conservé une copie locale.

git reset HEAD file (qui utilise par défaut le drapeau --mixed] est différent en ce que, dans le cas où le fichier est déjà dans le référentiel, il remplace la version d'index du fichier par celui du référentiel (HEAD ), en supprimant effectivement le modifications.

Dans le cas d'un fichier non versionné, il va détacher tout le fichier car le fichier n'était pas dans la tête. Dans cet aspect, git reset HEAD file et git rm --cached sont identiques, mais ils ne le sont pas (comme expliqué dans le cas de fichiers déjà dans le référentiel).

À la question de Why are there 2 ways to unstage a file in git? - il n'y a jamais vraiment une seule façon de faire quoi que ce soit dans git. c'est la beauté de celui-ci :)

324
manojlds

Tout simplement:

  • git rm --cached <file> fait que git arrête de suivre complètement le fichier (en le laissant dans le système de fichiers, contrairement à plain git rm *)
  • git reset HEAD <file> annule les modifications apportées au fichier depuis le dernier commit (mais ne les annule pas dans le système de fichiers, contrairement à ce que la commande son nom pourrait suggérer **). Le fichier reste sous contrôle de révision.

Si le fichier n’était pas sous contrôle de révision auparavant (c’est-à-dire que vous désassemblez un fichier que vous venez de lire git added pour la première fois), les deux commandes ont le même effet, d’où l’apparence de "deux façons de faire quelque chose ".

* Gardez à l'esprit l'avertissement que @DrewT mentionne dans sa réponse concernant git rm --cached d'un fichier précédemment validé dans le référentiel. Dans le contexte de cette question, d’un fichier venant d’être ajouté et non encore engagé, il n’ya pas de quoi s’inquiéter.

** J'ai eu très longtemps peur d'utiliser la commande git reset à cause de son nom - et encore aujourd'hui, je cherche souvent la syntaxe pour m'assurer de ne pas tout gâcher. ( update : J'ai finalement pris le temps de résume l'utilisation de git reset dans une page de tldr , alors maintenant J'ai un meilleur modèle mental de la façon dont cela fonctionne, et une référence rapide pour quand j'oublie certains détails.)

115
waldyrious

Ce fil est un peu vieux, mais je veux quand même ajouter une petite démonstration car ce n'est toujours pas un problème intuitif:

me$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   new file:   to-be-added
#   modified:   to-be-modified
#   deleted:    to-be-removed
#

me$ git reset -q HEAD to-be-added

    # ok

me$ git reset -q HEAD to-be-modified

    # ok

me$ git reset -q HEAD to-be-removed

    # ok

# or alternatively:

me$ git reset -q HEAD to-be-added to-be-removed to-be-modified

    # ok

me$ git status
# On branch master
# Changes not staged for commit:
#   (use "git add/rm <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   to-be-modified
#   deleted:    to-be-removed
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#   to-be-added
no changes added to commit (use "git add" and/or "git commit -a")

git reset HEAD (sans -q) avertit du fichier modifié et son code de sortie est 1, ce qui sera considéré comme une erreur dans un script.

Edit: git checkout HEAD to-be-modified to-be-removed fonctionne également pour la décomposition, mais supprime complètement la modification de l'espace de travail.

44
Daniel Alder

si vous avez accidentellement mis en place des fichiers que vous ne souhaitez pas valider et que vous souhaitez être sûr de conserver les modifications, vous pouvez également utiliser:

git stash
git stash pop

cela réinitialise HEAD et réapplique vos modifications, ce qui vous permet de reformater des fichiers individuels pour la validation. Cela est également utile si vous avez oublié de créer une branche de fonctionnalité pour les demandes d'extraction (git stash ; git checkout -b <feature> ; git stash pop).

35
ives

Ces 2 commandes présentent plusieurs différences subtiles si le fichier en question est déjà dans le référentiel et sous contrôle de version (précédemment validé, etc.):

  • git reset HEAD <file> désactive le fichier dans la validation en cours.
  • git rm --cached <file> démontera également le fichier pour les futurs commits. Il n'a pas été démarré jusqu'à ce qu'il soit ajouté à nouveau avec git add <file>.

Et il y a une autre différence importante:

  • Après avoir exécuté git rm --cached <file> et poussé votre branche vers la télécommande, toute personne tirant votre branche depuis la télécommande obtiendra le fichier EN FAIT de son dossier, même si vous avez défini le fichier dans votre répertoire de travail local. devient simplement non dépisté (c.-à-d. qu'il n'est pas supprimé physiquement du dossier).

Cette dernière différence est importante pour les projets qui incluent un fichier de configuration dans lequel chaque développeur de l’équipe a une configuration différente (c.-à-d. Paramètres de base, d’IP ou de port différents). Par conséquent, si vous utilisez git rm --cached <file>, toute personne qui tire votre branche vous devez recréer manuellement la configuration, ou vous pouvez lui envoyer le vôtre et le modifier à nouveau dans ses paramètres ip (etc.), car la suppression ne concerne que les personnes qui extraient votre branche de la télécommande.

15
DrewT

1.

D:\code\gt2>git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
#   (use "git rm --cached <file>..." to unstage)
#
#       new file:   a

(utilisez "git rm --cached ..." pour décompresser)

  • git est un système de pointeurs

  • vous n'avez pas encore engagé de changer votre pointeur

  • le seul moyen de "sortir les fichiers du compartiment indiqué" est de supprimer les fichiers que vous avez demandé à git de surveiller les modifications

2.

D:\code\gt2>git commit -m a
[master (root-commit) c271e05] a
0 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 a

git commit -m a

  • vous avez commis, 'sauvegardé'

3.

D:\code\gt2>git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       new file:   b
#

(utilisez "git reset HEAD ..." pour décompresser)

  • vous avez fait un commit dans votre code en ce moment
  • maintenant vous pouvez réinitialiser votre pointeur sur votre commit 'revenir à la dernière sauvegarde'
9

Disons que vous stage un répertoire complet via git add <folder>, mais que vous souhaitez exclure un fichier de la liste intermédiaire (c'est-à-dire la liste générée lors de l'exécution de git status) et conserver les modifications dans le fichier exclu (vous travailliez sur quelque chose et il n'est pas prêt pour la validation, mais vous ne voulez pas perdre votre travail ...). Vous pouvez simplement utiliser:

git reset <file>

Lorsque vous exécutez git status, vous constaterez que le ou les fichiers pour lesquels vous êtes reset sont unstaged et que le reste des fichiers pour lesquels vous avez added figurent toujours dans la liste staged.

8
jiminikiz

Je suis surpris que personne ne mentionne le git reflog ( http://git-scm.com/docs/git-reflog ):

# git reflog
<find the place before your staged anything>
# git reset HEAD@{1}

Reflog est un historique git qui non seulement suit les modifications apportées au référentiel, mais également les actions de l'utilisateur (par exemple, extraire, extraire vers une autre branche, etc.) et permet d'annuler ces actions. Ainsi, au lieu de décomposer le fichier qui a été mis en scène par erreur, vous pouvez revenir au point où vous n'avez pas préparé les fichiers.

Ceci est similaire à git reset HEAD <file> mais dans certains cas, il peut être plus granulaire.

Désolé, je ne réponds pas vraiment à votre question, mais vous indiquez une autre façon de décomposer les fichiers que j’utilise assez souvent (par exemple, les réponses de Ryan Stewart et waldyrious sont très utiles););) j’espère que cela aidera.

5
Alex

Il me semble que git rm --cached <file> supprime le fichier de l’index sans le supprimer du répertoire où un simple git rm <file> ferait les deux, tout comme un système d’exploitation rm <file> supprimerait le fichier du répertoire sans supprimer son versioning.

3
ernie.cordell