O comando que ele sugere para fazer isso corretamente após ter importado "uma longa e complicada história" é
Date: Wed, 5 Dec 2007 22:09:12 -0800 (PST)
From: Linus Torvalds <torvalds at linux-foundation dot org>
To: Daniel Berlin <dberlin at dberlin dot org>
cc: David Miller <davem at davemloft dot net>,
ismail at pardus dot org dot tr,
gcc at gcc dot gnu dot org,
git at vger dot kernel dot org
Subject: Re: Git and GCC
In-Reply-To: <4aca3dc20712052111o730f6fb6h7a329ee811a70f28@mail.gmail.com>
Message-ID: <alpine.LFD.0.9999.0712052132450.13796@woody.linux-foundation.org>
References: <4aca3dc20712051947t5fbbb383ua1727c652eb25d7e@mail.gmail.com>
<20071205.202047.58135920.davem@davemloft.net>
<4aca3dc20712052032n521c344cla07a5df1f2c26cb8@mail.gmail.com>
<20071205.204848.227521641.davem@davemloft.net>
<4aca3dc20712052111o730f6fb6h7a329ee811a70f28@mail.gmail.com>
Na quinta-feira, 6 de dezembro de 2007, Daniel Berlin escreveu:
Na verdade, acontece que git-gc --aggressive
isso faz essa coisa idiota para empacotar arquivos às vezes, independentemente de você ter convertido de um repositório SVN ou não.
Absolutamente. git --aggressive
é principalmente burro. É realmente útil apenas para o caso de "Eu sei que tenho uma embalagem muito ruim e quero jogar fora todas as decisões ruins de embalagem que tomei."
Para explicar isso, vale a pena explicar (você provavelmente está ciente disso, mas deixe-me passar pelo básico de qualquer maneira) como as cadeias delta git funcionam e como elas são tão diferentes da maioria dos outros sistemas.
Em outros SCMs, uma cadeia delta é geralmente fixa. Pode ser “para frente” ou “para trás” e pode evoluir um pouco conforme você trabalha com o repositório, mas geralmente é uma cadeia de alterações em um único arquivo representado como algum tipo de entidade SCM única. No CVS, é obviamente o *,v
arquivo, e muitos outros sistemas fazem coisas bastante semelhantes.
Git também faz cadeias delta, mas as faz muito mais "vagamente". Não há entidade fixa. Deltas são gerados contra qualquer outra versão aleatória que git considere ser um bom candidato delta (com várias heurísticas razoavelmente bem sucedidas), e não há absolutamente nenhuma regra rígida de agrupamento.
Em geral, isso é muito bom. É bom por várias razões conceituais ( ou seja , git internamente nunca realmente precisa se preocupar com toda a cadeia de revisão - ele realmente não pensa em termos de deltas), mas também é ótimo porque se livrar das regras inflexíveis de delta significa que o git não tem nenhum problema com a fusão de dois arquivos, por exemplo - simplesmente não existem *,v
“arquivos de revisão” arbitrários que tenham algum significado oculto.
Isso também significa que a escolha de deltas é uma questão muito mais aberta. Se você limitar a cadeia delta a apenas um arquivo, não terá muitas opções de escolha sobre o que fazer com os deltas, mas no git pode ser um problema totalmente diferente.
E é aí que --aggressive
entra o nome realmente ruim . Enquanto o git geralmente tenta reutilizar as informações delta (porque é uma boa ideia e não desperdiça tempo de CPU reencontrando todos os deltas bons que encontramos anteriormente), às vezes você quero dizer “vamos começar tudo de novo, com uma tela em branco, e ignorar todas as informações delta anteriores e tentar gerar um novo conjunto de deltas”.
Portanto, --aggressive
não se trata realmente de ser agressivo, mas de desperdiçar tempo de CPU refazendo uma decisão que já tomamos antes!
Às vezes, isso é uma coisa boa. Algumas ferramentas de importação em particular podem gerar deltas terrivelmente ruins. Qualquer coisa que use git fast-import
, por exemplo, provavelmente não tem um ótimo layout delta, então pode valer a pena dizer “Eu quero começar do zero”.
Mas quase sempre, em outros casos, é realmente uma coisa muito ruim de se fazer. Isso vai desperdiçar tempo de CPU e, especialmente se você realmente fez um bom trabalho no delta antes, o resultado final não vai reutilizar todos os bons deltas que você já encontrou, então você realmente vai acabar com muito pior resultado final também!
Vou enviar um patch para o Junio apenas para remover a git gc --aggressive
documentação. Pode ser útil, mas geralmente só é útil quando você realmente entende em um nível muito profundo o que está fazendo, e essa documentação não ajuda você a fazer isso.
Geralmente, fazer incrementais git gc
é a abordagem certa e melhor do que fazer git gc --aggressive
. Ele vai reutilizar deltas antigos e, quando esses deltas antigos não puderem ser encontrados (a razão para fazer GC incremental em primeiro lugar!), Ele criará novos.
Por outro lado, é definitivamente verdade que uma “importação inicial de uma história longa e envolvente” é um ponto em que vale a pena gastar muito tempo procurando deltas realmente bons . Então, todo usuário desde então (contanto que não use git gc --aggressive
para desfazê-lo!) Terá a vantagem desse evento único. Então, especialmente para grandes projetos com uma longa história, provavelmente vale a pena fazer algum trabalho extra, dizendo ao delta que localiza o código para enlouquecer.
Portanto, o equivalente a git gc --aggressive
- mas feito corretamente - é fazer (durante a noite) algo como
git repack -a -d --depth=250 --window=250
onde aquela coisa de profundidade é apenas sobre quão profundas as cadeias delta podem ser (torná-las mais longas para a história antiga - vale a pena o espaço acima), e a coisa de janela é sobre o tamanho da janela de um objeto que queremos que cada candidato delta examine.
E aqui, você pode querer adicionar o -f
sinalizador (que é “largar todos os deltas antigos”, já que agora você está realmente tentando ter certeza de que este realmente encontre bons candidatos.
E então vai levar uma eternidade e um dia ( ou seja , algo do tipo “faça durante a noite”). Mas o resultado final é que todos os downstream desse repositório receberão pacotes muito melhores, sem ter que gastar nenhum esforço com eles.
Linus