Divida uma confirmação anterior em várias confirmações
1225
Sem criar uma ramificação e fazer um monte de trabalho descolado em uma nova ramificação, é possível dividir uma única confirmação em algumas confirmações diferentes depois que ela foi confirmada no repositório local?
A coisa mais fácil de fazer sem uma nova recuperação interativa é (provavelmente) criar uma nova ramificação iniciando no commit antes do que você deseja dividir, escolher com cereja, confirmar, redefinir, ocultar, confirmar a movimentação do arquivo, reaplicar o stash e confirmar as alterações e, em seguida, mesclar com a ramificação anterior ou escolher os commits a seguir. (. Em seguida, mude o nome antigo ramo para o atual chefe) (. É provavelmente melhor seguir o conselho MBO e fazer um rebase interativo) (copiado a partir de 2010 resposta abaixo)
William Pursell
1
Eu deparei com esse problema depois que esmaguei acidentalmente dois commits durante uma rebase em um commit anterior. Minha maneira de corrigi-lo foi o de fazer o checkout da esmagado cometer, git reset HEAD~, git stash, em seguida, git cherry-picko primeiro cometer dentro do squash, então git stash pop. Meu caso cherry-pick é bastante específica aqui, mas git stashe git stash popé bastante útil para os outros.
Primeiro, comece com um diretório de trabalho limpo: não git statusdeve mostrar modificações, exclusões ou inclusões pendentes.
Agora, você deve decidir quais confirmações deseja dividir.
A) Dividindo o commit mais recente
Para dividir seu commit mais recente, primeiro:
$ git reset HEAD~
Agora comprometa as peças individualmente da maneira usual, produzindo quantos commits forem necessários.
B) Dividindo um commit mais atrás
Isso requer reorganizar , ou seja, reescrever o histórico. Para encontrar a confirmação correta, você tem várias opções:
Se fosse três commits de volta, então
$ git rebase -i HEAD~3
onde 3é quantos commits de volta é.
Se estava mais atrás na árvore do que você deseja contar, então
$ git rebase -i 123abcd~
onde 123abcdestá o SHA1 do commit que você deseja dividir.
Se você estiver em uma ramificação diferente (por exemplo, uma ramificação de recurso) que planeja mesclar no mestre:
$ git rebase -i master
Quando você receber a tela de edição de rebase, encontre a confirmação que deseja desmembrar. No início dessa linha, substitua pickpor edit( epara abreviar). Salve o buffer e saia. O rebase agora será interrompido logo após o commit que você deseja editar. Então:
$ git reset HEAD~
Confirme as peças individualmente da maneira usual, produzindo quantos commits forem necessários e, em seguida,
Obrigado por esta resposta. Eu queria ter alguns arquivos confirmados anteriormente na área de teste, portanto as instruções para mim eram um pouco diferentes. Antes que eu pudesse git rebase --continue, eu realmente tive que git add (files to be added), git commit, em seguida, git stash(para os arquivos restantes). Depois git rebase --continue, eu costumava git checkout stash .obter os arquivos restantes #
Você também deve aproveitar a vantagem de git add -padicionar apenas seções parciais de arquivos, possivelmente com a eopção de editar as diferenças para confirmar apenas um pedaço. git stashtambém é útil se você deseja levar algum trabalho adiante, mas removê-lo da confirmação atual.
Craig Ringer
2
Se você deseja dividir e reordenar as confirmações, o que eu gosto de fazer é dividir primeiro e depois reordenar separadamente usando outro git rebase -i HEAD^3comando. Dessa forma, se a divisão der errado, você não precisará desfazer tanto trabalho.
David M. Lloyd
4
@kralyk Os arquivos que foram recentemente confirmados no HEAD serão deixados no disco depois git reset HEAD~. Eles não estão perdidos.
No modo interativo, você pode marcar confirmações com a ação "editar". No entanto, isso não significa necessariamente que o git rebase espera que o resultado dessa edição seja exatamente um commit. Na verdade, você pode desfazer a confirmação ou adicionar outras confirmações. Isso pode ser usado para dividir um commit em dois:
Inicie uma rebase interativa com git rebase -i <commit>^, onde <commit>está o commit que você deseja dividir. De fato, qualquer intervalo de confirmação serve, desde que contenha esse commit.
Marque o commit que você deseja dividir com a ação "edit".
Quando se trata de editar essa confirmação, execute git reset HEAD^. O efeito é que o HEAD é rebobinado por um e o índice segue o exemplo. No entanto, a árvore de trabalho permanece a mesma.
Agora adicione as alterações ao índice que você deseja ter no primeiro commit. Você pode usar git add(possivelmente interativamente) ou git gui(ou ambos) para fazer isso.
Confirme o índice agora atual com qualquer mensagem de confirmação apropriada agora.
Repita as duas últimas etapas até que sua árvore de trabalho esteja limpa.
Palavra de cautela: com essa abordagem, perdi a mensagem de confirmação.
user420667
11
@ user420667 Sim, é claro. Estamos resetexecutando o commit, afinal - mensagem incluída. A coisa prudente a se fazer, se você sabe que vai dividir um commit, mas deseja manter parte / toda a sua mensagem, é tirar uma cópia dessa mensagem. Portanto, git showo commit antes do rebaseing, ou se você esquecer ou preferir isso: volte mais tarde através do reflog. Nada disso será "perdido" até que seja coletado em 2 semanas ou o que for.
underscore_d
4
~e ^são coisas diferentes, mesmo no Windows. Você ainda deseja o sinal de intercalação ^, portanto, basta escapar dele conforme apropriado para o seu shell. No PowerShell, é HEAD`^. Com o cmd.exe, você pode dobrá-lo para escapar como HEAD^^. Na maioria das conchas (todas?), Você pode colocar aspas como "HEAD^".
AndrewF
7
Você também pode fazer git commit --reuse-message=abcd123. A opção curta para isso é -C.
j0057
41
Use git rebase --interactivepara editar a confirmação anterior, executar git reset HEAD~e, em seguida, git add -padicionar algumas, fazer uma confirmação, adicionar mais algumas e fazer outra confirmação, quantas vezes quiser. Quando terminar, execute git rebase --continuee você terá todas as confirmações de divisão anteriormente na sua pilha.
Importante : Observe que você pode brincar e fazer todas as alterações desejadas, e não precisa se preocupar em perder alterações antigas, porque sempre é possível executar git reflogpara encontrar o ponto em seu projeto que contém as alterações desejadas (vamos chamá-lo a8c4ab) e, em seguida git reset a8c4ab.
Aqui está uma série de comandos para mostrar como funciona:
mkdir git-test; cd git-test; git init
agora adicione um arquivo A
vi A
adicione esta linha:
one
git commit -am one
adicione esta linha a A:
two
git commit -am two
adicione esta linha a A:
three
git commit -am three
agora o arquivo A se parece com isso:
one
two
three
e nossa git logaparência é a seguinte (bem, eu usogit log --pretty=oneline --pretty="%h %cn %cr ---- %s"
bfb8e46 Rose Perrone 4 seconds ago ---- three
2b613bc Rose Perrone 14 seconds ago ---- two
9aac58f Rose Perrone 24 seconds ago ---- one
Digamos que queremos dividir o segundo commit two,.
git rebase --interactive HEAD~2
Isso traz uma mensagem parecida com esta:
pick 2b613bc two
pick bfb8e46 three
Altere o primeiro pickpara um epara editar essa confirmação.
git reset HEAD~
git diff nos mostra que acabamos de desestabilizar o commit que fizemos para o segundo commit:
diff --git a/A b/A
index 5626abf..814f4a4 100644
--- a/A
+++ b/A
@@ -1 +1,2 @@
one
+two
Vamos preparar essa alteração e adicionar "e um terceiro" a essa linha no arquivo A.
git add .
Normalmente, esse é o ponto durante uma nova reformulação interativa em que executaríamos git rebase --continue, porque geralmente queremos voltar à nossa pilha de confirmações para editar uma confirmação anterior. Mas desta vez, queremos criar um novo commit. Então vamos correr git commit -am 'two and a third'. Agora editamos o arquivo Ae adicionamos a linha two and two thirds.
git add .git commit -am 'two and two thirds'git rebase --continue
Temos um conflito com o nosso commit three, então vamos resolvê-lo:
Nós vamos mudar
one
<<<<<<< HEAD
two and a third
two and two thirds
=======
two
three
>>>>>>> bfb8e46... three
para
one
two and a third
two and two thirds
three
git add .; git rebase --continue
Agora, nossa git log -paparência é assim:
commit e59ca35bae8360439823d66d459238779e5b4892
Author: Rose Perrone <[email protected]>
Date: Sun Jul 7 13:57:00 2013 -0700
three
diff --git a/A b/A
index 5aef867..dd8fb63 100644
--- a/A
+++ b/A
@@ -1,3 +1,4 @@
one
two and a third
two and two thirds
+three
commit 4a283ba9bf83ef664541b467acdd0bb4d770ab8e
Author: Rose Perrone <[email protected]>
Date: Sun Jul 7 14:07:07 2013 -0700
two and two thirds
diff --git a/A b/A
index 575010a..5aef867 100644
--- a/A
+++ b/A
@@ -1,2 +1,3 @@
one
two and a third
+two and two thirds
commit 704d323ca1bc7c45ed8b1714d924adcdc83dfa44
Author: Rose Perrone <[email protected]>
Date: Sun Jul 7 14:06:40 2013 -0700
two and a third
diff --git a/A b/A
index 5626abf..575010a 100644
--- a/A
+++ b/A
@@ -1 +1,2 @@
one
+two and a third
commit 9aac58f3893488ec643fecab3c85f5a2f481586f
Author: Rose Perrone <[email protected]>
Date: Sun Jul 7 13:56:40 2013 -0700
one
diff --git a/A b/A
new file mode 100644
index 0000000..5626abf
--- /dev/null
+++ b/A
@@ -0,0 +1 @@
+one
As respostas anteriores abordaram o uso de git rebase -ipara editar o commit que você deseja dividir e o comprometeu em partes.
Isso funciona bem ao dividir os arquivos em confirmações diferentes, mas se você deseja separar as alterações nos arquivos individuais, é necessário saber mais.
Tendo chegado ao commit que você deseja dividir, usando rebase -ie marcando edit, você tem duas opções.
Após o uso git reset HEAD~, percorra os patches individualmente usando git add -ppara selecionar os que você deseja em cada confirmação
Edite a cópia de trabalho para remover as alterações que você não deseja; comprometer esse estado provisório; e retire o commit completo para a próxima rodada.
A opção 2 é útil se você estiver dividindo uma confirmação grande, pois permite verificar se as versões intermediárias são construídas e executadas corretamente como parte da mesclagem. Isso ocorre da seguinte maneira.
Após usar rebase -ie editconfirmar a confirmação, use
git reset --soft HEAD~
para desfazer a confirmação, mas deixe os arquivos confirmados no índice. Você também pode fazer uma redefinição mista, omitindo --soft, dependendo de quão próximo do resultado final será o seu commit inicial. A única diferença é se você inicia com todas as alterações realizadas ou com todas elas não realizadas.
Agora entre e edite o código. Você pode remover alterações, excluir arquivos adicionados e fazer o que quiser para construir o primeiro commit da série que você está procurando. Você também pode compilá-lo, executá-lo e confirmar se possui um conjunto consistente de fontes.
Quando estiver satisfeito, prepare / descompacte os arquivos conforme necessário (eu gosto de usar git guipara isso) e confirme as alterações através da interface do usuário ou da linha de comando
git commit
Esse é o primeiro commit feito. Agora você deseja restaurar sua cópia de trabalho para o estado que ela tinha após a consolidação que está sendo dividida, para que você possa realizar mais alterações na sua próxima consolidação. Para encontrar o sha1 do commit que você está editando, use git status. Nas primeiras linhas do status, você verá o comando rebase que está sendo executado no momento, no qual você pode encontrar o sha1 do seu commit original:
$ git status
interactive rebase in progress; onto be83b41
Last commands done (3 commands done):
pick 4847406 US135756: add debugging to the file download code
e 65dfb6a US135756: write data and download from remote
(see more in file .git/rebase-merge/done)
...
Nesse caso, o commit que estou editando tem sha1 65dfb6a. Sabendo disso, posso verificar o conteúdo desse commit no meu diretório de trabalho usando o formato git checkoutque leva tanto o commit quanto o local do arquivo. Aqui eu uso .como local do arquivo para substituir toda a cópia de trabalho:
git checkout 65dfb6a .
Não perca o ponto no final!
Isso fará o check-out e preparará os arquivos como estavam após a confirmação que você está editando, mas em relação à confirmação anterior que você fez, portanto, quaisquer alterações que você já tenha confirmado não farão parte do commit.
Você pode ir em frente agora e confirmar como está para terminar a divisão ou sair novamente, excluindo algumas partes da confirmação antes de fazer outra confirmação provisória.
Se você deseja reutilizar a mensagem de confirmação original para uma ou mais confirmações, é possível usá-la diretamente dos arquivos de trabalho da rebase:
Obrigado!!! Essa deve ser a resposta aceita. Teria me poupado muito tempo e dor hoje. É a única resposta em que o resultado da confirmação final o leva ao mesmo estado que a confirmação em edição.
Doug Coburn
1
Gosto da maneira como você usa a mensagem de confirmação original.
Salamandar
Usando a opção 2, quando faço git checkout *Sha I'm Editing* ., sempre diz Updated 0 paths from *Some Sha That's Not In Git Log*e não dá alterações.
No modo interativo, você pode marcar confirmações com a ação "editar". No entanto, isso não significa necessariamente que git rebaseo resultado dessa edição seja exatamente uma confirmação. Na verdade, você pode desfazer a confirmação ou adicionar outras confirmações. Isso pode ser usado para dividir um commit em dois:
Inicie uma rebase interativa com git rebase -i <commit>^, onde <commit>está o commit que você deseja dividir. De fato, qualquer intervalo de confirmação serve, desde que contenha esse commit.
Marque o commit que você deseja dividir com a ação "edit".
Quando se trata de editar essa confirmação, execute git reset HEAD^. O efeito é que o HEAD é rebobinado por um e o índice segue o exemplo. No entanto, a árvore de trabalho permanece a mesma.
Agora adicione as alterações ao índice que você deseja ter no primeiro commit. Você pode usar git add(possivelmente interativamente) ou git gui (ou ambos) para fazer isso.
Confirme o índice agora atual com qualquer mensagem de confirmação apropriada agora.
Repita as duas últimas etapas até que sua árvore de trabalho esteja limpa.
Continue a rebase com git rebase --continue.
Se você não tiver certeza absoluta de que as revisões intermediárias são consistentes (elas compilam, passam no testuite etc.), devem ser usadas git stashpara ocultar as alterações ainda não confirmadas após cada confirmação, teste e alteração da confirmação, se forem necessárias correções. .
No Windows, lembre- ^se de um caractere de escape para a linha de comando: ele deve ser dobrado. Por exemplo, emitir em git reset HEAD^^vez degit reset HEAD^ .
Frédéric
@ Frédéric: s Eu nunca me deparei com isso. Pelo menos no PowerShell, esse não é o caso. Em seguida, usar ^duas vezes redefine duas confirmações acima do HEAD atual.
Farway
@ Farway, tente em uma linha de comando clássica. O PowerShell é outra besta, seu caráter de fuga é o backtilt.
Frédéric
Para resumir: "HEAD^"no cmd.exe ou no PowerShell, HEAD^^no cmd.exe,HEAD`^ no PowerShell. É útil aprender sobre como os shells - e seu shell em particular - funcionam (ou seja, como um comando se transforma em partes individuais que são passadas para o programa), para que você possa adaptar comandos on-line aos caracteres certos para seu shell em particular. (Não é específico para o Windows.)
AndrewF
11
Agora, no TortoiseGit mais recente do Windows, você pode fazer isso com muita facilidade.
Abra a caixa de diálogo rebase, configure-a e execute as seguintes etapas.
Clique com o botão direito do mouse no commit que você deseja dividir e selecione " Edit" (entre pick, squash, delete ...).
Clique em " Start" para começar a rebasear.
Quando chegar ao commit para dividir, verifique o Edit/Splitbotão " " e clique em " Amend" diretamente. A caixa de diálogo de confirmação é aberta.
Desmarque os arquivos que deseja colocar em uma confirmação separada.
Edite a mensagem de confirmação e clique em " commit".
Até que haja arquivos a serem confirmados, a caixa de diálogo de confirmação será aberta novamente. Quando não houver mais arquivos a serem confirmados, ele ainda perguntará se você deseja adicionar mais um commit.
Dar um pouco mais de contexto sobre como abordar os problemas do que apenas fornecer um RTFM seria um pouco mais útil.
Jordan Dea-Mattson
8
Por favor, note que também há git reset --soft HEAD^. É semelhante a git reset(cujo padrão é --mixed), mas mantém o conteúdo do índice. Portanto, se você adicionou / removeu arquivos, já os tem no índice.
Aqui está como dividir um commit no IntelliJ IDEA , PyCharm , PhpStorm etc
Na janela de log do Controle de versão, selecione a confirmação que você deseja dividir, clique com o botão direito do mouse e selecione a opção Interactively Rebase from Here
marque o que você deseja dividir como edit, clique emStart
Rebasing
Você deverá ver uma etiqueta amarela, o que significa que o HEAD está definido para esse commit. Clique com o botão direito do mouse nessa confirmação e selecioneUndo Commit
Agora que essas confirmações estão de volta à área de preparação, você pode confirmá-las separadamente. Depois que todas as alterações foram confirmadas, a confirmação antiga se torna inativa.
A coisa mais fácil de fazer sem uma nova recuperação interativa é (provavelmente) criar uma nova ramificação iniciando no commit antes do que você deseja dividir, escolher com cereja, confirmar, redefinir, ocultar, confirmar a movimentação do arquivo, reaplicar o stash e confirmar as alterações e, em seguida, mesclar com a ramificação anterior ou escolher as confirmações a seguir. (Em seguida, mude o nome da filial anterior para o cabeçalho atual.) (Provavelmente é melhor seguir os conselhos dos MBOs e fazer uma nova análise interativa.)
de acordo com os padrões da SO atualmente, isso deve ser qualificado como não resposta; mas isso ainda pode ser útil para outras pessoas, por isso, se você não se importa, mova isso para comentários da postagem original
YakovL
@YakovL Parece razoável. Sobre o princípio da ação mínima, não excluirei a resposta, mas não contestaria se outra pessoa o fizesse.
William Pursell
isso seria muito mais fácil do que todo rebase -i sugestões. Acho que isso não recebeu muita atenção devido à falta de formatação. Talvez você possa revisá-lo, agora que possui 126 mil pontos e provavelmente sabe SO. ;)
Faz mais de 8 anos, mas talvez alguém ache útil de qualquer maneira. Eu era capaz de fazer o truque sem rebase -i. A idéia é levar o git ao mesmo estado que estava antes de você git commit:
# first rewind back (mind the dot,# though it can be any valid path,# for instance if you want to apply only a subset of the commit)
git reset --hard <previous-commit>.# apply the changes
git checkout <commit-you-want-to-split># we're almost there, but the changes are in the index at the moment,# hence one more step (exactly as git gently suggests):# (use "git reset HEAD <file>..." to unstage)
git reset
Depois disso, você verá isso brilhante Unstaged changes after reset:e seu repositório estará em um estado como se estivesse prestes a confirmar todos esses arquivos. A partir de agora você pode facilmente cometer novamente, como costuma fazer. Espero que ajude.
git autorebase split COMMIT_ID
git reset HEAD~
,git stash
, em seguida,git cherry-pick
o primeiro cometer dentro do squash, entãogit stash pop
. Meu caso cherry-pick é bastante específica aqui, masgit stash
egit stash pop
é bastante útil para os outros.Respostas:
git rebase -i
vai fazer isso.Primeiro, comece com um diretório de trabalho limpo: não
git status
deve mostrar modificações, exclusões ou inclusões pendentes.Agora, você deve decidir quais confirmações deseja dividir.
A) Dividindo o commit mais recente
Para dividir seu commit mais recente, primeiro:
Agora comprometa as peças individualmente da maneira usual, produzindo quantos commits forem necessários.
B) Dividindo um commit mais atrás
Isso requer reorganizar , ou seja, reescrever o histórico. Para encontrar a confirmação correta, você tem várias opções:
Se fosse três commits de volta, então
onde
3
é quantos commits de volta é.Se estava mais atrás na árvore do que você deseja contar, então
onde
123abcd
está o SHA1 do commit que você deseja dividir.Se você estiver em uma ramificação diferente (por exemplo, uma ramificação de recurso) que planeja mesclar no mestre:
Quando você receber a tela de edição de rebase, encontre a confirmação que deseja desmembrar. No início dessa linha, substitua
pick
poredit
(e
para abreviar). Salve o buffer e saia. O rebase agora será interrompido logo após o commit que você deseja editar. Então:Confirme as peças individualmente da maneira usual, produzindo quantos commits forem necessários e, em seguida,
fonte
git rebase --continue
, eu realmente tive quegit add (files to be added)
,git commit
, em seguida,git stash
(para os arquivos restantes). Depoisgit rebase --continue
, eu costumavagit checkout stash .
obter os arquivos restantes #git add -p
adicionar apenas seções parciais de arquivos, possivelmente com ae
opção de editar as diferenças para confirmar apenas um pedaço.git stash
também é útil se você deseja levar algum trabalho adiante, mas removê-lo da confirmação atual.git rebase -i HEAD^3
comando. Dessa forma, se a divisão der errado, você não precisará desfazer tanto trabalho.git reset HEAD~
. Eles não estão perdidos.No manual git-rebase (seção SPLITTING COMMITS)
fonte
~
vez de^
.reset
executando o commit, afinal - mensagem incluída. A coisa prudente a se fazer, se você sabe que vai dividir um commit, mas deseja manter parte / toda a sua mensagem, é tirar uma cópia dessa mensagem. Portanto,git show
o commit antes dorebase
ing, ou se você esquecer ou preferir isso: volte mais tarde através doreflog
. Nada disso será "perdido" até que seja coletado em 2 semanas ou o que for.~
e^
são coisas diferentes, mesmo no Windows. Você ainda deseja o sinal de intercalação^
, portanto, basta escapar dele conforme apropriado para o seu shell. No PowerShell, éHEAD`^
. Com o cmd.exe, você pode dobrá-lo para escapar comoHEAD^^
. Na maioria das conchas (todas?), Você pode colocar aspas como"HEAD^"
.git commit --reuse-message=abcd123
. A opção curta para isso é-C
.Use
git rebase --interactive
para editar a confirmação anterior, executargit reset HEAD~
e, em seguida,git add -p
adicionar algumas, fazer uma confirmação, adicionar mais algumas e fazer outra confirmação, quantas vezes quiser. Quando terminar, executegit rebase --continue
e você terá todas as confirmações de divisão anteriormente na sua pilha.Importante : Observe que você pode brincar e fazer todas as alterações desejadas, e não precisa se preocupar em perder alterações antigas, porque sempre é possível executar
git reflog
para encontrar o ponto em seu projeto que contém as alterações desejadas (vamos chamá-loa8c4ab
) e, em seguidagit reset a8c4ab
.Aqui está uma série de comandos para mostrar como funciona:
mkdir git-test; cd git-test; git init
agora adicione um arquivo
A
vi A
adicione esta linha:
one
git commit -am one
adicione esta linha a A:
two
git commit -am two
adicione esta linha a A:
three
git commit -am three
agora o arquivo A se parece com isso:
e nossa
git log
aparência é a seguinte (bem, eu usogit log --pretty=oneline --pretty="%h %cn %cr ---- %s"
Digamos que queremos dividir o segundo commit
two
,.git rebase --interactive HEAD~2
Isso traz uma mensagem parecida com esta:
Altere o primeiro
pick
para ume
para editar essa confirmação.git reset HEAD~
git diff
nos mostra que acabamos de desestabilizar o commit que fizemos para o segundo commit:Vamos preparar essa alteração e adicionar "e um terceiro" a essa linha no arquivo
A
.git add .
Normalmente, esse é o ponto durante uma nova reformulação interativa em que executaríamos
git rebase --continue
, porque geralmente queremos voltar à nossa pilha de confirmações para editar uma confirmação anterior. Mas desta vez, queremos criar um novo commit. Então vamos corrergit commit -am 'two and a third'
. Agora editamos o arquivoA
e adicionamos a linhatwo and two thirds
.git add .
git commit -am 'two and two thirds'
git rebase --continue
Temos um conflito com o nosso commit
three
, então vamos resolvê-lo:Nós vamos mudar
para
git add .; git rebase --continue
Agora, nossa
git log -p
aparência é assim:fonte
As respostas anteriores abordaram o uso de
git rebase -i
para editar o commit que você deseja dividir e o comprometeu em partes.Isso funciona bem ao dividir os arquivos em confirmações diferentes, mas se você deseja separar as alterações nos arquivos individuais, é necessário saber mais.
Tendo chegado ao commit que você deseja dividir, usando
rebase -i
e marcandoedit
, você tem duas opções.Após o uso
git reset HEAD~
, percorra os patches individualmente usandogit add -p
para selecionar os que você deseja em cada confirmaçãoEdite a cópia de trabalho para remover as alterações que você não deseja; comprometer esse estado provisório; e retire o commit completo para a próxima rodada.
A opção 2 é útil se você estiver dividindo uma confirmação grande, pois permite verificar se as versões intermediárias são construídas e executadas corretamente como parte da mesclagem. Isso ocorre da seguinte maneira.
Após usar
rebase -i
eedit
confirmar a confirmação, usepara desfazer a confirmação, mas deixe os arquivos confirmados no índice. Você também pode fazer uma redefinição mista, omitindo --soft, dependendo de quão próximo do resultado final será o seu commit inicial. A única diferença é se você inicia com todas as alterações realizadas ou com todas elas não realizadas.
Agora entre e edite o código. Você pode remover alterações, excluir arquivos adicionados e fazer o que quiser para construir o primeiro commit da série que você está procurando. Você também pode compilá-lo, executá-lo e confirmar se possui um conjunto consistente de fontes.
Quando estiver satisfeito, prepare / descompacte os arquivos conforme necessário (eu gosto de usar
git gui
para isso) e confirme as alterações através da interface do usuário ou da linha de comandoEsse é o primeiro commit feito. Agora você deseja restaurar sua cópia de trabalho para o estado que ela tinha após a consolidação que está sendo dividida, para que você possa realizar mais alterações na sua próxima consolidação. Para encontrar o sha1 do commit que você está editando, use
git status
. Nas primeiras linhas do status, você verá o comando rebase que está sendo executado no momento, no qual você pode encontrar o sha1 do seu commit original:Nesse caso, o commit que estou editando tem sha1
65dfb6a
. Sabendo disso, posso verificar o conteúdo desse commit no meu diretório de trabalho usando o formatogit checkout
que leva tanto o commit quanto o local do arquivo. Aqui eu uso.
como local do arquivo para substituir toda a cópia de trabalho:Não perca o ponto no final!
Isso fará o check-out e preparará os arquivos como estavam após a confirmação que você está editando, mas em relação à confirmação anterior que você fez, portanto, quaisquer alterações que você já tenha confirmado não farão parte do commit.
Você pode ir em frente agora e confirmar como está para terminar a divisão ou sair novamente, excluindo algumas partes da confirmação antes de fazer outra confirmação provisória.
Se você deseja reutilizar a mensagem de confirmação original para uma ou mais confirmações, é possível usá-la diretamente dos arquivos de trabalho da rebase:
Por fim, depois de confirmar todas as alterações,
continuará e concluirá a operação de rebase.
fonte
git checkout *Sha I'm Editing* .
, sempre dizUpdated 0 paths from *Some Sha That's Not In Git Log*
e não dá alterações.git rebase --interactive
pode ser usado para dividir uma confirmação em confirmações menores. Os documentos do Git sobre rebase têm uma explicação concisa do processo - Divisões de consolidação :fonte
^
se de um caractere de escape para a linha de comando: ele deve ser dobrado. Por exemplo, emitir emgit reset HEAD^^
vez degit reset HEAD^
.^
duas vezes redefine duas confirmações acima do HEAD atual."HEAD^"
no cmd.exe ou no PowerShell,HEAD^^
no cmd.exe,HEAD`^
no PowerShell. É útil aprender sobre como os shells - e seu shell em particular - funcionam (ou seja, como um comando se transforma em partes individuais que são passadas para o programa), para que você possa adaptar comandos on-line aos caracteres certos para seu shell em particular. (Não é específico para o Windows.)Agora, no TortoiseGit mais recente do Windows, você pode fazer isso com muita facilidade.
Abra a caixa de diálogo rebase, configure-a e execute as seguintes etapas.
Edit
" (entre pick, squash, delete ...).Start
" para começar a rebasear.Edit/Split
botão " " e clique em "Amend
" diretamente. A caixa de diálogo de confirmação é aberta.commit
".Muito útil, obrigado TortoiseGit!
fonte
Você pode fazer o rebase interativo
git rebase -i
. A página de manual tem exatamente o que você deseja:http://git-scm.com/docs/git-rebase#_splitting_commits
fonte
Por favor, note que também há
git reset --soft HEAD^
. É semelhante agit reset
(cujo padrão é--mixed
), mas mantém o conteúdo do índice. Portanto, se você adicionou / removeu arquivos, já os tem no índice.Se mostra muito útil em caso de commits gigantes.
fonte
Aqui está como dividir um commit no IntelliJ IDEA , PyCharm , PhpStorm etc
Na janela de log do Controle de versão, selecione a confirmação que você deseja dividir, clique com o botão direito do mouse e selecione a opção
Interactively Rebase from Here
marque o que você deseja dividir como
edit
, clique emStart Rebasing
Você deverá ver uma etiqueta amarela, o que significa que o HEAD está definido para esse commit. Clique com o botão direito do mouse nessa confirmação e selecione
Undo Commit
Agora que essas confirmações estão de volta à área de preparação, você pode confirmá-las separadamente. Depois que todas as alterações foram confirmadas, a confirmação antiga se torna inativa.
fonte
A coisa mais fácil de fazer sem uma nova recuperação interativa é (provavelmente) criar uma nova ramificação iniciando no commit antes do que você deseja dividir, escolher com cereja, confirmar, redefinir, ocultar, confirmar a movimentação do arquivo, reaplicar o stash e confirmar as alterações e, em seguida, mesclar com a ramificação anterior ou escolher as confirmações a seguir. (Em seguida, mude o nome da filial anterior para o cabeçalho atual.) (Provavelmente é melhor seguir os conselhos dos MBOs e fazer uma nova análise interativa.)
fonte
rebase -i
sugestões. Acho que isso não recebeu muita atenção devido à falta de formatação. Talvez você possa revisá-lo, agora que possui 126 mil pontos e provavelmente sabe SO. ;)Eu acho que da melhor maneira que eu uso
git rebase -i
. Criei um vídeo para mostrar as etapas para dividir um commit: https://www.youtube.com/watch?v=3EzOz7e1ADIfonte
Se você tem isso:
Onde você confirmou um conteúdo no commit B:
Mas você deseja dividir B em C - D e obter este resultado:
Você pode dividir o conteúdo como este, por exemplo (conteúdo de diferentes diretórios em diferentes confirmações) ...
Redefina a ramificação de volta para a confirmação antes da divisão:
Crie o primeiro commit (C):
Crie o segundo commit (D):
fonte
Faz mais de 8 anos, mas talvez alguém ache útil de qualquer maneira. Eu era capaz de fazer o truque sem
rebase -i
. A idéia é levar o git ao mesmo estado que estava antes de vocêgit commit
:Depois disso, você verá isso brilhante
Unstaged changes after reset:
e seu repositório estará em um estado como se estivesse prestes a confirmar todos esses arquivos. A partir de agora você pode facilmente cometer novamente, como costuma fazer. Espero que ajude.fonte
Uma referência rápida dos comandos necessários, porque basicamente sei o que fazer, mas sempre esqueço a sintaxe correta:
Créditos à postagem de Emmanuel Bernard .
fonte