it-swarm.com.de

Wechsel von CVS zu Git: $ Id: $ Äquivalent?

Ich las eine Reihe von Fragen, in denen ich nach einfachen Quellcodeverwaltungswerkzeugen fragte, und Git schien eine vernünftige Wahl zu sein. Ich habe es am Laufen und es funktioniert soweit gut. Ein Aspekt, den ich an CVS mag, ist das automatische Inkrementieren einer Versionsnummer.

Ich verstehe, dass dies in einem verteilten Repository weniger Sinn macht, aber als Entwickler möchte/brauche ich so etwas. Lassen Sie mich erklären, warum:

Ich benutze Emacs. In regelmäßigen Abständen gehe ich durch und suche nach neuen Versionen der LISP-Quelldateien für Pakete von Drittanbietern. Angenommen, ich habe eine Datei namens foo.el, die laut Header die Version 1.3 ist. Wenn ich die neueste Version nachsehe und sehe, dass sie 1.143 oder 2.6 oder was auch immer ist, weiß ich, dass ich ziemlich weit hinten bin.

Wenn ich stattdessen ein paar 40-Zeichen-Hashes sehe, weiß ich nicht, was später ist, oder kann mir keine Vorstellung davon machen, wie viel später es ist. Ich würde es absolut hassen, wenn ich ChangeLogs manuell überprüfen müsste, nur um eine Vorstellung davon zu bekommen, wie veraltet ich bin.

Als Entwickler möchte ich diese Höflichkeit, so wie ich es sehe, auf die Leute ausdehnen, die meine Ausgabe verwenden (und ich mache mir vielleicht einen Scherz darüber, dass das jemand ist, aber lassen wir das für einen Moment beiseite). Ich möchte nicht daran denken müssen, die verdammte Zahl jedes Mal selbst zu erhöhen, oder einen Zeitstempel oder ähnliches. Das ist ein echter PITA, und das weiß ich aus Erfahrung.

Welche Alternativen habe ich? Wenn ich kein $ Id: $ -Äquivalent erhalten kann, wie kann ich sonst das liefern, wonach ich suche?

Ich sollte erwähnen, dass meine Erwartung ist, dass der Endbenutzer KEIN Git installiert haben wird und selbst wenn dies der Fall ist, kein lokales Repository vorhanden ist (tatsächlich erwarte ich, dass es nicht auf diese Weise verfügbar ist). 

115
Joe Casadonte

Die SHA ist nur eine Darstellung einer Version (wenn auch kanonisch). Der git describe-Befehl bietet andere an und tut dies recht gut.

Wenn ich zum Beispiel git describe in meinem Master-Zweig meines Java-Memcached-Clients source ausführte, erhalte ich Folgendes:

2.2-16-gc0cd61a

Das sagt zwei wichtige Dinge:

  1. Seit 2.2 wurden in diesem Baum genau 16 Commits ausgeführt
  2. Der exact -Quellbaum kann auf dem Klon eines anderen Benutzers angezeigt werden.

Angenommen, Sie haben zum Beispiel eine version-Datei mit der Quelle gepackt (oder sogar den gesamten Inhalt für die Verteilung umgeschrieben), um diese Nummer anzuzeigen. Nehmen wir an, die gepackte Version war 2.2-12-g6c4ae7a (keine Version, sondern eine gültige Version).

Sie können jetzt genau sehen, wie weit hinter Ihnen (4 Commits) sind, und Sie können genau sehen, welche 4 Commits:

# The RHS of the .. can be Origin/master or empty, or whatever you want.
% git log --pretty=format:"%h %an %s" 2.2-12-g6c4ae7a..2.2-16-gc0cd61a
c0cd61a Dustin Sallings More tries to get a timeout.
8c489ff Dustin Sallings Made the timeout test run on every protocol on every bui
fb326d5 Dustin Sallings Added a test for bug 35.
fba04e9 Valeri Felberg Support passing an expiration date into CAS operations.
64
Dustin

