web-dev-qa-db-ja.com

Gitでは、同じコミット内のファイルに現在のコミットハッシュを書き込むにはどうすればよいですか

私はここでGitフックを使って派手なことをしようとしていますが、その方法(または可能かどうか)を本当に知りません。

私がする必要があるのは、すべてのコミットでそのハッシュを取得し、そのハッシュでコミット内のファイルを更新することです。

何か案は?

112
Felipe Kamakura

念頭に置いたものに似た方法をお勧めします。ビルド/インストール/展開プロセスの一部として生成されるntrackedファイルにSHA1を配置します。明らかに簡単です(git rev-parse HEAD > filename 多分 git describe [--tags] > filename)、そしてそれはgitの追跡とは異なるファイルで終わるような狂ったことを避ける。

コードは、バージョン番号が必要なときにこのファイルを参照できます。または、ビルドプロセスで情報を最終製品に組み込むことができます。後者は、実際にはgit自体がバージョン番号を取得する方法です。ビルドプロセスは、リポジトリからバージョン番号を取得し、実行可能ファイルにビルドします。

76
Cascabel

誰かが私にidentの「man gitattributes」セクションを指摘しました。

ident

属性identがパスに設定されている場合、gitはblobオブジェクトの$ Id $を$ Id:に置き換え、その後に40文字の16進blobオブジェクト名が続き、チェックアウト時にドル記号$が続きます。ワークツリーファイルで$ Id:で始まり$で終わるバイトシーケンスは、チェックイン時に$ Id $に置き換えられます。

考えてみると、これはCVS、Subversionなども同様です。リポジトリを見ると、リポジトリ内のファイルには常に$ Id $などが含まれていることがわかります。それの拡張が含まれることはありません。テキストが展開されるのはチェックアウト時のみです。

12
Baron Schwartz

現在のコミットハッシュを記述することは不可能です。将来のコミットハッシュを事前に計算できた場合、ファイルを変更するとすぐに変更されます。

ただし、次の3つのオプションがあります。

  1. スクリプトを使用して「コミットID」をインクリメントし、どこかに含めます。醜い
  2. ハッシュを保存するファイルを.gitignoreします。あまり便利ではない
  3. pre-commit以前のコミットハッシュを格納します:) 99.99%のケースではコミットを変更/挿入しないので、これは機能します。最悪の場合でも、ソースリビジョンを特定できます。

私はフックスクリプトに取り組んでおり、「完了したら」ここに投稿しますが、それでも-デュークヌケムフォーエバーがリリースされる前に:))

[〜#〜] upd [〜#〜].git/hooks/pre-commitのコード::

#!/usr/bin/env bash
set -e

#=== 'prev-commit' solution by o_O Tync
#commit_hash=$(git rev-parse --verify HEAD)
commit=$(git log -1 --pretty="%H%n%ci") # hash \n date
commit_hash=$(echo "$commit" | head -1)
commit_date=$(echo "$commit" | head -2 | tail -1) # 2010-12-28 05:16:23 +0300

branch_name=$(git symbolic-ref -q HEAD) # http://stackoverflow.com/questions/1593051/#1593487
branch_name=${branch_name##refs/heads/}
branch_name=${branch_name:-HEAD} # 'HEAD' indicates detached HEAD situation

# Write it
echo -e "prev_commit='$commit_hash'\ndate='$commit_date'\nbranch='$branch'\n" > gitcommit.py

必要なのは、prev_commit,branchペアを実際のコミットハッシュに変換するツールだけです:)

このアプローチでコミットのマージを区別できるかどうかはわかりません。すぐにチェックします

11
kolypto

これは、 gitattributesfilter属性を使用することで実現できます。コミットIDを挿入するsmudgeコマンドと、それを削除するcleanコマンドを提供する必要があります。これにより、挿入されたファイルがコミットIDのために変更されないようになります。 。

したがって、コミットIDはファイルのBLOBに保存されることはありません。作業コピーで展開されているだけです。 (コミットIDを実際にBLOBに挿入すると、無限に再帰的なタスクになります。☺)このツリーを複製するユーザーは、自分で属性を設定する必要があります。

9
legoscia

コミットボックスの外側を考えてください!

これをファイルhooks/post-checkoutにポップします

#!/bin/sh
git describe --all --long > config/git-commit-version.txt

このバージョンは、どこでも使用できます。

4
Keith Patrick

コミット内のファイルが変更されると、コミットのハッシュも変更されるため、実際にそうしたいとは思わない。

3
midtiby

これがgit internalsを使用して困難な問題である理由を調べてみましょう。現在のコミットのsha1を取得するには

_#!/bin/bash
commit=$(git cat-file commit HEAD) #
sha1=($((printf "commit %s\0" $(echo "$commit" | wc -c); echo "$commit") | sha1sum))
echo ${sha1[0]}
_

基本的に、_git cat-file commit HEAD_によって返されたメッセージに対してsha1チェックサムを実行します。このメッセージを調べると、2つのことがすぐに問題として飛び出します。 1つはツリーsha1で、2つ目はコミット時間です。

現在、コミット時間は、メッセージを変更し、特定の時間にコミットするか、コミットするようにスケジューリングするのにかかる時間を推測することで簡単に処理されます。本当の問題は、git ls-tree $(git write-tree) | git mktreeから取得できるツリーsha1です。基本的に、すべてのファイルとそのsha1チェックサムのリストであるls-treeからのメッセージに対してsha1チェックサムを実行しています。

したがって、コミットsha1チェックサムは、ツリーsha1チェックサムに依存します。ツリーsha1チェックサムは、ファイルsha1チェックサムに直接依存し、サークルを完成させ、コミットsha1に依存します。したがって、あなたは自分で利用できるテクニックに循環的な問題を抱えています。

安全性の低いチェックサム を使用すると、総当たりでファイルのチェックサムをファイル自体に書き込むことができることが示されています。ただし、sha1でそのタスクを達成した作業はわかりません。これは不可能ではありませんが、私たちの現在の理解では不可能に近い(しかし、おそらく数年後にそれが些細なことになることを知っている人)。ただし、(ツリー)チェックサム(チェック)の(コミット)チェックサムをファイルに書き込む必要があるため、これはブルートフォースにするのがさらに困難です。

0
Novice C