Programa
Em determinadas situações, talvez queiramos redefinir o estado de um Git local para alinhá-lo com o repositório remoto, descartando assim todas as alterações locais. Isso é comumente chamado de forced pull.
Isso cria a ideia errônea de que a maneira de arquivar isso é usar a opção --force no comando git pull. Neste artigo, você aprenderá que essas são coisas diferentes.
Podemos substituir nosso estado local pelo estado remoto usando os comandos listados abaixo, substituindo pelo nome da sua filial. Essa ação excluirá permanentemente todas as alterações locais que você fez nesse ramo.
git fetch
git reset --hard origin/<branch_name>
Este artigo abordará os detalhes de como esses comandos funcionam. Vamos além das correções rápidas para entender a mecânica subjacente, aprendendo assim métodos mais eficazes para alcançar o resultado desejado sem o risco de perder mudanças importantes. Também esclarecemos o equívoco e aprendemos o que a opção --force de git pull realmente faz.
Quando considerar a substituição de alterações locais
Em geral, substituir alterações locais dessa forma vai contra o uso pretendido do Git. Para quase todas as situações, há um fluxo de trabalho Git adequado para resolvê-las. No entanto, algumas delas geralmente exigem um conhecimento mais profundo do Git e levam mais tempo para serem executadas. Mesmo que não seja uma prática recomendada, substituir alterações locais às vezes pode ser a maneira mais rápida de realizar o trabalho.
Para mim, isso geralmente acontece quando trabalho em um recurso com o qual não estou muito familiarizado. Começo criando uma ramificação e fazendo alguns commits. Quando fico preso, peço ajuda a um colega. Eles começam em um commit anterior, antes de eu cometer o erro, resolvem o problema e enviam suas alterações. Nesse momento, preciso substituir minha versão local pela versão remota atualizada e descartar minhas alterações locais, para que eu possa continuar trabalhando no recurso.
Outro exemplo é quando há um conflito e eu acho que é mais difícil ou mais demorado corrigir o conflito do que reimplementar nossas alterações na versão mais recente do código.
Independentemente do motivo, certifique-se sempre de que essas alterações realmente não são necessárias e podem ser excluídas com segurança ou faça backup da sua ramificação para evitar a perda de trabalhos importantes.
Como substituir corretamente as alterações locais
A primeira etapa é buscar (baixar) o conteúdo mais recente do repositório remoto em nosso computador local. Isso é feito usando ocomando fetch do git:
git fetch
Por padrão, isso buscará o conteúdo da ramificação atual, que geralmente é o que precisamos. Opcionalmente, podemos especificar a ramificação que desejamos baixar (substituindo abaixo pelo nome da ramificação que desejamos buscar):
git fetch origin/<branch_name>
Como alternativa, podemos usar a opção --all para fazer o download de tudo:
git fetch –all
A obtenção das alterações do repositório remoto não afetará os arquivos no diretório atual do branch de trabalho. O comando fetch faz o download das alterações do repositório remoto, mas não as mescla. O repositório local mantém uma visualização dos arquivos locais e dos arquivos remotos, e a busca atualiza a visualização dos arquivos remotos.
Depois de fazer o download das alterações do repositório remoto, podemos usar o comando reset do git para redefinir o ramo de trabalho atual em um determinado estado:
git reset --hard origin/<branch_name>
A opção --hard é necessária para garantir que as alterações locais sejam substituídas pelas alterações remotas. No comando acima, optamos por substituir o ramo de trabalho atual por origin/, que corresponde à versão remota desse ramo que acabou de ser obtida.
O comando git reset excluirá as alterações locais, mesmo que elas tenham sido confirmadas. Portanto, é recomendável que você crie um backup local da ramificação atual antes de executar esse comando. Isso pode ser feito usando:
git branch <name_of_the_backup_branck>
Substituindo pelo nome que você deseja que o ramo de backup tenha.
Juntando tudo isso, podemos substituir todas as alterações locais de uma determinada ramificação pela versão remota mais recente, fazendo o seguinte:
git fetch
git branch <name_of_the_backup_branch>
git reset --hard origin/<branch_name>
Limpeza completa com a exclusão de arquivos não rastreados
O Git não tocará em arquivos não rastreados (arquivos que nunca foram usados git add). Se também quisermos excluir esses arquivos, podemos fazer isso usando:
git clean -fdx
Esse é um comando perigoso que é usado para remover arquivos não rastreados do diretório de trabalho. É essencial que você use esse comando com cuidado, pois ele exclui permanentemente esses arquivos, impossibilitando sua recuperação por meio do Git. Aqui está um detalhamento das opções de comando:
-f: Essa opção força a operação de limpeza a prosseguir. O Git se recusará a excluir arquivos não rastreados do diretório de trabalho sem esse sinalizador como uma medida de segurança para evitar a perda acidental de dados.-d: Isso diz aogit cleanpara remover não apenas os arquivos não rastreados, mas também os diretórios não rastreados. Por padrão, ogit cleantem como alvo apenas os arquivos não rastreados e ignora os diretórios.-x: Por padrão, ogit cleanrespeitará as regras do.gitignoree não removerá arquivos ou diretórios que correspondam a esses padrões. A inclusão de -x substitui esse comportamento, instruindo o Git a remover também os arquivos/diretórios que são ignorados por.gitignoreou outras regras de ignorar. Isso resulta em uma limpeza muito completa, removendo todos os arquivos não rastreados no repositório, incluindo saídas de compilação, arquivos de registro e outros artefatos gerados que normalmente são ignorados.
Entendendo o Git Pull
A maneira usual de atualizar nosso repositório local com alterações remotas é usando o comando git pull . No entanto, esse comando não pode ser usado para substituir nossas alterações locais porque o git pull tentará mesclar nossa versão local com a remota.
No âmbito do sistema, o git pull executa as seguintes etapas:
- Ele usa o site
git fetchpara fazer o download da versão mais recente do repositório remoto. - Ele usa o site
git mergepara mesclar as ramificações locais e remotas.
Devido à etapa de mesclagem, o git pull não é um comando adequado em situações em que você deseja ignorar e descartar alterações locais.