Inzwischen gibt es Unterstützung für $ Id: $ in Git. Um es für die Datei README zu aktivieren, würden Sie "README ident" in .gitattributes eingeben. Platzhalter für Dateinamen werden unterstützt. Siehe man gitattributes für Details.

51

Dies ist keine unangemessene Anfrage vom OP.

Mein Anwendungsfall ist:

  1. Ich verwende Git für meinen persönlichen Code, daher keine Zusammenarbeit mit anderen.
  2. Ich behalte System-Bash-Skripts, die in /usr/local/bin gehen können, wenn sie fertig sind.

Ich verwende drei separate Maschinen mit demselben Git-Repository. Es wäre schön zu wissen, welche "Version" der Datei ich derzeit in /usr/local/bin habe, ohne ein manuelles "diff -u <Repo-Version> <Version in/usr/local/bin>" ausführen zu müssen.

Wenn Sie negativ sind, denken Sie daran, dass es andere Anwendungsfälle gibt. Nicht jeder verwendet Git für die Zusammenarbeit mit den Dateien im Git-Repository als "endgültigem" Speicherort.

Wie auch immer, ich habe so eine Attributdatei im Repository erstellt:

cat .git/info/attributes
# see man gitattributes
*.sh ident
*.pl ident
*.cgi ident

Dann füge $ Id $ irgendwo in die Datei ein (ich lege es gerne nach dem Shebang).

Das Commit Beachten Sie, dass dies die Erweiterung nicht automatisch wie erwartet ausführt. Sie müssen die Datei erneut zusammenstellen, z. B.

git commit foo.sh
rm foo.sh
git co foo.sh

Und dann sehen Sie zum Beispiel die Erweiterung:

$ head foo.sh
#!/bin/sh

# $Id: e184834e6757aac77fd0f71344934b1cd774e6d4 $

Einige gute Informationen finden Sie in Wie aktiviere ich die Ident-Zeichenfolge für ein Git-Repository?.

31
Imran-UK

Nicht sicher, ob dies jemals in Git sein wird. Um Zitat Linus zu zitieren:

"Die ganze Vorstellung von Keyword-Substitution ist einfach total idiotisch. Es ist trivial, außerhalb des eigentlichen Inhalts-Trackings zu arbeiten, wenn Sie wollen, dass es beim Freigeben von Bäumen als Teer-Kugeln usw. vorhanden ist."

Es ist jedoch ziemlich einfach, das Protokoll zu überprüfen. Wenn Sie den stabilen Zweig von foo.el verfolgen, können Sie sehen, welche neuen Commits im Protokoll des stabilen Zweigs enthalten sind und nicht in Ihrer lokalen Kopie enthalten sind. Wenn Sie die interne Versionsnummer von CVS simulieren möchten, können Sie den Zeitstempel des letzten Commits vergleichen.

Bearbeiten: Sie sollten die Skripte einer anderen Person schreiben oder verwenden, natürlich nicht manuell.

23
orip

Wie ich geschrieben habe vorher :

Die automatische Generierung von ID-Tags, die eine sinnvolle Versionsnummer enthalten, ist mit DSCM-Tools wie Bazaar nicht möglich, da sich die Entwicklungslinien aller unterscheiden können. Jemand könnte sich also auf die Version „1.41“ einer Datei beziehen, aber Ihre Version „1.41“ dieser Datei unterscheidet sich.

Grundsätzlich macht $ Id $ mit Bazaar, Git und anderen verteilten Quellcode-Verwaltungswerkzeugen keinen Sinn.

20
Bombe

Ich hatte das gleiche Problem. Ich brauchte eine Version, die einfacher als eine Hash-Zeichenfolge war und für Benutzer verfügbar war, die das Tool verwendeten, ohne eine Verbindung zum Repository herstellen zu müssen.

Ich habe es mit einem Git-Pre-Commit-Hook gemacht und mein Skript so geändert, dass es automatisch aktualisiert werden kann.

