Quel est l'avantage du processus de validation en deux étapes de git (staging)?

175

J'apprends git et j'ai remarqué qu'il comporte un processus de validation en deux étapes:

  1. git add <files>
  2. git commit

La première étape place les révisions dans ce qu'on appelle une "zone intermédiaire" ou "index".

Ce qui m'intéresse, c'est pourquoi cette décision de conception est prise et quels sont ses avantages?

Aussi, en tant qu’utilisateur git, faites-vous cela ou utilisez-vous simplement git commit -a?

Je demande ceci car je viens de bzr (bazar) qui n'a pas cette fonctionnalité.

thomasrutter
la source
3
+1 pour demander. J'utilise Tortoise SVN, qui a la même approche et je n'ai jamais compris pourquoi.
DPD
3
La zone de rassemblement n'est pas si inhabituelle. L'équivalent dans, par exemple, TFS serait de cocher ou de décocher la case en regard d'un fichier avant de l'archiver. Seuls les fichiers cochés sont validés. La différence avec Git est que si vous utilisez git add -p, vous pouvez choisir de valider une partie d'un fichier sans commettre une autre partie du même fichier .
Kyralessa
J'ai trouvé que ce lien résume la plupart des réponses fournies ici et ajoute quelques cas d'utilisation supplémentaires pour justifier la nécessité de la mise en scène.
Veverke
2
Cette question a en fait déjà
trouvé une
1
N'oubliez pas git statuset éventuellement git push. Pour tout le battage médiatique sur git, (et le code de partage GitHub est merveilleux), les pièces sont très ennuyeuses
user949300

Réponses:

83

Diviser le travail en commets séparés. Vous avez probablement plusieurs fois ouvert un fichier pour écrire un correctif sur une seule ligne, mais vous avez en même temps remarqué que le formatage était incorrect, que certains documents pouvaient être améliorés ou que d'autres correctifs n'étaient pas liés. Avec les autres RCS, vous devez l'écrire ou le mettre en mémoire, terminer le correctif pour lequel vous êtes venu, le commettre, puis revenir pour réparer les autres éléments (ou créer un commet boule de boue avec des éléments non liés). . Avec Git, il vous suffit de tout corriger en même temps, puis de valider et de valider la ligne unique séparément, avec git add -iou git-gui.

Ne casse pas la construction. Vous travaillez sur une modification compliquée. Vous essayez donc différentes choses, dont certaines fonctionnent mieux que d'autres, d'autres qui cassent les choses. Avec Git, vous organisiez les événements lorsque la modification les améliorait et checkout(ou en modifiiez davantage) lorsque les modifications ne fonctionnaient pas. Vous n’avez pas à compter sur la fonctionnalité d’annulation de l’éditeur, vous pouvez utiliser checkoutle référentiel entier au lieu de fichier par fichier, ainsi que toute erreur de niveau fichier (telle que la suppression d’un fichier qui n’a pas été validé ou la sauvegarde + la fermeture mauvaise modification) n'entraîne pas beaucoup de travail perdu.

