Comment supprimer le premier commit dans git?

179

Je suis curieux de savoir comment supprimer le premier commit dans git.

Quelle est la révision avant de commettre quoi que ce soit? Cette révision a-t-elle un nom ou une étiquette?

Jian Weihang
la source
2
Pour commencer avec git, vous devez savoir que la révision n'a pas de sens. Vous pouvez parler des commits ou de leurs SHA relatifs. Aussi, pourquoi voudriez-vous faire cela? Le premier commit est sur quoi tout est construit. Vous pouvez écraser quelques commits ensemble, y compris le premier commit, qui devient le nouveau premier commit, mais que signifie même supprimer le premier commit (ou en supprimer tout sauf le dernier)?
Shahbaz
@Shahbaz ouais, c'est la meilleure façon, regardez ici par exemple: ariejan.net/2011/07/05/git-squash-your-latests-commits-into-one
timaschew
5
Vous pouvez utiliser git rebase -i --root. Voir la réponse SO suivante pour plus de détails: stackoverflow.com/questions/2246208/…
MKroehnert
duplication possible de Puis-je supprimer le commit initial d'un dépôt Git?
Gordon Gustafson
Cette réponse a la bonne solution pour supprimer le commit racine de la branche actuelle:git filter-branch --parent-filter "sed 's/-p <the_commit>//'" HEAD
Jody Bruchon

Réponses:

321

Pour moi, le moyen le plus sûr est d'utiliser la update-refcommande:

git update-ref -d HEAD

Il supprimera la référence nommée HEAD, donc il réinitialisera (doucement, vous ne perdrez pas votre travail) tous vos commits de votre branche actuelle .

Si vous souhaitez fusionner le premier commit avec le second, vous pouvez utiliser la rebasecommande:

git rebase -i --root

Un dernier moyen pourrait être de créer une branche orpheline, une branche avec le même contenu mais sans historique de commit, et de valider votre nouveau contenu dessus:

git checkout --orphan <new-branch-name>
tzi
la source
7
C'est dommage que ce ne soit pas la réponse acceptée. C'est aussi dommage que la plupart des hits sur Google disent plus ou moins "vous ne pouvez pas annuler le premier commit". Cela a fait l'affaire pour moi. Merci!
danielpops
1
Merci @danielpops pour votre soutien! Il est bon de noter que j'ai répondu à cette question 3 ans plus tard. Git a évolué entre-temps.
tzi
J'ai utilisé rebase, marqué le deuxième commit comme "squash", puis j'ai fait une poussée --force vers l'origine. Merci!
Philip Atz
1
git update-ref -d HEAD est le moyen le plus sûr de supprimer tout l'historique, pas seulement le commit initial.
user1767316
Je l'ai fait et j'ai supprimé tous mes fichiers que j'avais ajoutés au premier commit. Triste. Au moins ce n'était pas beaucoup
Vyacheslav Tsivina
42

Il n'y a rien avant le premier commit, car chaque commit fait référence à un commit parent. Cela rend le premier commit spécial (un commit orphelin), il n'y a donc aucun moyen de faire référence à un "état" précédent.

Donc, si vous voulez corriger le commit, vous pouvez simplement git commit --amend: cela modifiera le commit sans en créer un autre.

Si vous voulez simplement tout recommencer, supprimez le .gitréférentiel et créez-en un autre avecgit init

CharlesB
la source
7
Cette réponse est incorrecte: il existe un moyen de revenir à l'état avant le premier commit. Voir la réponse de tzi ci-dessous.
David Nelson
2
De --amendplus, l'auteur ne mettra pas à jour correctement s'il était initialement mal configuré. C'est ce dont j'avais besoin, alors j'ai utilisé la réponse acceptée, puis j'ai simplement fait un nouveau commit à la place.
Mark Edington
11
# Check out to a temporary branch:
git checkout --orphan TEMP_BRANCH

# Add all the files:
git add -A

# Commit the changes:
git commit -am "Initial commit"

# Delete the old branch:
git branch -D master