Ich stütze die Version von der Anzahl der durchgeführten Commits ab. Dies ist eine geringfügige Bedingung für das Rennen, da zwei Personen gleichzeitig festlegen könnten und beide denken, sie würden dieselbe Versionsnummer begehen, aber wir haben nicht viele Entwickler für dieses Projekt.

Meiner ist in Ruby, aber es ist kein besonders komplexer Code. Das Ruby-Skript hat:

MYVERSION = '1.090'
## Call script to do updateVersion from .git/hooks/pre-commit
def updateVersion
  # We add 1 because the next commit is probably one more - though this is a race
  commits = %x[git log #{$0} | grep '^commit ' | wc -l].to_i + 1
  vers = "1.%0.3d" % commits

  t = File.read($0)
  t.gsub!(/^MYVERSION = '(.*)'$/, "MYVERSION = '#{vers}'")
  bak = $0+'.bak'
  File.open(bak,'w') { |f| f.puts t }
  perm = File.stat($0).mode & 0xfff
  File.rename(bak,$0)
  File.chmod(perm,$0)
  exit
end

Und dann habe ich eine Befehlszeilenoption (-updateVersion), die updateVersion für das Tool aufruft.

Zum Schluss gehe ich zum Git-Kopf und erstelle ein ausführbares Skript in .git/hooks/pre-commit.

Das Skript wechselt einfach zum Kopf des Git-Verzeichnisses und ruft mein Skript mit -updateVersion auf.

Bei jedem Einchecken wird die MYVERSION-Variable basierend auf der Anzahl der Commits aktualisiert.

9

Etwas, das mit Git-Repositories gemacht wird, ist die Verwendung des tag-Objekts. Dies kann verwendet werden, um ein Commit mit einer beliebigen Art von String zu kennzeichnen, und es kann zum Markieren von Versionen verwendet werden. Sie können diese Tags in einem Repository mit dem Befehl git tag sehen, der alle Tags zurückgibt.

Es ist einfach, einen Tag auszuchecken. Wenn zum Beispiel ein Tag v1.1 vorhanden ist, können Sie das Tag in einem Zweig wie folgt überprüfen:

git checkout -b v1.1

Da es sich um ein Objekt auf oberster Ebene handelt, sehen Sie den gesamten Verlauf des Commits sowie die Möglichkeit, Unterschiede auszuführen, Änderungen vorzunehmen und Zusammenführungen durchzuführen.

Nicht nur das, aber ein Tag bleibt bestehen, auch wenn der Zweig, auf dem er sich befand, gelöscht wurde, ohne wieder in die Hauptzeile eingefügt zu werden.

8
Abizern

Wenn $ Keywords $ für Sie unerlässlich sind, könnten Sie vielleicht stattdessen nach Mercurial suchen? Es hat eine hgkeyword-Erweiterung, die das implementiert, was Sie möchten. Mercurial ist sowieso als DVCS interessant.

8
Keltia

Wenn Sie nur möchten, dass die Leute sich ein Bild davon machen können, wie weit sie veraltet sind, kann Git sie auf verschiedene Weise darüber informieren. Sie vergleichen zum Beispiel die Daten des letzten Commits für ihren Kofferraum und Ihren Kofferraum. Sie können git cherry verwenden, um zu sehen, wie viele Commits in Ihrem Trunk aufgetreten sind, die in ihrem Trunk nicht vorhanden sind.

Wenn das alles ist, wofür Sie dies wünschen, würde ich nach einer Möglichkeit suchen, es ohne Versionsnummer anzugeben.

Ich würde mir auch nicht die Mühe machen, die Höflichkeit auf jemanden auszudehnen, wenn Sie nicht sicher sind, dass sie es wollen. :)

4
skiphoppy

RCS-IDs sind für Single-File-Projekte eine Nizza, aber $ ID $ sagt nichts über das Projekt aus (es sei denn, Sie haben ein Dummy-Check-In für eine Dummy-Versionsdatei erzwungen).

