ti-enxame.com

Como forçar o "git pull" a sobrescrever arquivos locais?

Como forçar uma substituição de arquivos locais em um git pull?

O cenário é o seguinte:

  • Um membro da equipe está modificando os modelos de um site em que estamos trabalhando
  • Eles estão adicionando algumas imagens ao diretório de imagens (mas esquecem de adicioná-las sob controle de origem)
  • Eles estão enviando as imagens pelo correio, depois para mim
  • Estou adicionando as imagens sob o controle de origem e empurrando-as para o GitHub juntamente com outras alterações
  • Eles não podem receber atualizações do GitHub porque o Git não quer sobrescrever seus arquivos.

Este é o erro que estou recebendo:

erro: arquivo de árvore de trabalho não rastreado 'public/images/icon.gif' seria sobrescrito por mesclagem

Como faço para forçar o Git a sobrescrevê-los? A pessoa é um designer - geralmente eu resolvo todos os conflitos manualmente, então o servidor tem a versão mais recente que eles precisam apenas atualizar em seu computador.

5771
Jakub Troszok

Importante: Se você tiver alguma alteração local, ela será perdida. Com ou sem a opção --hard, qualquer confirmação local que não tenha sido enviada será perdida.[*]

Se você tiver arquivos que são não rastreados pelo Git (por exemplo, conteúdo de usuário enviado), esses arquivos não serão afetados.


Eu acho que este é o caminho certo:

git fetch --all

Então você tem duas opções:

git reset --hard Origin/master

OU Se você estiver em algum outro ramo:

git reset --hard Origin/<branch_name>

Explicação:

git fetch baixa o mais recente do remoto sem tentar mesclar ou rebase nada.

Então o git reset redefine o branch master para o que você acabou de buscar. A opção --hard altera todos os arquivos em sua árvore de trabalho para corresponder aos arquivos em Origin/master


Manter commits locais atuais

[*]: Vale a pena notar que é possível manter os commits locais atuais criando uma ramificação de master antes de redefinir:

git checkout master
git branch new-branch-to-save-current-commits
git fetch --all
git reset --hard Origin/master

Depois disso, todos os commits antigos serão mantidos em new-branch-to-save-current-commits

Mudanças não confirmadas

Mudanças não comprometidas, no entanto (mesmo encenadas), serão perdidas. Certifique-se de esconder e cometer qualquer coisa que você precisa. Para isso, você pode executar o seguinte:

git stash

E, em seguida, para reaplicar essas alterações não confirmadas:

git stash pop
8139
RNA

Tente isto:

git reset --hard HEAD
git pull

Deve fazer o que quiser.

808
Travis Reeder

AVISO: git clean exclui todos os seus arquivos/diretórios não rastreados e não pode ser desfeito.


Às vezes, apenas clean -f não ajuda. Caso você tenha DIRETÓRIOS não acompanhados, a opção -d também é necessária:

# WARNING: this can't be undone!

git reset --hard HEAD
git clean -f -d
git pull

AVISO: git clean exclui todos os seus arquivos/diretórios não rastreados e não pode ser desfeito.

Considere usar o sinalizador -n (--dry-run) primeiro. Isso mostrará o que será excluído sem excluir nada:

git clean -n -f -d

Exemplo de saída:

Would remove untracked-file-1.txt
Would remove untracked-file-2.txt
Would remove untracked/folder
...
409
David Avsajanishvili

Como Hedgehog, acho que as respostas são terríveis. Mas embora a resposta de Hedgehog possa ser melhor, não acho que seja tão elegante quanto poderia ser. A maneira que eu encontrei para fazer isso é usando "buscar" e "mesclar" com uma estratégia definida. O que deve fazer com que suas alterações locais sejam preservadas, desde que não sejam um dos arquivos com os quais você está tentando forçar uma sobrescrita. 

Primeiro faça um commit de suas alterações

 git add *
 git commit -a -m "local file server commit message"

Em seguida, busque as alterações e sobrescreva se houver um conflito

 git fetch Origin master
 git merge -s recursive -X theirs Origin/master

"-X" é um nome de opção e "deles" é o valor para essa opção. Você está escolhendo usar "suas" alterações, em vez de "suas" alterações, se houver um conflito.

347
Richard Kersey

Em vez de fazer:

git fetch --all
git reset --hard Origin/master

Eu aconselharia fazer o seguinte:

git fetch Origin master
git reset --hard Origin/master

Não há necessidade de buscar todos os controles remotos e filiais se você vai redefinir para a origem/master branch certo?

251
Johanneke

Parece que a melhor maneira é fazer primeiro:

git clean

Para excluir todos os arquivos não acompanhados e continuar com o git pull usual ...

125
Jakub Troszok

Aviso, isso irá excluir permanentemente seus arquivos se você tiver qualquer diretório/* entradas no seu arquivo gitignore.

Algumas respostas parecem ser terríveis. Terrível no sentido do que aconteceu com @Lauri seguindo a sugestão de David Avsajanishvili.

Em vez disso (git> v1.7.6):

git stash --include-untracked
git pull

Mais tarde, você poderá limpar o histórico do stash.

Manualmente, um por um:

$ git stash list
[email protected]{0}: WIP on <branch>: ...
[email protected]{1}: WIP on <branch>: ...

$ git stash drop [email protected]{0}
$ git stash drop [email protected]{1}

Brutalmente, tudo de uma vez:

$ git stash clear

Claro, se você quiser voltar para o que você escondeu:

$ git stash list
...
$ git stash apply [email protected]{5}
102
Hedgehog

Você pode achar esse comando útil para descartar alterações locais:

git checkout <your-branch> -f

E, em seguida, faça uma limpeza (remove os arquivos não rastreados da árvore de trabalho):

git clean -f

Se você deseja remover diretórios não acompanhados além dos arquivos não acompanhados:

git clean -fd
88
Vishal

Em vez de se fundir com git pull, tente isto: 

git fetch --all

seguido por:

git reset --hard Origin/master.

82
Lloyd Moore

A única coisa que funcionou para mim foi:

git reset --hard HEAD~5

Isso levará de volta cinco commits e depois com

git pull

Eu achei que, ao olhar para cima como desfazer uma mesclagem Git .

55
Chris BIllante

O problema com todas essas soluções é que elas são muito complexas, ou, um problema ainda maior, é que elas removem todos os arquivos não rastreados do servidor da Web, o que não queremos, pois sempre há arquivos de configuração necessários que estão ativos. o servidor e não no repositório Git.

Aqui está a solução mais limpa que estamos usando:

# Fetch the newest code
git fetch

# Delete all files which are being added, so there
# are no conflicts with untracked files
for file in `git diff HEAD..Origin/master --name-status | awk '/^A/ {print $2}'`
do
    rm -f -- "$file"
done

# Checkout all files which were locally modified
for file in `git diff --name-status | awk '/^[CDMRTUX]/ {print $2}'`
do
    git checkout -- "$file"
done

# Finally pull all the changes
# (you could merge as well e.g. 'merge Origin/master')
git pull
  • O primeiro comando busca os dados mais recentes.

  • O segundo comando verifica se há arquivos que estão sendo adicionados ao repositório e exclui os arquivos não rastreados do repositório local, o que causaria conflitos.

  • O terceiro comando verifica todos os arquivos que foram modificados localmente.

  • Finalmente, fazemos um pull para atualizar para a versão mais recente, mas desta vez sem nenhum conflito, já que os arquivos não rastreados que estão no repositório não existem mais e todos os arquivos modificados localmente já são os mesmos que no repositório.

51
Strahinja Kustudic

Eu tive o mesmo problema. Ninguém me deu essa solução, mas funcionou para mim.

Eu resolvi isso por:

  1. Apague todos os arquivos. Deixe apenas o diretório .git.
  2. git reset --hard HEAD
  3. git pull
  4. git Push

Agora funciona.

39
John John Pichler

Primeiro de tudo, tente o caminho padrão:

git reset HEAD --hard # To remove all not committed changes!
git clean -fd         # To remove all untracked (non-git) files and folders!

Aviso : Os comandos acima podem resultar em perda de dados/arquivos somente se você não os tiver comprometido! Se você não tiver certeza, faça o backup primeiro de toda a sua pasta de repositório.

Então puxe-o novamente.

Se acima não vai ajudar e você não se preocupa com seus arquivos/diretórios não rastreados (faça o backup em primeiro lugar apenas no caso), tente os seguintes passos simples:

cd your_git_repo  # where 'your_git_repo' is your git repository folder
rm -rfv *         # WARNING: only run inside your git repository!
git pull          # pull the sources again

Isso irá REMOVER todos os arquivos git (excise .git/ dir, onde você tem todos os commits) e puxe-o novamente.


Por que git reset HEAD --hard poderia falhar em alguns casos?

  1. Regras personalizadas em .gitattributes file

    Ter a regra eol=lf em .gitattributes poderia fazer com que o git modificasse algumas alterações no arquivo, convertendo as terminações de linha CRLF em LF em alguns arquivos de texto.

    Se esse for o caso, você deve cometer essas alterações de CRLF/LF (revisando-as em git status) ou tente: git config core.autcrlf false para ignorá-las temporariamente.

  2. Incompatibilidade do sistema de arquivos

    Quando você usa um sistema de arquivos que não suporta atributos de permissão. No exemplo, você tem dois repositórios, um no Linux/Mac (ext3/hfs+) e outro no sistema de arquivos baseado em FAT32/NTFS.

    Como você percebe, existem dois tipos diferentes de sistemas de arquivos, então o que não suporta permissões Unix basicamente não pode redefinir permissões de arquivos no sistema que não suportam esse tipo de permissão, então não importa o quanto --hard você tente, git sempre detecta algumas "mudanças".

34
kenorb

Bônus:

Ao falar de pull/fetch/merge nas respostas anteriores, gostaria de compartilhar um truque interessante e produtivo,

git pull --rebase

Este comando acima é o comando mais útil na minha vida Git que economizou muito tempo.

Antes de enviar seu novo commit para o servidor, tente este comando e ele sincronizará automaticamente as mudanças mais recentes do servidor (com uma busca + mesclagem) e colocará seu commit no topo do log do Git. Não há necessidade de se preocupar com pull/merge manual.

Encontre detalhes em O que "git pull --rebase" do?.

33
Sazzad Hissain Khan

Eu tive um problema parecido. Eu tive que fazer isso:

git reset --hard HEAD
git clean -f
git pull
27
Ryan

Eu resumi outras respostas. Você pode executar git pull sem erros:

git fetch --all
git reset --hard Origin/master
git reset --hard HEAD
git clean -f -d
git pull

Aviso : Este script é muito poderoso, então você pode perder suas alterações.

27
Robert Moon

Com base em minhas próprias experiências semelhantes, a solução oferecida por Strahinja Kustudic acima é de longe a melhor. Como outros apontaram, simplesmente fazer uma reinicialização forçada removerá os arquivos all untracked, que podem incluir muitas coisas que você não deseja remover, como arquivos de configuração. O que é mais seguro é remover apenas os arquivos que estão prestes a serem adicionados e, provavelmente, você também deseja obter todos os arquivos modificados localmente que serão atualizados.

Com isso em mente, atualizei o script de Kustudic para fazer exatamente isso. Eu também consertei um erro de digitação (um ausente 'no original).

#/bin/sh

# Fetch the newest code
git fetch

# Delete all files which are being added,
# so there are no conflicts with untracked files
for file in `git diff HEAD..Origin/master --name-status | awk '/^A/ {print $2}'`
do
    echo "Deleting untracked file $file..."
    rm -vf "$file"
done

# Checkout all files which have been locally modified
for file in `git diff HEAD..Origin/master --name-status | awk '/^M/ {print $2}'`
do
    echo "Checking out modified file $file..."
    git checkout $file
done

# Finally merge all the changes (you could use merge here as well)
git pull
26
Rolf Kaiser

Acredito que há duas causas possíveis de conflito, que devem ser resolvidas separadamente, e, até onde posso dizer, nenhuma das respostas acima trata de ambas:

  • Os arquivos locais que não são acompanhados precisam ser excluídos, manualmente (mais seguro) ou como sugerido em outras respostas, por git clean -f -d

  • As confirmações locais que não estão no ramo remoto também precisam ser excluídas. IMO A maneira mais fácil de conseguir isso é com: git reset --hard Origin/master (substitua 'master' por qualquer branch que você esteja trabalhando, e execute um git fetch Origin primeiro)

23
tiho

Uma maneira mais fácil seria:

git checkout --theirs /path/to/file.extension
git pull Origin master

Isto irá sobrescrever seu arquivo local com o arquivo no git

20
maximus 69

Parece que a maioria das respostas aqui está focada na ramificação master; no entanto, há momentos em que estou trabalhando no mesmo branch de recursos em dois lugares diferentes e quero que um rebase em um se reflita no outro sem muito salto através de aros.

Com base em uma combinação da resposta do RNA e a resposta de torek a uma questão semelhante , eu descobri o que funciona esplendidamente:

git fetch
git reset --hard @{u}

Execute isso de uma ramificação e só redefinirá sua ramificação local para a versão upstream.

Isso pode ser bem colocado em um alias git (git forcepull) também:

git config alias.forcepull "!git fetch ; git reset --hard @{u}"

Ou, no seu arquivo .gitconfig:

[alias]
  forcepull = "!git fetch ; git reset --hard @{u}"

Apreciar!

20
JacobEvelyn

Eu tive o mesmo problema e, por algum motivo, até mesmo um git clean -f -d não faria isso. Aqui está o porquê: Por alguma razão, se seu arquivo é ignorado pelo Git (através de uma entrada .gitignore, eu suponho), ele ainda se preocupa em sobrescrevê-lo com um posterior pull , mas um clean não será remova-o, a menos que você adicione -x.

19
Tierlieb

Eu apenas resolvi isso sozinho por:

git checkout -b tmp # "tmp" or pick a better name for your local changes branch
git add -A
git commit -m 'tmp'
git pull
git checkout master # Or whatever branch you were on originally
git pull
git diff tmp

onde o último comando fornece uma lista de quais foram as alterações locais. Continue modificando a ramificação "tmp" até que seja aceitável e, em seguida, mescle de volta no master com: 

git checkout master && git merge tmp

Para a próxima vez, você provavelmente pode lidar com isso de uma maneira mais limpa, pesquisando "git stash branch", embora stash possa causar problemas nas primeiras tentativas, então faça primeiro experimentos em um projeto não crítico ...

18
Simon B.

Eu tenho uma situação estranha que nem git clean ou git reset funciona. Eu tenho que remover o arquivo conflitante de git index usando o seguinte script em todos os arquivos não acompanhados:

git rm [file]

Então eu sou capaz de puxar bem.

17
Chen Zhang

Eu conheço um método muito mais fácil e menos doloroso:

$ git branch -m [branch_to_force_pull] tmp
$ git fetch
$ git checkout [branch_to_force_pull]
$ git branch -D tmp

É isso aí!

16
ddmytrenko

Esses quatro comandos funcionam para mim.

git reset --hard HEAD
git checkout Origin/master
git branch -D master
git checkout -b master

Para verificar/puxar depois de executar esses comandos

git pull Origin master

Eu tentei muito, mas finalmente consegui sucesso com esses comandos.

13
vishesh chandra

Apenas faça

git fetch Origin branchname
git checkout -f Origin/branchname // This will overwrite ONLY new included files
git checkout branchname
git merge Origin/branchname

Assim, você evita todos os efeitos colaterais indesejados, como excluir arquivos ou diretórios que deseja manter, etc.

12
user2696128

Apesar da pergunta original, as respostas principais podem causar problemas para pessoas que têm um problema semelhante, mas não querem perder seus arquivos locais. Por exemplo, veja os comentários do Al-Punk e CrizCraig. 

A versão a seguir confirma suas alterações locais em uma ramificação temporária (tmp), faz check-out da ramificação original (que suponho que é master) e mescla as atualizações. Você poderia fazer isso com stash, mas descobri que geralmente é mais fácil simplesmente usar a abordagem branch/merge.

git checkout -b tmp
git add *; git commit -am "my temporary files"
git checkout master

git fetch Origin master
git merge -s recursive -X theirs Origin master

onde assumimos o outro repositório é Origin master.

12
Snowcrash

Redefinir o índice e a cabeça para Origin/master, mas não redefina a árvore de trabalho:

git reset Origin/master
11
user811773

Requisitos:

  1. Acompanhe as mudanças locais para que ninguém nunca as perca.
  2. Faça o repositório local corresponder ao repositório de origem remoto.

Solução:

  1. Stash as alterações locais.
  2. Busca com um limpo de arquivos e diretórios ignorar .gitignore e hard reset to Origem .

    git stash --include-untracked
    git fetch --all
    git clean -fdx
    git reset --hard Origin/master
    
9
vezenkov

Eu li todas as respostas, mas eu estava procurando por um único comando para fazer isso. Aqui está o que eu fiz. Adicionado um alias git para .gitconfig

[alias]
      fp = "!f(){ git fetch ${1} ${2} && git reset --hard ${1}/${2};};f"

Execute seu comando como 

git fp Origin master

equivalente a

git fetch Origin master
git reset --hard Origin/master
9
Venkat Kotra

Não use git reset --hard. Isso apagará as alterações que podem ser completamente indesejáveis. Em vez de:

git pull
git reset Origin/master
git checkout <file1> <file2> ...

É claro que você pode usar git fetch em vez de git pull já que claramente não vai se fundir, mas se você normalmente puxa, faz sentido continuar puxando para cá.

Então, o que acontece aqui é que git pull atualiza sua referência de origem/mestre ; git reset atualiza sua referência de ramificação local on para ser a mesma que Origem/mestre sem atualizar nenhum arquivo, portanto, seu estado de check-out não é alterado; então git checkout reverte os arquivos para o estado do seu índice de ramificação local conforme necessário. Nos casos em que exatamente o mesmo arquivo foi adicionado ao vivo e no mestre de envio, o índice já corresponde ao arquivo após a redefinição, portanto, no caso comum, você não precisa executar git checkout.

Se a ramificação upstream também contiver commits que você deseja aplicar automaticamente, será possível seguir uma variação sutil no processo:

git pull
git merge <commit before problem commit>
git reset <problem commit>
git checkout <file1> <file2> ...
git pull
8
Jim Driscoll

Essa é a melhor prática para reverter alterações:

  • git commit Confirme suas alterações em etapas para que elas sejam salvas no reflog (veja abaixo)
  • git fetch Busque as últimas mudanças no upstream
  • git reset --hard Origin/master Hard reset para o branch master de origem

O reflogregistros de ramificações e outras referências sendo atualizadas no repositório local. Ou simplesmente coloque - o reflog é o histórico de suas alterações.

Então, é sempre uma ótima prática para se comprometer. As confirmações são anexadas ao reflog, o que garante que você sempre terá uma maneira de recuperar o código excluído.

7
Jordan Georgiev

Eu usei este comando para me livrar dos arquivos locais, impedindo-me de fazer um pull/merge. Mas tenha cuidado! Execute git merge … primeiro para ver se há apenas os arquivos que você realmente deseja remover.

git merge Origin/master 2>&1 >/dev/null | grep ^[[:space:]] | sed s/^[[:space:]]//g | xargs -L1 rm
  • git merge lista entre outras coisas todos esses arquivos. Eles são prefixados por algum espaço em branco.
  • 2>&1 >/dev/null redireciona a saída de erro para a saída padrão, de modo que ela é escolhida por grep.
  • grep ^[[:space:]] filtra apenas as linhas com nomes de arquivos.
  • sed s/^[[:space:]]//g apara o espaço em branco desde o início.
  • xargs -L1 rm chama rm em cada um desses arquivos, excluindo-os.

Manuseie com cuidado: Independentemente das saídas git merge, a rm será chamada para every line começando com um espaço em branco.

5
Glutexo

Eu estava tentando usar o ramo Material2 no Angular2-Webpack-Starter e tinha um monte de tempo. Esta foi a única maneira que eu poderia baixar e usar esse ramo.

git clone --depth 1 https://github.com/angularclass/angular2-webpack-starter.git

cd angular2-webpack-starter/

git checkout -b material2

Abra a pasta do projeto e exclua todos os arquivos e pastas não ocultos. Deixe todos os escondidos.

git add .

git commit -m "pokemon go"

git reset --hard

git pull Origin material2

(Quando o editor aparecer, pressione ': wq' e pressione Enter)

Agora você está pronto.

5
Helzgate

No Windows, faça este comando único:

git fetch --all & git reset --hard Origin/master
3
Luca C.

Você pode ignorar esse arquivo com um arquivo na pasta base do projeto:

.gitignore

public/images/*

Em seguida, retire as alterações e remova essa linha do seu arquivo gitignore.

3
Daniel Gaytán

git fetch --all && git reset --hard Origin/master && git pull

1
Suge

1: redefinir para um commit anterior

git reset --hard HEAD

2: Excluir arquivos não rastreados

git clean -f

3: Puxe os commits

git pull

Fontes:

0
abhijithvijayan

se você quiser redefinir para o ramo de rastreamento remoto de uma maneira genérica, use:

git fetch
git reset --keep Origin/$(git rev-parse --abbrev-ref HEAD)

se você quiser redefinir suas alterações locais também:

git fetch
git reset --hard Origin/$(git rev-parse --abbrev-ref HEAD)
0
warch