私たちは仕事でSVNを使いますが、私の個人的なプロジェクトのために私はGitを使うことにしました。それで昨日Gitをインストールしましたが、リビジョン番号同等のものGitではとは何でしょうか。
バージョン3.0.8で作業していて、すべてのバグ修正には、このバグ修正について説明するときに使用できる独自のリビジョン番号があります。それで、Gitのコードを3.0.8にタグ付けしたら、リビジョン番号やその他のより詳細な種類のIDとして使用できますか?ハッシュは人間にとってそれほどユーザーフレンドリーではないと思います。
あなたのための善または悪ニュース、そのハッシュISリビジョン番号。 SVNからgitに切り替えたときも、これで問題がありました。
Gitの "tagging"を使って特定のリビジョンを特定のバージョンの "release"としてタグ付けすることで、そのリビジョンを参照しやすくすることができます。これをチェックしてください ブログ記事 。
理解するべき重要なことはgitがリビジョン番号を持つことができないということです - 分散した性質について考えてください。ユーザAとユーザBが両方とも自分のローカルリポジトリにコミットしている場合、gitはどのようにして合理的に連続したリビジョン番号を割り当てることができますか? Aはお互いの変更をプッシュ/プルする前にBの知識がありません。
もう1つ注目すべきことは、バグ修正ブランチの単純化された分岐です。
リリースから始めましょう:3.0.8。その後、そのリリースの後に、これを行います。
git branch bugfixes308
これはバグ修正のためのブランチを作成します。ブランチをチェックアウトしてください。
git checkout bugfixes308
今すぐあなたが望む任意のバグ修正の変更を加えます。
git commit -a
それらをコミットし、マスターブランチに戻ります。
git checkout master
それから他のブランチからそれらの変更を引っ張って下さい:
git merge bugfixes308
そのように、あなたは別々のリリース特有のバグ修正ブランチを持っています、しかしあなたはまだあなたのメイン開発トランクにバグ修正変更を引っ張っています。
最新のGit(私の場合は1.8.3.4)を使用してブランチを使用しないで、次のことができます。
$ git rev-list --count HEAD
68
git describe
コマンドは、特定のコミットを参照する、やや読みやすい名前を作成します。たとえば、ドキュメントから:
Git.git現在のツリーのようなもので、私は得ます:
[torvalds@g5 git]$ git describe parent v1.0.4-14-g2414721
つまり、私の "parent"ブランチの現在のヘッドはv1.0.4に基づいていますが、それに加えていくつかのコミットがあるので、describeは追加のコミットの数( "14")とコミットの省略名を追加しました最後にそれ自体( "2414721")を追加します。
特定のリリースをタグ付けするために賢明な名前のタグを使用する限り、これはSVNの「リビジョン番号」とほぼ同等であると考えることができます。
他のポスターは正しいです、「改訂番号」はありません。
一番いい方法は "リリース"にタグを使うことだと思います!
しかし、私は偽のリビジョン番号に以下を利用しました(クライアントがリビジョンと進捗を見るために、彼らは同じ増加するリビジョンを持っていたかったので) Subversionで慣れているところではgitです。
"HEAD"の "現在のリビジョン"がこれを使ってシミュレートされていることを示します。
git rev-list HEAD | wc -l
しかし、クライアントが "revision" 1302にバグがあると私に言った場合はどうなりますか?
このために、私は〜/ .gitconfigの[alias]セクションに以下を追加しました。
show-rev-number = !sh -c 'git rev-list --reverse HEAD | nl | awk \"{ if(\\$1 == "$0") { print \\$2 }}\"'
git show-rev-number 1302
を使うことはそれから "リビジョン"のためのハッシュを出力するでしょう:)
私はしばらく前にその「テクニック」について Blog Post(in German) を作りました。
GitはSubversionと同じリビジョン番号の概念を持っていません。代わりに、コミットで作成された各スナップショットは、SHA1チェックサムによってタグ付けされます。どうして?分散バージョン管理システムでrevnoを実行することにはいくつかの問題があります。
第一に、開発はまったく線形ではないので、数をつけることはプログラマーとしてのあなたの必要性を満たすような方法で解決する問題としてはかなり難しいです。数字を追加してこれを修正しようとすると、数字が期待どおりに動作しない場合、すぐに問題になる可能性があります。
第二に、リビジョン番号は異なるマシンで生成されるかもしれません。これは数字の同期をより困難にします - 特に接続性が一方向であるため。リポジトリを持っているすべてのマシンにアクセスできない場合もあります。
3つ目は、gitでは、現在は使用されなくなったOpenCMシステムによってやや開拓された、コミットのidentity(コミットとは何か)は、そのname(SHAと同等です。 _ id)このnaming = identityの概念は非常に強力です。あなたがコミット名を持って座っているとき、それはまた偽造不可能な方法でコミットを識別します。これにより、git fsck
コマンドを使って最初の最初のコミットへのコミットすべての破損をチェックすることができます。
これで、リビジョンのDAG(Directed Acyclic Graph)があり、これらが現在のツリーを構成するため、your問題を解決するためのいくつかのツールが必要です。最初に、与えられた接頭辞1516bdがあなたのコミットを一意に識別する場合、ハッシュの一部を省略することができます。しかし、これもかなり工夫されています。代わりに、秘訣はタグやブランチを使うことです。タグやブランチは、あなたが与えられたコミットSHA1-idに付ける「黄色い付箋」に似ています。タグは本質的には動かないことを意味しますが、新しいHEADがコミットされるとブランチは移動します。タグやブランチを中心にコミットを参照する方法があります。git-rev-parseのmanページを参照してください。
通常、特定のコードの部分を処理する必要がある場合、その部分は変更中であり、そのように言ってトピック名が付いたブランチになります。たくさんのブランチを作成すること(プログラマーあたり20-30は前例のないことではありませんが、4-5は他の人が作業するために公開されています)は効果的なgitの秘訣です。すべての作業は独自のブランチとして開始し、テスト時にマージする必要があります。未発表のブランチは完全に書き直すことができ、歴史を破壊するこの部分はgitの力です。
変更がマスターに受け入れられたのとき、それはいくらかフリーズして考古学になります。その時点で、あなたはそれをタグ付けすることができますが、より頻繁に特定のコミットへの参照はsha1 sumを通してバグトラッカーまたは問題トラッカーで作られます。タグはバージョンバンプとメンテナンスブランチ(古いバージョン)用の分岐点のために予約される傾向があります。
興味のある方は、git infos から自動的にバージョン番号を管理しています 。
<major>.<minor>.<patch>-b<build>
buildはコミットの総数です。興味深いコードが Makefile
にあります。これは、バージョン番号の異なる部分にアクセスするための関連部分です。
LAST_TAG_COMMIT = $(Shell git rev-list --tags --max-count=1)
LAST_TAG = $(Shell git describe --tags $(LAST_TAG_COMMIT) )
TAG_PREFIX = "latex-tutorial-v"
VERSION = $(Shell head VERSION)
# OR try to guess directly from the last git tag
#VERSION = $(Shell git describe --tags $(LAST_TAG_COMMIT) | sed "s/^$(TAG_PREFIX)//")
MAJOR = $(Shell echo $(VERSION) | sed "s/^\([0-9]*\).*/\1/")
MINOR = $(Shell echo $(VERSION) | sed "s/[0-9]*\.\([0-9]*\).*/\1/")
PATCH = $(Shell echo $(VERSION) | sed "s/[0-9]*\.[0-9]*\.\([0-9]*\).*/\1/")
# total number of commits
BUILD = $(Shell git log --oneline | wc -l | sed -e "s/[ \t]*//g")
#REVISION = $(Shell git rev-list $(LAST_TAG).. --count)
#ROOTDIR = $(Shell git rev-parse --show-toplevel)
NEXT_MAJOR_VERSION = $(Shell expr $(MAJOR) + 1).0.0-b$(BUILD)
NEXT_MINOR_VERSION = $(MAJOR).$(Shell expr $(MINOR) + 1).0-b$(BUILD)
NEXT_PATCH_VERSION = $(MAJOR).$(MINOR).$(Shell expr $(PATCH) + 1)-b$(BUILD)
Bash関数:
git_rev ()
{
d=`date +%Y%m%d`
c=`git rev-list --full-history --all --abbrev-commit | wc -l | sed -e 's/^ *//'`
h=`git rev-list --full-history --all --abbrev-commit | head -1`
echo ${c}:${h}:${d}
}
のようなものを出力する
$ git_rev
2:0f8e14e:20130220
あれは
commit_count:last_abbrev_commit:date_YYmmdd
コミットのSHA1ハッシュ はSubversionのリビジョン番号と同じです。
これは私が他の解決策に基づいて私のメイクファイルでしたことです。これはあなたのコードにリビジョン番号を与えるだけでなく、それはあなたがリリースを作り直すことを可能にするハッシュも追加します。
# Set the source control revision similar to Subversion to use in 'c'
# files as a define.
# You must build in the master branch otherwise the build branch will
# be prepended to the revision and/or "dirty" appended. This is to
# clearly ID developer builds.
REPO_REVISION_:=$(Shell git rev-list HEAD --count)
BUILD_BRANCH:=$(Shell git rev-parse --abbrev-ref HEAD)
BUILD_REV_ID:=$(Shell git rev-parse HEAD)
BUILD_REV_ID_SHORT:=$(Shell git describe --long --tags --dirty --always)
ifeq ($(BUILD_BRANCH), master)
REPO_REVISION:=$(REPO_REVISION_)_g$(BUILD_REV_ID_SHORT)
else
REPO_REVISION:=$(BUILD_BRANCH)_$(REPO_REVISION_)_r$(BUILD_REV_ID_SHORT)
endif
export REPO_REVISION
export BUILD_BRANCH
export BUILD_REV_ID
Gitからバージョン情報を取得し、タグ付けを簡単にするためのPowerShellユーティリティをいくつか書きました。
機能:Get-LastVersion、Get-Revision、Get-NextMajorVersion、Get-NextMinorVersion、TagNextMajorVersion、TagNextMinorVersion:
# Returns the last version by analysing existing tags,
# assumes an initial tag is present, and
# assumes tags are named v{major}.{minor}.[{revision}]
#
function Get-LastVersion(){
$lastTagCommit = git rev-list --tags --max-count=1
$lastTag = git describe --tags $lastTagCommit
$tagPrefix = "v"
$versionString = $lastTag -replace "$tagPrefix", ""
Write-Host -NoNewline "last tagged commit "
Write-Host -NoNewline -ForegroundColor "yellow" $lastTag
Write-Host -NoNewline " revision "
Write-Host -ForegroundColor "yellow" "$lastTagCommit"
[reflection.Assembly]::LoadWithPartialName("System.Version")
$version = New-Object System.Version($versionString)
return $version;
}
# Returns current revision by counting the number of commits to HEAD
function Get-Revision(){
$lastTagCommit = git rev-list HEAD
$revs = git rev-list $lastTagCommit | Measure-Object -Line
return $revs.Lines
}
# Returns the next major version {major}.{minor}.{revision}
function Get-NextMajorVersion(){
$version = Get-LastVersion;
[reflection.Assembly]::LoadWithPartialName("System.Version")
[int] $major = $version.Major+1;
$rev = Get-Revision
$nextMajor = New-Object System.Version($major, 0, $rev);
return $nextMajor;
}
# Returns the next minor version {major}.{minor}.{revision}
function Get-NextMinorVersion(){
$version = Get-LastVersion;
[reflection.Assembly]::LoadWithPartialName("System.Version")
[int] $minor = $version.Minor+1;
$rev = Get-Revision
$next = New-Object System.Version($version.Major, $minor, $rev);
return $next;
}
# Creates a tag with the next minor version
function TagNextMinorVersion($tagMessage){
$version = Get-NextMinorVersion;
$tagName = "v{0}" -f "$version".Trim();
Write-Host -NoNewline "Tagging next minor version to ";
Write-Host -ForegroundColor DarkYellow "$tagName";
git tag -a $tagName -m $tagMessage
}
# Creates a tag with the next major version (minor version starts again at 0)
function TagNextMajorVersion($tagMessage){
$version = Get-NextMajorVersion;
$tagName = "v{0}" -f "$version".Trim();
Write-Host -NoNewline "Tagging next majo version to ";
Write-Host -ForegroundColor DarkYellow "$tagName";
git tag -a $tagName -m $tagMessage
}
ビルド番号としてgitハッシュを使用することの問題は、単調増加ではないということです。 OSGiはビルド番号にタイムスタンプを使うことを提案します。 Subversionまたはperforceの変更番号の代わりにブランチへのコミットの数を使用できるようです。
各コミットには固有のハッシュがあります。それ以外にはgitにリビジョン番号はありません。もっとユーザーフレンドリにしたい場合は、コミットを自分でタグ付けする必要があります。
私はちょうど別の可能なアプローチに注意したいと思います-そしてそれはv 1.6.6以降に存在するgit
git-notes(1) を使用することです( Note to Self -Git )(私はgit
バージョン1.7.9.5を使用しています)。
基本的に、git svn
を使用して、線形履歴(標準レイアウト、ブランチ、タグなし)でSVNリポジトリを複製し、複製されたgit
リポジトリのリビジョン番号を比較しました。このgitクローンにはデフォルトでタグがないため、git describe
を使用できません。ここでの戦略は、線形履歴に対してのみ機能する可能性が高い-マージなどでどうなるかわからない。しかし、基本的な戦略は次のとおりです。
git rev-list
に尋ねるrev-list
はデフォルトで「逆時系列」にあるため、--reverse
スイッチを使用して、最も古い順にソートされたコミットのリストを取得しますbash
Shellを使用しますgit log
と--notes
を使用してログを参照します。これにより、コミットのメモもダンプされます。この場合は、「リビジョン番号」になりますgit status
に表示されません)まず、git
にはデフォルトのノートの場所がありますが、.git
の下の別のディレクトリに保存するノートのref
(erence)を指定することもできます。たとえば、git
リポジトリフォルダーで、git notes get-ref
を呼び出して、どのディレクトリになるかを確認できます。
$ git notes get-ref
refs/notes/commits
$ git notes --ref=whatever get-ref
refs/notes/whatever
注意すべき点は、notes add
を--ref
と組み合わせた場合、後でその参照を再度使用する必要があることです。そうしないと、「 No note found for object XXX ... 「。
この例では、ノートのref
を「linrev」(線形改訂用)と呼ぶことにしました-これは、手順が既存のノートに干渉する可能性が低いことも意味します。 git
初心者であるため、--git-dir
スイッチも使用していますが、それを理解するのにいくつかの問題がありました。したがって、:)
を「後で覚えておいてください」。また、--no-pager
を使用するときに、git log
を使用してless
の生成を抑制します。
したがって、サブフォルダmyrepo_git
がgit
リポジトリであるディレクトリにいると仮定します。できること:
### check for already existing notes:
$ git --git-dir=./myrepo_git/.git notes show
# error: No note found for object 04051f98ece25cff67e62d13c548dacbee6c1e33.
$ git --git-dir=./myrepo_git/.git notes --ref=linrev show
# error: No note found for object 04051f98ece25cff67e62d13c548dacbee6c1e33.
### iterate through rev-list three, oldest first,
### create a cmdline adding a revision count as note to each revision
$ ix=0; for ih in $(git --git-dir=./myrepo_git/.git rev-list --reverse HEAD); do \
TCMD="git --git-dir=./myrepo_git/.git notes --ref linrev"; \
TCMD="$TCMD add $ih -m \"(r$((++ix)))\""; \
echo "$TCMD"; \
eval "$TCMD"; \
done
# git --git-dir=./myrepo_git/.git notes --ref linrev add 6886bbb7be18e63fc4be68ba41917b48f02e09d7 -m "(r1)"
# git --git-dir=./myrepo_git/.git notes --ref linrev add f34910dbeeee33a40806d29dd956062d6ab3ad97 -m "(r2)"
# ...
# git --git-dir=./myrepo_git/.git notes --ref linrev add 04051f98ece25cff67e62d13c548dacbee6c1e33 -m "(r15)"
### check status - adding notes seem to not affect it:
$ cd myrepo_git/
$ git status
# # On branch master
# nothing to commit (working directory clean)
$ cd ../
### check notes again:
$ git --git-dir=./myrepo_git/.git notes show
# error: No note found for object 04051f98ece25cff67e62d13c548dacbee6c1e33.
$ git --git-dir=./myrepo_git/.git notes --ref=linrev show
# (r15)
### note is saved - now let's issue a `git log` command, using a format string and notes:
$ git --git-dir=./myrepo_git/.git --no-pager log --notes=linrev --format=format:"%h: %an: %ad: >>%s<< %N" HEAD
# 04051f9: _user_: Sun Apr 21 18:29:02 2013 +0000: >>test message 15 << (r15)
# 77f3902: _user_: Sun Apr 21 18:29:00 2013 +0000: >>test message 14<< (r14)
# ...
# 6886bbb: _user_: Sun Apr 21 17:11:52 2013 +0000: >>initial test message 1<< (r1)
### test git log with range:
$ git --git-dir=./myrepo_git/.git --no-pager log --notes=linrev --format=format:"%h: %an: %ad: >>%s<< %N" HEAD^..HEAD
# 04051f9: _user_: Sun Apr 21 18:29:02 2013 +0000: >>test message 15 << (r15)
### erase notes - again must iterate through rev-list
$ ix=0; for ih in $(git --git-dir=./myrepo_git/.git rev-list --reverse HEAD); do \
TCMD="git --git-dir=./myrepo_git/.git notes --ref linrev"; \
TCMD="$TCMD remove $ih"; \
echo "$TCMD"; \
eval "$TCMD"; \
done
# git --git-dir=./myrepo_git/.git notes --ref linrev remove 6886bbb7be18e63fc4be68ba41917b48f02e09d7
# Removing note for object 6886bbb7be18e63fc4be68ba41917b48f02e09d7
# git --git-dir=./myrepo_git/.git notes --ref linrev remove f34910dbeeee33a40806d29dd956062d6ab3ad97
# Removing note for object f34910dbeeee33a40806d29dd956062d6ab3ad97
# ...
# git --git-dir=./myrepo_git/.git notes --ref linrev remove 04051f98ece25cff67e62d13c548dacbee6c1e33
# Removing note for object 04051f98ece25cff67e62d13c548dacbee6c1e33
### check notes again:
$ git --git-dir=./myrepo_git/.git notes show
# error: No note found for object 04051f98ece25cff67e62d13c548dacbee6c1e33.
$ git --git-dir=./myrepo_git/.git notes --ref=linrev show
# error: No note found for object 04051f98ece25cff67e62d13c548dacbee6c1e33.
したがって、少なくともブランチのない完全に線形の履歴の特定のケースでは、リビジョン番号はこのアプローチと一致するようです-さらに、このアプローチにより、git log
をリビジョン範囲で使用しながら、正しいリビジョン番号を取得できるようです-ただし、コンテキストが異なるYMMV ...
これが誰かを助けることを願って、
乾杯!
編集:OK、ここでは少し簡単です。git
およびsetlinrev
と呼ばれる上記のループのunsetlinrev
エイリアスがあります。あなたのgitリポジトリフォルダにいるとき、(厄介なbash
エスケープに注意してください。 #16136745-セミコロンを含むGitエイリアスを追加 も参照してください。):
cat >> .git/config <<"EOF"
[alias]
setlinrev = "!bash -c 'ix=0; for ih in $(git rev-list --reverse HEAD); do \n\
TCMD=\"git notes --ref linrev\"; \n\
TCMD=\"$TCMD add $ih -m \\\"(r\\$((++ix)))\\\"\"; \n\
#echo \"$TCMD\"; \n\
eval \"$TCMD\"; \n\
done; \n\
echo \"Linear revision notes are set.\" '"
unsetlinrev = "!bash -c 'ix=0; for ih in $(git rev-list --reverse HEAD); do \n\
TCMD=\"git notes --ref linrev\"; \n\
TCMD=\"$TCMD remove $ih\"; \n\
#echo \"$TCMD\"; \n\
eval \"$TCMD 2>/dev/null\"; \n\
done; \n\
echo \"Linear revision notes are unset.\" '"
EOF
...したがって、線形の改訂ノートを含むログを実行する前に、単にgit setlinrev
を呼び出すことができます。 git unsetlinrev
は、完了したらそれらのメモを削除します。 git repoディレクトリ内の例:
$ git log --notes=linrev --format=format:"%h: %an: %ad: >>%s<< %N" HEAD^..HEAD
04051f9: _user_: Sun Apr 21 18:29:02 2013 +0000: >>test message 15 <<
$ git setlinrev
Linear revision notes are set.
$ git log --notes=linrev --format=format:"%h: %an: %ad: >>%s<< %N" HEAD^..HEAD
04051f9: _user_: Sun Apr 21 18:29:02 2013 +0000: >>test message 15 << (r15)
$ git unsetlinrev
Linear revision notes are unset.
$ git log --notes=linrev --format=format:"%h: %an: %ad: >>%s<< %N" HEAD^..HEAD
04051f9: _user_: Sun Apr 21 18:29:02 2013 +0000: >>test message 15 <<
シェルがこれらのエイリアスを完了するのにかかる時間は、リポジトリ履歴のサイズに依存します。
Ant ビルドプロセスをお持ちの方は、このターゲットを使ってgit上のプロジェクトのバージョン番号を生成することができます。
<target name="generate-version">
<exec executable="git" outputproperty="version.revisions">
<arg value="log"/>
<arg value="--oneline"/>
</exec>
<resourcecount property="version.revision" count="0" when="eq">
<tokens>
<concat>
<filterchain>
<tokenfilter>
<stringtokenizer delims="\r" />
</tokenfilter>
</filterchain>
<propertyresource name="version.revisions" />
</concat>
</tokens>
</resourcecount>
<echo>Revision : ${version.revision}</echo>
<exec executable="git" outputproperty="version.hash">
<arg value="rev-parse"/>
<arg value="--short"/>
<arg value="HEAD"/>
</exec>
<echo>Hash : ${version.hash}</echo>
<exec executable="git" outputproperty="version.branch">
<arg value="rev-parse"/>
<arg value="--abbrev-ref"/>
<arg value="HEAD"/>
</exec>
<echo>Branch : ${version.branch}</echo>
<exec executable="git" outputproperty="version.diff">
<arg value="diff"/>
</exec>
<condition property="version.dirty" value="" else="-dirty">
<equals arg1="${version.diff}" arg2=""/>
</condition>
<tstamp>
<format property="version.date" pattern="yyyy-mm-dd.HH:mm:ss" locale="en,US"/>
</tstamp>
<echo>Date : ${version.date}</echo>
<property name="version" value="${version.revision}.${version.hash}.${version.branch}${version.dirty}.${version.date}" />
<echo>Version : ${version}</echo>
<echo file="version.properties" append="false">version = ${version}</echo>
</target>
結果は次のようになります。
generate-version:
[echo] Generate version
[echo] Revision : 47
[echo] Hash : 2af0b99
[echo] Branch : master
[echo] Date : 2015-04-20.15:04:03
[echo] Version : 47.2af0b99.master-dirty.2015-04-20.15:04:03
バージョン番号を生成したときにコミットされていないファイルがある場合は、ダーティフラグがここにあります。通常、アプリケーションをビルドまたはパッケージ化するときには、コードを変更するたびにリポジトリに入れる必要があります。
Gitのマニュアルによると、タグはこの問題に対する素晴らしい答えです。
Gitで注釈付きタグを作成するのは簡単です。最も簡単な方法は、tagコマンドを実行するときに-aを指定することです。
$ git tag -a v1.4 -m 'my version 1.4'
$ git tag
v0.1
v1.3
v1.4
チェックアウト 2.6 Gitの基本 - タグ付け
コミットのSHA-1 IDと一緒に、サーバーの日付と時刻は役に立ちましたか?
このようなもの:
2013年8月19日11時30分25秒にコミットが行われ、6886bbb7be18e63fc4be68ba41917b48f02e09d7_19aug2013_113025と表示される
使用している このコマンドは、gitからバージョンとリビジョンを取得します。
git describe --tags --exact-match 2> /dev/null || git describe --always
返す
gcc7b71f
)v2.1.0
、リリースに使用)v5.3.0-88-gcc7b71f
)Visual Studioのポストビルドイベント
echo >RevisionNumber.cs static class Git { public static int RevisionNumber =
git >>RevisionNumber.cs rev-list --count HEAD
echo >>RevisionNumber.cs ; }
オンラインリポジトリで長い間調査した結果、論理的にはGitのリビジョン番号とコミット番号に違いがないことがわかりました。