l0b0
la source
3
Venant d’un DVCS (bzr) qui n’a pas cette fonctionnalité, cela ressemble beaucoup à ce que j’obtiens actuellement avec une combinaison d’utilisation libérale des tampons "undo" de mon éditeur, de la commande "revert <fichier>" et des commits sélectifs (" commettez <fichier> "). On dirait que cette fonctionnalité de git a le potentiel d’être plus méthodique.
thomasrutter
1
En ce qui concerne "les autres RCS", ce n'est pas nécessairement vrai. En fait, vous pouvez obtenir les mêmes fonctionnalités dans Mercurial en utilisant des correctifs .
Lucio Paiva
1
@ l0b0, à propos de votre deuxième point. S'il n'y avait qu'une validation en une étape, vous auriez pu valider les modifications (que vous utilisez avec git add) directement en tant que validation. Si vous découvriez que vous avez commis une erreur, vous venez de supprimer le commit et de revenir à votre position actuelle. Avec le concept de la mise en scène, ne faites-vous pas cela, mais ajoutez-vous plus de complexité?
alpha_989
Votre premier point a du sens, bien que je ne l’aie pas encore utilisé. Théoriquement, pourquoi ne pouvez-vous pas faire quelque chose comme un git add -icommit à une étape? Il vous suffirait de sélectionner un groupe de fichiers (ou de lignes dans des fichiers) liés à une seule fonctionnalité et d'effectuer un commit. Ensuite, vous reviendriez et feriez un deuxième commit lié à une autre fonctionnalité.
alpha_989
@thomasrutter, votre déclaration semble indiquer que la zone intermédiaire crée des "points d'annulation manuels". Dans VIM avec persistent-undo, vous pouvez obtenir un historique illimité de manière très fiable. Ceci est également suivi automatiquement de git-branchmanière typographique ( jovicailic.org/2017/04/vim-persistent-undo ). De plus, votre historique des annulations est automatiquement suivi chaque fois que vous passez en mode normal. Cela vous évite d'avoir à créer des "points d'annulation manuels". Pourquoi l'utilisation de vos éditeurs "annuler" les tampons n'est-elle pas aussi méthodique?
alpha_989
65

L'un des avantages pour moi est la possibilité "d'ajouter" des fichiers progressivement. Avant de valider, je passe en revue chaque fichier. Une fois le fichier revu, je l'ajoute. Quand je git statusou git diff, git ne me montre que les fichiers qui ont été modifiés et qui n’ont pas encore été ajoutés. Après avoir examiné tous les fichiers et les avoir ajoutés, je peux valider.

Alors oui, je trouve la zone de préparation très utile.

Et non, je ne l'utilise jamais git commit -a. Cependant, j'utilise souvent git add -u. De cette façon, je peux toujours visualiser ce qui doit être engagé.

David
la source
2
Exactement. L’avantage est un contrôle beaucoup plus fin sur ce que vous commettez.
Josh K
que se passe-t-il lorsque vous créez un fichier plusieurs fois? est-ce qu'il est "fusionné" dans la zone de transit?
m4l490n
21

L'avantage est assez simple: il vous donne le plein contrôle sur les fichiers que vous voulez valider quand. D'ailleurs, vous pouvez utiliser git add -ppour contrôler les lignes que vous voulez valider.

Rein Henrichs
la source
2
Je me suis toujours demandé comment faire cela. J'aimerais qu'il y ait un fichier .gitignorelinesafin que vous puissiez apporter des modifications locales aux lignes individuelles qui pourraient survivre aux commits et rester intactes.
Alex Gray
3
@ReinHenrichs, pensez aux fichiers de configuration qui doivent être modifiés par chaque développeur.
Ian
1
@ Ian Donc, une partie du fichier change peu fréquemment et est partagée et une partie du fichier change souvent, de manière incompatible, et n'est pas partagée? Soutenir cette fausse connascence sonne vraiment comme un anti-fonctionnalité.
Rein Henrichs
1
@ReinHenrichs, oui et il est très courant que le fichier contienne le nom du serveur de base de données et que chaque dev y ait sa propre base de données.
Ian
4
@ Ian Votre problème est vraiment là, car vous avez un fichier qui est supposé être la configuration pour l'application contient également une configuration spécifique machine / dev. Tous les systèmes de configuration que je connais vous permettent de scinder cela en plusieurs fichiers. Ainsi, par exemple, vous avez votre app.confqui contient les éléments que vous souhaitez partager, puis un db.confélément que vous venez de mettre dans la liste .gitignore. Problème résolu. Si vous utilisez quelque chose de propriétaire, vous devriez vraiment chercher à obtenir quelque chose d'aussi simple. Ou faites-le passer par un pré-processeur dans un événement de pré-génération. Beaucoup de solutions là-bas.
Aidiakapi
1

L’un des avantages que j’aime est la possibilité d’engager une partie du changement. C'est à dire, en utilisant git add -e. Je ne m'engage pas aussi souvent que je le devrais parfois, et la commande git add -e me permet d'annuler les modifications dans une certaine mesure.

leed25d
la source