Comment modifier un commit spécifié?

2233

Je soumets généralement une liste de commits pour examen. Si j'ai les commits suivants:

  1. HEAD
  2. Commit3
  3. Commit2
  4. Commit1

... Je sais que je peux modifier head commit avec git commit --amend. Mais comment puis-je modifier Commit1, étant donné que ce n'est pas le HEADcommit?

Sam Liao
la source
31
Voir une réponse alternative ici: stackoverflow.com/a/18150592/520567 Votre réponse acceptée est vraiment une réponse exacte à votre question mais si vous avez votre nouveau commit prêt avant de décider d'utiliser edit, alors cette réponse serait plus simple. Il peut également fonctionner avec plusieurs validations que vous souhaitez fusionner / écraser avec une ancienne.
akostadinov
6
Vous pouvez également voir Fractionner une validation dans Git Tools - Rewriting History pour plus d'informations.
hakre
Copie
tkruse

Réponses:

2957

Vous pouvez utiliser git rebase . Par exemple, si vous souhaitez modifier la validation bbc643cd, exécutez

$ git rebase --interactive 'bbc643cd^'

Veuillez noter le ^signe d'insertion à la fin de la commande, car vous devez en fait rebaser le commit avant celui que vous souhaitez modifier .

Dans l'éditeur par défaut, modifiez picken editdans la ligne mentionnant «bbc643cd».

Enregistrez le fichier et quittez: git interprétera et exécutera automatiquement les commandes du fichier. Vous vous retrouverez dans la situation précédente dans laquelle vous venez de créer un commit bbc643cd.

À ce stade, bbc643cdc'est votre dernier commit et vous pouvez facilement le modifier : apportez vos modifications puis validez-les avec la commande:

$ git commit --all --amend --no-edit

Après cela, tapez:

$ git rebase --continue

pour revenir à la validation HEAD précédente.

AVERTISSEMENT : notez que cela changera le SHA-1 de ce commit ainsi que tous les enfants - en d'autres termes, cela réécrit l'historique à partir de ce point. Vous pouvez interrompre les dépôts en faisant cela si vous poussez à l'aide de la commandegit push --force

ZelluX
la source
125
Une autre option intéressante dans ce flux est une fois que vous avez déplacé vers le commit que vous souhaitez modifier, au lieu de modifier les fichiers et que vous êtes bloqué par dessus le commit (celui que vous modifiez), vous voudrez peut-être diviser ce commit en deux commits différents (ou même plus). Dans ce cas, revenez au commit à éditer et exécutez "git reset HEAD ^". qui mettra les fichiers modifiés de ce commit dans la scène. Maintenant, choisissez et validez tous les fichiers comme vous le souhaitez. Ce flux est assez bien expliqué dans la page de manuel "git-rebase". Voir la section "Fractionnement des validations". bit.ly/d50w1M
Diego Pino
200
Dans Git 1.6.6 et plus récent, vous pouvez utiliser l' rewordaction dans git rebase -iau lieu de edit(il ouvre automatiquement l'éditeur et continue avec le reste des étapes de rebase; cela évite l'utilisation git commit --ammendet git rebase --continuelorsque vous avez seulement besoin de modifier le message de validation et non le contenu ).
Chris Johnsen
108
Il convient de noter que vous devrez peut-être exécuter git stashavant git rebaseet git stash popaprès, si vous avez des modifications en attente.
user123444555621
3
Existe-t-il une commande de raccourci pour modifier un commit spécifique dans le rebase interactif sans ouvrir l'éditeur, trouver le commit, le marquer comme éditant, puis revenir à la ligne de commande?
sstur
15
Notez qu'avec git plus récent, il serait plus sage de suivre des instructions rapides au lieu de les utiliser aveuglément git commit --all --amend --no-editici. Tout ce que j'avais à faire après, git rebase -i ...c'était de le faire git commit --amendnormalement git rebase --continue.
Eric Chen
453

Utilisez le rebase interactif génial:

git rebase -i @~9   # Show the last 9 commits in a text editor

