Come schiacciare si impegna in git dopo che sono stati spinti?


551

Questo dà una buona spiegazione della compressione di più commit:

http://git-scm.com/book/en/Git-Branching-Rebasing

ma non funziona per i commit che sono già stati spinti. Come posso eliminare gli ultimi commit sia nei miei repository locali che remoti?

EDIT: Quando lo faccio git rebase -i origin/master~4 master, mantieni il primo come pick, imposta gli altri tre come squash, quindi esci (tramite cx cc in emacs), ottengo:

$ git rebase -i origin/master~4 master
# Not currently on any branch.
nothing to commit (working directory clean)

Could not apply 2f40e2c... Revert "issue 4427: bpf device permission change option added"
$ git rebase -i origin/master~4 master
Interactive rebase already started

dove 2f40 è il pickcommit. E ora nessuno dei 4 commit appare git log. Mi aspettavo che il mio editor fosse riavviato in modo da poter inserire un messaggio di commit. Che cosa sto facendo di sbagliato?

Risposte:


781

Squash si impegna localmente con

git rebase -i origin/master~4 master

e quindi forzare la spinta con

git push origin +master

Differenza tra --forcee+

Dalla documentazione di git push:

Si noti che si --forceapplica a tutti i riferimenti che vengono inviati, quindi usarlo con push.defaultset su matchingo con destinazioni push multiple configurate con remote.*.pushpuò sovrascrivere i riferimenti diversi dal ramo corrente (compresi i riferimenti locali che sono strettamente dietro la loro controparte remota). Per forzare una spinta verso un solo ramo, usa + a davanti al refspec per spingere (ad es. git push origin +masterPer forzare una spinta sul masterramo).


30
puoi anchegit push --force origin master
Daenyth,

7
Daenyth : Sì, ma preferisco sempre questa sintassi poiché è più breve.
Alan Haggai Alavi,

86
E, naturalmente, renditi conto che se qualcun altro avrebbe potuto estrarre dal repository remoto, probabilmente non vorrai farlo - la risposta in quel caso è "tu no".
Cascabel,

10
Inoltre, penso che l'OP stia esattamente copiando il comando git rebase -i origin/master, e in realtà vuole sapere come riordinare i commit più indietro rispetto a quello, ad es git rebase -i origin/master~20 master.
Cascabel,

6
gstackoverflow :+forza solo il refspec a cui è prefissato. --forceforzerà la spinta di tutti i refspec. Si prega di consultare la risposta aggiornata.
Alan Haggai Alavi,

120

Su una filiale sono stato in grado di farlo in questo modo (per gli ultimi 4 commit)

git checkout my_branch
git reset --soft HEAD~4
git commit
git push --force origin my_branch

1
Farlo con il comando leggero su un ramo già spinto ha finito per spingere un sacco di altre persone che si impegna per me.
cchamberlain,

3
Una tonnellata? Come può essere più di 4? Puoi elaborare?
Jakob-r,

Di cui non sono sicuro, ma aveva qualcosa a che fare con il tentativo di eliminare un commit già spinto. Looks come altri vivono simile qui - stackoverflow.com/questions/5189560/...
cchamberlain

4
Avrei accettato questo come risposta attesa. Più pulita che ha accettato la risposta.
vikramvi,

4
Questa è la risposta più chiara e accettata in soli 4 passaggi
Ameya Salagre,

45

Piccola differenza rispetto alla risposta accettata, ma avevo molte difficoltà a schiacciarmi e alla fine ho capito.

$ git rebase -i HEAD~4
  • Nella schermata interattiva che si apre, sostituisci pick con squash nella parte superiore per tutte le commit che desideri squash.
  • Salvare e chiudere l'editor esc --> :wq

Invia al telecomando utilizzando:

$ git push origin branch-name --force

2
breve ed efficace, elaborato:
terwxqian

22

Molti problemi possono essere evitati solo creando un branchsu cui lavorare e non lavorare su master:

git checkout -b mybranch

I seguenti lavori per remotecommit già spinti e un mix di remotecommit push / localcommit solo:

# example merging 4 commits

git checkout mybranch
git rebase -i mybranch~4 mybranch

# at the interactive screen
# choose fixup for commit: 2 / 3 / 4

git push -u origin +mybranch

Ho anche alcune note di richiesta pull che possono essere utili.


17

git rebase -i master

aprirai l'editor vm e invierai qualcosa del genere

Pick 2994283490 commit msg1
f 7994283490 commit msg2
f 4654283490 commit msg3
f 5694283490 commit msg4
#Some message 
#
#some more

Qui ho cambiato pick per tutti gli altri commit in "f" (Stand per fixup).

git push -f origin feature/feature-branch-name-xyz

questo risolverà tutti i commit in un commit e rimuoverà tutti gli altri commit. L'ho fatto e mi ha aiutato.


3

Quando lavori con un Gitlab o Github puoi correre nei guai in questo modo. Tu schiacci i tuoi commit con uno dei metodi sopra. Il mio preferito è:

git rebase -i HEAD~4
or
git rebase -i origin/master

seleziona squash o fixup per il tuo commit. A questo punto verifichi con lo stato git. E il messaggio potrebbe essere:

    On branch ABC-1916-remote
    Your branch and 'origin/ABC-1916' have diverged,
    and have 1 and 7 different commits each, respectively.
      (use "git pull" to merge the remote branch into yours)

E puoi essere tentato di tirarlo. NON FARLO o ti troverai nella stessa situazione di prima.

Spingi invece verso la tua origine con:

git push origin +ABC-1916-remote:ABC-1916

Il + consente di forzare la spinta solo verso un ramo.


non c'è niente di sbagliato nel tirare, specialmente se si hanno conflitti che possono essere risolti più facilmente che se si forza la spinta
Ray_Poly

2

Per schiacciare due commit, uno dei quali era già stato spinto, su un singolo ramo il seguente ha funzionato:

git rebase -i HEAD~2
    [ pick     older-commit  ]
    [ squash   newest-commit ]
git push --force

Per impostazione predefinita, questo includerà il messaggio di commit del commit più recente come commento sul commit precedente.


2

1) git rebase -i HEAD~4

Elaborare: funziona sull'attuale ramo; HEAD ~ 4 significa schiacciare gli ultimi quattro commit; modalità interattiva (-i)

2) A questo punto, l'editor ha aperto, con l'elenco dei commit, per cambiare il secondo e successivi commit, sostituendo pick con squash e poi salvandolo.

output: refs / head / branch-name correttamente rielaborato e aggiornato.

3) git push origin refs/heads/branch-name --force

produzione:

remote:
remote: To create a merge request for branch-name, visit:
remote: http://xxx/sc/server/merge_requests/new?merge_request%5Bsource_branch%5D=sss
remote:To ip:sc/server.git
 + 84b4b60...5045693 branch-name -> branch-name (forced update)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.