Ich benötige die Zeitstempel der Dateien auf meinem lokalen Server und auf meinem Server, um synchron zu sein. Dies wird mit Subversion erreicht, indem use-commit-times = true in der Konfiguration festgelegt wird, sodass die letzte Änderung jeder Datei zum Zeitpunkt des Festschreibens erfolgt.
Jedes Mal, wenn ich mein Repository klone, möchte ich, dass die Zeitstempel der Dateien widerspiegeln, wann sie zuletzt im Remote-Repository geändert wurden, und nicht, wann ich das Repo geklont habe.
Gibt es eine Möglichkeit, dies mit git zu tun?
git annex
könnte nützlich sein, um Bilder zu verfolgenAntworten:
Ich bin nicht sicher, ob dies für ein DVCS geeignet wäre (wie in "Distributed" VCS).
Die große Diskussion hatte bereits 2007 stattgefunden (siehe diesen Thread)
Und einige von Linus 'Antworten waren nicht besonders begeistert von der Idee. Hier ist ein Beispiel:
(Hinweis: kleine Verbesserung: Nach dem Auschecken werden die Zeitstempel aktueller Dateien nicht mehr geändert (Git 2.2.2+, Januar 2015): "git checkout - wie kann ich Zeitstempel beim Wechseln von Zweigen beibehalten?" .)
Die lange Antwort war:
quelle
git
ist ein DVCS zum Bearbeiten von Quellcode, der in Ihr Endprodukt integriert wird. Wenn Sie ein Vertriebssystem wünschen, wissen Sie, wo Sie es finden könnenrsync
.Wenn Sie jedoch beim Auschecken wirklich Festschreibungszeiten für Zeitstempel verwenden möchten, verwenden Sie dieses Skript und platzieren Sie es (als ausführbare Datei) in der Datei $ GIT_DIR / .git / hooks / post-checkout:
Beachten Sie jedoch, dass dieses Skript eine große Verzögerung beim Auschecken großer Repositorys verursacht (wobei groß eine große Anzahl von Dateien bedeutet, keine große Dateigröße).
quelle
| head -n 1
sollte vermieden werden, da es einen neuen Prozess erzeugt,-n 1
fürgit rev-list
undgit log
kann stattdessen verwendet werden.`...`
und zu lesenfor
. Siehe Warum Sie keine Zeilen mit "für" lesen . Ich würde fürgit ls-files -z
und gehenwhile IFS= read -r -d ''
.git show --pretty=format:%ai --abbrev-commit "$(get_file_rev "$1")" | head -n 1
Sie dies tun könnengit show --pretty=format:%ai -s "$(get_file_rev "$1")"
, werden vomshow
Befehl viel weniger Daten generiert, und der Overhead sollte reduziert werden.UPDATE : Meine Lösung ist jetzt in Debian / Ubuntu / Mint, Fedora, Gentoo und möglicherweise anderen Distributionen verpackt:
https://github.com/MestreLion/git-tools#install
IMHO ist das Nicht-Speichern von Zeitstempeln (und anderen Metadaten wie Berechtigungen und Besitz) eine große Einschränkung von
git
.Linus 'Begründung, Zeitstempel seien schädlich, nur weil sie "verwirren
make
", ist lahm :make clean
reicht aus, um Probleme zu beheben.Gilt nur für Projekte, die
make
hauptsächlich C / C ++ verwenden. Es ist für Skripte wie Python, Perl oder Dokumentation im Allgemeinen völlig umstritten.Es schadet nur, wenn Sie die Zeitstempel anwenden . Es würde nicht schaden, sie im Repo zu lagern . Anwenden von ihnen könnte eine einfache seine
--with-timestamps
Option fürgit checkout
und Freunde (clone
,pull
usw.), auf den Benutzer setzen zu müssen .Sowohl Bazaar als auch Mercurial speichern Metadaten. Benutzer können sie beim Auschecken anwenden oder nicht. Aber in Git gibt es keine solche Option , da die ursprünglichen Zeitstempel nicht einmal im Repo verfügbar sind .
Für einen sehr kleinen Gewinn (der nicht alles neu kompilieren muss), der für eine Teilmenge von Projekten spezifisch ist , gehen einige Informationen über Dateien verloren ,
git
da ein allgemeines DVCS verkrüppelt wurde , und wie Linus sagte, ist es UNMÖGLICH, dies zu tun es jetzt. Traurig .Darf ich zwei Ansätze anbieten?
1 - http://repo.or.cz/w/metastore.git , von David Härdeman. Versucht, das zu tun, was
git
eigentlich hätte getan werden sollen : Speichert Metadaten (nicht nur Zeitstempel) beim Festschreiben im Repo (über den Pre-Commit-Hook) und wendet sie beim Ziehen erneut an (auch über Hooks).2 - Meine bescheidene Version eines Skripts, das ich zuvor zum Generieren von Release-Tarballs verwendet habe. Wie in anderen Antworten erwähnt, ist der Ansatz etwas anders : Für jede Datei wird der Zeitstempel des letzten Commits angewendet , bei dem die Datei geändert wurde.
Im Folgenden finden Sie eine wirklich einfache Version des Skripts als Proof-of-Concept für Python 2.7. Für den tatsächlichen Gebrauch empfehle ich dringend die obige Vollversion:
Die Leistung ist ziemlich beeindruckend, auch für Monster - Projekte
wine
,git
oder sogar den Linux - Kernel:quelle
git
tut Speicher Zeitstempel, etc. Es ist gesetzt einfach nicht die Zeitstempel standardmäßig. Schauen Sie sich die Ausgabe vongit ls-files --debug
git ls-files
arbeitet auf Arbeitsverzeichnis und Index, so dass es nicht tatsächlich bedeuten speichert , dass Informationen über den Repo. Wenn es gespeichert würde, wäre das Abrufen (und Anwenden) von mtime trivial.Ich nahm Giels Antwort und arbeitete sie anstelle eines Hook-Skripts nach dem Festschreiben in mein benutzerdefiniertes Bereitstellungsskript ein.
Update : Ich habe auch einen
| head -n
folgenden Vorschlag von @ eregon entfernt und Unterstützung für Dateien mit Leerzeichen hinzugefügt:quelle
--abbrev-commit
ist überflüssig,git show
da--pretty=format:%ai
er verwendet wird (Commit-Hash ist nicht Teil der Ausgabe) und| head -n 1
könnte durch die Verwendung von-s
Flag to ersetzt werdengit show
%ai
ist Autorendatum, ISO 8601- ähnliches Format, für strikte Verwendung von iso8601%aI
: git-scm.com/docs/git-showWir waren gezwungen, eine weitere Lösung zu erfinden, da wir spezielle Änderungszeiten und keine Festschreibungszeiten benötigten und die Lösung auch portabel sein musste (dh Python in Windows Git-Installationen zum Laufen zu bringen, ist wirklich keine einfache Aufgabe) und schnell. Es ähnelt der Lösung von David Hardeman, die ich aufgrund fehlender Dokumentation nicht verwendet habe (aus dem Repository konnte ich keine Vorstellung davon bekommen, was genau sein Code tut).
Diese Lösung speichert mtimes in einer Datei .mtimes im Git-Repository, aktualisiert sie bei Commits entsprechend (jsut selektiv die mtimes von bereitgestellten Dateien) und wendet sie beim Auschecken an. Es funktioniert sogar mit Cygwin / Mingw-Versionen von Git (möglicherweise müssen Sie jedoch einige Dateien aus Standard-Cygwin in den Ordner von Git kopieren).
Die Lösung besteht aus 3 Dateien:
Pre-Commit:
nach dem Auschecken
mtimestore - bash:
mtimestore - c ++
Weitere Informationen finden Sie hier https://github.com/kareltucek/git-mtime-extension Einige veraltete Informationen finden Sie unter http://www.ktweb.cz/blog/index.php?page=page&id=116
// edit - c ++ Version aktualisiert:
// Bearbeiten siehe Github für aktuelle Version
quelle
Das folgende Skript enthält die
-n 1
undHEAD
Vorschläge, funktioniert in den meisten Nicht-Linux-Umgebungen (wie Cygwin) und kann nachträglich an einer Kasse ausgeführt werden:Angenommen, Sie haben das obige Skript benannt
/path/to/templates/hooks/post-checkout
und / oder/path/to/templates/hooks/post-update
können Sie es in einem vorhandenen Repository ausführen über:quelle
Diese Lösung sollte ziemlich schnell laufen. Es werden die Zeiten für die Committer-Zeiten und die Zeiten für die Autorenzeiten festgelegt. Es verwendet keine Module und sollte daher einigermaßen portabel sein.
quelle
Hier ist eine optimierte Version der oben genannten Shell-Lösungen mit geringfügigen Korrekturen:
quelle
Hier ist eine Methode mit PHP:
Es ist ähnlich der Antwort hier:
Was entspricht den Use-Commit-Zeiten für Git?
Es erstellt eine Dateiliste wie diese Antwort, aber es erstellt aus,
git ls-files
anstatt nur im Arbeitsverzeichnis zu suchen. Dies löst das Problem des Ausschlusses.git
und das Problem der nicht verfolgten Dateien. Diese Antwort schlägt auch fehl, wenn das letzte Festschreiben einer Datei ein Zusammenführungs-Festschreiben war, mit dem ich es gelöst habegit log -m
. Wie die andere Antwort wird sie angehalten, sobald alle Dateien gefunden wurden, sodass nicht alle Commits gelesen werden müssen. Zum Beispiel mit:https://github.com/git/git
Zum Zeitpunkt dieser Veröffentlichung mussten nur 292 Commits gelesen werden. Außerdem werden alte Dateien aus dem Verlauf nach Bedarf ignoriert und eine bereits berührte Datei wird nicht berührt. Schließlich scheint es etwas schneller zu sein als die andere Lösung. Ergebnisse mit
git/git
Repo:quelle
Ich habe einige Anfragen für eine Windows-Version gesehen, also hier ist es. Erstellen Sie die folgenden zwei Dateien:
C: \ Programme \ Git \ mingw64 \ share \ git-core \ templates \ hooks \ post-checkout
C: \ Programme \ Git \ mingw64 \ share \ git-core \ templates \ hooks \ post-checkout.ps1
Hierbei wird git whatchanged verwendet , sodass alle Dateien in einem Durchgang durchlaufen werden , anstatt git für jede Datei aufzurufen.
quelle
Ich arbeite an einem Projekt, in dem ein Klon meines Repositorys für die Verwendung mit
rsync
basierten Bereitstellungen aufbewahrt wird. Ich verwende Zweige, um auf verschiedene Umgebungen abzuzielen, undgit checkout
bewirkt, dass sich die Dateimodifikationen ändern.Nachdem ich erfahren hatte, dass git keine Möglichkeit bietet, Dateien auszuchecken und Zeitstempel beizubehalten, stieß ich
git log --format=format:%ai --name-only .
in einer anderen SO-Frage auf den Befehl : Listet die letzten Festschreibungsdaten für eine große Anzahl von Dateien schnell auf .Ich verwende jetzt das folgende Skript für
touch
meine Projektdateien und -verzeichnisse, damit meine Bereitstellung mitrsync
einfacher zu unterscheiden ist:quelle