Como forçar o git pull a sobrescrever tudo em cada pull?

203

Eu tenho um repositório central do CENTRAL que tem três repositórios de desenvolvedor puxando e empurrando para ele normalmente.

Eu também tenho dois outros repositórios extraídos do repositório bare CENTRAL: um é o servidor ativo e o outro é um servidor de teste / estágio - cada um extraído de sua própria ramificação.

O cenário é o seguinte: eu tenho um post-updatescript de gancho no repositório CENTRAL que acessa automaticamente os repositórios de teste e ao vivo e executa um comando pull em cada um. Isso atualiza os servidores de teste e ativos, tudo dependendo de qual filial possui novas confirmações. Tudo isso funciona muito bem.

O problema é o seguinte: pode haver momentos em uma emergência em que os arquivos possam ser atualizados diretamente no servidor (via ftp ou qualquer outra coisa) e o script de pós-atualização do CENTRAL falhará, pois ocorrerão conflitos de mesclagem / substituição. Não há como evitar esse cenário, e é inevitável.

O que eu gostaria que acontecesse é o seguinte: quero que o pull dos sites ao vivo e de teste sempre sobrescreva / mescle no pull. Sempre. Esses repositórios serão apenas de atração, pois não são para desenvolvimento.

Em todas as minhas pesquisas, não consigo encontrar uma boa solução para que uma solicitação sempre force uma substituição dos arquivos locais. Tudo isso é possível? Seria um ótimo cenário de desenvolvimento, se sim.

bmilesp
fonte
1
Enquanto eu votei na resposta 'redefinir para o que você acabou de buscar' abaixo, acho que a solução para o seu problema real é não fazer alterações fora da banda. As modificações, por mais urgentes que sejam, sempre devem passar pelo controle de versão. Ninguém, exceto os operadores, deve ter acesso direto aos sites em execução (por exemplo, não desenvolvedores). Usar o controle de versão consistentemente significa que você tem um registro de quando as alterações foram feitas e quem as fez, além de melhores ferramentas para trabalhar com elas. Por que subvertê-lo, sem nenhum benefício real?
22412 Phil
1
@Novelocrat certo, eu entendo o que você está dizendo. Infelizmente, existem vários cenários em que alguém pode fazer upload de um arquivo diretamente no servidor. Nesse caso, eu precisaria executar vários comandos para sincronizar novamente os repositórios. Anteriormente, usamos um script FTP para mover arquivos do repositório para o servidor. O método proposto acima eliminaria simplesmente a etapa do FTP, que funcionou muito bem no passado.
bmilesp
3
Portanto, não permita que as pessoas acessem o servidor diretamente. Bloqueie o acesso ao FTP e SSH ou diga a eles que eles serão demitidos por fazer alterações irresponsáveis. Deixar esse tipo de prática continuar apenas prejudica você e sua equipe a longo prazo.
27512 Phil

Respostas:

510

Realmente a maneira ideal de fazer isso é não usar pullem tudo, mas em vez disso fetche reset:

git fetch origin master
git reset --hard FETCH_HEAD
git clean -df

(Alterando masterpara qualquer ramo que você deseja seguir.)

pullfoi desenvolvido para mesclar as alterações de alguma forma, enquanto para reseta cópia local corresponder a uma confirmação específica.

Você pode considerar opções ligeiramente diferentes, cleandependendo das necessidades do seu sistema.

Âmbar
fonte
3
@ user730569 reset --hardé um comando usado para forçar o estado do diretório de trabalho (e a ramificação atual) a um estado correspondente ao de uma confirmação específica.
30512 Amber
25
FETCH_HEADé uma referência criada automaticamente fetchpara representar a referência buscada. Não é mesclado, apenas sobrescrito diretamente sempre que você faz uma busca. cleané um comando que remove arquivos que não são rastreados git, os -dfsinalizadores indicam para remover os diretórios ( -d) e, na verdade, fazem a remoção ( -f).
30512 Amber
4
por que não existe uma palavra-chave para isso? Eu preciso disso com muito mais frequência do que puxar.
Wolfgang Fahl
14
Você pode usar git clean -dnantes de usar, git clean -dfpara ver quais arquivos / pastas serão excluídos. git clean -dfsó pode ser revertida se você tivesse um backup
Ibrahim Lawal
1
@NickMiddleweek, eu estava preocupado git clean -dfem remover arquivos com gitignor também, mas acontece que não. git clean --helpdiz "Normalmente, apenas os arquivos desconhecidos pelo Git são removidos, mas se a opção -x for especificada, os arquivos ignorados também serão removidos. Isso pode, por exemplo, ser útil para remover todos os produtos de construção".
nickang 24/08/19
6

Não sei como fazê-lo em um comando, mas você pode fazer algo como:

git reset --hard
git pull

ou mesmo

git stash
git pull
Matt Wolfe
fonte
Para executar em um comando: git reset --hard && git pull. Alternativamente, mas não melhor git reset --hard; git pull. Usar &&apenas executará o segundo comando se o primeiro comando tiver sido bem-sucedido. ;irá executá-lo independentemente do código de saída do primeiro comando.
mazunki
5

Para obter uma cópia da ramificação e forçar a substituição de arquivos locais da origem, use:

git reset --hard origin/current_branch

Todo o trabalho atual será perdido e será o mesmo que o ramo de origem

Andrew Atkinson
fonte
5
git reset --hard HEAD
git fetch --all
git reset --hard origin/your_branch
Dzmitry
fonte
2

Você pode mudar o gancho para limpar tudo.

# Danger! Wipes local data!

# Remove all local changes to tracked files
git reset --hard HEAD

# Remove all untracked files and directories
git clean -dfx

git pull ...
Dietrich Epp
fonte
2
o que x faz? por favor, explique as opções
Steve K
2
O x deve remover todos os arquivos não rastreados, eu acho. Difícil dizer no manpage-speak, e é por isso que temos SO.
JosephK
2
@ JosephphK: Isso está incorreto. O objetivo básico de git cleanjá é "Remover arquivos não rastreados da árvore de trabalho" (parte superior da página). Normalmente, isso não inclui arquivos ignorados, mas -xdiz git cleanpara incluir também arquivos ignorados (exceto que isso não afeta os arquivos ignorados pela -eopção).
Dietrich Epp
2

Se você ainda não confirmou as alterações locais desde o último pull / clone, você pode usar:

git checkout *
git pull

checkoutlimpará suas alterações locais com a última confirmação local e pulla sincronizará com o repositório remoto

Maviles
fonte