Como é que obrigo o "git pull" a sobrepor os ficheiros locais?
git pull
?
o cenário é o seguinte:
- um membro da equipa está a modificar os modelos de um site em que estamos a trabalhar
- estão a adicionar algumas imagens ao directório de imagens (mas esquece-se de as Adicionar sob controlo de origem) Estão a enviar as imagens por correio, mais tarde, para mim.
- estou a adicionar as imagens sob o controlo da fonte e a empurrá-las para o GitHub juntamente com outras alterações
- Eles não é possível obter actualizações do GitHub porque o Git não quer sobrepor os seus ficheiros.
Este é o erro que estou a obter:
error: Untracked working tree file 'public/images/icon.gif' would be overwritten by merge
Como é que obrigo o Git a sobrepô-los? A pessoa é um designer-geralmente eu resolvo todos os conflitos à mão, de modo que o servidor tem a versão mais recente que eles só precisam atualizar em seu computador.
30 answers
Importante: se tiver alterações locais, estas serão perdidas. Com ou sem opção --hard
, todos os commits locais que não tenham sido empurrados serão perdidos.[*]
Se tiver quaisquer ficheiros que não sejamrastreados pelo Git (por exemplo, conteúdo carregado do utilizador), estes ficheiros não serão afectados.
Acho que este é o caminho certo.
git fetch --all
Então, tens duas opções:
git reset --hard origin/master
Ou se estiver a tomar outro ramo:
git reset --hard origin/<branch_name>
Explicação:
git fetch
descarrega as últimas informações do remote sem tentar fundir ou refazer nada.
Então o git reset
repõe o ramo mestre para o que você acabou de obter. A opção --hard
altera todos os ficheiros na sua árvore de trabalho para corresponder aos ficheiros em origin/master
Manter os actuais commits locais
[*]: vale a pena notar que é possível manter os commits locais atuais criando um branch de master
antes nova fixação:
git checkout master
git branch new-branch-to-save-current-commits
git fetch --all
git reset --hard origin/master
Depois disto, todos os antigos commits serão guardados em new-branch-to-save-current-commits
.
Alterações por persistir
As alterações por persistir, no entanto (mesmo encenadas), serão perdidas. Certifica-te de guardar e enviar tudo o que precisares. Para isso você pode executar o seguinte:
git stash
E, em seguida, reaplicar estas alterações não autorizadas:
git stash pop
Tenta isto:
git reset --hard HEAD
git pull
Deve fazer o que quiseres.
Atenção: git clean
apaga todos os seus ficheiros/directórios não rastreados e não pode ser desfeito.
Às vezes apenas clean -f
não ajuda. No caso de ter pastas não-rastreadas, a opção d também é necessária:
# WARNING: this can't be undone!
git reset --hard HEAD
git clean -f -d
git pull
Atenção: git clean
apaga todos os seus ficheiros/directórios não rastreados e não pode ser desfeito.
Considere a utilização de {MM / AAAA}-n
(--dry-run
) bandeira primeiro. Isto mostrar-lhe-á o que será apagado sem apagar de facto nada:
git clean -n -f -d
Exemplo resultado:
Would remove untracked-file-1.txt
Would remove untracked-file-2.txt
Would remove untracked/folder
...
Primeiro faça um commit das suas alterações
git add *
git commit -a -m "local file server commit message"
Depois obter as alterações e sobrepor se existir is a conflict
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 "mudanças, em vez de" suas " mudanças 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 é necessário obter todos os comandos e ramos se você vai reiniciar para o ramo original/mestre direito?
Parece que a melhor maneira é fazer primeiro:
git clean
Para Apagar todos os ficheiros não rastreados e depois continuar com o habitual git pull
...
Atenção, ao fazer isto, irá apagar permanentemente os seus ficheiros se tiver quaisquer itens de directório/* no seu ficheiro 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 de (git > v1.7.6):
git stash --include-untracked
git pull
Depois podes limpar o histórico do esconderijo.
Manualmente, um a um:
$ git stash list
stash@{0}: WIP on <branch>: ...
stash@{1}: WIP on <branch>: ...
$ git stash drop stash@{0}
$ git stash drop stash@{1}
Brutalmente, de uma só vez.
$ git stash clear
Claro, se quiseres voltar. ao que escondeste.
$ git stash list
...
$ git stash apply stash@{5}
Poderá achar este comando útil para eliminar as alterações Locais:
git checkout <your-branch> -f
E depois fazer uma limpeza (remove os ficheiros não rastreados da árvore de trabalho):
git clean -f
Se quiser remover as pastas não rastreadas para além dos ficheiros não rastreados:
git clean -fd
Em vez de se fundir com {[[0]}, tente isto:
git fetch --all
Seguida de:
git reset --hard origin/master
.
git reset --hard HEAD~5
Isto leva-te de volta cinco commits e depois com
git pull
Descobri isso olhando para cima como desfazer uma junção Git .
O problema com todas estas soluções é que elas são todas muito complexas, ou, um problema ainda maior, é que elas removem todos os arquivos não rastreados do servidor web, o que nós não queremos, uma vez que há sempre Arquivos de configuração necessários que estão no servidor e não no repositório Git.
Aqui está a solução mais limpa que estamos a usar:
# 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 obtém os dados mais recentes.
O segundo comando verifica se há algum arquivos que estão sendo adicionados ao repositório e apaga aqueles arquivos não rastreados do repositório local que causariam conflitos.
O terceiro comando verifica todos os arquivos que foram modificados localmente.
Finalmente nós fazemos um pull para atualizar para a versão mais nova, mas desta vez sem quaisquer conflitos, uma vez que os arquivos não rastreados que estão no repo não existem mais e todos os arquivos modificados localmente são já o mesmo que no repositorio.
- apagar todos os ficheiros. Deixa só o ... directório git.
git reset --hard HEAD
git pull
git push
git reset HEAD --hard # Remove all not committed changes
Se acima não ajudar e não se importar com os seus ficheiros/directórios não rastreados( faça a cópia de segurança em primeiro lugar só para o 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 ficheiros git (excempt .git/
dir, onde você tem todos os commits) e puxá-lo de novo.
Por que git reset HEAD --hard
poderia falhar em alguns casos?
-
Regras aduaneiras em
.gitattributes file
Ter
eol=lf
governado .os gitatributes poderiam Faça com que o git modifique algumas alterações de ficheiros, convertendo as terminações de linha do CRLF para o LF em alguns ficheiros de texto.Se for esse o caso, você tem que enviar estas alterações CRLF / LF( revendo-as em
git status
), ou tentar:git config core.autcrlf false
para ignorá-las temporariamente. -
Sistema de Ficheiros incompleto
Quando está a usar um sistema de ficheiros que não suporta atributos de permissões. Por exemplo, você tem dois repositórios, um no Linux / Mac (
ext3
/hfs+
) e outra na base FAT32 / NTFS sistema.Como vê, existem dois tipos diferentes de sistemas de ficheiros, por isso o que não suporta as permissões do Unix, basicamente, não consegue repor as permissões do ficheiro no sistema que não suporta esse tipo de permissões, por isso, não importa como
--hard
tente, o git detecta sempre algumas "alterações".
git reset --hard HEAD
git clean -f
git pull
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
Atenção : este script é muito poderoso, então você pode perder suas mudanças.
Isso em mente, eu atualizei o script do Kustudic para fazer exatamente isso. Eu também corrigi um typo (um faltando ' 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
Bónus:
Ao falar em puxar / buscar / mesclar nas respostas anteriores, gostaria de partilhar um truque interessante e produtivo,git pull --rebase
Este comando acima é o comando mais útil na minha vida Git que salvou muito tempo.
Antes de carregar com o seu novo envio para o servidor, tente este comando e ele irá sincronizar automaticamente as últimas alterações do servidor (com uma junção fetch+) e irá colocar o seu envio no topo no registo Git. Não há. qualquer necessidade de se preocupar com o puxão/junção manual.
Encontra os detalhes em o que é que "git puxa --rebase" faz?.
Os arquivos locais que não são rastreados precisam ser apagados manualmente (Mais Seguro) ou como sugerido em outras respostas, por
git clean -f -d
Os commits locais que não estão no ramo remoto precisam ser excluídos também. IMO a maneira mais fácil de conseguir isto é com:
git reset --hard origin/master
(substitua 'master' por qualquer ramo que seja a trabalhar e executar umgit fetch origin
primeiro)
Uma maneira mais fácil seria:
git checkout --theirs /path/to/file.extension
git pull origin master
Isto irá sobrepor o seu ficheiro local com o ficheiro no git
Parece que a maioria das respostas aqui estão focadas no ramo {[[2]}; no entanto, há alturas em que estou a trabalhar no mesmo ramo de recurso em dois locais diferentes e quero um rebase em um para ser reflectido no outro sem muito saltar através de aros.
Com base numa combinação da resposta de RNA e da resposta de Tarek a uma pergunta semelhante , descobri isto que funciona esplendidamente:git fetch
git reset --hard @{u}
Faz isto a partir de um ramo e ele só vai reiniciar o teu ramificação local para a versão upstream.
Isto pode ser bem colocado num pseudónimo git (git forcepull
) bem como:
git config alias.forcepull "!git fetch ; git reset --hard @{u}"
Ou, no seu ficheiro .gitconfig
:
[alias]
forcepull = "!git fetch ; git reset --hard @{u}"
Divirtam-se!
-x
.
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 dá uma lista das suas alterações locais. Continue a modificar o ramo " tmp " até que seja aceitável e depois volte a juntar-se ao master com:
git checkout master && git merge tmp
Para a próxima vez, você provavelmente pode lidar com isso de uma forma mais limpa, procurando "git stash branch" embora stash é provável que lhe cause problemas nas primeiras tentativas, assim como fazer a primeira experiência em um projeto não-crítico...
git clean
Nem git reset
funciona. Tenho de remover o ficheiro em conflito de git index
usando o seguinte programa em cada ficheiro não rastreado:
git rm [file]
Então sou capaz de puxar muito bem.
git reset --hard HEAD
git checkout origin/master
git branch -D master
git checkout -b master
Para verificar / puxar após executar estes comandos
git pull origin master
Eu tentei muito, mas finalmente consegui sucesso com estes comandos.
Apesar da pergunta original, as respostas de topo podem causar problemas para as pessoas que têm um problema semelhante, mas não querem perder seus arquivos locais. Por exemplo, veja os comentários de Al-Punk e crizCraig.
A seguinte versão compromete as suas alterações locais a uma ramificação temporária (tmp
), verifica a ramificação original (que estou a assumir ser master
) e junta as actualizações. Você poderia fazer isso com stash
, mas eu descobri que é geralmente mais fácil simplesmente usar o branch / merge abordagem.
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 é origin master
.
Faz apenas
git fetch origin branchname
git checkout -f origin/branchname // This will overwrite ONLY new included files
git checkout branchname
git merge origin/branchname
Para evitar todos os efeitos secundários indesejados, como apagar ficheiros ou directórios que queria manter, etc.
Reinicie o índice e a cabeça para origin/master
, mas não reinicie a árvore de trabalho:
git reset origin/master
$ git branch -m [branch_to_force_pull] tmp
$ git fetch
$ git checkout [branch_to_force_pull]
$ git branch -D tmp
É isso!
[alias]
fp = "!f(){ git fetch ${1} ${2} && git reset --hard ${1}/${2};};f"
Execute o seu comando como
git fp origin master
Equivalente a
git fetch origin master
git reset --hard origin/master
Requisitos:
-
Rastreia as mudanças locais para que ninguém as perca.
- Faça com que o repositório local corresponda ao repositório de origem remota.
Solução:
- Esconder as alterações locais.
-
Buscar com limpo do ficheiros e diretórios ignorando .gitignore e hard reset to origin .
git stash --include-untracked git fetch --all git clean -fdx git reset --hard origin/master