Revertendo um único arquivo para uma versão anterior no git
Existe uma maneira de passar por diferentes compromissos em um arquivo. Digamos que eu modifiquei um arquivo 5 vezes e quero voltar a modificar 2, depois de já ter cometido e empurrado para um repositório.
No meu entender, a única maneira é manter muitos ramos, não é assim? Se eu'estou certo eu'vou ter centenas de ramos em poucos dias, então eu'provavelmente não estou entendendo isso realmente.
Alguém pode esclarecer isso, por favor?
581
3
Vamos's começar com uma descrição qualitativa do que queremos fazer (muito disto é dito na resposta de Ben Straub's). Nós'fizemos alguns commits, cinco dos quais mudaram um determinado arquivo, e queremos reverter o arquivo para uma das versões anteriores. Primeiro de tudo, git doesn't manter números de versão para arquivos individuais. Ele apenas rastreia o conteúdo - um commit é essencialmente um instantâneo da árvore de trabalho, juntamente com alguns metadados (por exemplo, mensagem de commit). Então, nós temos que saber qual commit tem a versão do arquivo que nós queremos. Uma vez que sabemos isso, nós'precisaremos fazer um novo commit revertendo o arquivo para esse estado. (Nós podemos'não nos limitarmos a mexer na história, porque nós'já empurrámos este conteúdo, e editar a história mexe com todos os outros).
Então que's comecem por encontrar o compromisso certo. Você pode ver os commits que fizeram modificações em determinado(s) arquivo(s) muito facilmente:
Se suas mensagens de commit são'não são suficientemente boas, e você precisa ver o que foi feito ao arquivo em cada commit, use a opção `-p/--patch':
Ou, se preferir a vista gráfica de gitk
Você também pode fazer isso assim que você'tiver iniciado o gitk através do menu view; uma das opções para uma view é uma lista de caminhos a serem incluídos.
De qualquer forma, você'será capaz de encontrar o SHA1 (hash) do commit com a versão do arquivo que você quer. Agora, tudo o que você tem que fazer é isto:
(O comando checkout primeiro lê o arquivo no índice, depois o copia para a árvore de trabalho, então lá'não há necessidade de usar
git add
para adicioná-lo ao índice em preparação para a submissão).Se o seu arquivo pode não ter um histórico simples (por exemplo, renomes e cópias), veja o excelente comentário de VonC's. O
git
pode ser direcionado para procurar mais cuidadosamente por tais coisas, às custas da velocidade. Se você'está confiante na história'é simples, você precisa'não se preocupe.Git doesn't pensa em termos de versões de arquivos. Uma versão em git é um instantâneo de toda a árvore.
Dado isto, o que você realmente quer é uma árvore que tenha o conteúdo mais recente da maioria dos arquivos, mas com o conteúdo de um arquivo o mesmo que era 5 commits atrás. Isto tomará a forma de um novo commit em cima dos antigos, e a última versão da árvore terá o que você quer.
Eu não'não sei se existe'é uma linha única que irá reverter um único arquivo para o conteúdo de 5 commits atrás, mas a solução lo-fi deve funcionar: checkout
master~5
, copiar o arquivo em outro lugar, checkoutmaster
, copiar o arquivo de volta, depois commit.Você pode fazer uma diferença que desfaça as mudanças que você quer e comprometer-se com isso.
Por exemplo, se você quiser desfazer as mudanças no intervalo 'de...até', faça o seguinte