Preciso que os carimbos de data / hora dos arquivos no meu local e no meu servidor estejam sincronizados. Isso é realizado com o Subversion definindo use-commit-times = true na configuração de forma que a última modificação de cada arquivo seja quando ele foi submetido.
Cada vez que clonar meu repositório, quero que os carimbos de data / hora dos arquivos reflitam quando foram alterados pela última vez no repositório remoto, não quando clonei o repo.
Existe alguma maneira de fazer isso com o git?
git annex
pode ser útil para rastrear imagensRespostas:
Não tenho certeza se isso seria apropriado para um DVCS (como em VCS "Distribuído")
A grande discussão já havia ocorrido em 2007 (veja este tópico)
E algumas das respostas de Linus não gostaram muito da ideia. Aqui está um exemplo:
(Observação: pequena melhoria: após um check-out, os carimbos de data / hora dos arquivos atualizados não são mais modificados (Git 2.2.2+, janeiro de 2015): "git checkout - como posso manter carimbos de data / hora ao trocar de branch?" .)
A longa resposta foi:
fonte
git
é um DVCS, para manipular o código-fonte que será integrado ao seu produto final. Se você quer um sistema de distribuição, você sabe onde encontrarrsync
.Se, no entanto, você realmente deseja usar tempos de confirmação para carimbos de data / hora ao fazer check-out, tente usar este script e coloque-o (como executável) no arquivo $ GIT_DIR / .git / hooks / post-checkout:
Observe, entretanto, que este script causará um grande atraso para fazer check-out de grandes repositórios (onde grande significa grande quantidade de arquivos, não tamanhos de arquivo grandes).
fonte
| head -n 1
deve ser evitado, pois gera um novo processo,-n 1
poisgit rev-list
egit log
pode ser usado em seu lugar.`...`
efor
; veja Por que você não lê linhas com "para" . Eu iria paragit ls-files -z
ewhile IFS= read -r -d ''
.git show --pretty=format:%ai --abbrev-commit "$(get_file_rev "$1")" | head -n 1
você pode fazergit show --pretty=format:%ai -s "$(get_file_rev "$1")"
, isso faz com que muito menos dados sejam gerados peloshow
comando e deve reduzir a sobrecarga.ATUALIZAÇÃO : minha solução agora está incluída em Debian / Ubuntu / Mint, Fedora, Gentoo e possivelmente outras distros:
https://github.com/MestreLion/git-tools#install
IMHO, não armazenar carimbos de data / hora (e outros metadados como permissões e propriedade) é uma grande limitação do
git
.A lógica de Linus de que os carimbos de data / hora são prejudiciais apenas porque "confundem
make
" é falha :make clean
é o suficiente para resolver quaisquer problemas.Aplica-se apenas a projetos que usam
make
, principalmente C / C ++. É completamente discutível para scripts como Python, Perl ou documentação em geral.Só há dano se você aplicar os carimbos de data / hora. Não haveria mal nenhum em armazená- los no repositório. Aplicá-los pode ser uma
--with-timestamps
opção simples paragit checkout
e amigos (clone
,pull
etc), a critério do usuário .Tanto o Bazaar quanto o Mercurial armazenam metadados. Os usuários podem aplicá-los ou não no check-out. Mas no git, como os timestamps originais nem mesmo estão disponíveis no repo, essa opção não existe.
Então, para um ganho muito pequeno (não ter que recompilar tudo) que é específico para um subconjunto de projetos,
git
como um DVCS geral foi danificado , algumas informações sobre os arquivos são perdidas e, como Linus disse, é INFEASÍVEL fazer Isso agora. Triste .Dito isso, posso oferecer 2 abordagens?
1 - http://repo.or.cz/w/metastore.git , de David Härdeman. Tenta fazer o que
git
deveria ter sido feito em primeiro lugar : armazena metadados (não apenas timestamps) no repositório ao fazer commit (via gancho de pré-confirmação) e os reaplica ao puxar (também por meio de ganchos).2 - Minha versão humilde de um script que usei antes para gerar tarballs de lançamento. Conforme mencionado em outras respostas, a abordagem é um pouco diferente : aplicar para cada arquivo o carimbo de data / hora do commit mais recente em que o arquivo foi modificado.
Abaixo está uma versão realmente básica do script, como uma prova de conceito, no Python 2.7. Para uso real, recomendo fortemente a versão completa acima:
O desempenho é bastante impressionante, mesmo para projetos de monstro
wine
,git
ou mesmo o kernel linux:fonte
git
faz armazenar timestamps, etc. Ele simplesmente não definir a data e hora por padrão. Basta olhar para a saída degit ls-files --debug
git ls-files
opera no diretório de trabalho e no índice, então não significa que realmente armazena essa informação no repo. Se armazenasse, recuperar (e aplicar) mtime seria trivial.Peguei a resposta de Giel e, em vez de usar um script de gancho post-commit, trabalhei em meu script de implantação personalizada.
Atualização : também removi uma
| head -n
sugestão de @eregon, e adicionei suporte para arquivos com espaços:fonte
--abbrev-commit
é supérfluo nogit show
comando devido a--pretty=format:%ai
ser usado (commit hash não faz parte da saída) e| head -n 1
pode ser substituído com o uso de-s
sinalizador paragit show
%ai
é a data do autor, formato semelhante ao ISO 8601 , para uso estrito iso8601%aI
: git-scm.com/docs/git-showfomos forçados a inventar outra solução, porque precisávamos especificamente de tempos de modificação e não de tempos de commit, e a solução também tinha que ser portátil (ou seja, fazer o python funcionar nas instalações git do Windows realmente não é uma tarefa simples) e rápido. Assemelha-se à solução de David Hardeman, que decidi não usar por falta de documentação (do repositório não consegui ter ideia do que exatamente o código dele faz).
Esta solução armazena mtimes em um arquivo .mtimes no repositório git, atualiza-os de acordo com os commits (apenas seletivamente os mtimes dos arquivos testados) e os aplica no checkout. Funciona mesmo com versões cygwin / mingw do git (mas você pode precisar copiar alguns arquivos do cygwin padrão para a pasta do git)
A solução consiste em 3 arquivos:
pré-compromisso:
pós-checkout
mtimestore - bash:
mtimestore - c ++
mais informações podem ser encontradas aqui https://github.com/kareltucek/git-mtime-extension algumas informações desatualizadas estão em http://www.ktweb.cz/blog/index.php?page=page&id=116
// editar - versão c ++ atualizada:
// edite veja o github para a versão atualizada
fonte
O script a seguir incorpora as sugestões
-n 1
eHEAD
, funciona na maioria dos ambientes não Linux (como Cygwin) e pode ser executado em uma verificação após o fato:Supondo que você nomeou o script acima
/path/to/templates/hooks/post-checkout
e / ou/path/to/templates/hooks/post-update
, você pode executá-lo em um repositório existente via:fonte
Esta solução deve ser executada muito rapidamente. Ele define as horas para as horas de committer e as horas para as horas do autor. Ele não usa módulos, portanto deve ser razoavelmente portátil.
fonte
Aqui está uma versão otimizada das soluções shell acima, com pequenas correções:
fonte
Aqui está um método com PHP:
É semelhante à resposta aqui:
Qual é o equivalente a use-commit-times para git?
ele constrói uma lista de arquivos como aquela resposta, mas constrói em
git ls-files
vez de apenas olhar no diretório de trabalho. Isso resolve o problema de exclusão.git
e também resolve o problema de arquivos não rastreados. Além disso, essa resposta falha se o último commit de um arquivo foi um commit de mesclagem, o que eu resolvigit log -m
. Como a outra resposta, irá parar assim que todos os arquivos forem encontrados, então não precisa ler todos os commits. Por exemplo com:https://github.com/git/git
nesta postagem, ele só tinha que ler 292 commits. Também ignora arquivos antigos do histórico conforme necessário e não afetará um arquivo que já foi alterado. Finalmente parece ser um pouco mais rápido do que a outra solução. Resultados com
git/git
repo:fonte
Eu vi alguns pedidos para uma versão do Windows, então aqui está. Crie os dois arquivos a seguir:
C: \ Arquivos de programas \ Git \ mingw64 \ share \ git-core \ templates \ hooks \ post-checkout
C: \ Arquivos de programas \ Git \ mingw64 \ share \ git-core \ templates \ hooks \ post-checkout.ps1
Isso utiliza git whatchanged , de modo que executa todos os arquivos em uma passagem, em vez de chamar git para cada arquivo.
fonte
Estou trabalhando em um projeto em que mantenho um clone do meu repositório para uso com
rsync
implantações baseadas. Eu uso branches para atingir diferentes ambientes e fazergit checkout
com que as modificações do arquivo mudem.Tendo aprendido que o git não fornece uma maneira de fazer check-out de arquivos e preservar carimbos de data / hora, me deparei com o comando
git log --format=format:%ai --name-only .
em outra pergunta do SO: Liste as datas dos últimos commits para um grande número de arquivos, rapidamente .Agora estou usando o seguinte script para
touch
os arquivos e diretórios do meu projeto, para quersync
seja mais fácil diferenciar minha implantação :fonte