Você deve usar o índice. Depois de fazer uma redefinição mista (" git reset HEAD ^"), adicione o primeiro conjunto de alterações no índice e as confirme. Em seguida, comprometa o resto.
Você pode usar " git add " para colocar todas as alterações feitas em um arquivo no índice. Se você não deseja organizar todas as modificações feitas em um arquivo, apenas algumas delas, você pode usar "git add -p".
Vamos ver um exemplo. Vamos supor que eu tivesse um arquivo chamado myfile, que contém o seguinte texto:
something
something else
something again
Eu o modifiquei no meu último commit para que agora fique assim:
1
something
something else
something again
2
Agora eu decido que quero dividi-lo em dois e quero que a inserção da primeira linha esteja no primeiro commit e a inserção da última linha no segundo commit.
Primeiro, volto ao pai do HEAD, mas quero manter as modificações no sistema de arquivos, então uso "git reset" sem argumento (o que fará a chamada redefinição "mista"):
$ git reset HEAD^
myfile: locally modified
$ cat myfile
1
something
something else
something again
2
Agora eu uso "git add -p" para adicionar as alterações que quero confirmar no índice (= eu as preparo). "git add -p" é uma ferramenta interativa que pergunta sobre quais alterações no arquivo devem ser adicionadas ao índice.
$ git add -p myfile
diff --git a/myfile b/myfile
index 93db4cb..2f113ce 100644
--- a/myfile
+++ b/myfile
@@ -1,3 +1,5 @@
+1
something
something else
something again
+2
Stage this hunk [y,n,a,d,/,s,e,?]? s # split this section into two!
Split into 2 hunks.
@@ -1,3 +1,4 @@
+1
something
something else
something again
Stage this hunk [y,n,a,d,/,j,J,g,e,?]? y # yes, I want to stage this
@@ -1,3 +2,4 @@
something
something else
something again
+2
Stage this hunk [y,n,a,d,/,K,g,e,?]? n # no, I don't want to stage this
Então eu confirmo esta primeira alteração:
$ git commit -m "Added first line"
[master cef3d4e] Added first line
1 files changed, 1 insertions(+), 0 deletions(-)
Agora eu posso confirmar todas as outras alterações (ou seja, o número "2" colocado na última linha):
$ git commit -am "Added last line"
[master 5e284e6] Added last line
1 files changed, 1 insertions(+), 0 deletions(-)
Vamos verificar o log para ver o que temos:
$ git log -p -n2 | cat
Commit 5e284e652f5e05a47ad8883d9f59ed9817be59d8
Author: ...
Date: ...
Added last line
Diff --git a/myfile b/myfile
Index f9e1a67..2f113ce 100644
--- a/myfile
+++ b/myfile
@@ -2,3 +2,4 @@
something
something else
something again
+2
Commit cef3d4e0298dd5d279a911440bb72d39410e7898
Author: ...
Date: ...
Added first line
Diff --git a/myfile b/myfile
Index 93db4cb..f9e1a67 100644
--- a/myfile
+++ b/myfile
@@ -1,3 +1,4 @@
+1
something
something else
something again
git reset [--patch|-p] <commit>
que você pode usar para evitar o problema de ter que fazer issogit add -p
após a redefinição. Estou certo? Usando o git 1.7.9.5.Metas:
splitme
) passado em dois.Plano:
splitme
.splitme
.As etapas de rebase (1 e 7) podem ser ignoradas se a
splitme
confirmação for mais recente.Se eu quisesse que os arquivos divididos fossem confirmados primeiro, então eu rebasei -i novamente e mudaria a ordem
fonte
git reset HEAD^
foi a peça que faltava no quebra-cabeça. Funciona bem com-p
também. Obrigado!-- $files
argumento paragit reset
. Com os caminhos passados,git reset
restaura esses arquivos no estado do commit referenciado, mas não altera nenhum commit. Se você deixar de lado os caminhos, "perderá" o commit que deseja alterar na próxima etapa.git reset HEAD^ -- .
. Surpreendentemente, esse não é exatamente o comportamento degit reset HEAD^
.Para alterar a confirmação atual em duas confirmações, você pode fazer algo como o seguinte.
Ou:
Isso desfaz o último commit, mas deixa tudo preparado. Você pode desestabilizar certos arquivos:
Como opção, reestabeleça partes desses arquivos:
Faça um novo primeiro commit:
O estágio e confirma o restante das alterações em um segundo commit:
Ou:
Desfazer e desestabilizar todas as alterações da última confirmação:
Preparar seletivamente a primeira rodada de alterações:
Confirmar:
Confirme o restante das alterações:
(Em qualquer uma das etapas, se você desfez uma confirmação que adicionou um arquivo totalmente novo e deseja adicioná-lo à segunda confirmação, será necessário adicioná-lo manualmente, pois
commit -a
apenas altera as etapas nos arquivos já rastreados.)fonte
Execute
git gui
, selecione o botão de opção "Alterar última confirmação" e desinstale (Confirmar> Desinstalar do commit, ou Ctrl- U) as alterações que você não deseja entrar no primeiro commit. Eu acho que é a maneira mais fácil de fazer isso.Outra coisa que você pode fazer é escolher a alteração sem confirmar (
git cherry-pick -n
) e, em seguida, manualmente ou comgit gui
as alterações desejadas selecionadas antes de confirmar.fonte
o --hard é o que está matando suas alterações.
fonte
Estou surpreso que ninguém tenha sugerido
git cherry-pick -n forum
. Isso preparará as alterações daforum
confirmação mais recente, mas não as comprometerá - você poderáreset
afastar as alterações desnecessárias e confirmar o que deseja manter.fonte
O método de dupla reversão-squash
git checkout HEAD~1 -- files with unwanted changes
egit commit
. Caso contrário, os arquivos com alterações mistas podem ser parcialmente preparadosgit reset file
egit add -p file
como uma etapa intermediária.) Chame isso de reverter .git revert HEAD
- Faça outro commit, que adiciona de volta as alterações indesejadas. Esta é a dupla reversãogit rebase -i HEAD~3
). Agora, esse commit fica livre das alterações indesejadas, pois estão no segundo commit.Benefícios
fonte
Como você escolhe a cereja, pode:
cherry-pick
com a--no-commit
opção adicionada.reset
e useadd --patch
,add --edit
ou apenasadd
para preparar o que você deseja manter.commit
as mudanças encenadas.--reuse-message=<old-commit-ref>
ou--reedit-message=<old-commit-ref>
opções aocommit
comando.reset --hard
.Outra maneira, preservando ou editando a mensagem de confirmação original:
cherry-pick
o commit original como normal.add
para encenar a reversão.commit --amend
para efetuar a reversão no commit escolhido pela cereja.fonte
Essa pode ser outra solução direcionada para casos em que há uma confirmação enorme e uma pequena quantidade de arquivos precisa ser movida para uma nova confirmação. Isso funcionará se um conjunto de
<path>
arquivos que ser extraído da última confirmação no HEAD e todos movidos para uma nova confirmação. Se forem necessárias várias confirmações, outras soluções podem ser usadas.Primeiro faça correções nas áreas preparadas e não preparadas que conteriam as alterações para reverter o código para antes e depois da modificação, respectivamente:
Para entender o que vai acontecer (seta e comentários não fazem parte do comando):
Reverter
<path>
alterações na última confirmação:Crie uma nova confirmação com
<path>
alterações:Isso tem o efeito de criar uma nova confirmação contendo as alterações extraídas da última confirmação.
fonte