Git pull após atualização forçada


333

Acabei de esmagar alguns commits git rebasee fiz um git push --force(que é mau, eu sei).

Agora os outros engenheiros de software têm uma história diferente e, quando fazem isso git pull, o Git se fundirá. Existe uma maneira de corrigir isso, exceto fazendo um rm my-repo; git clone git@example.org:my-repo.git?

Eu preciso de algo como o oposto de git push --force, mas git pull --forcenão deu os resultados pretendidos.


16
eles podem excluir seu ramo e re criá-lo também, sem ter que apagar toda a repo:git checkout master && git branch -D test && git checkout -b test origin/test
Florian Klein


Respostas:


511

Para receber os novos commits

git fetch

Redefinir

Você pode redefinir a confirmação para uma filial local usando git reset.

Para alterar a confirmação de uma ramificação local:

git reset origin/master --hard

Tenha cuidado, porém, como a documentação coloca:

Redefine o índice e a árvore de trabalho. Quaisquer alterações nos arquivos rastreados na árvore de trabalho desde que <commit> sejam descartadas.

Se você deseja realmente manter as alterações localmente, faça uma --softredefinição. O que atualizará o histórico de consolidação da ramificação, mas não alterará nenhum arquivo no diretório ativo (e você poderá confirmá-los).

Rebase

Você pode reproduzir seus commits locais sobre qualquer outro commit / branch usando git rebase:

git rebase -i origin/master

Isso invocará o rebase no modo interativo, onde você poderá escolher como aplicar cada confirmação individual que não está no histórico que você está refazendo.

Se as confirmações que você removeu (com git push -f) já foram inseridas no histórico local, elas serão listadas como confirmações que serão reaplicadas - elas precisarão ser excluídas como parte da reestruturação ou serão simplesmente incluídas novamente na história para o ramo - e reaparecer no histórico remoto no próximo impulso.

Use a ajuda git command --helppara obter mais detalhes e exemplos de qualquer um dos comandos acima (ou outros).


2
@iblue escolha entre perder todas as alterações, remover o histórico de consolidação, mas manter as alterações no arquivo ou tentar aplicar cada consolidação sobre o novo cabeçalho. A opção mais simples é provavelmente uma reinicialização suave.
AD7six

1
@iblue Quando seu colega usa `git reabse origin / master 'e, enquanto isso, eles já tinham algum commit antes, o git escreverá seu commit na parte de trás do commit.
Tim

6
Pode valer a pena mencionar que, se isto é para um ramo diferente:git reset origin/otherbranch --hard
bmaupin

Então, para esclarecer, este é tanto : Opção 1: reset --hard, ou Opção 2: reset --soft+ rebase, certo?
PlasmaBinturong

2
O @PlasmaBinturong No. git reset --soft origin/masteralterará o histórico de confirmação para corresponder as diferenças remotas e de estágio com o remoto que será confirmado . Não haveria necessidade de se refazer nesse cenário (e você seria impedido de fazê-lo por causa das alterações não confirmadas) porque não há diferença no histórico de confirmação. As duas opções são redefinidas ou reformuladas - não uma combinação de ambas. Faça uma pergunta se seu cenário for diferente do que eu respondi aqui.
AD7six

16

Isso não consertará ramificações que já possuem o código que você não deseja (veja abaixo como fazer isso), mas se elas tivessem puxado alguma ramificação e agora desejam que ela esteja limpa (e não "à frente") origem / alguma ramificação), então você simplesmente:

git checkout some-branch   # where some-branch can be replaced by any other branch
git branch base-branch -D  # where base-branch is the one with the squashed commits
git checkout -b base-branch origin/base-branch  # recreating branch with correct commits

Nota: Você pode combinar tudo isso colocando && entre eles

Nota2: Florian mencionou isso em um comentário, mas quem lê comentários ao procurar respostas?

Nota 3: Se você tiver galhos contaminados, poderá criar novos com base no novo "galho burro" e apenas a escolha de cereja será confirmada.

Ex:

git checkout feature-old  # some branch with the extra commits
git log                   # gives commits (write down the id of the ones you want)
git checkout base-branch  # after you have already cleaned your local copy of it as above
git checkout -b feature-new # make a new branch for your feature
git cherry-pick asdfasd   # where asdfasd is one of the commit ids you want
# repeat previous step for each commit id
git branch feature-old -D # delete the old branch

Agora, o feature-new é o seu ramo sem o comprometimento extra (possivelmente ruim)!


Isto é o que eu realmente queria. Alguém reformulou o ramo principal (porque Deus sabe por que motivo), mas eu não tive alterações locais que quisesse cometer ou algo assim. Então, tudo o que eu precisava fazer era excluir minha filial principal local (que parecia muito estranha) e fazer um checkout novamente. Obrigado!
Danilo Carvalho

@ peter-Mortensen edições devem estar de acordo com substancial para stackoverflow.com/help/editing
Tom Prats

para a última etapa, você também pode usar git checkout -b base-branch origin/base-branchcomgit checkout --track origin/base-branch
bluesmonk

2

Puxe com rebase

Uma atração regular é buscar + mesclar, mas o que você deseja é buscar + rebater. Esta é uma opção com o pullcomando:

git pull --rebase

Eu uso isso o tempo todo para obter o código mais recente do master no meu ramo de recursos sem ter todos esses commits de mesclagem no histórico.
herman
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.