Precisa redefinir a ramificação git para a versão de origem

440

Eu estava acidentalmente trabalhando em um ramo que não deveria estar por um tempo, então eu o ramifiquei, dando o nome apropriado. Agora, quero sobrescrever o ramo que não deveria estar na versão de origem (github). Existe uma maneira fácil de fazer isso? Tentei excluir a ramificação e, em seguida, redefinir a ramificação de rastreamento, mas isso me dá a versão em que eu estava trabalhando novamente.

Brad Herman
fonte
Com Git 2,23 (agosto de 2019): git switch -C mybranch origin/mybranch. Veja minha resposta editada abaixo
VonC 30/08/19

Respostas:

814

Se você ainda não enviou a origem, é possível redefinir sua ramificação para a ramificação upstream com:

git checkout mybranch
git reset --hard origin/mybranch

(Certifique-se de referenciar seu último commit em um ramo separado, como você mencionou na sua pergunta)

Observe que logo após a redefinição, mybranch@{1}refere-se à confirmação antiga, antes da redefinição.

Mas se você já fez o push, consulte " Criar ramificação git e reverta o original para o estado upstream " para outras opções.


Com Git 2,23 (agosto de 2019) , que seria um comando: git switch.
Nomeadamente:git switch -C mybranch origin/mybranch

Exemplo

C:\Users\vonc\git\git>git switch -C master origin/master
Reset branch 'master'
Branch 'master' set up to track remote branch 'master' from 'origin'.
Your branch is up to date with 'origin/master'.

Isso restaura o índice e a árvore de trabalho, como git reset --hardfaria.


Como comentado por Brad Herman , um reset --hardiria remover qualquer novo arquivo ou redefinir arquivo modificado para CABEÇA .

Na verdade, para ter certeza de começar de uma "lista limpa", um git clean -f -dapós a redefinição garantiria uma árvore de trabalho exatamente idêntica à ramificação para a qual você acabou de redefinir.


Esta postagem do blog sugere esses aliases ( masterapenas para ramificação, mas você pode adaptá-los / estendê-los):

[alias]
   resetorigin = !git fetch origin && git reset --hard origin/master && git clean -f -d
   resetupstream = !git fetch upstream && git reset --hard upstream/master && git clean -f -d

Então você pode digitar:

git resetupstream

ou

git resetorigin
VonC
fonte
26
Isto irá apagar unstaged / ESCALONADOS mudanças (do --hard)
Peter Ehrlich
5
Eu usei o git reset --hard origin/mybranchcomando várias vezes quando não me importei com nenhuma alteração local e só queria uma cópia limpa que correspondesse à origem. No entanto, hoje, isso não funcionou - eu ainda tinha um punhado de arquivos novos e sem etapas, e o git continuava me prometendo que estava no HEAD. A nota sobre git clean -f -disso corrigiu isso, limpando todos os novos arquivos que eu não queria.
Matthew Clark
@MatthewClark Isso é esperado: veja o comentário em stackoverflow.com/q/4327708/6309
VonC
1
Ótimo! Também muitas vezes eu usei git reset --hard HEADpara reverter para a submissão anterior, ignorando quaisquer alterações
daronwolff
Isso também é possível com o sourctree?
Lonzak
20

Supondo que foi isso que aconteceu:

# on branch master
vi buggy.py                 # you edit file
git add buggy.py            # stage file
git commit -m "Fix the bug" # commit
vi tests.py                 # edit another file but do not commit yet

Então você percebe que faz alterações no ramo errado.

git checkout -b mybranch    # you create the correct branch and switch to it

Mas masterainda aponta para o seu commit. Você quer que aponte para onde apontou antes.

Solução

A maneira mais fácil é:

git branch --force master origin/master

Outra maneira é:

git checkout master
git reset --soft origin/master
git checkout mybranch

Observe que o uso reset --hardfará com que suas alterações não confirmadas sejam perdidas ( tests.pyno meu exemplo).

user28667
fonte
Isso parece mais seguro do que na minha resposta;) +1
VonC
8

Eu tenho um repositório particular em um servidor e regularmente o reencaminhao / force-push para ele, o que torna necessário redefinir a filial local no meu outro computador com frequência. Por isso, criei o seguinte apelido "catchup", que permite fazer isso para o ramo atual. Diferente da outra resposta, não há nome de filial codificado nesse alias.

Segure firme.

[alias]
  catchup = "!f(){ echo -n \"reset \\033[0;33m$(git symbolic-ref -q --short HEAD)\\033[0m to \\033[0;33m$(git for-each-ref --format='%(upstream:short)' $(git symbolic-ref -q HEAD))\\033[0m? (Y/n) \"; read -r ans; if [ \"$ans\" = \"y\" -o \"$ans\" = \"Y\" -o -z \"$ans\" ]; then git reset --hard $(git for-each-ref --format='%(upstream:short)' $(git symbolic-ref -q HEAD)); else echo \"catchup aborted\"; fi }; f"

Formatado corretamente (não funcionará com as novas linhas em .gitconfig), fica assim:

"
!f(){
  echo -n \"reset \\033[0;33m$(git symbolic-ref -q --short HEAD)\\033[0m to \\033[0;33m$(git for-each-ref --format='%(upstream:short)' $(git symbolic-ref -q HEAD))\\033[0m? (Y/n) \";
  read -r ans;
  if [ \"$ans\" = \"y\" -o \"$ans\" = \"Y\" -o -z \"$ans\" ]; then
    git reset --hard $(git for-each-ref --format='%(upstream:short)' $(git symbolic-ref -q HEAD));
  else
    echo \"catchup aborted\";
  fi
}; f
"
  • O \\033[0;33me \\033[0mé para enfatizar a ramificação atual e a montante com cores.
  • $(git symbolic-ref -q --short HEAD) é o nome do ramo atual
  • $(git for-each-ref --format='%(upstream:short)' $(git symbolic-ref -q HEAD)) é o montante da ramificação atual.

Como a redefinição é uma chamada potencialmente perigosa (especialmente com a opção --hard, você perderá as alterações não confirmadas), ela primeiro informa o que está prestes a fazer. Por exemplo, se você estiver no dev-container da filial com controle remoto chamado qcpp / dev-container e entrar git catchup, será solicitado:

redefinir dev-container para qcpp / dev-container? (S / n)

Se você digitar y ou apenas pressionar return, ele fará a redefinição. Se você inserir mais alguma coisa, a redefinição não será realizada.

Se você deseja ser super seguro e evitar programaticamente a perda de alterações não-encenadas / não confirmadas, pode usar o apelido acima ainda mais com as verificações de acordo com o índice diff .

A palavra obrigatória de aviso: se você estiver trabalhando em um repositório público em que outras pessoas se basearam no trabalho, e você precisar desse alias, estará fazendo algo errado ™ .

DerManu
fonte
1

Eu tentei isso e ele não redefiniu minha ramificação atual para o meu github remoto mais recente. Pesquisei no Google e encontrei https://itsyndicate.org/blog/how-to-use-git-force-pull-properly/

o que sugeriu

git fetch origin master
git reset --hard origin/master

Eu queria redefinir minha ramificação v8, então fiz

git fetch origin v8
git reset --hard origin/v8

e funcionou

SimpleSi
fonte
Bem, é bom que você mencione buscar. Eu fiz isso uma vez, sem e tudo reposto a 2 anos :)
Adam