Recherchez le commit que vous souhaitez, passez pickà e( edit), puis enregistrez et fermez le fichier. Git reviendra à ce commit, vous permettant soit:

  • utiliser git commit --amendpour apporter des modifications, ou
  • utiliser git reset @~pour ignorer le dernier commit, mais pas les modifications apportées aux fichiers (c'est-à-dire vous amener au point où vous en étiez lorsque vous aviez modifié les fichiers, mais que vous n'aviez pas encore engagé).

Ce dernier est utile pour faire des choses plus complexes comme le fractionnement en plusieurs validations.

Ensuite, exécutez git rebase --continueet Git rejouera les modifications suivantes au-dessus de votre commit modifié. Vous pouvez être invité à résoudre certains conflits de fusion.

Remarque: @est un raccourci pour HEAD, et ~est le commit avant le commit spécifié.

En savoir plus sur la réécriture de l'historique dans les documents Git.


N'ayez pas peur de rebaser

ProTip ™: N'ayez pas peur d'expérimenter avec des commandes "dangereuses" qui réécrivent l'historique * - Git ne supprime pas vos validations pendant 90 jours par défaut; vous pouvez les trouver dans le reflog:

$ git reset @~3   # go back 3 commits
$ git reflog
c4f708b HEAD@{0}: reset: moving to @~3
2c52489 HEAD@{1}: commit: more changes
4a5246d HEAD@{2}: commit: make important changes
e8571e4 HEAD@{3}: commit: make some changes
... earlier commits ...
$ git reset 2c52489
... and you're back where you started

* Méfiez-vous des options comme --hardet --forcebien - ils peuvent éliminer les données.
* De plus, ne réécrivez pas l'historique sur les branches sur lesquelles vous collaborez.



Sur de nombreux systèmes, git rebase -iVim ouvrira par défaut. Vim ne fonctionne pas comme la plupart des éditeurs de texte modernes, alors regardez comment rebaser avec Vim . Si vous préférez utiliser un autre éditeur, changez-le avec git config --global core.editor your-favorite-text-editor.

Zaz
la source
29
Le milieu de votre réponse est un endroit étrange pour mettre ce que je ne peux que décrire comme une petite publicité pour VIM. Cela n'a rien à voir avec la question et ne fait qu'encombrer votre réponse.
Intents
21
@Intentss: Ah, je peux voir pourquoi cela avait l'air bizarre. Le raisonnement derrière cela était que Vim est l'éditeur de texte par défaut sur de nombreux systèmes, donc la première expérience de rebasage interactif de beaucoup de gens est un écran où la saisie fait voler le curseur partout. Ensuite, ils changent leur éditeur pour autre chose, et leur deuxième expérience de rebasage interactif est assez normale, mais les laisse se demander pourquoi il utilise un fichier texte au lieu d'une interface graphique. Pour obtenir un flux avec le rebasage, vous avez besoin de quelque chose comme Vim ou du mode de rebase d'Emacs.
Zaz
9
D'accord. Étant donné que tant de gens trouvent cette partie non pertinente, je l'ai condensée en 3 lignes et j'ai également expliqué comment changer l'éditeur si nécessaire.
Zaz
17
Impressionnant! Je ne savais pas que vous pouviez utiliser @comme raccourci HEAD. Merci d'avoir posté ça.
James Ko
3
git reset @~exactement ce que je voulais faire après avoir choisi de valider git rebase .... Tu es mon héros)
18augst
79

Le rebasage interactif avec --autosquashest quelque chose que j'utilise fréquemment lorsque j'ai besoin de corriger des validations précédentes plus profondément dans l'histoire. Cela accélère essentiellement le processus illustré par la réponse de ZelluX et est particulièrement pratique lorsque vous avez plus d'un commit que vous devez modifier.

De la documentation:

--autosquash

Lorsque le message du journal de validation commence par «squash!…» (Ou «fixup!…»), Et qu'il existe une validation dont le titre commence par la même…, modifiez automatiquement la liste des tâches de rebase -i afin que la validation marqué pour l'écrasement vient juste après le commit à modifier