# Rename the temporary branch to master:
git branch -m master

# Finally, force update to our repository:
git push -f origin master
Megha Sahu
la source
3
Pas de réponse: la question était "comment supprimer le premier commit" et non "comment tout supprimer sauf le dernier commit".
peterh
1
Je cherchais exactement cela. Merci!
Krzysztof Tomaszewski
6

Vous voudrez peut-être simplement modifier votre premier commit (car il y a toujours un premier commit dans un dépôt git). Pensez à utiliser git commit --amend --reset-authorplutôt que d'habitude git commit --amend.

Max Beikirch
la source
1
Pas de réponse: la question voulait supprimer le premier commit, et non pas modifier les propriétés du dernier.
peterh - Réintégrer Monica
@ peterh-ReinstateMonica Pour clarification: les commits peuvent être modifiés pendant le rebase interactif pour changer complètement leur contenu, mais --reset-author doit également être fourni pour changer l'auteur. Avec cela, vous pouvez remplacer complètement le premier commit à votre guise. Voir aussi la réponse de CharlesB.
Max Beikirch
3

Je cherchais un moyen d'annuler tous les commits git d'un repo, comme s'ils ne s'étaient jamais produits.

La réinitialisation fonctionnera jusqu'à un certain point. Cependant, le tout premier (chronologiquement le plus ancien commit git) sera toujours problématique, car il n'a pas de parent, ce qui entraînera une erreur.

Aucune de ces réponses ne l'a résolu pour moi. Mais après de nombreuses recherches et essais et erreurs, j'ai trouvé que cela fonctionnait!

git update-ref -d HEAD
git push origin master -f

J'espère que cela vous aide. Passez une bonne journée.

kp123
la source
1
Pour être clair pour tous ceux qui liront cette réponse: cela supprime chaque commit, mais OP veut seulement supprimer le premier commit fait à un dépôt; ne l'exécutez pas pour supprimer le premier commit car cela supprimera TOUS les commits.
Jody Bruchon du
2

Une autre façon de procéder est:

  1. Checkout dans une branche que vous souhaitez conserver (par exemple dev) git checkout dev
  2. Maintenant, supprimez la branche que vous souhaitez réinitialiser git branch -D master
  3. Maintenant, créez une branche vide avec le même nom git checkout --orphan master

Bien sûr, tout cela dépendra de votre cas d'utilisation, mais si vous avez plus d'une branche, la suppression du .gitrépertoire n'a pas de sens.

Kumarharsh
la source
3
Après cela, vous devez supprimer la branche dans remote avant de pousser. Sinon, lorsque vous essayez de pousser, vous aurez cette erreur:! [rejeté] master -> master (pas d'avance rapide) - erreur: échec de l'envoi de certaines références à '[email protected]: r1 / r2.git' - indice: les mises à jour ont été rejetées car la pointe de votre branche actuelle est derrière - indice: son homologue distant. Intégrez les modifications distantes (par exemple, indice: 'git pull ...') avant de pousser à nouveau ... - Si vous faites un git pull, tous les commits reviennent.
dxvargas
2

Si vous souhaitez conserver d'autres branches, mais par exemple faire masterredémarrer la branche sans historique commun aux autres branches, un moyen sûr d'y parvenir est de créer un nouveau référentiel et d'en pousser le contenu dans l'ancien:

cd ..
git init newrepo
cd newrepo
# make some initial commits
git push ../oldrepo master:newmaster

Cela crée une newmasterbranche dans l'ancien référentiel, avec un historique qui n'est commun à aucune des autres branches. Bien sûr, vous pouvez également remplacer le fichier masteravec git push -f.

Si vous souhaitez détruire toutes les branches et tout le contenu existant, exécutez simplement

rm -rf .git/
user1338062
la source
1
Pas de réponse: l'OP voulait supprimer le premier commit, et ne pas démarrer un nouveau dépôt git avec l'arbre de travail actuel comme commit initial.
peterh
@peterh Je suis d'accord, git rebase --rootc'est probablement ce que OP voulait, mais étant donné que cette réponse a deux votes positifs, je m'abstiendrai de la supprimer au cas où quelqu'un la trouverait toujours pertinente.
user1338062
Je pense que cette réponse est tout à fait pertinente - si vous voulez supprimer le premier commit dans une branche, et qu'il n'y a qu'un seul commit! (Mais vous voulez également conserver les autres commits dans d'autres branches; et vous voulez également le faire pour que les changements aboutissent soit à Bitbucket, soit à Github, pas seulement localement.) Je pense que cette réponse est une façon de le faire, et Je pense que c'est peut-être le seul moyen de le faire. (C'est parce que - aussi loin que je peux voir - il n'y a aucun moyen de forcer le transfert d'une branche locale sans commits sur une branche distante avec quelques commits.)
MikeBeaton
0

