Je suis nouveau dans le contrôle de version et je comprends que «commettre» consiste essentiellement à créer une sauvegarde tout en mettant à jour la nouvelle version «actuelle» de ce sur quoi vous travaillez.
Ce que je ne comprends pas, c'est à quoi sert la mise en scène d'un point de vue pratique. La mise en scène est-elle quelque chose qui n'existe que de nom ou sert-elle un objectif? Quand vous vous engagez, ça va tout commettre de toute façon, non?
Edit: Je pense que je peux confondre la terminologie. Un fichier «intermédiaire» est-il la même chose qu'un fichier «suivi»?
Réponses:
Lorsque vous validez, il ne validera que les changements dans l'index (les fichiers "staged"). Il existe de nombreuses utilisations pour cela, mais la plus évidente est de diviser vos changements de travail en morceaux plus petits et autonomes. Peut-être avez-vous corrigé un bogue lors de l'implémentation d'une fonctionnalité. Vous pouvez
git add
juste ce fichier (ougit add -p
pour ajouter juste une partie d'un fichier!) Et puis valider ce correctif avant de valider tout le reste. Si vous utilisez,git commit -a
vous ne faites que forcer unadd
de tout juste avant la validation. Ne pas utiliser-a
si vous souhaitez tirer parti des fichiers intermédiaires.Vous pouvez également traiter les fichiers intermédiaires comme une copie de travail intermédiaire avec les
--cached
commandes to many. Par exemple,git diff --cached
vous montrera en quoi la scène diffère deHEAD
sorte que vous puissiez voir ce que vous êtes sur le point de valider sans mélanger vos autres modifications de travail.la source
git reset --hard
.git diff --staged
et vérifiez quels fichiers vous avez modifiés et où et commencez à apporter d'autres modifications.la source
Un objectif pratique de la mise en scène est la séparation logique des validations de fichiers.
Comme la préparation vous permet de continuer à apporter des modifications aux fichiers / répertoire de travail, et d'effectuer des validations par parties lorsque vous pensez que les choses sont prêtes, vous pouvez utiliser des étapes distinctes pour des modifications logiquement non liées.
Supposons que vous ayez 4 fichiers
fileA.html
,fileB.html
,fileC.html
etfileD.html
. Vous apportez des modifications aux 4 fichiers et êtes prêt à valider mais les modifications dansfileA.html
etfileB.html
sont logiquement liées (par exemple, la même nouvelle implémentation de fonctionnalité dans les deux fichiers) tandis que les modifications dansfileC.html
etfileD.html
sont séparées et logiquement sans rapport avec les fichiers précédents. Vous pouvez tout d' abord les fichiers de scènefileA.html
etfileB.html
et engager ceux -ci .Ensuite, à l'étape suivante, vous installez et validez les modifications apportées aux deux fichiers restants.
la source
git commit -m "Implemented new feature XYZ" fileA.html fileB.html
fonctionnerait très bien sans avoir besoin des commandes git add. Je viens du monde subversion où la mise en scène n'est pas un concept, donc, je ne suis pas convaincu de l'utilité de la mise en scène gitIl est plus facile de comprendre l'utilisation des commandes git
add
etcommit
si vous imaginez qu'un fichier journal est maintenu dans votre référentiel sur Github. Le fichier journal d'un projet typique pour moi peut ressembler à:Je commence généralement ma journée par une
git pull
demande et je la termine par unegit push
demande. Donc, tout ce qui se passe dans le journal d'une journée correspond à ce qui se passe entre eux. Au cours de chaque journée, il y a une ou plusieurs tâches logiques que j'effectue qui nécessitent de changer quelques fichiers. Les fichiers modifiés au cours de cette tâche sont répertoriés dans un index.Chacune de ces sous-tâches (tâche A et tâche B ici) sont des commits individuels. La
git add
commande ajoute des fichiers à la liste «Index des fichiers modifiés». Ce processus est également appelé mise en scène. legit commit
commande enregistre / finalise les modifications et la liste d'index correspondante avec un message personnalisé.N'oubliez pas que vous ne modifiez toujours que la copie locale de votre référentiel et non celle sur Github. Après cela, ce n'est que lorsque vous faites un 'git push' que toutes ces modifications enregistrées, ainsi que vos fichiers d'index pour chaque commit, sont enregistrés sur le référentiel principal (sur Github).
À titre d'exemple, pour obtenir la deuxième entrée dans ce fichier journal imaginaire, j'aurais fait:
En un mot,
git add
etgit commit
vous permet de décomposer une modification du référentiel principal en sous-modifications logiques systématiques. Comme d'autres réponses et commentaires l'ont souligné, il y a bien sûr de nombreuses autres utilisations. Cependant, c'est l'un des usages les plus courants et un principe directeur derrière le fait que Git soit un système de contrôle de révision en plusieurs étapes contrairement à d'autres systèmes populaires comme Svn.la source
La zone de préparation nous aide à créer les commits avec une plus grande flexibilité. Par artisanat, je veux dire diviser les commits en unités logiques. Ceci est très important si vous voulez un logiciel maintenable. La manière la plus évidente d'y parvenir:
Vous pouvez travailler sur plusieurs fonctionnalités / bogues dans un seul répertoire de travail tout en créant des commits significatifs. Avoir un répertoire de travail unique qui contient tout notre travail actif est également très pratique. (Cela peut être fait sans zone de préparation, à condition que les modifications ne chevauchent jamais un fichier. Et vous avez également la responsabilité supplémentaire de suivre manuellement si elles se chevauchent)
Vous pouvez trouver plus d'exemples ici: Utilisations de l'index
Et la meilleure partie est que les avantages ne s'arrêtent pas à cette liste de flux de travail. Si un flux de travail unique se produit, vous pouvez être presque sûr que la zone de préparation vous aidera.
la source
Pour développer la réponse de Ben Jackson , ce qui est bien, regardons de près la question initiale. (Voir sa réponse pour savoir pourquoi taper des questions; c'est plus sur ce qui se passe .)
Ce n'est pas tout à fait vrai. Les sauvegardes et le contrôle de version sont certainement liés - la mesure exacte dépend exactement de certaines choses qui sont dans une certaine mesure une question d'opinion - mais il existe certainement des différences, ne serait-ce que dans l'intention: les sauvegardes sont généralement conçues pour la reprise après sinistre (la machine tombe en panne, le feu détruit bâtiment entier, y compris tous les supports de stockage, etc.). Le contrôle de version est généralement conçu pour des interactions plus fines et offre des fonctionnalités que les sauvegardes ne font pas. Les sauvegardes sont généralement stockées pendant un certain temps, puis jetées comme «trop anciennes»: une sauvegarde plus récente est tout ce qui compte. Le contrôle de version enregistre normalement pour toujours chaque version validée.
Oui et non. La conception de Git ici est quelque peu particulière. Il existe des systèmes de contrôle de version qui ne nécessitent pas d'étape de préparation distincte. Par exemple, Mercurial, qui ressemble beaucoup à Git en termes d'utilisation, ne nécessite pas d'
hg add
étape distincte , au-delà de la toute première qui introduit un tout nouveau fichier. Avec Mercurial, vous utilisez lahg
commande qui sélectionne un commit, puis vous faites votre travail, puis vous exécutezhg commit
et vous avez terminé. Avec Git, vous utilisezgit checkout
, 1 puis vous faites votre travail, puis vous exécutezgit add
, et puisgit commit
. Pourquoi le plusgit add
étape ?Le secret ici est ce que Git appelle, diversement, l' index , ou la zone de transit , ou parfois - rarement de nos jours - le cache . Ce sont tous des noms pour la même chose.
Non, mais ceux-ci sont liés. Un fichier suivi est celui qui existe dans l'index de Git. Pour bien comprendre l'index, il est bon de commencer par comprendre les commits.
Depuis la version 2.23 de Git, vous pouvez utiliser à la
git switch
place degit checkout
. Dans ce cas particulier, ces deux commandes font exactement la même chose. La nouvelle commande existe parce qu'elle agit checkout
été surchargée de trop de choses; ils ont été divisés en deux commandes distinctes,git switch
etgit restore
pour rendre l'utilisation de Git plus facile et plus sûre.S'engage
Dans Git, un commit enregistre un instantané complet de chaque fichier que Git connaît. (Quels fichiers Git connaît-il? Nous le verrons dans la section suivante.) Ces instantanés sont stockés sous une forme spéciale, en lecture seule, Git seule, compressée et dédupliquée, qu'en général seul Git lui-même peut lire . (Il y a plus de choses dans chaque commit que juste cet instantané, mais c'est tout ce que nous allons couvrir ici.)
La déduplication aide à gagner de l'espace: nous ne modifions normalement que quelques fichiers, puis nous faisons un nouveau commit. Alors plupart des fichiers d'un commit sont pour la plupart les mêmes que les fichiers du commit précédent. En réutilisant simplement ces fichiers directement, Git économise beaucoup d'espace: si nous n'avons touché qu'un seul fichier, le nouveau commit ne prend de l'espace que pour une nouvelle copie. Même dans ce cas, il est compressé - parfois très compressé, bien que cela se produise en fait plus tard - de sorte qu'un
.git
répertoire peut en fait être plus petit que les fichiers qu'il contient, une fois qu'ils sont développés en fichiers ordinaires de tous les jours. La déduplication est sûre car les fichiers validés sont figés pour toujours. Personne ne peut en changer un, il est donc sûr que les commits dépendent des copies des uns et des autres.Cependant, étant donné que les fichiers stockés sont dans ce format spécial, figé pour toujours, uniquement Git, Git doit développer chaque fichier en une copie ordinaire de tous les jours. Cette copie ordinaire n'est pas celle de Git copie : c'est votre copie, à faire comme vous voudrez. Git écrira simplement à ceux-ci lorsque vous lui direz de le faire, afin que vous ayez vos copies avec lesquelles travailler. Ces copies utilisables se trouvent dans votre arbre de travail ou votre arbre de travail .
Cela signifie que lorsque vous extrayez un commit particulier, il y a automatiquement deux copies de chaque fichier:
Git a une copie figée pour toujours, Git-ified dans le commit actuel . Vous ne pouvez pas modifier cette copie (bien que vous puissiez bien sûr sélectionner un autre commit, ou faire un nouveau commit).
Vous avez, dans votre arbre de travail, une copie au format normal. Vous pouvez faire tout ce que vous voulez, en utilisant l'une des commandes de votre ordinateur.
D'autres systèmes de contrôle de version (dont Mercurial comme mentionné ci-dessus) s'arrêtent ici, avec ces deux exemplaires. Vous venez de modifier la copie de votre arbre de travail, puis de vous engager. Git ... pas.
L'index
Entre ces deux copies, Git stocke une troisième copie 2 de chaque fichier. Cette troisième copie est au format figé , mais contrairement à la copie figée du commit, vous pouvez la modifier. Pour le changer, vous utilisez
git add
.La
git add
commande signifie que la copie d'index du fichier correspond à la copie de l'arbre de travail . Autrement dit, vous dites à Git: Remplacez la copie dédupliquée au format gelé qui se trouve dans l'index maintenant, en compressant ma copie mise à jour de l'arbre de travail, en la dédupliquant et en la préparant à être gelée dans un nouveau commit. Si vous n'utilisezgit add
, l'index contient toujours la copie au format gelé de la validation actuelle.Lorsque vous exécutez
git commit
, Git compile tout ce qui se trouve dans l'index à ce moment-là à utiliser comme nouvel instantané. Comme il est déjà au format figé et pré-dédupliqué, Git n'a pas à faire beaucoup de travail supplémentaire.Cela explique également ce que sont les fichiers non suivis . Un fichier non suivi est un fichier qui se trouve dans votre arbre de travail mais qui n'est pas dans l'index de Git pour le moment . Peu importe comment le dossier s'est terminé dans cet état. Peut-être que vous l'avez copié d'un autre endroit sur votre ordinateur, dans votre arbre de travail. Peut-être que vous l'avez créé ici. Il y avait peut- être une copie dans l'index de Git, mais vous avez supprimé cette copie avec
git rm --cached
. D'une manière ou d'une autre, il y a une copie ici dans votre arbre de travail, mais il n'y en a pas de copie dans l'index de Git. Si vous effectuez un nouveau commit maintenant, ce fichier ne sera pas dans le nouveau commit.Notez que remplit
git checkout
initialement l'index de Git à partir du commit que vous extrayez. Ainsi, l'index commence par correspondre au commit. Git remplit également votre arbre de travail à partir de cette même source. Donc, au départ, les trois correspondent. Lorsque vous modifiez des fichiers dans votre arbre de travail et eux, eh bien, maintenant l'index et votre arbre de travail correspondent. Alors tu coursgit add
git commit
et Git effectue un nouveau commit à partir de l'index, et maintenant les trois correspondent à nouveau.Étant donné que Git effectue de nouveaux commits à partir de l'index, nous pouvons mettre les choses de cette façon: l'index de Git contient le prochain commit que vous prévoyez de faire. Cela ignore le rôle étendu que l'index de Git assume lors d'une fusion en conflit, mais nous aimerions quand même l'ignorer pour le moment. :-)
C'est tout ce qu'il y a à faire - mais c'est quand même assez compliqué! C'est particulièrement délicat car il n'y a pas de moyen facile de voir exactement ce qu'il y a dans l'index de Git. 3 Mais il existe une commande Git qui vous dit ce qui se passe, d'une manière assez utile, et cette commande l'est
git status
.2 Techniquement, ce n'est pas du tout une copie . Au lieu de cela, c'est une référence au fichier Git-ified, pré-dédupliqué et tout. Il y a également d'autres éléments ici, tels que le mode, le nom du fichier, un numéro de transfert et des données de cache pour accélérer Git. Mais à moins que vous ne vous mettiez à travailler avec certaines des commandes de bas niveau de Git -
git ls-files --stage
etgit update-index
en particulier - vous pouvez le considérer comme une copie.3 La
git ls-files --stage
commande vous montrera les noms et les numéros de transfert de chaque fichier dans l'index de Git, mais ce n'est généralement pas très utile de toute façon.git status
La
git status
commande fonctionne en fait en exécutant deuxgit diff
commandes distinctes pour vous (et en faisant également d'autres choses utiles, telles que vous dire sur quelle branche vous vous trouvez).Le premier
git diff
compare le commit actuel - qui, rappelez-vous, est figé pour toujours - à ce qui se trouve dans l'index de Git. Pour les fichiers identiques , Git ne dira rien du tout. Pour les fichiers différents , Git vous indiquera que ce fichier est préparé pour la validation . Cela inclut tous les nouveaux fichiers, si la validation n'a passub.py
en elle, mais l'indice n'avoir en elle, ce fichier est ajouté et tous les fichiers supprimés, qui étaient (et sont) dans la commettras mais ne sont pas en l'index plus (sub.py
git rm
, peut-être).Le second
git diff
compare tous les fichiers de l'index de Git aux fichiers de votre arbre de travail. Pour les fichiers identiques , Git ne dit rien du tout. Pour les fichiers différents , Git vous indiquera que ce fichier n'est pas préparé pour la validation . Contrairement à la première différence, cette liste particulière n'inclut pas les fichiers qui sont tout nouveaux: si le fichieruntracked
existe dans votre arbre de travail, mais pas dans l'index de Git, Git l'ajoute simplement à la liste des fichiers non suivis . 4À la fin, après avoir accumulé ces fichiers non suivis dans une liste, les noms de ces fichiers
git status
seront également annoncés , mais il y a une exception spéciale: si le nom d'un fichier est répertorié dans un fichier, cela supprime cette dernière liste. Notez que lister un fichier suivi - celui qui est dans l'index de Git - dans un n'a aucun effet ici : le fichier est dans l'index, donc il est comparé et est validé, même s'il est répertorié dans . Le fichier ignorer ne supprime que les plaintes de "fichier non suivi". 5.gitignore
.gitignore
.gitignore
4 Lorsque vous utilisez la version courte de
git status
-git status -s
, les fichiers non suivis ne sont pas aussi séparés, mais le principe est le même. Accumuler les fichiers comme celui-ci permet également degit status
résumer un tas de noms de fichiers non suivis en imprimant simplement un nom de répertoire, parfois. Pour obtenir la liste complète, utilisezgit status -uall
ougit status -u
.5 Lister un fichier permet également d' ajouter en masse de nombreuses opérations sur les fichiers comme
git add .
ou degit add *
sauter le fichier non suivi. Cette partie devient un peu plus compliquée, car vous pouvez l'utilisergit add --force
pour ajouter un fichier qui serait normalement ignoré. Il existe d'autres cas spéciaux normalement mineurs, qui s'ajoutent tous à ceci: le fichier.gitignore
peut être appelé plus correctement.git-do-not-complain-about-these-untracked-files-and-do-not-auto-add-them
ou quelque chose d'aussi peu maniable. Mais c'est trop ridicule, donc.gitignore
ça l'est.git add -u
,git commit -a
, Etc.Il y a plusieurs raccourcis pratiques à connaître ici:
git add .
ajoutera tous les fichiers mis à jour dans le répertoire courant et tout sous-répertoire. Cela respecte.gitignore
, donc si un fichier actuellement non suivi n'est pas critiqué pargit status
, il ne sera pas ajouté automatiquement.git add -u
ajoutera automatiquement tous les fichiers mis à jour n'importe où dans votre arbre de travail . 6 Cela affecte uniquement les fichiers suivis . Notez que si vous avez supprimé la copie de l'arborescence de travail, cela supprimera également la copie d'index (git add
cela fait-il partie de faire correspondre l'index à l'arborescence de travail ).git add -A
est comme courir àgit add .
partir du niveau supérieur de votre arbre de travail (mais voir la note de bas de page 6).En plus de cela, vous pouvez exécuter
git commit -a
, ce qui équivaut à peu près à 7 à courirgit add -u
et ensuitegit commit
. Autrement dit, cela vous donne le même comportement qui est pratique dans Mercurial.Je déconseille généralement le
git commit -a
modèle: je trouve qu'il vaut mieux l'utilisergit status
souvent, regardez attentivement la sortie , et si le statut n'est pas celui que vous attendiez, découvrez pourquoi c'est le cas. En utilisantgit commit -a
, il est trop facile de modifier accidentellement un fichier et de valider une modification que vous n'aviez pas l'intention de valider. Mais c'est surtout une question de goût / d'opinion.6 Si votre version de Git est antérieure à Git 2.0, soyez prudent ici:
git add -u
ne fonctionne que sur le répertoire et les sous-répertoires actuels, vous devez donc d'abord monter au niveau supérieur de votre arbre de travail. L'git add -A
option a un problème similaire.7 Je dis à peu près équivalent car
git commit -a
fonctionne en fait en créant un index supplémentaire et en utilisant cet autre index pour faire le commit. Si le commit fonctionne , vous obtenez le même effet que doinggit add -u && git commit
. Si le commit ne fonctionne pas - si vous obligez Git à ignorer le commit de l'une des nombreuses façons dont vous pouvez le faire - alors aucun fichier n'estgit add
-ed par la suite, car Git jette l'index supplémentaire temporaire et revient à utiliser l'index principal .Il y a des complications supplémentaires qui entrent en jeu si vous utilisez
git commit --only
ici. Dans ce cas, Git crée un troisième index, et les choses deviennent très délicates, surtout si vous utilisez des hooks pré-commit. C'est une autre raison d'utiliser desgit add
opérations distinctes .la source
Je vois l'intérêt d'utiliser stage pour réduire les commits comme mentionné par @Ben Jackson et @Tapashee Tabassum Urmi et parfois je l'utilise à cette fin, mais je l'utilise principalement pour agrandir mes commits! voici mon point:
Disons que je veux ajouter une petite fonctionnalité qui nécessite plusieurs étapes plus petites. Je ne vois aucun intérêt à avoir un commit séparé pour les étapes plus petites et à inonder ma chronologie. Cependant je souhaite sauvegarder chaque étape et revenir en arrière si nécessaire,
Je mets simplement en scène les plus petites étapes les unes sur les autres et quand je sens que cela vaut la peine d'être engagé, je m'engage. De cette façon, je supprime les commits inutiles de la chronologie tout en étant capable d'annuler (vérifier) la dernière étape.
Je vois d'autres façons de faire cela (simplifier l'historique de git) que vous pourriez utiliser en fonction de vos préférences:
la source
C'est comme une case à cocher qui permet de choisir les fichiers à valider.
par exemple, si j'ai édité
fileA.txt
etfileB.txt
.Mais je veux valider les modifications defileA.txt
seulement. parce que je n'en ai pas encore fini avecfileB.txt
.Je peux simplement utiliser
git add fileA.txt
et m'engager en utilisantgit commit -m "changed fileA.txt"
et continuer à travailler avecfileB.txt
et après avoir terminé, je peux m'engagerfileB.txt
facilementla source