forçar - git pull overwrite local repo




Como eu forço o “git pull” a sobrescrever arquivos locais? (20)

Como faço para 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:

error: Untracked working tree file 'public/images/icon.gif' would be overwritten by merge

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.


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

Se você tiver algum arquivo que não seja rastreado pelo Git (por exemplo, conteúdo do usuário carregado), 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 transfere o mais recente do remoto sem tentar mesclar ou rebase nada.

Então o git reset do git reset reseta 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 commits locais atuais criando uma ramificação do 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

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 recém-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 no log do Git. Não há necessidade de se preocupar com pull / merge manual.

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


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.


Apesar da pergunta original, as principais respostas 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 do crizCraig.

A versão a seguir confirma suas alterações locais em uma ramificação temporária ( tmp ), faz o check-out da ramificação original (que, suponho, é a master ) e mescla as atualizações. Você poderia fazer isso com o 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 que o outro repositório é o origin master .


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.


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ê for redefinir para a origem / ramificação principal, certo?


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.


Eu acredito que há duas causas possíveis de conflito, que devem ser resolvidas separadamente, e tanto quanto eu posso dizer nenhuma das respostas acima lida com ambos:

  • Arquivos locais que são untracked 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 em que você esteja trabalhando, e execute uma git fetch origin first)


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í!


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 : esse script é muito poderoso, então você pode perder suas alterações.


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


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

Eu resolvi isso por:

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

Agora funciona.


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 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.


Parece que a maioria das respostas aqui está focada no ramo 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 da RNA e da resposta de torek a uma pergunta semelhante , 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 forcepull ( 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!


Primeiro de tudo, tente o caminho padrão:

git reset HEAD --hard # Remove all not committed changes

Se acima não vai ajudar e você não se preocupa com seus arquivos / diretórios não rastreados (faça o backup primeiro 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

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

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

  1. Regras personalizadas no .gitattributes file

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

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

  2. Incompatibilidade do sistema de arquivos

    Quando você está usando 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 quão --hard você tente, git sempre detecta algumas "mudanças".


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

git reset origin/master

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


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

AVISO: o git clean apaga 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: o git clean apaga todos os seus arquivos / diretórios não rastreados e não pode ser desfeito.

Considere usar o --dry-run -n ( --dry-run ) primeiro. Isso mostrará o que será excluído sem realmente 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
...

Requisitos:

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

Solução:

  1. Armazenar as alterações locais.
  2. Buscar com uma limpeza de arquivos e diretórios ignorando .gitignore e hard reset para origem .

    git stash --include-untracked
    git fetch --all
    git clean -fdx
    git reset --hard origin/master
    




git-fetch