Como remover o primeiro commit no git?

179

Estou curioso sobre como remover o primeiro commit no git.

Qual é a revisão antes de cometer alguma coisa? Esta revisão possui um nome ou tag?

Jian Weihang
fonte
2
Para começar com o git, você deve saber que a revisão não faz sentido. Você pode falar sobre confirmações ou seus SHAs relativos. Além disso, por que você quer fazer isso? O primeiro commit é no que tudo é construído. Você pode compactar algumas confirmações juntas, incluindo a primeira confirmação, que se torna a nova primeira confirmação, mas o que significa até excluir a primeira confirmação (ou excluir qualquer, exceto a última confirmação)?
Shahbaz
@Shahbaz sim, isso é o melhor caminho, olha aqui, por exemplo: ariejan.net/2011/07/05/git-squash-your-latests-commits-into-one
timaschew
5
Você pode usar git rebase -i --root. Consulte a seguinte resposta do SO para obter detalhes: stackoverflow.com/questions/2246208/…
MKroehnert 3/13/13
possível duplicata de Posso remover o commit inicial de um repositório Git?
Gordon Gustafson
Esta resposta tem a solução correta para excluir o commit raiz do ramo atual:git filter-branch --parent-filter "sed 's/-p <the_commit>//'" HEAD
Jody Bruchon

Respostas:

321

Para mim, a maneira mais segura é usar o update-refcomando:

git update-ref -d HEAD

Ele excluirá a referência nomeada HEADe redefinirá (suavemente, você não perderá seu trabalho) todos os seus commits do seu ramo atual .

Se o que você deseja é mesclar o primeiro commit com o segundo, você pode usar o rebasecomando:

git rebase -i --root

Uma última maneira poderia ser criar uma ramificação órfã, uma ramificação com o mesmo conteúdo, mas sem histórico de confirmação, e confirmar seu novo conteúdo:

git checkout --orphan <new-branch-name>
tzi
fonte
7
É uma pena que esta não seja a resposta aceita. Também é muito ruim que a maioria dos acessos no google diga "você não pode desfazer o primeiro commit". Isso fez o truque para mim. Obrigado!
Danielpops
1
Obrigado @danielpops pelo seu apoio! É bom notar que eu respondi a essa pergunta três anos depois. Enquanto isso, o Git evoluiu.
tzi
Eu usei rebase, marquei o segundo commit como "squash" e, em seguida, forcei a origem. Obrigado!
Philip Atz
1
O git update-ref -d HEAD é a maneira mais segura de remover todo o histórico, não apenas o commit inicial.
user1767316
Eu fiz isso e ele excluiu todos os meus arquivos que adicionei ao primeiro commit. Triste. Pelo menos não foi muito
Vyacheslav Tsivina 12/07
42

Não há nada antes do primeiro commit, pois todo commit está se referindo a um commit pai. Isso torna o primeiro commit especial (um órfão), portanto não há como se referir a um "estado" anterior.

Portanto, se você deseja corrigir o commit, você pode simplesmente git commit --amend: isso modificará o commit sem criar outro.

Se você deseja apenas começar tudo de novo, exclua o .gitrepositório e faça outro comgit init

CharlesB
fonte
7
Esta resposta está incorreta: existe uma maneira de reverter para o estado antes da primeira confirmação. Veja a resposta da tzi abaixo.
David Nelson
2
O --amendtambém não atualizará o autor corretamente se ele tiver sido inicialmente configurado incorretamente. Era disso que eu precisava, então usei a resposta aceita e fiz um novo commit.
Mark Edington
11
# Check out to a temporary branch:
git checkout --orphan TEMP_BRANCH

# Add all the files:
git add -A

# Commit the changes:
git commit -am "Initial commit"

# Delete the old branch:
git branch -D master

# Rename the temporary branch to master:
git branch -m master

# Finally, force update to our repository:
git push -f origin master
Megha Sahu
fonte
3
Não é uma resposta: a pergunta era "como remover o primeiro commit" e não "como excluir tudo, exceto o último commit".
peterh - Restabelece Monica
1
Eu estava procurando exatamente por isso. Obrigado!
Krzysztof Tomaszewski
6

Você pode apenas editar seu primeiro commit (como sempre há um primeiro commit em um repositório git). Considere usar em git commit --amend --reset-authorvez do habitual git commit --amend.

Max Beikirch
fonte
1
Não é uma resposta: a pergunta queria excluir o primeiro commit e não modificar as propriedades do último.
peterh - Restabelece Monica
@ peterh-ReinstateMonica Para esclarecimento: As confirmações podem ser alteradas durante o rebase interativo para alterar completamente o conteúdo, mas --reset-author também precisa ser fornecido para alterar o autor. Com isso, você pode substituir completamente o primeiro commit ao seu gosto. Veja também a resposta de CharlesB.
Max Beikirch
3

Eu estava procurando uma maneira de desfazer todos os commits git de um repositório, como se nunca tivessem acontecido.

O rebaseamento funcionará até certo ponto. No entanto, o primeiro (cronologicamente o mais antigo commit do git) sempre será problemático, uma vez que não possui um pai, o que resultará em erro.

Nenhuma dessas respostas resolveu isso para mim. Mas, depois de muita pesquisa e tentativa e erro, achei que funcionava!

git update-ref -d HEAD
git push origin master -f

Espero que isso ajude você. Tenha um ótimo dia.

kp123
fonte
1
Para ficar claro para quem lê esta resposta: isso exclui todos os commit, mas o OP quer excluir o primeiro commit feito em um repo; não execute isso para excluir o primeiro commit porque ele excluirá TODOS os commit.
Jody Bruchon
2