Supposons que vous ayez une histoire qui ressemble à ceci:

$ git log --graph --oneline
* b42d293 Commit3
* e8adec4 Commit2
* faaf19f Commit1

et vous souhaitez apporter des modifications à Commit2, puis validez vos modifications à l'aide de

$ git commit -m "fixup! Commit2"

Alternativement, vous pouvez utiliser le commit-sha au lieu du message de validation, "fixup! e8adec4ou même juste un préfixe du message de validation.

Ensuite, lancez un rebase interactif sur la validation avant

$ git rebase e8adec4^ -i --autosquash

votre éditeur s'ouvrira avec les commits déjà correctement commandés

pick e8adec4 Commit2
fixup 54e1a99 fixup! Commit2
pick b42d293 Commit3

il vous suffit de sauvegarder et de quitter

thrau
la source
21
Vous pouvez également utiliser git commit --fixup=@~au lieu de git commit -m "fixup! Commit2". Ceci est particulièrement utile lorsque vos messages de validation sont plus longs et qu'il serait difficile de taper le tout.
Zaz
42

Courir:

$ git rebase --interactive commit_hash^

chacun ^indique le nombre de validations que vous souhaitez modifier, s'il ne s'agit que d'une seule (le hachage de validation que vous avez spécifié), il vous suffit d'en ajouter une ^.

En utilisant Vim vous changez les mots pickpour rewordles commits que vous souhaitez modifier, sauvegarder et quitter ( :wq). Ensuite, git vous demandera à chaque commit que vous avez marqué comme reformulé afin que vous puissiez changer le message de commit.

Chaque message de validation que vous devez enregistrer et quitter ( :wq) pour passer au message de validation suivant

Si vous souhaitez quitter sans appliquer les modifications, appuyez sur :q!

EDIT : pour naviguer dans vimvous utilisez jpour monter, kpour descendre, hpour aller à gauche et lpour aller à droite (tout cela en NORMALmode, appuyez ESCpour aller en NORMALmode). Pour modifier un texte, appuyez suri pour accéder au INSERTmode dans lequel vous insérez du texte. Appuyez ESCpour revenir en NORMALmode :)

MISE À JOUR : Voici un excellent lien de la liste github Comment annuler (presque) n'importe quoi avec git

betoharres
la source
4
A parfaitement fonctionné pour moi. À noter git push --force?
u01jmg3
Ce git push --forcequi remplace les commits à distance par vos commits locaux. Ce n'est pas le cas de ce sujet :)
betoharres
@BetuUuUu bien sûr, si vos validations sont poussées vers la télécommande et que vous avez modifié le message de validation localement, vous voudriez forcer la transmission vers la télécommande, n'est-ce pas?
Sudip Bhandari
@SudipBhandari C'est le sentiment que j'ai. Je n'ai pas forcé, et maintenant j'ai une branche supplémentaire, reflétant tous les commits sur celui dont j'ai changé le message, ce qui est super laid.
ruffin
2
@greenhouse si vous modifiez et forcez, alors les autres membres de l'équipe rencontreront très probablement des conflits de fusion. Vous devez donc être généralement très prudent à ce sujet. Mais si vous modifiez quelque chose que personne d'autre n'a encore récupéré, ça devrait aller (ils ne le remarqueront pas). Je considérerais donc la force en dernier recours et consulterais toujours l'état du dépôt avec les autres membres.
Tomasz Kaczmarzyk
18

Si, pour une raison quelconque, vous n'aimez pas les éditeurs interactifs, vous pouvez utiliser git rebase --onto.

Dites que vous souhaitez modifier Commit1. Tout d'abord, branchez d' avant Commit1 :

git checkout -b amending [commit before Commit1]

Deuxièmement, saisissez Commit1avec cherry-pick:

git cherry-pick Commit1

Maintenant, modifiez vos modifications en créant Commit1':

git add ...
git commit --amend -m "new message for Commit1"