Man könnte trotzdem interessiert sein, wie man Äquivalente von $ Author $, $ Date $, $ Revision $, $ RCSfile $ usw. auf Dateiebene oder auf Commit-Ebene erhält (wie man sie an Stellen setzt, an denen sich einige Schlüsselwörter befinden, ist ein anderer Frage). Ich habe keine Antwort darauf, sehe jedoch die Notwendigkeit, diese zu aktualisieren, insbesondere wenn die Dateien (jetzt in Git) von RCS-kompatiblen Systemen (CVS) stammen.

Solche Schlüsselwörter können interessant sein, wenn die Quellen unabhängig von einem Git-Repository verteilt werden (das ist auch das, was ich mache). Meine Lösung ist wie folgt:

Jedes Projekt hat ein eigenes Verzeichnis, und im Projektstammverzeichnis habe ich eine Textdatei mit dem Namen .version, deren Inhalt die aktuelle Version beschreibt (der Name, der beim Exportieren der Quellen verwendet wird).

Während der Arbeit für das nächste Release extrahiert ein Skript diese .version-Nummer, einige Git-Versionsdeskriptoren (wie git describe) und eine monotone Build-Nummer in .build (plus Host und Datum) in eine automatisch generierte Quelldatei, die mit dem endgültigen Programm verknüpft ist Sie erfahren aus welcher Quelle und wann sie gebaut wurde.

Ich entwickle neue Funktionen in separaten Zweigen, und als Erstes füge ich n (für "next") zur .version-Zeichenfolge hinzu (mehrere Zweige, die aus demselben Stamm stammen, würden dieselbe temporäre .version-Nummer verwenden). Vor der Veröffentlichung entscheide ich, welche Zweige zusammengeführt werden sollen (hoffentlich haben alle den gleichen .version). Bevor Sie die Zusammenführung begehen, aktualisiere ich .version auf die nächste Nummer (größere oder kleinere Aktualisierung, abhängig von den zusammengeführten Funktionen).

3
U. Windl

Wenn ich es richtig verstehe, möchten Sie im Wesentlichen wissen, wie viele Commits für eine bestimmte Datei seit der letzten Aktualisierung aufgetreten sind.

Rufen Sie zunächst die Änderungen im entfernten Origin ab, aber fügen Sie sie nicht in Ihrem Zweig master zusammen:

% git fetch

Rufen Sie dann ein Protokoll der Änderungen auf, die zwischen einer master-Verzweigung und dem entfernten Origin/master in einer bestimmten Datei vorgenommen wurden.

% git log master..Origin/master foo.el

Dadurch erhalten Sie die Protokollnachrichten aller Commits, die seit der letzten Fusion von Origin/master in Ihre master im Remote-Repository aufgetreten sind.

Wenn Sie nur eine Zählung der Änderungen wünschen, leiten Sie sie an wc weiter. Sprich so:

% git rev-list master..Origin/master foo.el | wc -l
3
Otto

Ich stimme denjenigen zu, die der Meinung sind, dass der Token-Ersatz eher zu Build-Tools als zu Versionskontroll-Tools gehört.

Sie sollten über ein automatisiertes Release-Tool verfügen, um die Versions-IDs in den Quellen zum Zeitpunkt der Veröffentlichung des Releases festzulegen.

1

Wenn Sie möchten, dass die Git-Commit-Informationen barrierefrei in Ihren Code eingefügt werden, müssen Sie müssen einen vorbereitenden Schritt ausführen, um sie dorthin zu bringen. In Bash für C/C++ könnte es ungefähr so ​​aussehen:

prebuild.sh

#!/bin/bash
commit=$(git rev-parse HEAD)
tag=$(git describe --tags --always ${commit})
cat <<EOF >version.c
#include "version.h"
const char* git_tag="${tag}";
const char* git_commit="${commit}";
EOF

mit version.h sieht aus wie:

#pragma once
const char* git_tag;
const char* git_commit;

