Combina i primi due commit di un repository Git?
-
22-07-2019 - |
Domanda
Supponi di avere una cronologia contenente i tre commit A, B e C :
A-B-C
Vorrei combinare i due commit A e B in un unico commit AB :
AB-C
Ho provato
git rebase -i A
che apre il mio editor con i seguenti contenuti:
pick e97a17b B
pick asd314f C
Lo cambio a
squash e97a17b B
pick asd314f C
Quindi Git 1.6.0.4 dice:
Cannot 'squash' without a previous commit
C'è un modo o è semplicemente impossibile?
Soluzione
Usa git rebase -i --root
a partire da Git versione 1.7.12 .
Nel file rebase interattivo, modifica la seconda riga di commit B in squash e lascia le altre righe su pick :
pick f4202da A
squash bea708e B
pick a8c6abc C
Questo combinerà i due commit A e B in un commit AB .
Trovato in questa risposta .
Altri suggerimenti
Hai provato:
git rebase -i A
È possibile iniziare così se si continua con modifica
anziché squash
:
edit e97a17b B
pick asd314f C
quindi esegui
git reset --soft HEAD^
git commit --amend
git rebase --continue
Fatto.
A
era il commit iniziale, ma ora vuoi che B
sia il commit iniziale. i commit git sono alberi interi, non diff anche se sono normalmente descritti e visualizzati in termini di diff che introducono.
Questa ricetta funziona anche se ci sono più commit tra A e B e B e C.
# Go back to the last commit that we want
# to form the initial commit (detach HEAD)
git checkout <sha1_for_B>
# reset the branch pointer to the initial commit,
# but leaving the index and working tree intact.
git reset --soft <sha1_for_A>
# amend the initial tree using the tree from 'B'
git commit --amend
# temporarily tag this new initial commit
# (or you could remember the new commit sha1 manually)
git tag tmp
# go back to the original branch (assume master for this example)
git checkout master
# Replay all the commits after B onto the new initial commit
git rebase --onto tmp <sha1_for_B>
# remove the temporary tag
git tag -d tmp
Nel caso di rebase interattivo, devi farlo prima di A in modo che l'elenco sia:
pick A
pick B
pick C
diventare:
pick A
squash B
pick C
Se A è il commit iniziale, devi avere un commit iniziale diverso prima che A. Git pensi alle differenze, funzionerà sulla differenza tra (A e B) e (B e C). Quindi la zucca non funziona nel tuo esempio.
Nel caso in cui tu abbia centinaia o migliaia di commit, usando la risposta di kostmo di
git rebase -i --root
può essere poco pratico e lento, solo a causa dell'elevato numero di commit che lo script rebase deve elaborare due volte , una volta per generare l'elenco dell'editor di rebase interattivo (dove si seleziona quale azione intraprendere per ogni commit) e una volta per eseguire effettivamente la re-applicazione dei commit.
Ecco una soluzione alternativa che eviterà in primo luogo il costo di generazione dell'elenco dell'editor di rebase interattivo non utilizzando un rebase interattivo . In questo modo, è simile a Soluzione di Charles Bailey . È sufficiente creare un ramo orfano dal secondo commit, quindi rifare tutti i commit discendenti su di esso:
git checkout --orphan orphan <second-commit-sha>
git commit -m "Enter a commit message for the new root commit"
git rebase --onto orphan <second-commit-sha> master
Documentazione
In una domanda correlata, sono riuscito a trovare un approccio diverso alla necessità di schiacciare il primo commit, che è, beh, quello di renderlo il secondo.
Se sei interessato: git: come inserire un commit come primo, spostando tutti gli altri?
Comando Git per squadra: git rebase -i HEAD ~ [numero di commit]
Diciamo che hai una cronologia di commit inferiore a git:
pick 5152061 feat: Aggiunto supporto per il salvataggio dell'immagine. (UN)
pick 39c5a04 Correzione: correzioni di errori. (B)
pick 839c6b3 fix: conflitto risolto. (C)
Ora vuoi schiacciare A e B su AB, esegui i passaggi seguenti:
pick 5152061 feat: Aggiunto supporto per il salvataggio dell'immagine. (UN)
s 39c5a04 Correzione: correzioni di errori. (B)
pick 839c6b3 fix: conflitto risolto. (C)
Nota: per il commit di squash possiamo usare squash o s.
Il risultato finale sarà:
pick 5152061 feat: Aggiunto supporto per il salvataggio dell'immagine. (AB)
pick 839c6b3 fix: conflitto risolto. (C)
Devi eseguire un po 'di magia da riga di comando.
git checkout -b a A
git checkout B <files>
git commit --amend
git checkout master
git rebase a
Questo dovrebbe lasciarti con un ramo che ha AB e C come commit.