Et enfin, après avoir caché tout autre changement, transplantez le reste de vos commits au- masterdessus de votre nouveau commit:

git rebase --onto amending Commit1 master

Lire: "rebaser, sur la branche amending, tous les commits entre Commit1(non inclus) et master(inclus)". Autrement dit, Commit2 et Commit3, coupant entièrement l'ancien Commit1. Vous pouvez simplement les choisir, mais cette méthode est plus facile.

N'oubliez pas de nettoyer vos succursales!

git branch -d amending
FeepingCreature
la source
4
vous pouvez utiliser git checkout -b amending Commit1~1pour obtenir le commit préalable
Arin Taylor
Les deux premières étapes sont-elles équivalentes à git checkout -b amending Commit1?
Haoshu
16

Basé sur la documentation

Modification du message d'anciens ou de plusieurs messages de validation

git rebase -i HEAD~3 

Ce qui précède affiche une liste des 3 derniers validations sur la branche actuelle, changez 3 en quelque chose d'autre si vous en voulez plus. La liste ressemblera à ce qui suit:

pick e499d89 Delete CNAME
pick 0c39034 Better README
pick f7fde4a Change the commit message but push the same commit.

Remplacez pick par reword avant chaque message de validation que vous souhaitez modifier. Supposons que vous modifiez le deuxième commit de la liste, votre fichier ressemblera à ceci:

pick e499d89 Delete CNAME
reword 0c39034 Better README
pick f7fde4a Change the commit message but push the same commit.

Enregistrez et fermez le fichier de liste de validation, cela fera apparaître un nouvel éditeur pour vous permettre de modifier votre message de validation, de modifier le message de validation et de l'enregistrer.

Finalement, appuyez sur les commits modifiés.

git push --force
juste moi
la source
J'obtiens l'erreur suivante: erreur: il y a eu un problème avec l'éditeur 'vi'. Veuillez fournir le message en utilisant l'option -m ou -F.
Erick Maynard
12

Commande complètement non interactive (1)

Je pensais juste partager un alias que j'utilise pour cela. Il est basé sur un rebase interactif non interactif. Pour l'ajouter à votre git, exécutez cette commande (explication donnée ci-dessous):

git config --global alias.amend-to '!f() { SHA=`git rev-parse "$1"`; git commit --fixup "$SHA" && GIT_SEQUENCE_EDITOR=true git rebase --interactive --autosquash "$SHA^"; }; f'

Le plus grand avantage de cette commande est le fait qu'il ne s'agit pas de vim .


(1) étant donné qu'il n'y a pas de conflits lors du rebasage, bien sûr

Usage

git amend-to <REV> # e.g.
git amend-to HEAD~1
git amend-to aaaa1111

Le nom amend-tosemble approprié à mon humble avis. Comparez le flux avec --amend:

git add . && git commit --amend --no-edit
# vs
git add . && git amend-to <REV>

Explication

  • git config --global alias.<NAME> '!<COMMAND>'- crée un alias git global nommé <NAME>qui exécutera la commande non-git<COMMAND>
  • f() { <BODY> }; f - une fonction bash "anonyme".
  • SHA=`git rev-parse "$1"`; - convertit l'argument en révision git, et affecte le résultat à la variable SHA
  • git commit --fixup "$SHA"- fixup-commit pour SHA. Voir les git-commitdocuments
  • GIT_SEQUENCE_EDITOR=true git rebase --interactive --autosquash "$SHA^"
    • git rebase --interactive "$SHA^" une partie a été couverte par d'autres réponses.
    • --autosquashest ce qui est utilisé en conjonction avec git commit --fixup, voir les git-rebasedocuments pour plus d'informations
    • GIT_SEQUENCE_EDITOR=trueest ce qui rend le tout non interactif. Ce hack que j'ai appris de ce billet de blog .
