Jeter les commits locaux à Git

1469

En raison d'une mauvaise sélection de cerises, mon référentiel Git local a actuellement cinq commits d'avance sur l'origine et n'est pas en bon état. Je veux me débarrasser de tous ces commits et recommencer.

Évidemment, supprimer mon répertoire de travail et re-cloner le ferait, mais tout télécharger à nouveau depuis GitHub semble être exagéré, et pas une bonne utilisation de mon temps.

C'est peut git revert- être ce dont j'ai besoin, mais je ne veux pas finir par 10 commits avant l'origine (ou même six), même si cela remet le code lui-même dans le bon état. Je veux juste prétendre que la dernière demi-heure ne s'est jamais produite.

Existe-t-il une commande simple qui fera cela? Cela semble être un cas d'utilisation évident, mais je n'en trouve aucun exemple.


Notez que cette question concerne spécifiquement les validations , pas :

  • fichiers non suivis
  • changements non planifiés
  • Modifications par étapes, mais non validées
David Moles
la source

Réponses:

2470

Si vos commits excédentaires ne sont visibles que pour vous, vous pouvez simplement faire git reset --hard origin/<branch_name> pour revenir à l'endroit où se trouve l'origine. Cela réinitialisera l'état du référentiel à la validation précédente et annulera toutes les modifications locales.

Faire un git revertfait de nouveaux commits pour supprimer les anciens commits d'une manière qui garde l'histoire de chacun saine d'esprit.

Ben Jackson
la source
91
git reset --hard <commit hash, branch, or tag>si vous souhaitez accéder à une référence spécifique autre qu'une branche distante.
Sam Soffes
55
Juste pour être clair, si vous ne travaillez pas mastersur une autre branche, vous devez exécutergit reset --hard origin/<your-branch-name>
Zoltán
33
Cela supprimera non seulement les commits locaux, mais supprimera également tout ce qui se trouve dans votre arborescence de travail (c'est-à-dire vos fichiers locaux). Si tout ce que vous voulez faire est de ne pas engager, mais laissez votre travail intact, vous devez faire "git reset HEAD ^" ... per stackoverflow.com/questions/2845731/…
aaronbauman
3
Vous voudrez peut-être faire une extraction après cela. Cela a corrigé le nombre de validations en attente d'être poussé sur SourceTree.
Stan
2
git reset --hard origin/<branch_name>Il réinitialisera également la configuration du projet, alors prenez soin de cela. J'ai un gros .cfgfichier qui a été réinitialisé par défaut. J'ai dû à nouveau y consacrer des heures.
MAC
271

Supprimez simplement votre branche principale locale et recréez-la comme suit:

git branch -D master
git checkout origin/master -b master
Ramon Zarazua B.
la source
2
Cela fonctionne bien lorsque le retour en arrière de vos modifications coûterait trop de temps, ce qui m'est arrivé après quelques rebases.
aross
1
Utile pour les problèmes de traction / poussée des sous-arbres parmi les membres de l'équipe!
Jorge Orpinel
C'est parfait lorsque vous souhaitez restaurer une branche au lieu de simplement master.
Vladimir Ralev
1
ce n'est pas un bon moyen de supprimer un seul commit local. Mieux à utilisergit reset --hard origin/<branch_name>
Kirit Vaghela
1
Peut-être que cette solution fonctionnera, mais cela ne signifie pas qu'elle est la bonne.
Adly
202

Essayer:

git reset --hard <the sha1 hash>

pour réinitialiser votre tête là où vous voulez être. Utilisez gitk pour voir à quel commit vous voulez être. Vous pouvez également réinitialiser dans gitk.

Anders Zommarin
la source
5
Surévalué ce b / c ce sont des informations utiles, mais la réponse de Ben Jackson obtient la coche pour résoudre exactement ce que je voulais - d'une manière qui ne m'a pas obligé à rechercher des hachages de validation. :)
David Moles
2
C'est celui où votre nouvelle succursale n'a jamais été poussé à l' origine encore
Jan
126

Supprimez le commit le plus récent:

git reset --hard HEAD~1

Supprimez le commit le plus récent, sans détruire le travail que vous avez fait:

git reset --soft HEAD~1

James L.
la source
5
Réponse utile. Je vous remercie! J'ai utilisé git reset --soft origin / master
Tarun Kumar
2
@TarunKumar MERCI! J'utilise l'intégration VS, et votre solution a été le seul moyen que j'ai pu effacer un tas de commits de fusion que je ne voulais pas dans une branche que je n'avais pas la permission de m'enregistrer.
DVK
Merci, juste ce que je cherchais, "git reset --soft HEAD ~ 1" a fait le travail car je me suis engagé involontairement et je voulais revenir mais j'avais d'autres fichiers que je ne voulais pas être détruits après le retour.
edvard_munch
47

Si vous utilisez l' application Atlassian SourceTree , vous pouvez utiliser l'option de réinitialisation dans le menu contextuel.

entrez la description de l'image ici

murmure
la source
42

Lors de votre tentative de succursale:

git reset --hard origin/<branch_name>

