• Assurez la sécurité des applications de la bonne manière! Détectez, protégez, surveillez, accélérez et plus encore…
  • Dans cet article, vous découvrirez différentes façons de jouer avec les commits dans Git.

    En tant que développeur, vous auriez à plusieurs reprises dans de telles situations où vous auriez voulu revenir à l'un de vos commits précédents, mais vous ne savez pas comment le faire. Et même si vous connaissez le Git commandes comme reset, revert, rebase, vous n'êtes pas au courant des différences entre elles. Alors commençons et comprenons ce que sont git reset, revert et rebase.

    Réinitialiser Git

    Git reset est une commande complexe, utilisée pour annuler les modifications.

    Vous pouvez considérer git reset comme une fonction de restauration. Avec git reset, vous pouvez passer d'un commit à l'autre. Il existe trois modes d'exécution d'une commande git reset: –soft, –mixed et –hard. Par défaut, la commande git reset utilise le mode mixte. Dans un workflow de réinitialisation git, trois mécanismes de gestion internes de git entrent en jeu: TÊTE, zone de transit (index) et le directeur de travail.

    git reset - geekflare

    Le répertoire de travail est l'endroit où vous travaillez actuellement, c'est l'endroit où vos fichiers sont présents. En utilisant une commande git status, vous pouvez voir quels sont tous les fichiers / dossiers présents dans le répertoire de travail.

    La zone de transit (index) est l'endroit où git suit et enregistre toutes les modifications dans les fichiers. Les modifications enregistrées sont reflétées dans le répertoire .git. Vous utilisez git add "filename" pour ajouter le fichier à la zone de préparation. Et comme avant, lorsque vous exécutez git status, vous verrez quels fichiers sont présents dans la zone de préparation.

    La branche actuelle dans Git est appelée HEAD. Il pointe vers le dernier commit, qui s'est produit dans la branche d'extraction actuelle. Il est traité comme un pointeur pour toute référence. Une fois que vous passez à une autre succursale, le HEAD se déplace également vers la nouvelle succursale.

    Laissez-moi vous expliquer comment git reset fonctionne dans les modes hard, soft et mixed. Le mode difficile est utilisé pour accéder au commit pointé, le répertoire de travail est rempli avec les fichiers de ce commit et la zone de préparation est réinitialisée. Dans la réinitialisation logicielle, seul le pointeur est remplacé par la validation spécifiée. Les fichiers de tous les commits restent dans le répertoire de travail et la zone de préparation avant la réinitialisation. En mode mixte (par défaut), le pointeur et la zone de transit sont tous deux réinitialisés.

    Git Reset Hard

    Le but de la réinitialisation matérielle de git est de déplacer le HEAD vers le commit spécifié. Il supprimera toutes les validations qui se sont produites après la validation spécifiée. Cette commande modifiera l'historique de validation et pointera vers la validation spécifiée.

    Dans cet exemple, je vais ajouter trois nouveaux fichiers, les valider, puis effectuer une réinitialisation matérielle.

    Comme vous pouvez le voir dans la commande ci-dessous, pour le moment, il n'y a rien à valider.

    $ git status
    On branch master
    Your branch is ahead of 'origin/master' by 2 commits.
    
    (use "git push" to publish your local commits)
    
    nothing to commit, working tree clean

    Maintenant, je vais créer 3 fichiers et y ajouter du contenu.

    $ vi file1.txt
    $ vi file2.txt
    $ vi file3.txt

    Ajoutez ces fichiers au référentiel existant.

    $ git add file*

    Lorsque vous réexécutez la commande status, elle reflétera les nouveaux fichiers que je viens de créer.

    $ git status
    On branch master
    Your branch is ahead of 'origin/master' by 2 commits.
    
    (use "git push" to publish your local commits)
    
    Changes to be committed:
    
    (use "git restore --staged <file>..." to unstage)
    
    new file:
    file1.txt
    
    new file:
    file2.txt
    
    new file:
    file3.txt

    Avant de commettre, laissez-moi vous montrer, j'ai actuellement un journal de 3 commits dans Git.

    $ git log --oneline
    0db602e (HEAD -> master) one more commit
    59c86c9 new commit
    e2f44fc (origin/master, origin/HEAD) test

    Maintenant, je vais m'engager dans le référentiel.

    $ git commit -m 'added 3 files'
    [master d69950b] added 3 files
    3 files changed, 3 insertions(+)
    create mode 100644 file1.txt
    create mode 100644 file2.txt
    create mode 100644 file3.txt

    Si je fais des fichiers ls, vous verrez que les nouveaux fichiers ont été ajoutés.

    $ git ls-files
    demo
    dummyfile
    newfile
    file1.txt
    file2.txt
    file3.txt

    Lorsque j'exécute la commande log dans git, j'ai 4 commits et HEAD pointe vers le dernier commit.

    $ git log --oneline
    d69950b (HEAD -> master) added 3 files
    0db602e one more commit
    59c86c9 new commit
    e2f44fc (origin/master, origin/HEAD) test

    Si je supprime le fichier1.txt manuellement et que je fais un état git, il affichera le message que les modifications ne sont pas préparées pour la validation.

    $ git status
    On branch master
    Your branch is ahead of 'origin/master' by 3 commits.
    
    (use "git push" to publish your local commits)
    
    Changes not staged for commit:
    
    (use "git add/rm <file>..." to update what will be committed)
    
    (use "git restore <file>..." to discard changes in working directory)
    
    deleted:
    file1.txt
    
    no changes added to commit (use "git add" and/or "git commit -a")

    Maintenant, je vais exécuter la commande de réinitialisation matérielle.

    $ git reset --hard
    HEAD is now at d69950b added 3 files

    Si je revérifie le statut, je constaterai qu'il n'y a rien à valider et que le fichier que j'ai supprimé est revenu dans le référentiel. La restauration s'est produite car après la suppression du fichier, je ne me suis pas engagé, donc après une réinitialisation matérielle, il est revenu à l'état précédent.

    $ git status
    On branch master
    Your branch is ahead of 'origin/master' by 3 commits.
    
    (use "git push" to publish your local commits)
    
    nothing to commit, working tree clean

    Si je vérifie le journal de git, voici à quoi il ressemblera.

    $ git log
    commit d69950b7ea406a97499e07f9b28082db9db0b387 (HEAD -> master)
    Author: mrgeek <[email protected]>
    Date:
    Mon May 17 19:53:31 2020 +0530
    
    added 3 files
    
    commit 0db602e085a4d59cfa9393abac41ff5fd7afcb14
    Author: mrgeek <[email protected]>
    Date:
    Mon May 17 01:04:13 2020 +0530
    
    one more commit
    
    commit 59c86c96a82589bad5ecba7668ad38aa684ab323
    Author: mrgeek <[email protected]>
    Date:
    Mon May 17 00:54:53 2020 +0530
    
    new commit
    
    commit e2f44fca2f8afad8e4d73df6b72111f2f2fd71ad (origin/master, origin/HEAD)
    Author: mrgeek <[email protected]>
    Date:
    Mon May 17 00:16:33 2020 +0530
    
    test

    Le but de la réinitialisation matérielle est de pointer vers le commit spécifié et de mettre à jour le répertoire de travail et la zone de préparation. Laissez-moi vous montrer un autre exemple. Actuellement, la visualisation de mes commits ressemble à ci-dessous:

    git dur

    Ici, je vais exécuter la commande avec HEAD ^, ce qui signifie que je veux réinitialiser le commit précédent (un commit en arrière).

    $ git reset --hard HEAD^
    HEAD is now at 0db602e one more commit

    Vous pouvez voir que le pointeur de tête a maintenant changé en 0db602e à partir de d69950b.

    $ git log --oneline
    0db602e (HEAD -> master) one more commit
    59c86c9 new commit
    e2f44fc (origin/master, origin/HEAD) test

    git dur 1

    Si vous vérifiez le journal, la validation de d69950b a disparu et la tête pointe maintenant vers 0db602e SHA.

    $ git log
    commit 0db602e085a4d59cfa9393abac41ff5fd7afcb14 (HEAD -> master)
    Author: mrgeek <[email protected]>
    Date:
    Mon May 17 01:04:13 2020 +0530
    
    one more commit
    
    commit 59c86c96a82589bad5ecba7668ad38aa684ab323
    Author: mrgeek <[email protected]>
    Date:
    Mon May 17 00:54:53 2020 +0530
    
    new commit
    
    commit e2f44fca2f8afad8e4d73df6b72111f2f2fd71ad (origin/master, origin/HEAD)
    Author: mrgeek <[email protected]>
    Date:
    Mon May 17 00:16:33 2020 +0530
    
    Test

    Si vous exécutez les fichiers ls, vous pouvez voir que file1.txt, file2.txt et files3.txt ne sont plus dans le référentiel car ce commit et son fichier ont été supprimés après la réinitialisation matérielle.

    $ git ls-files
    demo
    dummyfile
    newfile

    Réinitialisation logicielle Git

    De même, je vais maintenant vous montrer un exemple de réinitialisation logicielle. Considérez, j'ai à nouveau ajouté les 3 fichiers comme mentionné ci-dessus et les ai validés. Le journal git apparaîtra comme indiqué ci-dessous. Vous pouvez voir que 'soft reset' est mon dernier commit, et HEAD pointe également vers cela.

    $ git log --oneline
    aa40085 (HEAD -> master) soft reset
    0db602e one more commit
    59c86c9 new commit
    e2f44fc (origin/master, origin/HEAD) test

    Les détails de la validation dans le journal peuvent être consultés à l'aide de la commande ci-dessous.

    $ git log
    commit aa400858aab3927e79116941c715749780a59fc9 (HEAD -> master)
    Author: mrgeek <[email protected]>
    Date:
    Mon May 17 21:01:36 2020 +0530
    
    soft reset
    
    commit 0db602e085a4d59cfa9393abac41ff5fd7afcb14
    Author: mrgeek <[email protected]>
    Date:
    Mon May 17 01:04:13 2020 +0530
    
    one more commit
    
    commit 59c86c96a82589bad5ecba7668ad38aa684ab323
    Author: mrgeek <[email protected]>
    Date:
    Mon May 17 00:54:53 2020 +0530
    
    new commit
    
    commit e2f44fca2f8afad8e4d73df6b72111f2f2fd71ad (origin/master, origin/HEAD)
    Author: mrgeek <[email protected]>
    Date:
    Mon May 17 00:16:33 2020 +0530
    
    test

    À l'aide de la réinitialisation logicielle, je souhaite passer à l'un des anciens commits avec SHA 0db602e085a4d59cfa9393abac41ff5fd7afcb14

    Pour ce faire, je vais exécuter la commande ci-dessous. Vous devez passer plus de 6 caractères de départ de SHA, le SHA complet n'est pas requis.

    $ git reset --soft 0db602e085a4

    Maintenant, lorsque j'exécute le journal git, je peux voir que HEAD a été réinitialisé au commit que j'ai spécifié.

    $ git log
    commit 0db602e085a4d59cfa9393abac41ff5fd7afcb14 (HEAD -> master)
    Author: mrgeek <[email protected]>
    Date:
    Mon May 17 01:04:13 2020 +0530
    
    one more commit
    
    commit 59c86c96a82589bad5ecba7668ad38aa684ab323
    Author: mrgeek <[email protected]>
    Date:
    Mon May 17 00:54:53 2020 +0530
    
    new commit
    
    commit e2f44fca2f8afad8e4d73df6b72111f2f2fd71ad (origin/master, origin/HEAD)
    Author: mrgeek <[email protected]>
    Date:
    Mon May 17 00:16:33 2020 +0530
    
    test

    Mais la différence ici est que les fichiers du commit (aa400858aab3927e79116941c715749780a59fc9) où j'avais ajouté 3 fichiers sont toujours dans mon répertoire de travail. Ils n'ont pas été supprimés. C'est pourquoi vous devriez utiliser une réinitialisation logicielle plutôt qu'une réinitialisation matérielle. Il n'y a aucun risque de perdre les fichiers en mode logiciel.

    $ git ls-files
    demo
    dummyfile
    file1.txt
    file2.txt
    file3.txt
    newfile

    Git Revenir

    Dans Git, la commande revert est utilisée pour effectuer une opération de retour, c'est-à-dire pour annuler certaines modifications. C'est similaire à la commande reset, mais la seule différence ici est que vous effectuez un nouveau commit pour revenir à un commit particulier. En bref, il est juste de dire que la commande git revert est un commit.

    La commande Git revert ne supprime aucune donnée lors de l'exécution de l'opération de rétablissement.

    Disons que j'ajoute 3 fichiers et que j'effectue une opération de validation git pour l'exemple de retour.

    $ git commit -m 'add 3 files again'
    [master 812335d] add 3 files again
    3 files changed, 3 insertions(+)
    create mode 100644 file1.txt
    create mode 100644 file2.txt
    create mode 100644 file3.txt

    Le journal affichera le nouveau commit.

    $ git log --oneline
    812335d (HEAD -> master) add 3 files again
    0db602e one more commit
    59c86c9 new commit
    e2f44fc (origin/master, origin/HEAD) test

    Maintenant, je voudrais revenir à l'un de mes commits passés, disons - «59c86c9 new commit». Je lancerais la commande ci-dessous.

    $ git revert 59c86c9

    Cela ouvrira un fichier, vous trouverez les détails du commit auquel vous essayez de revenir, et vous pouvez donner un nom à votre nouveau commit ici, puis enregistrer et fermer le fichier.

    Revert "new commit"
    
    This reverts commit 59c86c96a82589bad5ecba7668ad38aa684ab323.
    
    # Please enter the commit message for your changes. Lines starting
    # with '#' will be ignored, and an empty message aborts the commit.
    #
    # On branch master
    # Your branch is ahead of 'origin/master' by 4 commits.
    # (use "git push" to publish your local commits)
    #
    # Changes to be committed:
    # modified: dummyfile

    Après avoir enregistré et fermé le fichier, c'est la sortie que vous obtiendrez.

    $ git revert 59c86c9
    [master af72b7a] Revert "new commit"
    1 file changed, 1 insertion(+), 1 deletion(-)

    Maintenant, pour apporter les modifications nécessaires, contrairement à la réinitialisation, revert a effectué un nouveau commit supplémentaire. Si vous vérifiez à nouveau le journal, vous trouverez un nouveau commit en raison de l'opération de restauration.

    $ git log --oneline
    af72b7a (HEAD -> master) Revert "new commit"
    812335d add 3 files again
    0db602e one more commit
    59c86c9 new commit
    e2f44fc (origin/master, origin/HEAD) test

    git revenir

    Git log aura toute l'historique des commits. Si vous souhaitez supprimer les validations de l'historique, alors revenir n'est pas un bon choix, mais si vous souhaitez conserver les modifications de validation dans l'historique, alors revenir est la commande appropriée au lieu de réinitialiser.

    Git Rebase

    Dans Git, rebase est le moyen de déplacer ou de combiner les commits d'une branche sur une autre branche. En tant que développeur, je ne créerais pas mes fonctionnalités sur la branche principale dans un scénario réel. Je travaillerais sur ma propre branche (une `` branche de fonctionnalité ''), et quand j'ai quelques commits dans ma branche de fonctionnalité avec la fonctionnalité ajoutée, je voudrais alors la déplacer vers la branche principale.

    Rebase peut parfois être un peu déroutant à comprendre car il est très similaire à une fusion. Le but de la fusion et du rebasage des deux est de prendre les commits de ma branche de fonctionnalité et de les placer dans une branche principale ou toute autre branche. Considérez, j'ai un graphique qui ressemble à ceci:

    git rebase

    Supposons que vous travaillez en équipe avec d'autres développeurs. Dans ce cas, vous pouvez imaginer que cela pourrait devenir très complexe lorsque de nombreux autres développeurs travaillent sur différentes branches de fonctionnalités et qu'ils ont fusionné plusieurs modifications. Il devient déroutant de tracer.

    C'est donc là que le rebase va vous aider. Cette fois, au lieu de faire une fusion git, je vais faire un rebase, où je veux prendre mes deux commits de branche de fonctionnalité et les déplacer vers la branche maître. Un rebase prendra tous mes commits de la branche de fonctionnalité et les déplacera au-dessus des commits de la branche principale. Donc, dans les coulisses, git duplique les commits de la branche de fonctionnalité sur la branche maître.

    git rebase 1

    Cette approche vous donnera un graphique en ligne droite propre avec tous les commits d'affilée.

    git revenir 2

    Il est facile de retracer ce que les commits sont allés où. Vous pouvez imaginer que si vous faites partie d'une équipe avec de nombreux développeurs, tous les commits sont toujours consécutifs. Donc, c'est vraiment facile à suivre même si plusieurs personnes travaillent sur le même projet en même temps.

    Laissez-moi vous montrer cela pratiquement.

    Voici à quoi ressemble ma branche principale actuellement. Il a 4 commits.

    $ git log --oneline
    812335d (HEAD -> master) add 3 files again
    0db602e one more commit
    59c86c9 new commit
    e2f44fc (origin/master, origin/HEAD) test

    Je vais exécuter la commande ci-dessous pour créer et basculer vers une nouvelle branche appelée feature, et cette branche sera créée à partir du 2ème commit, c'est-à-dire 59c86c9

    (master)
    $ git checkout -b feature 59c86c9
    Switched to a new branch 'feature'

    Si vous vérifiez le journal dans la branche de fonctionnalité, il n'a que 2 commits provenant du maître (ligne principale).

    (feature)
    $ git log --oneline
    59c86c9 (HEAD -> feature) new commit
    e2f44fc (origin/master, origin/HEAD) test

    Je vais créer la fonctionnalité 1 et la valider dans la branche des fonctionnalités.

    (feature)
    $ vi feature1.txt
    
    (feature)
    $ git add .
    The file will have its original line endings in your working directory
    
    (feature)
    $ git commit -m 'feature 1'
    [feature c639e1b] feature 1
    1 file changed, 1 insertion(+)
    create mode 100644 feature1.txt

    Je vais créer une autre fonctionnalité, c'est-à-dire la fonctionnalité 2, dans la branche des fonctionnalités et la valider.

    (feature)
    $ vi feature2.txt
    
    (feature)
    $ git add .
    The file will have its original line endings in your working directory
    
    (feature)
    $ git commit -m 'feature 2'
    [feature 0f4db49] feature 2
    1 file changed, 1 insertion(+)
    create mode 100644 feature2.txt

    Maintenant, si vous vérifiez le journal de la branche de fonctionnalité, il a deux nouveaux commits, que j'ai exécutés ci-dessus.

    (feature)
    $ git log --oneline
    0f4db49 (HEAD -> feature) feature 2
    c639e1b feature 1
    59c86c9 new commit
    e2f44fc (origin/master, origin/HEAD) test

    Maintenant, je veux ajouter ces deux nouvelles fonctionnalités à la branche principale. Pour cela, j'utiliserai la commande rebase. À partir de la branche de fonctionnalité, je vais rebaser contre la branche principale. Cela va ancrer ma branche de fonctionnalités contre les dernières modifications.

    (feature)
    $ git rebase master
    Successfully rebased and updated refs/heads/feature.

    Maintenant, je vais aller de l'avant et vérifier la branche principale.

    (feature)
    $ git checkout master
    Switched to branch 'master'
    Your branch is ahead of 'origin/master' by 3 commits.
    
    (use "git push" to publish your local commits)

    Et enfin, rebasez la branche master par rapport à ma branche de fonctionnalité. Cela prendra ces deux nouveaux commits sur ma branche de fonctionnalités et les rejouera au-dessus de ma branche principale.

    (master)
    $ git rebase feature
    Successfully rebased and updated refs/heads/master.

    Maintenant, si je vérifie le journal sur la branche principale, je peux voir que les deux commits de ma branche de fonctionnalités ont été ajoutés avec succès à ma branche principale.

    (master)
    $ git log --oneline
    766c996 (HEAD -> master, feature) feature 2
    c036a11 feature 1
    812335d add 3 files again
    0db602e one more commit
    59c86c9 new commit
    e2f44fc (origin/master, origin/HEAD) test

    Tout cela concernait les commandes de réinitialisation, de retour et de rebase dans Git.

    Conclusion

    Tout était sur les commandes de réinitialisation, de retour et de rebase dans Git. J'espère que ce guide étape par étape vous a été utile. Maintenant, vous savez comment jouer avec vos commits selon les besoins en utilisant les commandes mentionnées dans l'article.