Potrzebuję sygnatur czasowych plików na moim serwerze lokalnym i na serwerze, aby były zsynchronizowane. Osiąga się to w Subversion, ustawiając w konfiguracji use-commit-times = true, tak aby ostatnia modyfikacja każdego pliku miała miejsce, gdy został zatwierdzony.
Za każdym razem, gdy klonuję repozytorium, chcę, aby sygnatury czasowe plików odzwierciedlały datę ich ostatniej zmiany w repozytorium zdalnym, a nie datę sklonowania repozytorium.
Czy jest jakiś sposób, aby to zrobić za pomocą git?
git annex
może być przydatne do śledzenia obrazówOdpowiedzi:
Nie jestem pewien, czy będzie to odpowiednie dla DVCS (jak w „Distributed” VCS)
Ogromna dyskusja odbyła się już w 2007 roku (zobacz ten wątek)
Niektórzy z odpowiedzi Linusa nie byli zachwyceni tym pomysłem. Oto jedna próbka:
(Uwaga: niewielka poprawa: po wyewidencjonowaniu sygnatury czasowe aktualnych plików nie są już modyfikowane (Git 2.2.2+, styczeń 2015): „git checkout - jak mogę zachować znaczniki czasu podczas przełączania gałęzi?” ).
Długa odpowiedź brzmiała:
źródło
git
to DVCS do manipulowania kodem źródłowym, który zostanie wbudowany w produkt końcowy. Jeśli potrzebujesz systemu dystrybucji, wiesz, gdzie go znaleźćrsync
.Jeśli jednak naprawdę chcesz użyć czasu zatwierdzenia dla znaczników czasu podczas sprawdzania, spróbuj użyć tego skryptu i umieść go (jako plik wykonywalny) w pliku $ GIT_DIR / .git / hooks / post-checkout:
Należy jednak pamiętać, że ten skrypt spowoduje dość duże opóźnienie przy sprawdzaniu dużych repozytoriów (gdzie duże oznacza dużą liczbę plików, a nie duże rozmiary plików).
źródło
| head -n 1
Należy unikać jak ikra nowy proces,-n 1
zagit rev-list
igit log
może być stosowany zamiast.`...`
ifor
; zobacz Dlaczego nie czytasz wierszy z „dla” . Poszedłbym nagit ls-files -z
iwhile IFS= read -r -d ''
.git show --pretty=format:%ai --abbrev-commit "$(get_file_rev "$1")" | head -n 1
możesz to zrobićgit show --pretty=format:%ai -s "$(get_file_rev "$1")"
, powoduje generowanie znacznie mniej danych przezshow
polecenie i powinno zmniejszyć narzut.AKTUALIZACJA : Moje rozwiązanie jest teraz spakowane w dystrybucji Debian / Ubuntu / Mint, Fedora, Gentoo i prawdopodobnie innych:
https://github.com/MestreLion/git-tools#install
IMHO, nieprzechowywanie sygnatur czasowych (i innych metadanych, takich jak uprawnienia i własność), jest dużym ograniczeniem
git
.Rozumowanie Linusa, że sygnatury czasowe są szkodliwe tylko dlatego, że „dezorientuje
make
”, jest kiepskie :make clean
wystarczy, aby naprawić wszelkie problemy.Dotyczy tylko projektów, które używają
make
, głównie C / C ++. Jest to całkowicie dyskusyjne w przypadku skryptów takich jak Python, Perl lub ogólnie dokumentacji.Szkoda jest tylko wtedy, gdy zastosujesz znaczniki czasu. Przechowywanie ich w repozytorium nie byłoby szkodliwe . Ich stosowania może być prostym
--with-timestamps
rozwiązaniem dlagit checkout
i przyjaciele (clone
,pull
etc), na użytkownika uznania.Zarówno Bazaar, jak i Mercurial przechowują metadane. Użytkownicy mogą je zastosować lub nie podczas płatności. Ale w git, ponieważ oryginalne znaczniki czasu nie są nawet dostępne w repozytorium, nie ma takiej opcji.
Tak więc, dla bardzo małego zysku (brak konieczności ponownej kompilacji wszystkiego), który jest charakterystyczny dla podzbioru projektów,
git
ponieważ ogólny DVCS został uszkodzony , niektóre informacje z plików są tracone i, jak powiedział Linus, jest to NIEDOPROGRAMOWANE. teraz. Smutne .To powiedziawszy, czy mogę zaoferować 2 podejścia?
1 - http://repo.or.cz/w/metastore.git , autor: David Härdeman. Próbuje zrobić to, co
git
powinno było zrobić w pierwszej kolejności : przechowuje metadane (nie tylko znaczniki czasu) w repozytorium podczas zatwierdzania (za pomocą haka przed zatwierdzeniem) i ponownie je stosuje podczas ściągania (również za pomocą haków).2 - Moja skromna wersja skryptu, którego użyłem wcześniej do generowania paczek z wydaniami. Jak wspomniano w innych odpowiedzi, podejście jest trochę inaczej : do zastosowania dla każdego akt datownik z najnowszym popełnienia gdzie plik został zmodyfikowany.
Poniżej znajduje się naprawdę prosta wersja skryptu, jako dowód słuszności koncepcji, w Pythonie 2.7. Do rzeczywistego użytku zdecydowanie polecam pełną wersję powyżej:
Wydajność jest imponująca, nawet w przypadku potwornych projektów
wine
,git
a nawet jądra Linuksa:źródło
git
nie przechowywać znaczniki czasu itd To po prostu nie ustawia timestampów domyślnie. Wystarczy spojrzeć na wynikgit ls-files --debug
git ls-files
działa na katalogu roboczym i indeksie, więc nie oznacza to, że faktycznie przechowuje te informacje w repozytorium. Gdyby przechował, pobranie (i zastosowanie) mtime byłoby trywialne.Wziąłem odpowiedź Giela i zamiast używać skryptu przechwytującego po zatwierdzeniu, umieściłem ją w moim niestandardowym skrypcie wdrażania.
Aktualizacja : usunąłem również jedną
| head -n
sugestię @ eregon i dodałem obsługę plików ze spacjami:źródło
--abbrev-commit
jest zbytecznegit show
polecenia z powodu--pretty=format:%ai
jest stosowany (popełnienia mieszania nie jest częścią wyjściu) i| head -n 1
może być zastąpiona za pomocą-s
flag, abygit show
%ai
to data autora, format podobny do ISO 8601 , dla ścisłego użycia ISO8601%aI
: git-scm.com/docs/git-showbyliśmy zmuszeni wymyślić jeszcze jedno rozwiązanie, ponieważ potrzebowaliśmy konkretnie czasu modyfikacji, a nie czasu zatwierdzenia, a także rozwiązanie musiało być przenośne (tj. sprawienie, aby Python działał w instalacjach git systemu Windows naprawdę nie jest prostym zadaniem) i szybkie. Przypomina rozwiązanie Davida Hardemana, z którego zrezygnowałem ze względu na brak dokumentacji (z repozytorium nie mogłem się zorientować, co dokładnie robi jego kod).
To rozwiązanie przechowuje mtimes w pliku .mtimes w repozytorium git, aktualizuje je odpowiednio przy zatwierdzeniach (jsut selektywnie mtimes plików pomostowych) i stosuje je przy pobieraniu. Działa nawet z wersjami git cygwin / mingw (ale może być konieczne skopiowanie niektórych plików ze standardowego cygwin do folderu git)
Rozwiązanie składa się z 3 plików:
wstępne zobowiązanie:
po wymeldowaniu
mtimestore - bash:
mtimestore - c ++
więcej informacji można znaleźć tutaj https://github.com/kareltucek/git-mtime-extension niektóre nieaktualne informacje są dostępne pod adresem http://www.ktweb.cz/blog/index.php?page=page&id=116
// edit - aktualizacja wersji c ++:
// edytuj zobacz github, aby uzyskać aktualną wersję
źródło
Poniższy skrypt zawiera sugestie
-n 1
iHEAD
, działa w większości środowisk innych niż Linux (takich jak Cygwin) i można go uruchomić przy kasie po fakcie:Zakładając, że nazwałeś powyższy skrypt
/path/to/templates/hooks/post-checkout
i / lub/path/to/templates/hooks/post-update
możesz uruchomić go na istniejącym repozytorium poprzez:źródło
To rozwiązanie powinno działać dość szybko. Ustala momenty na czasy autora i czasy na czasy autora. Nie wykorzystuje modułów, więc powinien być w miarę przenośny.
źródło
Oto zoptymalizowana wersja powyższych rozwiązań powłoki, z drobnymi poprawkami:
źródło
Oto metoda z PHP:
Jest podobna do odpowiedzi tutaj:
Jaki jest odpowiednik czasów zatwierdzania użycia dla git?
tworzy listę plików, taką jak ta odpowiedź, ale buduje na podstawie
git ls-files
zamiast tylko szukać w katalogu roboczym. To rozwiązuje problem wykluczania.git
, a także rozwiązuje problem nieśledzonych plików. Również ta odpowiedź nie powiedzie się, jeśli ostatnim zatwierdzeniem pliku było zatwierdzenie scalające, które rozwiązałemgit log -m
. Podobnie jak druga odpowiedź, zatrzyma się po znalezieniu wszystkich plików, więc nie musi czytać wszystkich zatwierdzeń. Na przykład z:https://github.com/git/git
od tego wysłania musiał przeczytać tylko 292 zatwierdzenia. W razie potrzeby ignoruje również stare pliki z historii i nie dotknie pliku, który został już dotknięty. Wreszcie wydaje się, że jest trochę szybszy niż inne rozwiązanie. Wyniki z
git/git
repozytorium:źródło
Widziałem prośby o wersję dla systemu Windows, więc oto one. Utwórz następujące dwa pliki:
C: \ Program Files \ Git \ mingw64 \ share \ git-core \ templates \ hooks \ post-checkout
C: \ Program Files \ Git \ mingw64 \ share \ git-core \ templates \ hooks \ post-checkout.ps1
Używa git whatchanged , więc przechodzi przez wszystkie pliki w jednym przebiegu zamiast wywoływać git dla każdego pliku.
źródło