Dethariel
la source
1
On peut aussi faire amend-togérer des fichiers non stadés: git config --global alias.amend-to '!f() { SHA=git rev-parse "$ 1"; git stash -k && git commit --fixup "$SHA" && GIT_SEQUENCE_EDITOR=true git rebase --interactive --autosquash "$SHA^" && git stash pop; }; f'
Dethariel
2
Un problème avec cette méthode est qu'elle pourrait appliquer des corrections non liées.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
N'est-ce pas la question de changer le message de commit? Parce que cette réponse ne répond pas à cela, ou du moins pas directement.
wytten
@wytten la question ne demande pas de changer le message de commit, il s'agit de modifier le commit le n'est pas HEAD. Donc, une réponse à votre question serait "non, ce n'est pas le but de la question"
Dethariel
Je suis confus, alors comment pouvons-nous changer le message de validation?
ggb667
8

Modification de rebase interactive automatisée suivie d'un retour de validation prêt pour une refonte

Je me suis retrouvé à corriger un commit passé assez fréquemment pour que j'écrive un script pour cela.

Voici le workflow:

  1. git commit-edit <commit-hash>
    

    Cela vous déposera au commit que vous souhaitez modifier.

  2. Corrigez et organisez le commit comme vous le souhaitiez en premier lieu.

    (Vous voudrez peut-être utiliser git stash savepour conserver tous les fichiers que vous ne commettez pas)

  3. Refaire le commit avec --amend, par exemple:

    git commit --amend
    
  4. Terminez le rebase:

    git rebase --continue
    

Pour que ce qui précède fonctionne, placez le script ci-dessous dans un fichier exécutable appelé git-commit-editquelque part dans votre $PATH:

#!/bin/bash

set -euo pipefail

