Comment écraser tout git commet dans un?

Comment écrasez-vous tout votre repository jusqu’au premier commit?

Je peux revenir à la première validation, mais cela me laisserait 2 commits. Existe-t-il un moyen de référencer le commit avant le premier?

Le moyen le plus simple est peut-être de créer un nouveau référentiel avec l’état actuel de la copie de travail. Si vous souhaitez conserver tous les messages de validation, vous pouvez d’abord git log > original.log , puis le modifier pour votre message de validation initial dans le nouveau référentiel:

 rm -rf .git git init git add . git commit 

ou

 git log > original.log # edit original.log as desired rm -rf .git git init git add . git commit -F original.log 

Dans les versions récentes de git, vous pouvez utiliser git rebase --root -i .

Pour chaque engagement sauf le premier, changez le pick pour le squash .

Mettre à jour

J’ai fait un alias git squash-all .
Exemple d’utilisation : git squash-all "a brand new start" .

 [alias] squash-all = "!f(){ git reset $(git commit-tree HEAD^{tree} -m \"${1:-A new start}\");};f" 

Avertissement : n’oubliez pas de fournir un commentaire, sinon le message de validation par défaut “Un nouveau départ” serait utilisé.

Ou vous pouvez créer l’alias avec la commande suivante:

 git config --global alias.squash-all '!f(){ git reset $(git commit-tree HEAD^{tree} -m "${1:-A new start}");};f' 

Bon mot

 git reset $(git commit-tree HEAD^{tree} -m "A new start") 

Note : ici, ” A new start ” est juste un exemple, n’hésitez pas à utiliser votre propre langue.

TL; DR

Pas besoin d’écraser, utilisez git commit-tree pour créer un commit orphelin et aller avec.

Explique

  1. créer un seul commit via l’ git commit-tree

    Qu’est git commit-tree HEAD^{tree} -m "A new start" ce que git commit-tree HEAD^{tree} -m "A new start" fait:

    Crée un nouvel object de validation basé sur l’object d’arbre fourni et émet le nouvel identifiant d’object de validation sur la sortie standard. Le message de journal est lu à partir de l’entrée standard, à moins que les options -m ou -F ne soient fournies.

    L’expression HEAD^{tree} signifie l’object d’arbre correspondant à HEAD , à savoir la pointe de votre twig actuelle. voir Objets d’arbre et Objets d’ engagement .

  2. réinitialiser la twig actuelle au nouveau commit

    Ensuite, git reset simplement la twig en cours sur le nouvel object commit créé.

De cette façon, rien dans l’espace de travail n’est touché, pas plus que le rebase / squash, ce qui le rend très rapide. Et le temps nécessaire est sans importance pour la taille du référentiel ou la profondeur de l’historique.

Variation: Nouveau repository d’un modèle de projet

Ceci est utile pour créer le “commit initial” dans un nouveau projet en utilisant un autre référentiel en tant que template / archetype / seed / skeleton. Par exemple:

 cd my-new-project git init git fetch --depth=1 -n https://github.com/toolbear/panda.git git reset --hard $(git commit-tree FETCH_HEAD^{tree} -m "initial commit") 

Cela évite d’append le référentiel de modèle en tant que distant ( origin ou autre) et réduit l’historique du référentiel de modèles dans votre validation initiale.

Si tout ce que vous voulez faire est d’écraser tous vos commits jusqu’à la validation racine, alors que

 git rebase --interactive --root 

peut fonctionner, ce n’est pas pratique pour un grand nombre de commits (par exemple, des centaines de commits), car l’opération de rebase s’exécutera probablement très lentement pour générer la liste des validations de l’éditeur de rebase interactif et exécuter elle-même le rebase.

Voici deux solutions plus rapides et plus efficaces lorsque vous écrasez un grand nombre de commits:

Solution alternative n ° 1: twigs orphelines

Vous pouvez simplement créer une nouvelle twig orpheline à la pointe (c’est-à-dire la validation la plus récente) de votre twig actuelle. Cette twig orpheline constitue la validation racine initiale d’un arbre historique de validation entièrement nouveau et séparé, ce qui équivaut à écraser tous vos commits:

 git checkout --orphan new-master master git commit -m "Enter commit message for your new initial commit" # Overwrite the old master branch reference with the new one git branch -M new-master master 

Documentation:

  • git-checkout (1) Page de manuel .

Solution alternative n ° 2: réinitialisation logicielle

Une autre solution efficace consiste à utiliser simplement une réinitialisation mixte ou logicielle sur le commit :

 git branch beforeReset git reset --soft  git commit --amend # Verify that the new amended root is no different # from the previous branch state git diff beforeReset 

