Como você compacta todo o seu repositório até o primeiro commit?
Posso mudar para o primeiro commit, mas isso me deixaria com 2 commits. Existe uma maneira de referenciar o commit antes do primeiro?
git
rebase
git-rebase
squash
git-rewrite-history
Verhogen
fonte
fonte
--root
na verdade, não é a melhor solução para esmagar todos os commits, se houver muitos deles para esmagar): Combine os dois primeiros commits de um repositório Git? .Respostas:
Talvez a maneira mais fácil seja apenas criar um novo repositório com o estado atual da cópia de trabalho. Se você deseja manter todas as mensagens de confirmação, você pode primeiro fazer
git log > original.log
e editar isso para sua mensagem de confirmação inicial no novo repositório:ou
fonte
git rebase -i --root
. Veja: stackoverflow.com/a/9254257/109618A partir do git 1.6.2 , você pode usar
git rebase --root -i
.Para cada confirmação, exceto a primeira, altere
pick
parasquash
.fonte
squash
para todas as confirmações. O primeiro precisa serpick
.Atualizar
Eu fiz um pseudônimo
git squash-all
.Exemplo de utilização :
git squash-all "a brand new start"
.Embargo : lembre-se de fornecer um comentário, caso contrário, a mensagem de confirmação padrão "Um novo começo" seria usada.
Ou você pode criar o alias com o seguinte comando:
One Liner
Nota : aqui "
A new start
" é apenas um exemplo, fique à vontade para usar seu próprio idioma.TL; DR
Não há necessidade de esmagar, use
git commit-tree
para criar um commit órfão e siga em frente.Explicar
crie uma única confirmação via
git commit-tree
O que
git commit-tree HEAD^{tree} -m "A new start"
faz é:A expressão
HEAD^{tree}
significa o objeto de árvore correspondente aHEAD
, ou seja, a ponta do seu ramo atual. veja Árvore-objetos e commit-Objects .redefinir a ramificação atual para o novo commit
Em seguida,
git reset
basta redefinir a ramificação atual para o objeto de confirmação recém-criado.Dessa forma, nada no espaço de trabalho é tocado, nem há necessidade de rebase / squash, o que o torna muito rápido. E o tempo necessário é irrelevante para o tamanho do repositório ou a profundidade do histórico.
Variação: novo repositório a partir de um modelo de projeto
Isso é útil para criar o "commit inicial" em um novo projeto usando outro repositório como modelo / arquétipo / semente / esqueleto. Por exemplo:
Isso evita adicionar o repositório de modelo como um controle remoto (
origin
ou não) e recolhe o histórico do repositório de modelo no seu commit inicial.fonte
git push -f
para propagação.git clone
. Se você adicionar--hard
agit reset
e alternarHEAD
comFETCH_HEAD
nogit commit-tree
você pode criar cometer um inicial após buscar o repo modelo. Editei a resposta com uma seção no final demonstrando isso.${1?Please enter a message}
Se tudo o que você deseja fazer é compactar todos os seus commit até o commit raiz, então enquanto
pode funcionar, é impraticável para um grande número de confirmações (por exemplo, centenas de confirmações), porque a operação de rebase provavelmente será executada muito lentamente para gerar a lista de confirmação do editor de rebase interativo, bem como executar a rebase.
Aqui estão duas soluções mais rápidas e eficientes quando você está esmagando um grande número de confirmações:
Solução alternativa nº 1: filiais órfãs
Você pode simplesmente criar um novo ramo órfão na ponta (ou seja, o commit mais recente) do seu ramo atual. Esse ramo órfão forma o commit raiz inicial de uma árvore de histórico de commit totalmente nova e separada, que é efetivamente equivalente a esmagar todos os seus commit:
Documentação:
Solução alternativa nº 2: redefinição suave
Outra solução eficiente é simplesmente usar uma redefinição mista ou suave para o commit raiz
<root>
:Documentação:
fonte
git push origin master --force
.git push --force
Isso criará um commit órfão com a árvore do HEAD e produzirá seu nome (SHA-1) no stdout. Em seguida, basta redefinir sua filial lá.
fonte
git reset $(git commit-tree HEAD^{tree} -m "commit message")
tornaria mais fácil.echo "message" | git commit-tree "HEAD^{tree}"
Eis como acabei fazendo isso, caso funcione para outra pessoa:
Lembre-se de que sempre existe o risco de fazer coisas assim, e nunca é uma má idéia criar uma ramificação salva antes de iniciar.
Comece registrando
Role para confirmar primeiro, copie SHA
Substitua
<#sha#>
com o SHA copiado do logVerifique se tudo está verde, caso contrário, execute
git add -A
Alterar todas as alterações atuais no primeiro commit atual
Agora force o push deste ramo e ele substituirá o que está lá.
fonte
Eu li algo sobre o uso de enxertos, mas nunca investiguei muito.
De qualquer forma, você pode esmagar os últimos 2 commits manualmente com algo como isto:
fonte
A maneira mais fácil é usar o comando 'encanamento'
update-ref
para excluir a ramificação atual.Você não pode usar
git branch -D
, pois possui uma válvula de segurança para impedir a exclusão da ramificação atual.Isso coloca você de volta ao estado 'commit inicial', onde você pode começar com um commit inicial novo.
fonte
Primeiro, junte todos os seus commits em um único commit usando
git rebase --interactive
. Agora você tem dois commits para esmagar. Para fazer isso, leia qualquer um dosfonte
Em uma linha de 6 palavras
fonte
git help checkout
sobre--orphan
git help checkout --orphan
criar um backup
redefinir para confirmação especificada
depois adicione todos os arquivos ao teste
confirmar sem atualizar a mensagem
empurrar novo ramo com squashed compromete-se a repo
fonte
<root>
confirmação para a qual você redefinirá.git commit --amend --no-edit
confirmará todas as alterações na confirmação atual,<root>
sem a necessidade de editar a mensagem de confirmação.Para esmagar usando enxertos
Adicione um arquivo
.git/info/grafts
, coloque lá o hash de confirmação que você deseja que seja seu rootgit log
agora começará a partir desse commitPara torná-lo 'real' executado
git filter-branch
fonte
Esta resposta é aprimorada em algumas das opções acima (vote-as), assumindo que, além de criar o único commit (sem pais sem histórico), você também deseja manter todos os dados de commit desse commit:
É claro que o commit-SHA do novo / único commit será alterado, pois representa um novo (não) histórico, tornando-se um commit sem pai / root.
Isso pode ser feito lendo
git log
e configurando algumas variáveis paragit commit-tree
. Supondo que você deseja criar uma única confirmaçãomaster
em uma nova ramificaçãoone-commit
, mantendo os dados de confirmação acima:fonte
Para fazer isso, você pode redefinir seu repositório git local para a primeira hashtag de confirmação, para que todas as suas alterações após essa confirmação sejam desassistidas, e você pode confirmar com a opção --amend.
E edite o primeiro nome de confirmação, se necessário, e salve o arquivo.
fonte
Para mim, funcionou assim: eu tinha 4 confirmações no total e usei o rebase interativo:
O primeiro commit permanece e eu fiz 3 commit mais recentes.
Caso você esteja preso no editor que aparece a seguir, verá algo como:
Você precisa primeiro confirmar e esmagar os outros. O que você deve ter é:
Para isso, use a tecla INSERT para alterar o modo 'inserir' e 'editar'.
Para salvar e sair do editor, use
:wq
. Se o cursor estiver entre essas linhas de confirmação ou em outro lugar, pressione ESC e tente novamente.Como resultado, tive dois commits: o primeiro que permaneceu e o segundo com a mensagem "Esta é uma combinação de 3 commits".
Verifique os detalhes aqui: https://makandracards.com/makandra/527-squash-several-git-commits-into-a-single-commit
fonte
Eu costumo fazer assim:
Verifique se tudo está confirmado e anote o último ID de confirmação, caso algo dê errado, ou crie uma ramificação separada como backup.
Execute
git reset --soft `git rev-list --max-parents=0 --abbrev-commit HEAD`
para redefinir sua cabeça para o primeiro commit, mas deixe seu índice inalterado. Todas as alterações desde o primeiro commit agora parecerão prontas para serem confirmadas.Execute
git commit --amend -m "initial commit"
para alterar seu commit no primeiro commit e altere a mensagem de commit ou, se desejar manter a mensagem de commit existente, você poderá executargit commit --amend --no-edit
Corra
git push -f
para forçar a pressionar suas alteraçõesfonte