J'utilise Perforce depuis plusieurs années. J'aimerais passer à l'utilisation de git pour mon code personnel, mais tous les tutoriels git que j'ai vus supposent que vous êtes un contrôle de source complet n00b (ce qui les rend incroyablement fastidieux) ou que vous êtes habitué à svn (ce que je ne suis pas).
Je connais p4, et je comprends aussi l'idée derrière un système de contrôle de source distribué (donc je n'ai pas besoin d'un argumentaire de vente, merci). Ce que je voudrais, c'est une table de traduction de la commande p4 vers des commandes git équivalentes, ainsi que les commandes "ne peut pas vivre sans" qui n'ont pas d'équivalent p4.
Puisque je soupçonne que chaque utilisateur de p4 utilise un sous-ensemble différent de p4, voici quelques-unes des choses que je fais régulièrement dans p4 que j'aimerais pouvoir faire dans git qui ne sont pas immédiatement évidentes à partir des documents que j'ai consultés :
- créer plusieurs listes de modifications en attente dans un seul client. (
p4 change
) - modifier une liste de modifications en attente. (aussi
p4 change
) - voir une liste de toutes mes listes de modifications en attente (
p4 changes -s pending
) - liste de tous les fichiers modifiés dans mon client (
p4 opened
) ou dans une liste de modifications en attente (p4 describe
) - voir un diff d'une liste de modifications en attente (j'utilise un script wrapper pour cela qui utilise
p4 diff
etp4 describe
) - pour un fichier donné, voir quelles listes de modifications soumises ont affecté quelles lignes (
p4 annotate
) - pour un fichier donné, voir une liste des descriptions des listes de modifications qui ont affecté le fichier (
p4 log
) - soumettre une liste de modifications en attente (
p4 submit -c
) - abandonner une liste de modifications en attente (
p4 revert
)
Beaucoup d'entre eux tournent autour de "listes de modifications". "changelist" est la terminologie p4. Quel est le terme équivalent à git?
On dirait que les branches pourraient être ce que les utilisateurs de git utilisent à la place de ce que p4 appelle les listes de modifications. Un peu déroutant, car p4 a aussi quelque chose qui s'appelle une branche bien qu'ils ne semblent être que des concepts vaguement liés. (Bien que j'ai toujours pensé que le concept de branche de p4 était assez étrange, il est encore une fois différent du concept RCS classique d'une branche.)
Quoi qu'il en soit ... Je ne sais pas comment accomplir ce que je fais normalement dans les listes de modifications p4 avec les branches de git. Dans p4, je peux faire quelque chose comme ceci:
$ p4 edit a.txt
$ p4 change a.txt
Change 12345 created.
À ce stade, j'ai une liste de modifications qui contient a.txt. Je peux modifier la description et continuer à travailler sans soumettre la liste des modifications. De plus, s'il s'avère que j'ai besoin d'apporter des modifications à certains autres fichiers, comme par exemple un correctif dans une autre couche du code, je peux le faire dans le même client:
$ p4 edit z.txt
$ p4 change z.txt
Change 12346 created.
Maintenant, j'ai deux listes de modifications distinctes dans le même client. Je peux travailler sur ces derniers simultanément, et je n'ai rien à faire pour "basculer entre" eux. Quand vient le temps de m'engager, je peux les soumettre séparément:
$ p4 submit -c 12346 # this will submit the changes to z.txt
$ p4 submit -c 12345 # this will submit the changes to a.txt
Je ne peux pas comprendre comment répliquer cela dans git. D'après mes expériences, il ne semble pas que ce git add
soit associé à la branche actuelle. Pour autant que je sache, quand je git commit
vais valider tous les fichiers que j'ai git add
créés, quelle que soit la branche dans laquelle je me trouvais à l'époque:
$ git init
Initialized empty Git repository in /home/laurence/git-playground/.git/
$ ls
a.txt w.txt z.txt
$ git add -A .
$ git commit
Initial commit.
3 files changed, 3 insertions(+), 0 deletions(-)
create mode 100644 a.txt
create mode 100644 w.txt
create mode 100644 z.txt
$ vi a.txt z.txt
2 files to edit
$ git status
# On branch master
# Changed but not updated:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: a.txt
# modified: z.txt
#
no changes added to commit (use "git add" and/or "git commit -a")
$ git branch aardvark
$ git checkout aardvark
M a.txt
M z.txt
Switched to branch 'aardvark'
$ git add a.txt
$ git checkout master
M a.txt
M z.txt
Switched to branch 'master'
$ git branch zebra
$ git checkout zebra
M a.txt
M z.txt
Switched to branch 'zebra'
$ git add z.txt
$ git status
# On branch zebra
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: a.txt
# modified: z.txt
#
$ git checkout aardvark
M a.txt
M z.txt
Switched to branch 'aardvark'
$ git status
# On branch aardvark
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: a.txt
# modified: z.txt
Dans cet exemple, les branches aardvark et zebra semblent contenir exactement le même ensemble de modifications, et en fonction de la sortie de celles- git status
ci, il semble que faire un commit dans l'une ou l'autre aura le même effet. Est-ce que je fais quelque chose de mal?
Réponses:
Je n'ai pas beaucoup utilisé forcément, donc ce n'est peut-être pas exactement une traduction 1: 1. Là encore, les systèmes de contrôle de source distribués comme git et mercurial ont de toute façon un flux de travail différent, donc il n'y a vraiment pas (et il ne devrait pas y avoir) de traduction 1: 1. Quoi qu'il en soit, voici:
Créez plusieurs listes de modifications en attente -> Utilisez plutôt des branches. Dans git, les branches sont légères et rapides, prennent moins d'une seconde à créer et généralement moins de deux secondes à fusionner. N'ayez pas peur des branches et rebase souvent.
Ou faites tout cela en une seule ligne:
Voir une liste de toutes les listes de modifications en attente -> Étant donné que l'équivalent de plusieurs listes de modifications en attente est plusieurs branches, affichez simplement les branches:
Si vous souhaitez également afficher les branches distantes:
Il est recommandé de supprimer immédiatement une branche après une fusion réussie afin de ne pas avoir à garder une trace des branches en attente de fusion et de celles qui ont déjà été fusionnées.
Liste tous les fichiers modifiés -> Pour une seule "liste de modifications" en attente dans une branche spécifique, git a un concept d'index ou de cache. Pour valider une modification, vous devez d'abord ajouter des fichiers à cet index. Cela vous permet de sélectionner manuellement le groupe de fichiers représentant un seul changement ou d'ignorer les fichiers non pertinents. Pour voir l'état des fichiers ajoutés ou non à cet index, faites simplement:
Voir un diff d'une liste de modifications en attente -> Il y a deux parties à cela. Tout d'abord pour voir une différence entre le répertoire de travail et l'index:
Mais si vous voulez connaître la différence entre ce que vous tapez maintenant et le dernier commit, vous demandez vraiment une différence entre le répertoire de travail + index et la HEAD:
Pour un fichier donné, voir quelles listes de modifications soumises ont affecté quelles lignes -> C'est facile:
ou encore mieux, si vous êtes dans un environnement fenêtré:
Git gui prend plus de temps pour analyser le fichier (il a été écrit en tcl au lieu de C) mais il a beaucoup de fonctionnalités intéressantes, y compris la possibilité de "voyager dans le temps" dans le passé en cliquant sur un ID de validation. Je souhaite seulement qu'ils implémentent une fonctionnalité pour "voyager dans le temps" dans le futur afin que je puisse découvrir comment un bug donné sera finalement résolu ;-)
Pour un fichier donné, voir une liste des descriptions des listes de modifications qui ont affecté le fichier -> aussi facile:
Mais git log est un outil beaucoup plus puissant que cela. En fait, la plupart de mes scripts personnels se superposent à git log pour lire le référentiel. Lisez la page de manuel.
Soumettez une liste de modifications en attente -> Aussi facile:
Voir ma réponse à une question précédente pour voir mon workflow git typique: Apprendre Git. Besoin de savoir si je suis sur la bonne voie
Si vous suivez le flux de travail que j'ai décrit, vous constaterez que des outils comme gitk sont beaucoup plus précieux car ils vous permettent de voir clairement les groupes de modifications.
Réponse supplémentaire:
Git est très flexible et il existe plusieurs façons de faire ce que vous décrivez. La chose à retenir est de toujours démarrer une nouvelle branche pour chaque fonctionnalité sur laquelle vous travaillez. Cela signifie que la branche master n'est pas touchée, donc vous pouvez toujours y revenir pour corriger les bogues. Travailler dans git devrait presque toujours commencer par:
Vous pouvez maintenant éditer le fichier a.txt. Pour travailler simultanément sur une autre fonctionnalité, procédez comme suit:
Vous pouvez maintenant éditer le fichier z.txt. Pour revenir à a.txt:
Mais attendez, il y a des changements dans new-feature-z et git ne vous permettra pas de changer de branche. À ce stade, vous avez deux choix. Le premier est le plus simple, validez toutes les modifications dans la branche actuelle:
C'est ce que je recommande. Mais si vous n'êtes vraiment pas prêt à valider le code, vous pouvez le cacher temporairement:
Vous pouvez maintenant passer à la branche new-feature-a. Pour revenir au code sur lequel vous travailliez, ouvrez simplement la cachette:
Lorsque tout est terminé, fusionnez toutes les modifications apportées au master:
Parce que les fusions sont si rapides et faciles (faciles parce que les conflits sont si rares et la résolution des conflits, quand cela se produit, pas trop difficile), nous utilisons des branches dans git pour tout.
Voici un autre exemple d'utilisation courante de branches dans git que vous ne voyez pas dans d'autres outils de contrôle de source (sauf peut-être mercurial):
Besoin de continuer à modifier vos fichiers de configuration pour refléter votre environnement de développement? Ensuite, utilisez une branche:
Maintenant, modifiez vos fichiers de configuration dans votre éditeur préféré puis validez les modifications:
Désormais, chaque nouvelle branche peut démarrer à partir de la branche dev-config au lieu de master:
Une fois que vous avez terminé, supprimez les modifications dans dev-config de new-feature-branch en utilisant le rebase interactif:
Supprimez les commits que vous ne souhaitez pas, puis enregistrez-les. Vous avez maintenant une branche propre sans modifications de configuration personnalisées. Il est temps de revenir au maître:
Il convient de noter que la suppression des modifications avec
git rebase -i
fonctionne même lorsque toutes les modifications se produisent dans le même fichier. Git se souvient des modifications, pas du contenu du fichier *.* note: en fait, techniquement pas tout à fait vrai, mais en tant qu'utilisateur, c'est ce que l'on ressent
Plus de réponse supplémentaire:
Ainsi, d'après vos commentaires, il semble que vous souhaitiez que deux branches existent simultanément afin que vous puissiez tester le fonctionnement du code combiné. Eh bien, c'est un bon moyen d'illustrer la puissance et la flexibilité des branches.
Tout d'abord, un mot sur l'implication de la branche bon marché et de l'historique modifiable sur votre flux de travail. Quand j'utilisais CVS et SVN, j'étais toujours un peu réticent à m'engager. C'est parce que la validation de code instable serait inévitablement f ** k le code de travail des autres. Mais avec git j'ai perdu cette peur. C'est parce que dans git, les autres personnes ne recevront pas mes modifications tant que je ne les fusionnerai pas avec master. Alors maintenant, je me retrouve à commettre du code toutes les 5 lignes que j'écris. Vous n'avez pas besoin d'une prévoyance parfaite pour vous engager. Vous avez juste besoin de changer votre état d'esprit: commit-to-branch == add-to-changeset, merge-to-master == commit-changeset.
Alors, revenons aux exemples. Voici comment je le ferais. Supposons que vous ayez une branche
new-feature-z
et que vous souhaitiez la testernew-feature-a
. Je créerais juste une nouvelle branche pour la tester:Vous pouvez maintenant tester. Si vous avez besoin de modifier quelque chose pour que feature-z fonctionne avec feature-a, faites-le. Si tel est le cas, vous pouvez fusionner les modifications dans la branche appropriée. Permet
git rebase -i
de supprimer les modifications non pertinentes de la fusion.Vous pouvez également utiliser git rebase pour modifier temporairement la base de new-feature-z pour qu'elle pointe vers new-feature-a:
Maintenant, l'historique des branches est modifié de sorte que new-feature-z soit basé sur new-feature-a au lieu de master. Vous pouvez maintenant tester. Tout changement effectué dans cette branche appartiendra à la branche new-feature-z. Si vous avez besoin de modifier une nouvelle fonctionnalité, revenez-y simplement et le rebase pour obtenir les nouvelles modifications:
Lorsque vous avez terminé, rebasez simplement vers master pour supprimer les modifications de new-feature-a:
N'ayez pas peur de créer une nouvelle succursale. N'ayez pas peur de démarrer une succursale jetable. N'ayez pas peur de jeter les branches. Et puisque merge == submit et commit == add-to-changeset n'ayez pas peur de vous engager souvent. N'oubliez pas que la validation est l'outil d'annulation ultime du développeur.
Oh, et autre chose, dans git, les branches supprimées existent toujours dans votre référentiel. Donc, si vous avez accidentellement supprimé quelque chose que vous réalisez plus tard comme utile après tout, vous pouvez toujours le récupérer en recherchant dans l'historique. Alors n'ayez pas peur de jeter les branches.
la source
Je n'ai pas assez d'expérience p4 pour produire une feuille de triche réelle, mais il y a au moins quelques similitudes sur lesquelles se rabattre. Un "changeset" p4 est un git "commit".
Les modifications apportées à votre espace de travail local sont ajoutées à «l'index» avec
git add
, et l'index est ensuite validé avecgit commit
. L'index est donc votre liste de modifications en attente, à toutes fins utiles.Vous regardez les modifications avec
git diff
etgit status
, oùgit diff
affiche généralement les modifications entre l'espace de travail et l'index, maisgit diff --cached
affiche les modifications entre l'index et le référentiel (= votre liste de modifications en attente).Pour plus d'informations, je recommande http://progit.org/book/ . Puisque vous connaissez le contrôle de version en général, vous pouvez probablement en parcourir beaucoup et en extraire les informations spécifiques à git ...
la source
Je souffre comme vous de l'absence du concept de "changelist" qui n'est pas exactement le même que celui des branches git.
J'écrirais un petit script qui créera un fichier de liste de modifications avec la liste des fichiers de cette liste de modifications.
Une autre commande pour soumettre juste une certaine liste de modifications en appelant simplement git commit -a @ change_list_contents.txt puis "git commit"
J'espère que ça aide, Elias
la source
Il existe une alternative plus légère dans git qui pourrait faire partie de votre flux de travail; en utilisant la zone de préparation de git.
Je fais souvent des changements puis je les soumets en plusieurs commits (par exemple, ajouter des déclarations de débogage, refactoriser, corriger un bogue). Plutôt que de configurer vos listes de modifications perforce, puis d'apporter des modifications, puis de soumettre, vous pouvez simplement effectuer vos modifications, puis choisir comment les soumettre (éventuellement en utilisant la zone de préparation de git).
Vous pouvez valider des fichiers particuliers depuis la ligne de commande avec:
Ou préparez explicitement les fichiers en premier:
git gui vous permettra de sélectionner des lignes ou des morceaux dans les fichiers pour créer un commit dans la zone de préparation. Ceci est très utile si vous avez des modifications dans un fichier que vous souhaitez inclure dans différents commits. Être passé de git à forcé et c'est une chose qui me manque vraiment.
Il y a une petite mise en garde à garder à l'esprit avec ce flux de travail. Si vous apportez des modifications A et B à un fichier, testez le fichier, puis validez A, vous n'avez pas testé cette validation (indépendamment de B).
la source
Cela ne répond pas spécifiquement à votre question, mais je ne sais pas si vous savez qu'une version 2 utilisateurs, 5 espaces de travail de perforce peut être téléchargée et utilisée gratuitement à partir du site Web de perforce .
De cette façon, vous pouvez utiliser forforce à la maison pour vos projets personnels si vous le souhaitez. Le seul inconvénient, ce sont les 5 espaces de travail qui peuvent être un peu limitatifs, mais c'est assez incroyable d'avoir forcément disponible pour un usage domestique.
la source
Ayant utilisé à la fois Perforce et git assez largement, je ne peux voir qu'une seule façon de me rapprocher des listes de modifications Perforce avec git.
La première chose à comprendre est que pour implémenter correctement cette fonctionnalité dans git de manière à ce que ce ne soit pas un kluge complet, par exemple essayer de la faire passer dans les branches, il faudrait le changement suivant: git nécessiterait plusieurs zones de préparation pour une seule branche .
Les listes de modifications Perforce permettent un flux de travail qui n'a tout simplement pas d'équivalent dans git. Considérez le flux de travail suivant:
Si vous essayez de faire cela en utilisant des branches dans git, vous vous retrouverez avec deux branches, dont l'une a les modifications du fichier
A
, l'autre les modifications du fichierB
, mais aucun endroit où vous pouvez voir les modifications apportées aux deux fichiersA
etB
à le même temps.Le plus proche approximation que je peux voir est d'utiliser
git add . -p
, puis utilisez les'a'
et'd'
sous-commandes pour sélectionner ou rejeter des fichiers entiers. Cependant, ce n'est pas tout à fait la même chose, et la différence ici provient d'une disparité fondamentale dans le mode de fonctionnement général des deux systèmes.Git (et subversion, non pas que cela compte pour cette discussion) permet à un fichier d'être modifié sans en parler à personne à l'avance. Vous changez simplement un fichier, puis laissez git trier le tout lorsque vous validez les modifications. Perforce vous oblige à extraire activement un fichier avant que les modifications ne soient autorisées, et c'est pour cette raison que des listes de modifications doivent exister. Par essence, Perforce vous oblige à ajouter un fichier à l'index avant de le modifier. D'où la nécessité de plusieurs listes de modifications dans Perforce, et aussi la raison pour laquelle git n'a pas d'équivalent. Il n'en a tout simplement pas besoin.
la source
Avec Git 2.27 (Q2 2020), "
git p4
" a appris quatre nouveaux hooks et aussi "--no-verify
" une option pour les contourner (et lep4-pre-submit
hook " " existant ).Voir commit 1ec4a0a , commit 38ecf75 , commit cd1e0dc (14 février 2020) et commit 4935c45 , commit aa8b766 , commit 9f59ca4 , commit 6b602a2 (11 février 2020) par Ben Keene (
seraphire
) .(Fusionné par Junio C Hamano -
gitster
- dans commit 5f2ec21 , 22 avril 2020)Avant Git 2.28 (Q3 2020), l'
--prepare-p4-only
option " " est censée s'arrêter après avoir relu un ensemble de modifications, mais a continué (par erreur?)Voir commit 2dfdd70 (12 mai 2020) par Ben Keene (
seraphire
) .(Fusionné par Junio C Hamano -
gitster
- dans commit 7a8fec9 , 02 juin 2020)la source