Outra maneira de fazer é:

  1. Finalize a compra para um ramo que você deseja manter (diga dev) git checkout dev
  2. Agora, exclua a ramificação que deseja redefinir git branch -D master
  3. Agora, crie uma ramificação vazia com o mesmo nome git checkout --orphan master

Obviamente, tudo isso dependeria da sua base de dados, mas se você tiver mais de uma ramificação, excluir o .gitdiretório não fará sentido.

kumarharsh
fonte
3
Depois de fazer isso, você deve excluir a ramificação no controle remoto antes de pressionar. Caso contrário, ao tentar enviar, você terá este erro:! [rejeitado] master -> master (avanço não rápido) - erro: falha ao enviar algumas referências para '[email protected]: r1 / r2.git' - dica: as atualizações foram rejeitadas porque a dica de sua ramificação atual é behind - hint: sua contraparte remota. Integre as alterações remotas (por exemplo, dica: 'git pull ...') antes de pressionar novamente ... - Se você fizer um git pull, todas as confirmações retornarão.
Dxvargas 29/12/16
2

Se você deseja manter outras ramificações, mas, por exemplo, fazer com que a masterramificação inicie novamente sem histórico comum para outras ramificações, uma maneira segura de conseguir isso é criar um novo repositório e enviar o conteúdo dele para o antigo:

cd ..
git init newrepo
cd newrepo
# make some initial commits
git push ../oldrepo master:newmaster

Isso cria newmasterramificação no repositório antigo, com histórico que não é comum a nenhuma das outras ramificações. Claro, você pode simplesmente substituir o mastertambém com git push -f.

Se você deseja destruir todas as ramificações e todo o conteúdo existente, basta executar

rm -rf .git/
user1338062
fonte
1
Não é uma resposta: o OP queria remover o primeiro commit e não iniciar um novo repositório git com a árvore de trabalho atual como commit inicial.
peterh - Restabelece Monica
@ Peterh Concordo git rebase --rootque provavelmente é o que o OP queria, mas, considerando que esta resposta tem dois votos positivos, evitarei excluí-la caso alguém ainda a ache relevante.
user1338062
Eu acho que essa resposta é exatamente relevante - se você deseja excluir o primeiro comprometer em algum ramo, e não é apenas um cometer! (Mas você também deseja manter os outros commits em outros ramos; e também deseja fazer isso para que as alterações terminem no Bitbucket ou no Github, não apenas localmente.) Acredito que essa resposta seja uma maneira de fazer isso, e Eu acho que pode ser a única maneira de fazer isso. (Isso porque - também, tanto quanto eu posso ver -. Não há nenhuma maneira de forçar empurrar um ramo local sem commits mais de uma filial remota com alguns commits)
MikeBeaton
0

Se você acabou de confirmar, mas não o enviou, remova o diretório .git e git initnovamente ...

Ali Sajid
fonte
@ Peterh Sim, ele faz. Você está assumindo (eu acho) que a pergunta do OP é sobre querer excluir o primeiro commit, mas manter os commit subsequentes. Outra possibilidade (que eu acho que combina perfeitamente com a pergunta do OP - e para a qual esta resposta é uma resposta) é excluir o primeiro e único commit de um ramo, revertendo-o novamente para ficar completamente vazio novamente.
MikeBeaton
@MikeBeaton Você está certo. Retiro meu comentário, mas preciso votar para encerrar a pergunta como pouco clara. Observe que, embora apenas eu tenha feito esse comentário, há atrás de mim 40000 visitantes, e uma parte significativa deles encontrou essa pergunta no google - e eles não conseguiram o que queriam.
peterh - Restabelece Monica
Isso parece extremo. Excluir a pergunta? Não poderia (perfeitamente) ser argumentado que uma resposta completa para o que é uma pergunta perfeitamente razoável é que existem duas abordagens diferentes que precisam ser adotadas, dependendo de ... etc.? (Quero dizer, eu, por exemplo, gostaria de saber como remover o primeiro commit, quando este não é o único commit, e também como remover o primeiro commit, quando este é o único commit. Certamente não é óbvio e certamente depende sobre os detalhes específicos da implementação, que de fato resulta que são necessárias abordagens realmente bastante diferentes em cada caso.)
MikeBeaton
0

A resposta para a pergunta depende se:

  • Você deseja remover o primeiro e apenas confirmar em uma ramificação (enquanto deixa outras ramificações como eram) ou se

  • Você deseja remover o primeiro commit em alguma ramificação, enquanto 'deixa no lugar' as confirmações subsequentes (e as outras ramificações).

O segundo deles é relativamente mais simples. Você basicamente precisa se refazer na raiz - a maioria das respostas aqui são sobre maneiras de fazer isso.

Fazer o segundo (remover o primeiro e apenas confirmar de um ramo, deixando outros ramos em paz) é mais difícil. Ou, pelo menos, especialmente mais difícil se você quiser que isso aconteça e que a mudança seja refletida no GitHub ou no Bitbucket. Não há (até onde eu saiba) nenhuma maneira no Git de empurrar ou forçar a empurrar um ramo sem confirmação. E também há (novamente, até onde eu vejo), nenhuma maneira de criar um novo ramo vazio, sem confirmações no GitHub ou no Bitbucket. Portanto, você basicamente precisa criar um novo repositório para criar uma ramificação completamente vazia e, em seguida, adicionar novamente as ramificações que deseja (incluindo as confirmações que deseja) - conforme a resposta de @ user1338062.

Espero que esta resposta esclareça o que pode não ter sido óbvio - que existem duas abordagens diferentes que precisam ser adotadas, para dois cenários diferentes (mais ou menos razoáveis), que são as duas coisas que você pode querer fazer, para dominar completamente o que o OP pede.

MikeBeaton
fonte