web-dev-qa-db-fra.com

Retourner une série de fusion poussées et s'engage dans Git (sans historique de réécriture)

Le contexte

L'un de mes coéquipiers a poussé à tort à tort que certains commises à notre principale branche de développement. Nous sommes une petite équipe colloquée. Notre référentiel à distance est hébergé sur un serveur interne.

Voici le sommet de notre journal de validation (tous ces engagements ont déjà été poussés):

$ git log develop -6 --pretty=oneline --abbrev-commit
faada93 Merge branch 'develop' of <our_repo_path>.git
244d174 Support classes again
a97a877 Pruned all unused references (again).
8c29252 Merge branch 'develop' of <our_repo_path>.git
a78b993 Support models & methods - product types & categories
da8b496 Resolved JIRA issue PPF-182

da8b496 est la dernière commission que nous voulions garder dans notre succursale develop, nous devions donc revoir les 5 derniers engagements. Nous avons créé une nouvelle succursale de 8c29252 Pour continuer à travailler dans une "branche de fonctionnalité".

J'ai essayé beaucoup de choses, guidée par cette réponse et ce post de Linus et a fini par faire ce que vous pouvez voir dans mon historique de terminal ci-dessous. Mais je ne sais pas si ce que j'ai fini par faire est "de la bonne façon". Les informations que j'ai trouvées étaient complexes; Je n'ai pas pu discerner une "meilleure solution" pour ce problème particulier.

Question

L'approche que j'ai choisie (voir les détails ci-dessous) un bon moyen de revenir à ces 5 commits, sans nuire à notre histoire? Y a-t-il un moyen plus facile ou "plus correct" d'accomplir la même chose?

Entre autres choses, j'ai envisagé de créer une nouvelle branche de da8b496 (git checkout -b new-develop da8b496) et abandonner notre succursale actuelle develop, mais cela n'a tout simplement pas senti raison.


Ce que j'ai fini par faire (détails)

Premièrement, j'ai créé une nouvelle succursale pour les commits a78b993 et 8c29252, parce que ces commits contiennent des travaux que nous voulons conserver et finalement fusionner à notre principale branche de développement.

$ git checkout -b new-feature-brach 8c29252

Ensuite, j'ai commencé à renvoyer les engagements incriminés dans notre agence de développement.

J'ai essayé ceci en premier, mais cela n'a pas fonctionné (probablement parce que certains des engagements sont fusionnés):

$ git revert a78b993..HEAD
error: a cherry-pick or revert is already in progress
hint: try "git cherry-pick (--continue | --quit | --abort)"
fatal: revert failed

Donc ... je retourne manuellement chaque commit à la place; un par un:

$ git revert -m 1 faada93
[develop 40965a5] Revert "Merge branch 'develop' of <our_repo_path>.git"
8 files changed, 167 insertions(+), 3 deletions(-)

$ git revert 244d174
[develop 3cebd68] Revert "Support classes again"
45 files changed, 557 insertions(+), 1572 deletions(-)
(list of affected files)

$ git revert a97a877
error: could not revert a97a877... Pruned all unused references (again).
hint: after resolving the conflicts, mark the corrected paths
hint: with 'git add <paths>' or 'git rm <paths>'
hint: and commit the result with 'git commit'

$ git mergetool
Merging:
exampleFile1.cs
exampleFile2.cs

Deleted merge conflict for 'exampleFile1.cs':
{local}: deleted
{remote}: modified file
Use (m)odified or (d)eleted file, or (a)bort? m

Deleted merge conflict for 'exampleFile2.cs':
{local}: deleted
{remote}: modified file
Use (m)odified or (d)eleted file, or (a)bort? m

$ git commit -m "Adding files to be reverted along with the next commit."
[develop 15bc02b] Adding files to be able to revert the next commit in line.
2 files changed, 239 insertions(+)
(list of affected files here)

$ git revert -m 1 8c29252
# On branch develop
# Your branch is ahead of 'Origin/develop' by 3 commits.
#   (use "git Push" to publish your local commits)
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#       exampleFile1.cs.orig
#       exampleFile2.cs.orig
nothing added to commit but untracked files present (use "git add" to track)

$ git revert a78b993
[develop 841e77c] Revert "Support models & methods - product types & categories"
2 files changed, 239 deletions(-)
(list of affected files here)

Commettez votre journal après que toutes les revêtements ont été effectués:

$ git log develop -10 --pretty=oneline --abbrev-commit
841e77c Revert "Support models & methods - product types & categories"
15bc02b Adding files to be able to revert the next commit in line.
3cebd68 Revert "Support classes again"
40965a5 Revert "Merge branch 'develop' of <our_repo_path>.git"
faada93 Merge branch 'develop' of <our_repo_path>.git
244d174 Support classes again
a97a877 Pruned all unused references (again).
8c29252 Merge branch 'develop' of <our_repo_path>.git
a78b993 Support models & methods - product types & categories
da8b496 Resolved JIRA issue PPF-182

Graphique après revertit:

$ git log --graph --oneline -8 develop
* 841e77c Revert "Support models & methods - product types & categories"
* 15bc02b Adding files to be able to revert the next commit in line.
* 3cebd68 Revert "Support classes again"
* 40965a5 Revert "Merge branch 'develop' of <our_repo_path>.git"
*   faada93 Merge branch 'develop' of <our_repo_path>.git
|\
| * a97a877 Pruned all unused references (again).
| *   8c29252 Merge branch 'develop' of <our_repo_path>.git
| |\
| | * da8b496 Resolved JIRA issue PPF-182

Me semble correct. Enfin, je supprime certains fichiers de sauvegarde que je ne veux pas garder:

$ git clean -fd
(list of affected files here)

L'état actuel est propre:

$ git status
# On branch develop
# Your branch is ahead of 'Origin/develop' by 4 commits.
#   (use "git Push" to publish your local commits)
#
nothing to commit, working directory clean

Et puis je repousse tout retour à la télécommande:

git Push Origin develop
25
Leif

Vous avez une petite équipe co-localisée, alors la communication n'est pas un problème. Faites ressembler à l'historique de commettre comme il aurait dû regarder:

git branch -f develop dab4896
git branch newfeature 8c29252
git Push -f Origin develop newfeature

et faire ressortir tout le monde. Vous avez terminé.

Ce type d'erreur est l'une des raisons de réécrire.

9
jthill

Même si votre histoire a changé, vous pouvez créer des succursales qui vous permettent de revenir en arrière et d'expérimenter. Git signifie jamais avoir à dire: "Vous devriez avoir." Si vous convergent sur une réalité que vous préférez, alors allez-y. Sinon, jetez-le.

Les exemples ci-dessous créeront de nouvelles branches qui laissent tout le reste de votre référentiel seul.

Alternative 1: Git Revert

Créez d'abord une branche de rayures au point où vous avez commencé votre aventure.

$ git checkout -b tmp-revert FAADA93

En spécifiant une gamme de validation, git revert annulera plusieurs commits.

$ git revert da8b496..faada93

Alternative 2: Git Engagement-Arbre

Considérez le diagramme ci-dessous de GIT INTERNALS - Objets GIT , section 10.2 dans la deuxième édition de pro git par Scott Chacon et Ben Straub. La principale commit ("troisième commit") a un hachage SHA1 qui commence 1a410e. Dans le contexte de cette histoire, 1a410e^{tree} serait résolu à 3c4e9c, c'est-à-dire l'objet de l'arbre immédiatement à la troisième commit.

Git Object Graph, Figure 151 from *Pro Git*Figure 151 à partir de Pro Git , 2e éd.

Étudiez ce modèle pour comprendre comment git Tracks Contenu. Créer un nouveau quatrième commettre dont l'arbre est identique à la deuxième société (c'est-à-dire 0155eb) ajouterait un nouvel objet de validation qui serait partager ou "pointez sur" l'arborescence et des blobs existants plutôt que d'ajouter de nouveaux objets en double.

Lisez sur pour apprendre à accomplir cette couture de bas niveau avec git commit-tree .

Commencez par créer une autre branche temporaire pour travailler.

$ Checkout GIT -B TMP-CTREE FAADA93

À ce stade, vous voulez créer un nouveau commit où son arbre (c'est-à-dire que le code engagé) est identique à celui de da8b496, la dernière commission que vous vouliez garder. Cet arbre est directement adressable dans GIT: da8b496^{tree}.

git commit-tree est "plomberie" une commande de bas niveau en git-par opposition à la "porcelaine". Cela peut se sentir maladroit ou inconnu d'utiliser, mais dans ce cas, il donne un contrôle précis du résultat souhaité.

Créer un nouveau commit non attaché dont l'arbre est le même que da8b496 'S et dont le parent (-p) est la pointe de la branche actuelle, faada93 dans ton cas. Noter que git commit-tree lit le message de validation du nouveau commit sur l'entrée standard, que la commande ci-dessous fournit avec la commande echo.

$ Echo revenir à DA8B496 |\[.____nouveau-commit-sha1

La partie en italique ci-dessus ne fait pas partie de la commande. Il indique que git commit-tree génère le hachage SHA1 du commit nouvellement créé. Connaître la nouvelle SHA1 de BIVIT, vous pouvez déplacer la branche vers ce point, E.g.,

$ git fusion nouveau-commit-sha1

Dans la commande ci-dessus, remplacez New-BIGET-SHA1 avec la sortie de git commit-tree. (Tu pourrais faire la même chose git reset --hard new-commit-sha1, mais la réinitialisation matérielle est un outil tranchant où l'utilisation occasionnelle est mieux évitée.)

Vous pouvez rouler tout ce qui précède en une seule commande composée.

$ git fusion --ff-seul $ (echo revenir à DA8B496 |\[.____] Git Big-Tree DA8B496 ^ ^ {{Tree} -P $ (GIT REV-PARSE TMP-CTREE))

Les --ff-only basculer vers git merge est destiné à empêcher les surprises. Votre intention est que le nouveau engagement de s'engager d'être un transfert rapide ou un descendant de la direction actuelle - son enfant immédiat, en fait!

Nettoyer

Pour supprimer les branches temporaires ci-dessus, passez à un autre et au feu, monsieur McManus. Vos autres branches seront tout comme vous les avez laissées.

$ check-out Développement 
 $ GIT Branch -D TMP-REVERT TMP-CTREE

Les deux doivent être identiques, comme vous pouvez vérifier avec

$ GIT DIFF TMP-REVERT TMP-CTREE

Pour en garder un, fusionnez-le dans votre branche develop.

$ check-out Développement 
 $ git fusion - peu uniquement TMP-CTREE [.____] $ GIT Push Origin Développer
12
Greg Bacon

Ce que vous essayez de faire est très risqué.

en effet, vous pouvez revenir et supprimer les engagements que vous avez déjà poussé au repo, mais si quelqu'un a déjà tiré vos modifications et qu'il a pris le comidid que vous allez supprimer, le repo peut devenir "instable" et git ne sera pas capable de Manipulez la traction et pousse depuis que vous avez supprimé Engage, qui est maintenant retiré de l'histoire.

Faites ceci (revenir et supprimer et supprimer des validons) uniquement et seulement si personne n'a tiré de ce commis.

0
CodeWizard