Validez l'inversion (à l'état, sans commits locaux), en utilisant " git log" ou " git status" par conséquent.

parasir
la source
1
@Troyseph: toutes les réponses énumérées ci-dessus, j'ai essayé en l'état et je n'ai pas réussi à corriger le scénario. L'approche générique, qui n'a été illustrée dans aucune des réponses ci-dessus, est ce à quoi on a tenté de répondre ici.
parasrish
3
La réponse acceptée est la même que la vôtre, moins le nom générique de la branche, et dans les commentaires @Zoltan dit explicitementJust to be clear, if you're not working on master but on another branch, you should run git reset --hard origin/<your-branch-name>
Troyseph
1
C'est la meilleure réponse à mon avis.
dwjohnston
21

git reset --hard @{u}* supprime toutes vos modifications locales sur la branche actuelle, y compris les validations. Je suis surpris que personne n'ait encore posté cela, étant donné que vous n'aurez pas à chercher ce qui vous engage à revenir ou à jouer avec les branches.

* Autrement dit, réinitialiser à la branche actuelle à - @{upstream}généralement origin/<branchname>, mais pas toujours

Kevin Chen
la source
1
Certaines coquilles comme le poisson interpréteront le "@", vous devrez donc peut-être mettre le '@ {u}' entre guillemets, par exemple `git reset --hard '@ {u}'. Quoi qu'il en soit, bonne trouvaille!
trysis
La réponse impressionnante est impressionnante
Marko
1
Comment imprimez-vous la valeur de @ {u}?
Philip Rego
12

Pour voir / obtenir l'ID SHA-1 du commit que vous souhaitez revenir également

gitk --all

Pour revenir à ce commit

git reset --hard sha1_id

!Remarque. Toutes les validations effectuées après cette validation seront supprimées (et toutes vos modifications apportées au projet). Il est donc préférable de cloner le projet dans une autre branche ou de le copier dans un autre répertoire.

Nicolas
la source
c'est idéal pour les situations où la télécommande n'est plus disponible, et il suffit de réinitialiser à une validation locale. gitk est génial - n'était pas au courant auparavant.
theRiley
Si vous êtes déjà dans gitk, vous pouvez aussi simplement faire un clic droit sur le commit et sélectionner "reset branch XY to here".
mkrieger1
Et les commits les plus récents ne seront pas immédiatement supprimés. Il n'y a tout simplement plus de branche pointant vers eux (rappelez-vous, une branche n'est rien d'autre qu'un "signet" pour un commit particulier).
mkrieger1
9

J'ai eu une situation où je voulais supprimer un commit qui n'a pas été poussé, mais le commit était avant un autre. Pour ce faire, j'ai utilisé la commande suivante

git rebase -i HEAD~2 -> il va rebaser les deux derniers commits

Et j'ai utilisé «drop» pour la signature de validation que je voulais supprimer.

Robert
la source
9

Supprimer les fichiers non suivis (modifications locales non validées)

git clean -df

Supprimer définitivement toutes les validations locales et obtenir la dernière validation à distance

git reset --hard origin/<branch_name>
ElasticCode
la source
8

Pour les git rebase -ivalidations locales qui ne sont pas poussées, vous pouvez également utiliser pour supprimer ou écraser une validation.

Nikhil Katre
la source
1
Je sais que ce n'est peut-être pas la solution la plus courte, mais je vous ai voté positivement car à mon humble avis git rebase -iest un moyen plus générique pour résoudre de nombreux problèmes similaires et peut être utile dans une variété de situations.
Stefan Marinov
1
Utilisez le dropmot - clé (au lieu de supprimer une ligne) lors de la suppression de toutes les validations pour éviter que le rebase soit abandonné.
Michal Čizmazia
6

La solution simple consistera à faire correspondre la branche principale locale HEAD à l'origine / branche principale HEAD

git reset --hard origin/master

PS: origin / master - est un pointeur distant vers la branche master. Vous pouvez remplacer le maître par n'importe quel nom de branche

narwanimonish
la source
4

Avant de répondre, ajoutons un peu de contexte, expliquant ce que c'est HEAD. car certaines des options ci-dessous entraîneront une tête détachée

First of all what is HEAD?

HEADest simplement une référence au commit actuel (le plus récent) sur la branche courante.
Il ne peut y en avoir qu'un seul HEADà un moment donné. (à l'exclusiongit worktree )

Le contenu de HEADest stocké à l'intérieur .git/HEADet contient les 40 octets SHA-1 de la validation en cours.


detached HEAD

Si vous n'êtes pas sur le dernier commit - ce qui signifie qu'il HEADpointe vers un commit antérieur dans l'historique, c'est appelé detached HEAD.

entrez la description de l'image ici

Sur la ligne de commande, il ressemblera à ceci - SHA-1 au lieu du nom de la branche car le HEADne pointe pas vers la pointe de la branche actuelle

entrez la description de l'image ici

entrez la description de l'image ici

Quelques options sur la façon de récupérer à partir d'une tête détachée:


git checkout

git checkout <commit_id>
git checkout -b <new branch> <commit_id>
git checkout HEAD~X // x is the number of commits t go back

Cela va extraire une nouvelle branche pointant vers le commit souhaité.
Cette commande extrait un commit donné.
À ce stade, vous pouvez créer une branche et commencer à travailler à partir de ce point.

# Checkout a given commit. 
# Doing so will result in a `detached HEAD` which mean that the `HEAD`
# is not pointing to the latest so you will need to checkout branch
# in order to be able to update the code.
git checkout <commit-id>

# create a new branch forked to the given commit
git checkout -b <branch name>

git reflog

Vous pouvez également toujours utiliser le reflog.
git reflogaffichera tout changement qui a mis à jour le HEADet vérifier l'entrée de reflog souhaitée mettra le HEADdos à ce commit.

Chaque fois que le HEAD est modifié, il y aura une nouvelle entrée dans le reflog

git reflog
git checkout HEAD@{...}

Cela vous ramènera à votre engagement souhaité

entrez la description de l'image ici


git reset --hard <commit_id>

"Déplacer" votre HEAD vers le commit souhaité.

# This will destroy any local modifications.
# Don't do it if you have uncommitted work you want to keep.
git reset --hard 0d1d7fc32

# Alternatively, if there's work to keep:
git stash
git reset --hard 0d1d7fc32
git stash pop
# This saves the modifications, then reapplies that patch after resetting.
# You could get merge conflicts if you've modified things which were
# changed since the commit you reset to.
  • Remarque: ( depuis Git 2.7 ),
    vous pouvez également utiliser le git rebase --no-autostash.

git revert <sha-1>

"Annuler" la validation ou la plage de validation donnée.
La commande de réinitialisation "annulera" toutes les modifications apportées au commit donné.
Un nouveau commit avec le patch d'annulation sera validé tandis que le commit d'origine restera également dans l'historique.

# add new commit with the undo of the original one.
# the <sha-1> can be any commit(s) or commit range
git revert <sha-1>

Ce schéma illustre quelle commande fait quoi.
Comme vous pouvez le voir, reset && checkoutmodifiez le HEAD.

entrez la description de l'image ici

CodeWizard
la source
3

Pour ceux qui s'intéressent à la solution Visual Studio, voici l'exercice:

  1. Dans la Team Explorerfenêtre, connectez-vous au référentiel cible.
  2. Ensuite Branches, cliquez avec le bouton droit sur la branche d'intérêt et sélectionnez View history.
  3. Cliquez avec le bouton droit sur un commit dans la Historyfenêtre et choisissez Reset -> Delete changes (--hard).

Cela supprimera vos commits locaux et réinitialisera l'état de votre dépôt sur le commit sélectionné. C'est-à-dire que vos modifications après avoir retiré le dépôt seront perdues.

Bozhidar Stoyneff
la source
2

Si votre branche est en avance de ' origin/XXX' de 5 commits.

Vous pouvez émettre:

git reset --hard HEAD~5

Et cela devrait supprimer les 5 derniers commits.

Ha Choo
la source
0
git reset --hard <SHA-Code>

Cela vous sera utile si vous avez fait des erreurs sur votre copie locale et que vous voulez vous assurer qu'elles ne sont pas transmises par erreur à votre succursale distante.

Le code SHA peut être obtenu en consultant la version Web de votre tableau de bord git pour le dernier commit de la branche.

De cette façon, vous pouvez être synchronisé avec le dernier commit de la branche.

Tu peux faire git pull après avoir terminé avec succès la réinitialisation matérielle pour confirmer rien de nouveau à synchroniser, c'est-à-dire que vous pouvez voir le message.

Votre agence est à jour avec Origin/<Branch Name>

Sameer Ashraf
la source
0

Si vous mettez votre dépôt local dans un désordre complet, alors un moyen fiable de supprimer les commits locaux dans Git est de ...

  1. Utilisez "git config --get remote.origin.url" pour obtenir l'URL d'origine distante
  2. Renommez le dossier git local en "my_broken_local_repo"
  3. Utilisez "git clone <url_from_1>" pour obtenir une nouvelle copie locale du référentiel git distant

D'après mon expérience, Eclipse gère assez bien le monde qui change autour de lui. Cependant, vous devrez peut-être sélectionner des projets affectés dans Eclipse et les nettoyer pour forcer Eclipse à les reconstruire. Je suppose que d'autres IDE peuvent également avoir besoin d'une reconstruction forcée.

Un avantage secondaire de la procédure ci-dessus est que vous découvrirez si votre projet repose sur des fichiers locaux qui n'ont pas été mis dans git. Si vous trouvez qu'il vous manque des fichiers, vous pouvez les copier depuis "my_broken_local_repo" et les ajouter à git. Une fois que vous avez la certitude que votre nouveau référentiel local a tout ce dont vous avez besoin, vous pouvez supprimer "my_broken_local_repo".

Adam Gawne-Cain
la source
0

Si vous voulez simplement supprimer les validations locales et conserver les modifications effectuées dans les fichiers, faites
git reset @ ~
D'autres réponses traitaient de la réinitialisation matérielle

Ashish Banker
la source