Documentation:

  • git-reset (1) Page Manuelle .
 echo "message" | git commit-tree HEAD^{tree} 

Cela créera un commit orphelin avec l’arbre de HEAD et affichera son nom (SHA-1) sur stdout. Ensuite, réinitialisez simplement votre succursale.

 git reset SHA-1 

Voici comment j’ai fini par le faire, juste au cas où cela fonctionnerait pour quelqu’un d’autre:

Rappelez-vous qu’il y a toujours un risque à faire des choses comme ça, et ce n’est jamais une mauvaise idée de créer une twig de sauvegarde avant de commencer.

Commencez par vous connecter

 git log --oneline 

Faites défiler pour d’abord valider, copiez SHA

 git reset --soft < #sha#> 

Remplacez < #sha#> par le SHA copié à partir du journal

 git status 

Assurez-vous que tout est vert, sinon lancez git add -A

 git commit --amend 

Modifier tous les changements actuels au premier engagement actuel

Maintenant, forcez cette twig et cela écrasera ce qui existe.

Le plus simple est d’utiliser la commande ‘plumbing’ update-ref pour supprimer la twig en cours.

Vous ne pouvez pas utiliser git branch -D car il comporte une soupape de sécurité pour vous empêcher de supprimer la twig actuelle.

Cela vous ramène à l’état de “validation initiale” où vous pouvez commencer par un nouvel engagement initial.

 git update-ref -d refs/heads/master git commit -m "New initial commit" 

J’ai lu quelque chose sur l’utilisation de greffes mais je n’ai jamais beaucoup étudié.

Quoi qu’il en soit, vous pouvez écraser ces deux dernières commits manuellement avec quelque chose comme ceci:

 git reset HEAD~1 git add -A git commit --amend 

Tout d’abord, écrasez tous vos commits en un seul commit en utilisant git rebase --interactive . Maintenant, il ne vous rest plus que deux engagements à écraser. Pour ce faire, lisez l’un des

  • Comment combiner les deux premiers commits d’un référentiel Git?
  • git: comment écraser les deux premiers commits?

Courge en utilisant des greffes

Ajouter un fichier .git/info/grafts , y mettre le hash de commit que vous voulez devenir votre root

git log va maintenant commencer à partir de ce commit

Pour le rendre «réel», exécutez git filter-branch

“Solution alternative n ° 1: twigs orphelines” m’aide.

“git rebase –interactive –root” bloqué sur le conflit de fichiers gitignored.

Cette réponse améliore un peu plus haut (veuillez les voter), en supposant que, en plus de créer celui qui a été validé (no-parents no-history), vous souhaitez également conserver toutes les données de validation de ce commit:

  • Auteur (nom et email)
  • Date d’auteur
  • Commiter (nom et email)
  • Date engagée
  • Envoyer un message de journal

Bien sûr, le commit-SHA du commit nouveau / single changera, car il représente un nouvel historique (non), devenant un commit sans parent / root.

Cela peut être fait en lisant git log et en définissant des variables pour git commit-tree . En supposant que vous souhaitiez créer un seul commit à partir du master dans une nouvelle twig one-commit , en conservant les données de validation ci-dessus:

 git checkout -b one-commit master ## create new branch to reset git reset --hard \ $(eval "$(git log master -n1 --format='\ COMMIT_MESSAGE="%B" \ GIT_AUTHOR_NAME="%an" \ GIT_AUTHOR_EMAIL="%ae" \ GIT_AUTHOR_DATE="%ad" \ GIT_COMMITTER_NAME="%cn" \ GIT_COMMITTER_EMAIL="%ce" \ GIT_COMMITTER_DATE="%cd"')" 'git commit-tree master^{tree} <  

Je le fais habituellement comme ceci:

  • Assurez-vous que tout est validé et notez le dernier identifiant de validation en cas de problème ou créez une twig distincte en tant que sauvegarde.

  • Exécutez git reset --soft `git rev-list --max-parents=0 --abbrev-commit HEAD` pour réinitialiser votre tête au premier commit, mais laissez votre index inchangé. Toutes les modifications depuis la première validation apparaissent désormais prêtes à être validées.

  • Lancez git commit --amend -m "initial commit" pour modifier votre commit au premier commit et modifier le message de validation, ou si vous voulez garder le message de commit existant, vous pouvez lancer git commit --amend --no-edit

  • Exécuter git push -f pour forcer vos modifications

créer une sauvegarde

 git branch backup 

réinitialiser à la validation spécifiée

 git reset --soft  

append tous les fichiers au staging

 git add . 

valider sans mettre à jour le message

 git commit --amend --no-edit 

pousser nouvelle twig avec écrasé s’engage à repo

 git push -f 

En une ligne de 6 mots

 git checkout --orphan new_root_branch && git commit