Leçon 23 · Récupération
Résoudre les conflits de fusion et de rebase
Résolvez le même titre concurrent dans une fusion et dans un rebase, voyez pourquoi « le nôtre » et « le leur » s'échangent entre eux, enregistrez un résultat combiné délibéré et terminez chaque opération sans perdre l'idée de l'une ou l'autre personne.
- Niveau: Intermédiaire
- 14 minutes de lecture
- 7 minutes de vidéo
- Mis à jour
- Avant cette leçon: Fusionner des branches avec un historique divergent, Rebaser un travail inédit sur une nouvelle base
Progression enregistrée dans ce navigateur.
La lecture charge la vidéo depuis YouTube (mode de confidentialité amélioré).
Ce que vous apprendrez
- Lisez un conflit réel : la base, le camp actuel et le camp entrant.
- Expliquez pourquoi « les nôtres » et « les leurs » échangent entre une fusion et un rebase.
- Écrivez une résolution délibérée, puis marquez-la comme résolue.
- Continuez l'opération et vérifiez que rien n'est laissé à moitié.
Avant de commencer
Deux coéquipiers ont modifié la même ligne de la page. Le conflict/sara, Sara a modifié le titre du héros en "Examiner les modifications en toute confiance". Le conflict/omar, Omar a modifié la même ligne par "Comprendre chaque modification enregistrée". Les deux branches partent du commit M, où le titre était "Voir clairement votre travail.", et chaque branche a exactement un commit. Vous faites deux copies identiques de cette divergence : une pour la fusion (gittree-conflict-merge) et une pour le rebase (gittree-conflict-rebase). Dans les deux cas, conflict/sara est extrait et l'arborescence de travail est propre. Aucune fusion ou rebase n'est en cours.
Tout est local et sur le forfait gratuit (GitTree vous demande de vous connecter) : pas de compte d'hébergement, pas de fournisseur, pas d'Internet. Chaque identité est fictive (exemple.com). N'exécutez jamais cette leçon dans un projet réel.
Apportez les modifications dans GitTree ou avec les commandes Git natives, pas les deux dans la même copie. La lecture du résultat est toujours sûre. Les étiquettes de menu proviennent des propres chaînes de GitTree 2.0 et les commandes natives ont été exécutées avec Git 2.43 dans des copies jetables. Les étapes GitTree n'ont pas été exécutées le macOS, Windows ou Linux.
Effets de concept et d'état
Un conflit de contenu signifie que Git ne peut pas choisir un résultat seul : les deux parties ont modifié les mêmes lignes différemment. Git arrête et conserve trois versions du fichier dans l'index : l'étape 1 est la base commune, l'étape 2 est « la nôtre » et l'étape 3 est « la leur ». Il écrit également des marqueurs de conflit dans le fichier de votre arborescence de travail. Supprimer les marqueurs dans un éditeur ne résout rien pour Git : le fichier n'est résolu que lorsque vous enregistrez le résultat et le stagez, ce qui ramène à l'étape 0.
« Les nôtres » et « les leurs » sont des positions, pas des personnes. Dans une fusion, vous êtes sur la branche de Sara, donc la nôtre est la version de Sara (le côté actuel) et la leur est celle d'Omar (le côté entrant). Dans un rebase de Sara sur Omar, Git se déplace d'abord vers la branche d'Omar puis rejoue le commit de Sara, donc la nôtre est la version d'Omar (la branche sur laquelle vous rebasez) et la leur est le commit de Sara. GitTree imprime le rôle à côté de chaque nom afin que vous n'ayez pas à vous souvenir : "(actuel)" et "(entrant)" dans une fusion, "(rebasing on)" et "(your commit)" dans un rebase.
Le bon résultat est rarement un côté. Ici, la résolution envisagée est "Examinez chaque changement avec confiance.", ni la ligne de Sara ni celle d'Omar. Gardez toutes les autres lignes de la page exactement telles qu’elles étaient. Marquer le fichier résolu étape votre résultat ; continuer est une étape distincte qui termine la validation de fusion ou recrée la validation de Sara sur celle d'Omar.
Lorsque l'opération est arrêtée, la branche se trouve là où l'opération l'a laissée et le fichier est en conflit. Rien n'atteint un serveur.
Préparer l’état exact du projet
Faites une divergence, puis copiez-la deux fois. Commencez à partir d'une copie ordinaire distincte du projet telle que la leçon 18 l'a laissé et laissez votre gittree-features original intact. Les versions des pages sont ci-dessous : MERGED est la base partagée, SARA et OMAR sont les deux versions concurrentes, et RESOLVED est le résultat que vous allez sauvegarder.
Entrées de fichiers complètes
Enregistrez uniquement à la phase nommée ci-dessous. Ce sont des corps UTF-8/LF complets avec une nouvelle ligne finale ; ne collez jamais les clôtures Markdown. Les fichiers exécutables inchangés héritent de l'entrée nommée. Les versions dans des variantes distinctes ne doivent pas écraser l'original.
index.html — FUSIONNÉ
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>GitTree Features — course demo</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<header class="site-header">
<a href="#main">GitTree Features</a>
</header>
<main id="main" tabindex="-1">
<section class="hero" aria-labelledby="hero-title">
<p class="eyebrow">GitTree Learn demo project</p>
<h1 id="hero-title">See your work clearly.</h1>
<p id="hero-copy">Choose one change, then check what Git saved.</p>
</section>
<section class="features" aria-labelledby="features-title">
<h2 id="features-title">Follow your work</h2>
<div class="cards">
<article class="feature-card">
<h3>History</h3>
<p>Read commits and branches together.</p>
</article>
<article class="feature-card">
<h3>Changes</h3>
<p>Review the exact content selected for a commit.</p>
</article>
<article class="feature-card">
<h3>Recovery</h3>
<p>Inspect the scope of a recovery point before using it.</p>
</article>
</div>
</section>
<section aria-labelledby="plans-title">
<h2 id="plans-title">Choose the workflow you need</h2>
<div class="cards">
<article class="feature-card">
<h3>Local Git</h3>
<p>Local Git workflows work without signing in.</p>
</article>
<article class="feature-card">
<h3>Connected workflows</h3>
<p>Provider integrations and Nour require Pro or an applicable trial.</p>
</article>
</div>
</section>
</main>
<footer><p>Built by a fictional team for GitTree Learn. Review one change at a time.</p></footer>
<script type="module" src="site.js"></script>
</body>
</html>index.html — LEP
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>GitTree Features — course demo</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<header class="site-header">
<a href="#main">GitTree Features</a>
</header>
<main id="main" tabindex="-1">
<section class="hero" aria-labelledby="hero-title">
<p class="eyebrow">GitTree Learn demo project</p>
<h1 id="hero-title">Review changes with confidence.</h1>
<p id="hero-copy">Choose one change, then check what Git saved.</p>
</section>
<section class="features" aria-labelledby="features-title">
<h2 id="features-title">Follow your work</h2>
<div class="cards">
<article class="feature-card">
<h3>History</h3>
<p>Read commits and branches together.</p>
</article>
<article class="feature-card">
<h3>Changes</h3>
<p>Review the exact content selected for a commit.</p>
</article>
<article class="feature-card">
<h3>Recovery</h3>
<p>Inspect the scope of a recovery point before using it.</p>
</article>
</div>
</section>
<section aria-labelledby="plans-title">
<h2 id="plans-title">Choose the workflow you need</h2>
<div class="cards">
<article class="feature-card">
<h3>Local Git</h3>
<p>Local Git workflows work without signing in.</p>
</article>
<article class="feature-card">
<h3>Connected workflows</h3>
<p>Provider integrations and Nour require Pro or an applicable trial.</p>
</article>
</div>
</section>
</main>
<footer><p>Built by a fictional team for GitTree Learn. Review one change at a time.</p></footer>
<script type="module" src="site.js"></script>
</body>
</html>index.html — OMAR
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>GitTree Features — course demo</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<header class="site-header">
<a href="#main">GitTree Features</a>
</header>
<main id="main" tabindex="-1">
<section class="hero" aria-labelledby="hero-title">
<p class="eyebrow">GitTree Learn demo project</p>
<h1 id="hero-title">Understand each saved change.</h1>
<p id="hero-copy">Choose one change, then check what Git saved.</p>
</section>
<section class="features" aria-labelledby="features-title">
<h2 id="features-title">Follow your work</h2>
<div class="cards">
<article class="feature-card">
<h3>History</h3>
<p>Read commits and branches together.</p>
</article>
<article class="feature-card">
<h3>Changes</h3>
<p>Review the exact content selected for a commit.</p>
</article>
<article class="feature-card">
<h3>Recovery</h3>
<p>Inspect the scope of a recovery point before using it.</p>
</article>
</div>
</section>
<section aria-labelledby="plans-title">
<h2 id="plans-title">Choose the workflow you need</h2>
<div class="cards">
<article class="feature-card">
<h3>Local Git</h3>
<p>Local Git workflows work without signing in.</p>
</article>
<article class="feature-card">
<h3>Connected workflows</h3>
<p>Provider integrations and Nour require Pro or an applicable trial.</p>
</article>
</div>
</section>
</main>
<footer><p>Built by a fictional team for GitTree Learn. Review one change at a time.</p></footer>
<script type="module" src="site.js"></script>
</body>
</html>index.html — RÉSOLU
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>GitTree Features — course demo</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<header class="site-header">
<a href="#main">GitTree Features</a>
</header>
<main id="main" tabindex="-1">
<section class="hero" aria-labelledby="hero-title">
<p class="eyebrow">GitTree Learn demo project</p>
<h1 id="hero-title">Review each change with confidence.</h1>
<p id="hero-copy">Choose one change, then check what Git saved.</p>
</section>
<section class="features" aria-labelledby="features-title">
<h2 id="features-title">Follow your work</h2>
<div class="cards">
<article class="feature-card">
<h3>History</h3>
<p>Read commits and branches together.</p>
</article>
<article class="feature-card">
<h3>Changes</h3>
<p>Review the exact content selected for a commit.</p>
</article>
<article class="feature-card">
<h3>Recovery</h3>
<p>Inspect the scope of a recovery point before using it.</p>
</article>
</div>
</section>
<section aria-labelledby="plans-title">
<h2 id="plans-title">Choose the workflow you need</h2>
<div class="cards">
<article class="feature-card">
<h3>Local Git</h3>
<p>Local Git workflows work without signing in.</p>
</article>
<article class="feature-card">
<h3>Connected workflows</h3>
<p>Provider integrations and Nour require Pro or an applicable trial.</p>
</article>
</div>
</section>
</main>
<footer><p>Built by a fictional team for GitTree Learn. Review one change at a time.</p></footer>
<script type="module" src="site.js"></script>
</body>
</html>Dans GitTree
Ouvrez la palette avec Commande+Maj+P (Ctrl+Maj+P sur Ubuntu). Les actions sur une branche nommée utilisent le menu contextuel de cette branche.
- Construisez les deux copies comme le montre la section suivante. Ouvrez gittree-conflict-merge, avec
conflict/saraextrait. - Cliquez avec le bouton droit sur
conflict/omaret choisissez Merge conflict/omar into conflict/sara. Sous Record it as, choisissez Always a merge commit. La boîte de dialogue avertit « S'arrêtera avec un conflit dans 1 fichier » ; choisissez Merge. La fusion s'arrête, ce qui est le résultat attendu. - La bannière indique "Fusionner conflit/omar en conflit/sara" avec "1 conflit", et Continue n'est pas encore disponible : "Résolvez d'abord les 1 conflits". Choisissez Resolve.
- Ouvrez
index.htmlà partir de Conflicted files. Lisez les deux côtés, conflict/sara (current) et conflict/omar (incoming), et utilisez Show Base pour lire le Base (common ancestor). - Choisissez Edit Output, remplacez le titre en conflit par
Review each change with confidence.et conservez une ligne sur deux. Choisissez ensuite Save and Mark Resolved. Supprimer les marqueurs et fermer le fichier ne suffit pas. - De retour sur la bannière, choisissez Continue. Si un message vous est proposé, conservez celui proposé. Attendez la fin de la fusion : le nouveau commit a deux parents.
- Ouvrez gittree-conflict-rebase, avec
conflict/saraextrait. Cliquez avec le bouton droit surconflict/omaret choisissez Rebase conflict/sara onto conflict/omar. Laissez les options sous Options for this rebase désactivées, puis choisissez Rebase conflict/sara. Cela s'arrête avec un conflit. - Choisissez Resolve et ouvrez
index.html. Les côtés sont désormais conflict/omar (rebasing onto) et conflict/sara (your commit) : les rôles sont inversés. Faites de même Edit Output → Save and Mark Resolved, puis Continue. - Vérifiez les deux copies : le fichier est RÉSOLU, aucun fichier en conflit n'est laissé et aucune bannière ne s'affiche. Gardez les deux résultats séparés et ne poussez pas.
Pour chaque commit ordinaire du cours : Summary est le sujet indiqué, Description est vide et les options Amend Previous Commit, Skip Hooks, Add Signed-off-by, Different Author, Push After Commit et Allow Empty Commit restent désactivées.
Dans la borne
Dans une copie propre séparée du résultat de la leçon 18 :
git switch --create conflict/sara
BASE_SHA="$(git rev-parse HEAD)"Enregistrez SARA sous index.html, puis :
git add -- index.html
git -c user.name="Sara Lindqvist" -c user.email=sara@example.com commit --quiet -m "feat: Sara clarifies the hero"
git switch --quiet --create conflict/omar "$BASE_SHA"Enregistrez OMAR sous index.html, puis :
git add -- index.html
git -c user.name="Omar Haddad" -c user.email=omar@example.com commit --quiet -m "feat: Omar explains the hero"
git switch --quiet conflict/saraBASE_SHA est M, avant l'un ou l'autre commit concurrent. Faites deux copies propres de cette divergence, une pour la fusion et une pour le rebase (cd .. && cp -R gittree-features gittree-conflict-merge && cp -R gittree-features gittree-conflict-rebase). Dans la copie de fusion :
git merge --no-ff --no-edit conflict/omar
git ls-files --unmerged
git show :2:index.html
git show :3:index.htmlLa fusion s'arrête avec le code de sortie 1 et git ls-files --unmerged répertorie trois entrées, les étapes 1, 2 et 3. git show :2:index.html est la version de Sara (la nôtre) et :3: est celle d'Omar (la leur) ; :1: est la base. Enregistrez RÉSOLU sous index.html, puis :
git add -- index.html
git -c core.editor=true merge --continue
git ls-files --unmerged
git status --shortLes deux dernières commandes n'impriment rien. Dans la copie de rebase intacte :
git rebase conflict/omar
git show :2:index.html
git show :3:index.htmlLe rebase s'arrête. Maintenant, :2: est la version d'Omar et :3: celle de Sara : les rôles sont inversés. Enregistrez RÉSOLU sous index.html, puis :
git add -- index.html
git -c core.editor=true rebase --continue
git ls-files --unmerged
git status --shortLes deux fichiers sont désormais RÉSOLUS et rien n'est fusionné. core.editor=true n'accepte que le message de validation existant pour cette seule commande ; cela ne modifie pas les paramètres de votre éditeur. Pour quitter une opération arrêtée sans résolution, utilisez git merge --abort ou git rebase --abort.
Résultat
Where you end: la copie de fusion a un nouveau commit avec deux parents et le titre combiné ; la copie de rebase a le commit de Sara recréé sur celui d'Omar avec le même en-tête combiné. Dans les deux cas, index.html est égal à RÉSOLU, aucune entrée de conflit n'est laissée, l'opération est terminée et l'état est propre.
Erreurs courantes
- En supposant que « le nôtre » signifie toujours votre propre fonctionnalité. Cela signifie que le côté sur lequel Git se trouve, et cela change avec l'opération.
- Prendre un parti en gros (« Take All ») avant de lire les deux versions et le reste du dossier.
- Supprimer les marqueurs de conflit mais ne jamais enregistrer et marquer le fichier comme résolu.
- Répéter une fusion ou un rebase déjà terminé.
Si quelque chose ne va pas
Si un arrêt semble incorrect, Abort… de la bannière restaure l'état à partir duquel l'opération a commencé et supprime les résolutions prises jusqu'à présent ; GitTree conserve d'abord un instantané de récupération. Si le fichier a changé pendant que vous l'éditiez, utilisez les choix Compare et Use as Output plutôt que de forcer une ancienne sauvegarde. Conservez une copie de votre brouillon avant de le remplacer.
Vérifiez votre compréhension
Répondez à chaque question, puis lisez pourquoi. Les questions marquées « Obligatoire » comptent pour terminer la leçon.
0 sur 6 corrects
Répondez correctement aux questions requises pour terminer la leçon.
Vérifié dans ce navigateur.
Pratique
Prouvez les rôles d'étape pour les deux opérations avec git show :2:index.html et git show :3:index.html, puis enregistrez le même fichier RÉSOLU et terminez chaque opération. Prédisez ce qui resterait dans la page si vous preniez aveuglément « le nôtre » dans les deux exemplaires.
Votre propre confirmation : le site ne peut pas voir votre ordinateur.
Pour terminer la leçon, répondez correctement aux questions demandées et confirmez l'exercice pratique.
Récapitulatif
- Nos rôles et les leurs dépendent de l’opération.
- Enregistrez d'abord et marquez résolu, puis continuez.
- Vérifiez ensuite l'ensemble du fichier et l'état de fonctionnement.
En rapport
Termes du glossaire introduits
Conflit — تعارض; base — الأساس; le nôtre — نسختنا; le leur — نسختهم; résoudre — حلّ.
Transcription vidéo
La narration de la vidéo, repère par repère.
Afficher la transcription
- Un conflit n'est pas une erreur. C'est un question à laquelle vous seul pouvez répondre.
- Deux personnes ont changé la même ligne du même fichier.
- Sara a écrit un titre. Omar a écrit un autre. Les deux sont partis de la même page.
- Git ne peut pas deviner quelle ligne gagne, donc il s'arrête et vous demande.
- Tout d'abord, construisez les succursales de Sara et d'Omar, et deux exemplaires identiques.
- Dans le premier exemplaire, nous fusionnons. Dans la seconde, nous rebasons.
- Ouvrez la copie de fusion, sur la branche de Sara.
- Faites un clic droit sur la branche d'Omar et choisissez son Commande de fusion.
- La boîte de dialogue prévient déjà : cela va s'arrêter avec un conflit dans un fichier.
- Choisissez Toujours un commit de fusion, puis Fusionner une fois. Cela s'arrête, comme prévu.
- La bannière montre un conflit. Continuer est pas encore disponible.
- Choisissez Résoudre et ouvrez index.html.
- Deux faces : la branche de Sara est actuelle, Celui d'Omar arrive.
- Show Base révèle l'ancêtre commun, le page avant l’un ou l’autre changement.
- Modifiez maintenant la sortie. Remplacez le titre par une ligne délibérée.
- Enregistrez et marquez résolu. Ce n'est que maintenant que Git traiter le fichier comme résolu.
- De retour sur la bannière, choisissez Continuer. Le fusionner les finitions.
- Le nouveau commit a deux parents, et le rubrique combinée.
- Maintenant la copie de rebase, également sur celle de Sara branche.
- Faites un clic droit sur la branche d'Omar et rebasez La branche de Sara dessus.
- Laissez les options désactivées et rebasez une fois. Il s'arrête avec un conflit.
- Regardez les étiquettes. Maintenant, la succursale d'Omar est celui sur lequel nous nous rebasons.
- Le commit de Sara est celui qui est rejoué. Les rôles ont été inversés.
- Même résolution : modifier la sortie, puis enregistrer et Marquer résolu, puis Continuer.
- Le commit de Sara est recréé au-dessus de Celui d'Omar, avec le même en-tête.
- Dans le terminal, listez les entrées non fusionnées d'une fusion arrêtée.
- La deuxième étape est à nous : le cap de Sara. Scène trois sont à eux : ceux d'Omar.
- Dans un rebase arrêté, étapes deux et trois sont l'inverse.
- Après le correctif, rien n'est fusionné et le statut est vide.
- La pointe de la copie de fusion a deux parents ; le L'astuce de la copie de rebase en a une.
- Modifier l'entrée : supprimer les marqueurs et enregistrer, mais ne pas marquer comme résolu.
- Git voit toujours trois étapes, alors continuez reste indisponible.
- Bloqué? Abandonner remet la branche là où l'opération commença.
- GitTree enregistre d'abord un instantané de récupération, donc même un abandon est sûr.
- Ne prenez jamais tout d'un côté devant vous lisez les deux versions.
- Pratique : prouver les rôles sur scène dans les deux copies, puis terminez les deux.
- Ensuite, continuez, sautez ou abandonnez une opération cela s'est arrêté.