Dann, wo immer Sie es brauchen, in Ihrem Code #include "version.h" und verweisen Sie git_tag oder git_commit nach Bedarf.

Und dein Makefile könnte ungefähr so ​​aussehen:

all: package
version:
  ./prebuild.sh
package: version
  # the normal build stuff for your project

Dies hat den Vorteil:

  • abrufen der derzeit korrekten Werte für dies unabhängig von Verzweigung, Zusammenführen von Cherry-Picking und dergleichen.

Diese Implementierung von prepublish.sh hat die Nachteile von:

  • erzwingen einer Neukompilierung, auch wenn sich der git_tag/git_commit nicht geändert hat.
  • lokale geänderte Dateien, die noch nicht festgeschrieben wurden, werden nicht berücksichtigt, sie wirken sich jedoch auf den Build aus.
    • verwenden Sie git describe --tags --always --dirty, um diesen Anwendungsfall abzufangen.
  • verschmutzt den globalen Namespace.

Ein Fancier prebuild.sh, der diese Probleme vermeiden könnte, wird dem Leser als Übung überlassen.

0
Jesse Chisholm

Da du Emacs benutzt, könntest du Glück haben :)

Ich bin zufällig auf diese Frage gestoßen, und auch zufällig bin ich gekommen durch Lively vor ein paar Tagen ein Emacs-Paket, mit dem Sie lebhafte Teile von Emacs LISP in Ihrem Dokument haben können. Ich habe es nicht versucht, um ehrlich zu sein, aber es kam mir in den Sinn, als ich das las.

0
Amr Mostafa

Um die Erweiterung auf alle Dateien in allen Unterverzeichnissen des Repositorys anzuwenden, fügen Sie dem obersten Verzeichnis im Repository (d. H. Wo Sie normalerweise die .gitattributes-Datei ablegen) eine .gitignore-Datei hinzu, die Folgendes enthält:

* ident

Um dies zu sehen, müssen Sie zunächst eine effektive Überprüfung der Datei (en) durchführen, beispielsweise das Löschen oder Bearbeiten der Dateien. Stellen Sie sie dann wieder her mit:

git checkout .

Und Sie sollten $Id$ sehen, ersetzt durch etwas wie:

$Id: ea701b0bb744c90c620f315e2438bc6b764cdb87 $

Von man gitattributes:

ident

Wenn das Attribut ident für einen Pfad festgelegt ist, ersetzt Git $ Id $ in der Blob-Objekt mit $ Id:, gefolgt vom 40-stelligen Hexadezimal-Blob-Objekt Name, gefolgt von einem Dollarzeichen $ an der Kasse. Jede Bytefolge, die beginnt mit $ Id: und endet mit $ in der Worktree-Datei, wird beim Einchecken durch $ Id $ ersetzt.

Diese ID ändert sich jedes Mal, wenn eine neue Version der Datei festgeschrieben wird.

0
Nagev

Ich kam auch von SCCS, RCS und CVS (%W% %G% %U%).

Ich hatte eine ähnliche Herausforderung. Ich wollte wissen, welche Version ein Code auf jedem System ist, auf dem er ausgeführt wird. Das System kann an ein Netzwerk angeschlossen sein oder nicht. Das System kann Git installiert haben oder nicht. Auf dem System ist möglicherweise das GitHub-Repository installiert.

Ich wollte die gleiche Lösung für verschiedene Arten von Code (.sh, .go, .yml, .xml usw.). Ich wollte, dass eine Person ohne Kenntnisse von Git oder GitHub die Frage beantworten kann "Welche Version laufen Sie?"

Also, ich schrieb einen Wrapper um ein paar Git-Befehle. Ich benutze es, um eine Datei mit einer Versionsnummer und einigen Informationen zu kennzeichnen. Es löst meine Herausforderung. Es kann dir helfen.

https://github.com/BradleyA/markit

git clone https://github.com/BradleyA/markit
cd markit
0
Bradley Allen