Que tal o git pull --force?
Ao examinar a documentação do comando git pull , você verá que ele oferece a opção --force. É um equívoco comum pensar que essa opção forçará a execução do comando git pull, apagando as alterações locais com as alterações remotas.
Quando fornecemos a opção --force para git pull, essa opção é passada para git fetch. Assim, o site git pull --force executa as seguintes etapas:
git fetch --forcegit merge

Aprendemos que o fetch é usado para atualizar a visualização local do repositório remoto. Se a única diferença entre o repositório local atual e o repositório remoto for a falta de alguns commits (a ramificação local está atrás da versão remota), então o git fetch simplesmente atualizará a visualização local acrescentando esses novos commits ao histórico.

No entanto, pode ser que alguém tenha reescrito o histórico de commits do ramo remoto, tornando-o incompatível com a visualização local. Nesse caso, o fetch não funcionará.

Você pode contornar isso usando a opção --force, que forçará o Git a ignorar o histórico local e substituí-lo pelo histórico remoto.
Vemos que a opção --force está relacionada a forçar a substituição do histórico do commit e não tem nada a ver com ignorar as alterações locais no diretório do ramo de trabalho.
Integração de mudanças locais
Sobrescrever as alterações locais com as alterações remotas não é uma prática comum do Git, mas pode ser útil em determinados casos em que não queremos lidar com conflitos ou não nos importamos com nossas alterações locais.
Fusão
Em geral, você pode fazer as alterações e lidar com os conflitos. As pessoas tendem a ter medo de lidar com conflitos. Alguns conflitos podem ser muito difíceis de lidar, mas nem sempre é esse o caso. Um conflito ocorre quando:
- Tanto o ramo local quanto o ramo remoto têm alterações na mesma parte de um arquivo.
- Um arquivo é excluído em um lado e modificado no outro.
Nesses casos, o Git não consegue adivinhar quais alterações queremos manter, e precisamos informá-lo manualmente. O Git destacará o conflito nos arquivos da seguinte forma:

Para resolver um conflito, editamos o arquivo excluindo essas linhas, exceto as que queremos manter. Depois de lidar com todos os conflitos, podemos confirmar as alterações. Para obter um guia detalhado, confira este tutorial sobre como resolver conflitos de mesclagem no Git.
Seleção de cerejas
Se realmente quisermos primeiro fazer com que nossa versão local corresponda à versão remota e, em seguida, integrar nossas alterações, podemos trazer os commits do ramo de backup para o ramo atual, dessa forma:
git cherry-pick <commit_hash>
Aqui, é o hash do commit que você deseja integrar. Isso pressupõe que, antes de fazer git reset, criamos uma ramificação de backup com git branch e que as alterações locais foram confirmadas.
Para localizar o , podemos listar os hashes de confirmação na ramificação de backup usando o seguinte comando:
git log <name_of_the_backup_branck>
Stashing
Como alternativa, se não quisermos confirmar nossas alterações ou criar um ramo de backup, podemos armazenar nossas alterações antes de fazer a mesclagem usando:
git stash
Esse comando pode ser usado para salvar temporariamente o trabalho atual sem confirmá-lo no histórico do ramo. O armazenamento deixa de lado suas modificações, permitindo que você tenha um diretório de trabalho limpo.
Após a redefinição, podemos recuperar as alterações usando o seguinte comando:
git stash pop
Usando o armazenamento, todo o fluxo de trabalho seria mais ou menos assim:
git fetch
git stash
git reset --hard origin/<branch_name>
git stash pop
Para saber mais, confira esta folha de dicas com o stash e outros comandos do git.
Conclusão
Apesar de não ser uma prática recomendada, às vezes nos encontramos em uma situação em que queremos apenas fazer com que o nosso ramo local corresponda ao conteúdo do ramo remoto e, ao mesmo tempo, descartar nossas alterações locais.
Há um equívoco de que isso é conseguido usando git pull --force. Isso está incorreto porque git pull --force combina git fetch --force e git merge. Portanto, ele tenta mesclar as alterações locais com as alterações remotas, sem substituí-las.
A maneira correta de substituir as alterações locais pelo conteúdo do repositório remoto é:
git fetch
git reset --hard origin/<branch_name>
O comando git reset deve ser usado com cautela, pois excluirá as alterações locais, mesmo que tenham sido confirmadas. Se você tiver commits locais e criar uma ramificação de backup, poderá trazê-los de volta usando git cherry-pick. Se não tivermos feito o commit e quisermos salvar temporariamente nosso trabalho local, poderemos usar git stash antes de redefinir e, em seguida, git stash pop para trazer nossas alterações de volta.
