cours
Force de traction Git : Comment écraser une branche locale avec une branche distante ?
Dans certaines situations, nous pouvons souhaiter réinitialiser l'état d'un fichier local de Git pour l'aligner sur le référentiel distant, ce qui a pour effet d'annuler toutes les modifications locales. C'est ce que l'on appelle communément unetraction forcée .
Cela crée l'idée fausse que la manière d'archiver est d'utiliser l'option --force
dans la commande git pull
. Dans cet article, nous apprenons qu'il s'agit de deux choses différentes.
Si vous êtes novice en matière de Git, nous vous conseillons de lire d'abord notre tutoriel Git push et pull.
Nous pouvons remplacer notre état local par l'état distant en utilisant les commandes ci-dessous, en remplaçant par le nom de votre branche. Cette action supprimera définitivement toutes vos modifications locales dans cette branche.
git fetch
git reset --hard origin/<branch_name>
Cet article explique en détail le fonctionnement de ces commandes. Nous allons au-delà des solutions rapides pour comprendre les mécanismes sous-jacents, ce qui nous permet d'apprendre des méthodes plus efficaces pour atteindre le résultat souhaité sans risquer de perdre des changements importants. Nous dissipons également les idées fausses et apprenons ce que fait réellement l'option --force
de git pull
.
Devenez ingénieur en données
Quand faut-il envisager d'écraser les modifications locales ?
En général, l'écrasement des modifications locales de cette manière va à l'encontre de l'utilisation prévue de Git. Pour presque toutes les situations, il existe un flux de travail Git approprié pour les résoudre. Cependant, certaines d'entre elles nécessitent souvent une compréhension plus approfondie de Git et prennent plus de temps à mettre en œuvre. Même si ce n'est pas la meilleure pratique, l'écrasement des modifications locales peut parfois être le moyen le plus rapide d'effectuer le travail.
Pour moi, cela se produit généralement lorsque je travaille sur une fonctionnalité que je ne connais pas très bien. Je commence par créer une branche et faire quelques commits. Lorsque je suis bloqué, je demande de l'aide à un collègue. Ils partent d'un commit antérieur, avant que je ne commette l'erreur, résolvent le problème et transfèrent leurs modifications. À ce stade, je dois remplacer ma version locale par la version distante mise à jour, tout en abandonnant mes modifications locales, afin de pouvoir continuer à travailler sur la fonctionnalité.
Un autre exemple est celui d'un conflit, et j'ai le sentiment qu'il est plus difficile ou plus long de résoudre le conflit que de réimplémenter nos changements dans la dernière version du code.
Quelle que soit la raison, assurez-vous toujours que ces modifications ne sont pas vraiment nécessaires et qu'elles peuvent être supprimées en toute sécurité ou sauvegardez votre branche pour éviter de perdre un travail important.
Comment écraser correctement les modifications locales ?
La première étape consiste à récupérer (télécharger) le dernier contenu du dépôt distant sur notre machine locale. Cela se fait à l'aide de lacommande fetch
de git:
git fetch
Par défaut, cela permet de récupérer le contenu de la branche courante, ce qui est généralement ce dont nous avons besoin. Nous pouvons optionnellement spécifier la branche que nous souhaitons télécharger (en remplaçant ci-dessous par le nom de la branche que nous souhaitons récupérer) :
git fetch origin/<branch_name>
Vous pouvez également utiliser l'option --all
pour tout télécharger :
git fetch –all
La récupération des modifications du référentiel distant n'affectera pas les fichiers de votre répertoire de travail actuel. La commande fetch
télécharge les modifications du référentiel distant mais ne les fusionne pas. Le référentiel local conserve une vue des fichiers locaux et des fichiers distants, et la récupération met à jour la vue des fichiers distants.
Après avoir téléchargé les modifications du dépôt distant, nous pouvons utiliser la commande reset
de git pour réinitialiser la branche de travail actuelle dans un état donné :
git reset --hard origin/<branch_name>
L'option --hard
est nécessaire pour s'assurer que les modifications locales sont écrasées par les modifications à distance. Dans la commande ci-dessus, nous avons choisi de remplacer la branche de travail actuelle par origin/
qui correspond à la version distante de cette branche qui vient d'être récupérée.
La commande git reset
supprime les modifications locales, même si elles ont été validées. Il est donc recommandé de créer une sauvegarde locale de la branche actuelle avant d'exécuter cette commande. Vous pouvez le faire en utilisant :
git branch <name_of_the_backup_branck>
Remplacer par le nom que vous souhaitez donner à la branche de sauvegarde.
En mettant tout cela ensemble, nous pouvons remplacer toutes les modifications locales d'une branche donnée par la dernière version distante en procédant comme suit :
git fetch
git branch <name_of_the_backup_branch>
git reset --hard origin/<branch_name>
Si vous souhaitez approfondir vos connaissances sur le travail avec les branches dans Git, consultez le tutoriel Git Clone a Specific Branch (Cloner une branche spécifique).
Nettoyage complet en supprimant les fichiers non suivis
Git ne touchera pas aux fichiers non suivis (fichiers qui n'ont jamais été utilisés par git add
). Si nous voulons également supprimer ces fichiers, nous pouvons le faire en utilisant :
git clean -fdx
Il s'agit d'une commande dangereuse utilisée pour supprimer les fichiers non suivis du répertoire de travail. Il est essentiel d'utiliser cette commande avec prudence car elle supprime définitivement ces fichiers, ce qui rend impossible leur récupération par Git. Voici un aperçu des options de commande :
-f
: Cette option force la poursuite de l'opération de nettoyage. Git refusera de supprimer les fichiers non suivis du répertoire de travail sans ce drapeau comme mesure de sécurité pour éviter la perte accidentelle de données.-d
: Cela indique àgit clean
de supprimer non seulement les fichiers non suivis, mais aussi les répertoires non suivis. Par défaut,git clean
ne cible que les fichiers non suivis et ignore les répertoires.-x
: Par défaut,git clean
respecte les règles de.gitignore
et ne supprime pas les fichiers ou les répertoires qui correspondent à ces modèles. L'ajout de -x annule ce comportement, en demandant à Git de supprimer également les fichiers/répertoires qui sont ignorés par.gitignore
ou d'autres règles d'ignorance. Il en résulte un nettoyage très complet, qui supprime tous les fichiers non suivis dans le référentiel, y compris les sorties de compilation, les fichiers journaux et les autres artefacts générés qui sont généralement ignorés.
Comprendre Git Pull
La façon habituelle de mettre à jour notre référentiel local avec les modifications effectuées à distance est d'utiliser la commande git pull
. Cependant, cette commande ne peut pas être utilisée pour remplacer nos modifications locales car git pull
essaiera de fusionner notre version locale avec la version distante.
Sous le capot, git pull
effectue les opérations suivantes :
- Il utilise
git fetch
pour télécharger la dernière version du référentiel distant. - Il utilise
git merge
pour fusionner les branches locales et distantes.
En raison de l'étape de fusion, git pull
n'est pas une commande appropriée dans les situations où nous voulons ignorer et rejeter les modifications locales.
Que pensez-vous de la git pull --force
?
En consultant la documentation de la commande git pull
, nous constatons qu'elle propose une option --force
. On croit souvent à tort que cette option force la commande git pull
à s'exécuter en effaçant les modifications locales avec les modifications à distance.
Lorsque nous fournissons l'option --force
à git pull
, cette option est transmise à git fetch
. Ainsi, git pull --force
effectue les étapes suivantes :
git fetch --force
git merge
Nous avons appris que fetch est utilisé pour mettre à jour la vue locale du référentiel distant. Si la seule différence entre votre dépôt local actuel et le dépôt distant est quelques commits manquants (la branche locale est en retard sur la version distante), alors git fetch
mettra simplement à jour la vue locale en ajoutant ces nouveaux commits à l'historique.
Cependant, il se peut que quelqu'un ait réécrit l'historique des livraisons de la branche distante, la rendant incompatible avec la vue locale. Dans ce cas, fetch ne fonctionnera pas.
Nous pouvons contourner ce problème en utilisant l'option --force
qui forcera Git à ignorer l'historique local et à l'écraser avec l'historique distant.
Nous voyons que l'option --force
est liée au fait de forcer l'écrasement de l'historique des livraisons et n'a rien à voir avec le fait d'ignorer les changements locaux dans le répertoire de la branche de travail.
Intégrer les changements locaux
L'écrasement des modifications locales par les modifications distantes n'est pas une pratique courante de Git mais peut être utile dans certains cas où nous ne voulons pas gérer de conflits ou ne nous soucions pas de nos modifications locales.
Fusionner
D'habitude, on retire les modifications et on gère les conflits. Les gens ont tendance à avoir peur des conflits. Certains conflits peuvent être insurmontables, mais ce n'est pas toujours le cas. Un conflit survient lorsque
- La branche locale et la branche distante ont toutes deux modifié la même partie d'un fichier.
- Un fichier est supprimé d'un côté et modifié de l'autre.
Dans ce cas, Git ne peut pas deviner quelles modifications nous voulons conserver, et nous devons le lui indiquer manuellement. Git mettra en évidence le conflit dans les fichiers comme suit :
Pour résoudre un conflit, nous modifions le fichier en supprimant ces lignes, à l'exception de celles que nous voulons conserver. Après avoir traité tous les conflits, nous pouvons valider les modifications. Pour un guide approfondi, consultez ce tutoriel sur comment résoudre les conflits de fusion dans Git.
La cueillette des cerises
Si nous voulons vraiment que notre version locale corresponde d'abord à la version distante et que nous puissions ensuite intégrer nos modifications, nous pouvons intégrer les modifications de la branche de sauvegarde dans la branche actuelle, comme suit :
git cherry-pick <commit_hash>
Ici, est le hash du commit que nous voulons intégrer. Cela suppose qu'avant de faire
git reset
, nous avons créé une branche de sauvegarde avec git branch
et que les modifications locales ont été validées.
Pour trouver l'adresse , nous pouvons lister les hachages des livraisons dans la branche de sauvegarde en utilisant la commande suivante :
git log <name_of_the_backup_branck>
Mise en réserve
Alternativement, si nous ne voulons pas livrer nos changements ou créer une branche de sauvegarde, nous pouvons cacher nos changements avant de les fusionner en les utilisant :
git stash
Cette commande peut être utilisée pour sauvegarder temporairement le travail en cours sans l'intégrer à l'historique de la branche. La mise en cache met de côté vos modifications, ce qui vous permet d'avoir un répertoire de travail propre.
Après la réinitialisation, nous pouvons rétablir les modifications à l'aide de la commande suivante :
git stash pop
En utilisant la mise en réserve, l'ensemble du flux de travail ressemblerait à ce qui suit :
git fetch
git stash
git reset --hard origin/<branch_name>
git stash pop
Pour en savoir plus, consultez cette avec stash et d'autres commandes git.
Conclusion
Bien qu'il ne s'agisse pas d'une bonne pratique, nous nous trouvons parfois dans une situation où nous voulons simplement que notre branche locale corresponde au contenu de la branche distante tout en supprimant nos modifications locales.
On croit à tort que cela se fait à l'aide de git pull --force
. Ceci est incorrect car git pull --force
combine git fetch --force
et git merge
. Par conséquent, il tente de fusionner les modifications locales avec les modifications à distance, sans les écraser.
La manière correcte d'écraser les modifications locales avec le contenu du référentiel distant est la suivante :
git fetch
git reset --hard origin/<branch_name>
La commande git reset
doit être utilisée avec précaution car elle supprime les modifications locales, même si elles ont été validées. Si nous avions des commits locaux et que nous avons créé une branche de sauvegarde, nous pouvons les ramener en utilisant git cherry-pick
. Si nous n'avons pas effectué de validation et que nous souhaitons sauvegarder temporairement notre travail local, nous pouvons utiliser git stash
avant la réinitialisation, puis git stash pop
pour rétablir nos modifications.
Obtenez une certification pour le poste de Data Engineer de vos rêves
Nos programmes de certification vous aident à vous démarquer et à prouver aux employeurs potentiels que vos compétences sont adaptées à l'emploi.

En savoir plus sur Git !
cours
Concepts GitHub
cursus