script_name=${0##*/}

warn () { printf '%s: %s\n' "$script_name" "$*" >&2; }
die () { warn "$@"; exit 1; }

[[ $# -ge 2 ]] && die "Expected single commit to edit. Defaults to HEAD~"

# Default to editing the parent of the most recent commit
# The most recent commit can be edited with `git commit --amend`
commit=$(git rev-parse --short "${1:-HEAD~}")
message=$(git log -1 --format='%h %s' "$commit")

if [[ $OSTYPE =~ ^darwin ]]; then
  sed_inplace=(sed -Ei "")
else
  sed_inplace=(sed -Ei)
fi

export GIT_SEQUENCE_EDITOR="${sed_inplace[*]} "' "s/^pick ('"$commit"' .*)/edit \\1/"'
git rebase --quiet --interactive --autostash --autosquash "$commit"~
git reset --quiet @~ "$(git rev-parse --show-toplevel)"  # Reset the cache of the toplevel directory to the previous commit
git commit --quiet --amend --no-edit --allow-empty  #  Commit an empty commit so that that cache diffs are un-reversed

echo
echo "Editing commit: $message" >&2
echo
Tom Hale
la source
7

Entré dans cette approche (et c'est probablement exactement la même chose que l'utilisation de rebase interactif) mais pour moi, c'est un peu simple.

Remarque: Je présente cette approche dans le but d'illustrer ce que vous pouvez faire plutôt que comme une alternative quotidienne. Puisqu'il comporte de nombreuses étapes (et éventuellement quelques mises en garde.)

Dites que vous souhaitez modifier le commit 0et que vous êtes actuellement surfeature-branch

some-commit---0---1---2---(feature-branch)HEAD

Commander à ce commit et créer un quick-branch. Vous pouvez également cloner votre branche de fonctionnalité en tant que point de récupération (avant de commencer).

?(git checkout -b feature-branch-backup)
git checkout 0
git checkout -b quick-branch

Vous allez maintenant avoir quelque chose comme ça:

0(quick-branch)HEAD---1---2---(feature-branch)

Les changements de scène, cachent tout le reste.

git add ./example.txt
git stash

Validez les modifications et revenez à feature-branch

git commit --amend
git checkout feature-branch

Vous allez maintenant avoir quelque chose comme ça:

some-commit---0---1---2---(feature-branch)HEAD
           \
             ---0'(quick-branch)

Rebaser feature-branchsur quick-branch(résoudre tout conflit en cours de route). Appliquer la cachette et retirer quick-branch.

git rebase quick-branch
git stash pop
git branch -D quick-branch

Et vous vous retrouvez avec:

some-commit---0'---1'---2'---HEAD(feature-branch)

Git ne dupliquera pas (bien que je ne puisse pas vraiment dire dans quelle mesure) le commit 0 lors du rebasage.

Remarque: tous les hachages de validation sont modifiés à partir de la validation que nous avions initialement l'intention de modifier.

Olga
la source
6

Pour obtenir une commande non interactive, mettez un script avec ce contenu dans votre PATH:

#!/bin/sh
#
# git-fixup
# Use staged changes to modify a specified commit
set -e
cmt=$(git rev-parse $1)
git commit --fixup="$cmt"
GIT_EDITOR=true git rebase -i --autosquash "$cmt~1"

Utilisez-le en mettant en scène vos modifications (avec git add), puis exécutez git fixup <commit-to-modify>. Bien sûr, il restera interactif si vous rencontrez des conflits.

Pelle Nilsson
la source
1
Cela fonctionne bien. J'ai ajouté quelques fonctionnalités supplémentaires pour faire des corrections fragmentaires d'un arbre sale pour perfectionner un ensemble de commit. `dirtydiff = $ (git diff); if ["$ {dirtydiff}"! = ""]; puis faites écho à "Stashing dirty tree"> & 2; git stash; Fi;
Simon Feltman
6

git stash + rebase automatisation

Pour quand j'ai besoin de modifier un ancien commit beaucoup de fois pour les revues Gerrit, j'ai fait:

git-amend-old() (
  # Stash, apply to past commit, and rebase the current branch on to of the result.
  current_branch="$(git rev-parse --abbrev-ref HEAD)"
  apply_to="$1"
  git stash
  git checkout "$apply_to"
  git stash apply
  git add -u
  git commit --amend --no-edit
  new_sha="$(git log --format="%H" -n 1)"
  git checkout "$current_branch"
  git rebase --onto "$new_sha" "$apply_to"
)

GitHub en amont .

Usage:

  • modifier le fichier source, pas besoin git adds'il est déjà en dépôt
  • git-amend-old $old_sha

J'aime cela --autosquashcar il n'écrase pas les autres corrections non liées.

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
la source
Très bonne solution de contournement, cela devrait être une option par défaut git amendpour appliquer des modifications à un commit spécifique avec l'utilisation de la cachette actuelle, très intelligent!
caiohamamura
5

J'ai résolu ça,

1) en créant un nouveau commit avec les changements que je veux ..

r8gs4r commit 0

2) Je sais quel engagement j'ai besoin de fusionner avec lui. qui est commit 3.

donc, git rebase -i HEAD~4 # 4 représente les 4 derniers commit (ici le commit 3 est à la 4ème place)

3) dans le rebasage interactif, la validation récente sera située en bas. il se ressemblera,

pick q6ade6 commit 3
pick vr43de commit 2
pick ac123d commit 1
pick r8gs4r commit 0

4) ici, nous devons réorganiser la validation si vous souhaitez fusionner avec une spécification spécifique. ça devrait être,

parent
|_child

pick q6ade6 commit 3
f r8gs4r commit 0
pick vr43de commit 2
pick ac123d commit 1

après la réorganisation, vous devez remplacer p pickpar f(la correction se fusionnera sans message de validation) ou s(la fusion de squash avec le message de validation peut changer en cours d'exécution)

puis enregistrez votre arbre.

fusionner maintenant fait avec commit existant.

Remarque: Ce n'est pas une méthode préférable, sauf si vous êtes autonome. si vous avez une grande équipe, ce n'est pas une méthode acceptable pour réécrire l'arbre git se terminera par des conflits que vous ne connaissez pas. si vous voulez maintenir votre arbre propre avec moins de commits, essayez ceci et si sa petite équipe sinon ce n'est pas préférable .....

Mohideen bin Mohammed
la source
C'est une bonne solution si vous ne souhaitez pas effectuer de modification en direct lors d'un rebase interactif.
Dunatotatos
4

La meilleure option consiste à utiliser la "commande de rebase interactive" .

La git rebasecommande est incroyablement puissante. Il vous permet de modifier les messages de validation , de combiner les , de les réorganiser ... etc.

Chaque fois que vous rebaserez une validation, un nouveau SHA sera créé pour chaque validation, que le contenu soit modifié ou non! Vous devez être prudent lorsque vous utilisez cette commande car elle peut avoir des implications drastiques, surtout si vous travaillez en collaboration avec d'autres développeurs. Ils peuvent commencer à travailler avec votre commit pendant que vous en rebasiez certains. Après avoir forcé à pousser les commits, ils seront désynchronisés et vous pourrez le découvrir plus tard dans une situation désordonnée. Donc sois prudent!

Il est recommandé de créer une backupbranche avant de rebaser, donc chaque fois que vous trouvez des choses hors de contrôle, vous pouvez revenir à l'état précédent.

Maintenant, comment utiliser cette commande?

git rebase -i <base> 

-isignifie "interactif" . Notez que vous pouvez effectuer un rebase en mode non interactif. ex:

#interactivly rebase the n commits from the current position, n is a given number(2,3 ...etc)
git rebase -i HEAD~n 

HEADindique votre emplacement actuel (peut également être un nom de branche ou valider SHA). Le ~nmoyen "n beforeé, doncHEAD~n sera donc la liste des" n "commits avant celui sur vous êtes actuellement.

git rebase a une commande différente comme:

  • p ou pick pour garder le commit tel quel.
  • r ou reword : pour conserver le contenu du commit mais modifier le message de commit.
  • s ou squash : pour combiner les modifications de ce commit dans le commit précédent (le commit au dessus dans la liste).
  • ... etc.

    Remarque: Il est préférable de faire fonctionner Git avec votre éditeur de code pour simplifier les choses. Comme par exemple si vous utilisez du code visuel, vous pouvez ajouter comme ceci git config --global core.editor "code --wait". Ou vous pouvez rechercher dans Google comment associer votre éditeur de code préféré avec GIT.

Exemple de git rebase

Je voulais changer les 2 derniers commits que j'ai faits alors je traite comme ceci:

  1. Afficher les validations actuelles:
    #This to show all the commits on one line
    $git log --oneline
    4f3d0c8 (HEAD -> documentation) docs: Add project description and included files"
    4d95e08 docs: Add created date and project title"
    eaf7978 (origin/master , origin/HEAD, master) Inital commit
    46a5819 Create README.md
    
  2. Maintenant, j'utilise git rebasepour changer les 2 derniers messages de commit: $git rebase -i HEAD~2 Il ouvre l'éditeur de code et montre ceci:

    pick 4d95e08 docs: Add created date and project title
    pick 4f3d0c8 docs: Add project description and included files
    
    # Rebase eaf7978..4f3d0c8 onto eaf7978 (2 commands)
    #
    # Commands:
    # p, pick <commit> = use commit
    # r, reword <commit> = use commit, but edit the commit message
    ...
    

    Puisque je veux changer le message de commit pour ces 2 commits. Je vais donc taper rou rewordà la place de pick. Enregistrez ensuite le fichier et fermez l'onglet. Notez que cela rebaseest exécuté dans un processus en plusieurs étapes, la prochaine étape consiste donc à mettre à jour les messages. Notez également que les validations sont affichées dans l'ordre chronologique inverse de sorte que la dernière validation est affichée dans celle-ci et la première validation dans la première ligne et ainsi de suite.

  3. Mettre à jour les messages: mettre à jour le premier message:

    docs: Add created date and project title to the documentation "README.md"
    
    # Please enter the commit message for your changes. Lines starting
    # with '#' will be ignored, and an empty message aborts the commit.
    ...
    

    enregistrer et fermer Modifier le deuxième message

    docs: Add project description and included files to the documentation "README.md"
    
    # Please enter the commit message for your changes. Lines starting
    # with '#' will be ignored, and an empty message aborts the commit.
    ...
    

    sauver et fermer.

  4. Vous obtiendrez un message comme celui-ci à la fin du rebase: Successfully rebased and updated refs/heads/documentationce qui signifie que vous réussissez. Vous pouvez afficher les modifications:

    5dff827 (HEAD -> documentation) docs: Add project description and included files to the documentation "README.md"
    4585c68 docs: Add created date and project title to the documentation "README.md"
    eaf7978 (origin/master, origin/HEAD, master) Inital commit
    46a5819 Create README.md
    

    Je souhaite que cela puisse aider les nouveaux utilisateurs :).

DINA TAKLIT
la source
2

Pour moi, c'était pour supprimer certaines informations d'identification d'un dépôt. J'ai essayé de rebaser et j'ai rencontré une tonne de conflits apparemment sans rapport en cours de route pour essayer de rebaser - continuer. Ne vous embêtez pas à essayer de vous rebaser, utilisez l'outil appelé BFG (brew install bfg) sur mac.

Pastille
la source
0

Si vous n'avez pas encore poussé les validations, vous pouvez revenir à une validation précédente en utilisant git reset HEAD^[1,2,3,4...]

Par exemple

git commit <file1> -m "Updated files 1 and 2"
git commit <file3> -m "Updated file 3"

Oups, j'ai oublié d'ajouter file2 au premier commit ...

git reset HEAD^1 // because I only need to go back 1 commit

git add <file2>

Cela ajoutera file2 au premier commit.

rharvey
la source
0

Eh bien, cette solution peut sembler très stupide, mais peut vous sauver dans certaines conditions.

Un de mes amis vient de commettre accidentellement de très gros fichiers (quatre fichiers auto-générés allant de 3 Go à 5 Go chacun), puis a fait des validations de code supplémentaires en plus de cela avant de réaliser le problème qui git pushne fonctionnait plus!

Les fichiers avaient été répertoriés .gitignoremais après avoir renommé le dossier du conteneur, ils ont été exposés et validés! Et maintenant, il y avait quelques autres validations du code en plus de cela, mais pushfonctionnait pour toujours (essayant de télécharger des Go de données!) Et finalement échouerait en raison des limites de taille de fichier de Github .

Le problème avec rebase interactif ou quelque chose de similaire était qu'ils traiteraient de fouiller ces fichiers énormes et prendraient une éternité pour faire quoi que ce soit. Néanmoins, après avoir passé près d'une heure dans la CLI, nous ne savions pas si les fichiers (et les deltas) étaient réellement supprimés de l'historique ou tout simplement pas inclus dans les validations actuelles. La poussée ne fonctionnait pas non plus et mon ami était vraiment coincé.

Donc, la solution que j'ai trouvée était:

  1. Renommez le dossier git actuel en ~/Project-old.
  2. Clonez à nouveau le dossier git depuis github (vers ~/Project ).
  3. Passez à la même succursale.
  4. Manuellement, cp -rles fichiers du ~/Project-olddossier vers~/Project .
  5. Assurez-vous que les fichiers volumineux, qui ne doivent pas être archivés, sont mvédités et inclus dans.gitignore correctement.
  6. Assurez-vous également de ne pas écraser le .gitdossier dans le dossier récemment cloné.~/Project par l'ancien. C'est là que vivent les journaux de l'histoire problématique!
  7. Examinez maintenant les modifications. Cela devrait être l'union de tous les commits récents, à l'exception des fichiers problématiques.
  8. Finalement, validez les changements, et c'est bien d'être pushédité.

Le plus gros problème avec cette solution est qu'elle traite de la copie manuelle de certains fichiers et qu'elle fusionne toutes les validations récentes en une seule (évidemment avec un nouveau hash de validation). B

Les grands avantages sont que, c'est très clair à chaque étape, cela fonctionne très bien pour les fichiers énormes (ainsi que les fichiers sensibles) , et il ne laisse aucune trace dans l'histoire!

Aide à
la source