Si vous venez de le valider mais que vous ne l'avez pas poussé, supprimez simplement le répertoire .git et git initencore une fois ...

Ali Sajid
la source
@peterh Oui, c'est vrai. Vous supposez (je pense) que la question de l'OP est de vouloir supprimer le premier commit mais de conserver les commits suivants. Une autre possibilité (qui, je pense, correspond parfaitement à la question de l'OP - et à laquelle cette réponse est une réponse) est de vouloir supprimer le premier et le seul commit d'une branche, le ramenant à nouveau complètement vide.
MikeBeaton
@MikeBeaton Vous avez raison. Je supprime mon commentaire, mais je dois ensuite voter pour clore la question car elle n'est pas claire. Notez bien que ce n'est que moi qui ai fait ce commentaire, mais derrière moi il y a 40000 visiteurs, et une partie importante d'entre eux a trouvé cette question avec google - et ils n'ont pas obtenu ce qu'ils voulaient.
peterh - Réintégrer Monica le
Cela semble extrême. Supprimer la question? Ne pourrait-on pas (parfaitement) affirmer qu'une réponse complète à ce qui est une question parfaitement raisonnable est qu'il y a deux approches différentes qui doivent être adoptées, selon que ... etc.? (Je veux dire, je, pour un, voudrais savoir comment faire pour supprimer le premier engagement quand il est pas le seul commettre, et aussi comment supprimer le premier commit quand il est le seul commettras. Il est certainement pas évident, et certainement dépend sur les détails spécifiques de la mise en œuvre, qu'il s'avère en fait que des approches vraiment différentes sont nécessaires dans chaque cas.)
MikeBeaton
0

La réponse à la question dépend de si:

  • Vous voulez supprimer le premier ET UNIQUEMENT commit sur une branche (tout en laissant les autres branches telles qu'elles étaient), ou si

  • Vous voulez supprimer le premier commit sur une branche, tout en «laissant en place» les commits suivants (et les autres branches).

Le second est relativement plus simple. Vous devez essentiellement rebase à la racine - la plupart des réponses ici concernent les moyens de le faire.

Faire le second (supprimer le premier et le seul commit d'une branche tout en laissant les autres branches seules) est plus difficile. Ou, du moins, particulièrement plus difficile si vous voulez que cela se produise et que le changement soit reflété dans GitHub ou Bitbucket. Il n'y a (pour autant que je sache) aucun moyen du tout dans Git de pousser ou de forcer à pousser une branche sans commits. Et il n'y a pas non plus (encore une fois, pour autant que je sache) aucun moyen de créer une nouvelle branche vide sans commits dans GitHub ou Bitbucket. Donc, vous devez essentiellement créer un nouveau référentiel afin de créer une branche complètement vide, puis rajouter les branches que vous voulez (y compris les commits que vous voulez) - selon la réponse de @ user1338062.

J'espère donc que cette réponse clarifie ce qui n'aurait peut-être pas été évident - qu'il y a deux approches différentes à adopter, pour deux scénarios différents (plus ou moins raisonnables) qui sont les deux choses que vous voudrez peut-être être en mesure de faire, dans l'ordre pour maîtriser pleinement ce que le PO demande.

MikeBeaton
la source