Git hooks로 멋진 일을하려고하지만 실제로 어떻게 해야하는지 (또는 가능한지) 모르겠습니다.
내가해야 할 일은 : 모든 커밋마다 해시를 가져 와서 커밋의 파일을이 해시로 업데이트하고 싶습니다.
어떤 아이디어?
Git hooks로 멋진 일을하려고하지만 실제로 어떻게 해야하는지 (또는 가능한지) 모르겠습니다.
내가해야 할 일은 : 모든 커밋마다 해시를 가져 와서 커밋의 파일을이 해시로 업데이트하고 싶습니다.
어떤 아이디어?
답변:
SHA1을 추적되지 않은 파일 에 배치 하고 빌드 / 설치 / 배포 프로세스의 일부로 생성 된 것과 비슷한 작업을 수행하는 것이 좋습니다 . 분명히하기 쉽습니다 ( git rev-parse HEAD > filename
또는 아마도 git describe [--tags] > filename
), git의 추적과 다른 파일로 끝나는 것과 같은 미친 짓을 피합니다.
그러면 코드에서 버전 번호가 필요할 때이 파일을 참조하거나 빌드 프로세스에서 정보를 최종 제품에 통합 할 수 있습니다. 후자는 실제로 git 자체가 버전 번호를 얻는 방법입니다. 빌드 프로세스는 저장소에서 버전 번호를 가져온 다음 실행 파일에 빌드합니다.
현재 커밋 해시를 작성하는 것은 불가능합니다. 향후 커밋 해시를 미리 계산하면 파일을 수정하자마자 변경됩니다.
그러나 세 가지 옵션이 있습니다.
pre-commit
, 가게 이전 해시를 커밋 : 당신은 너무,이 의지 작업, 99.99 %의 경우에 커밋 삽입 / 수정하지 마십시오. 최악의 경우 여전히 소스 개정을 식별 할 수 있습니다.나는 후크 스크립트를 작성 중이며 여기에 '완료되면'게시하지만 Duke Nukem Forever 이전에 출시되었습니다 :))
업데이트 : 코드 .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
페어를 실제 커밋 해시 로 변환하는 도구입니다. :)
이 방법으로 커밋을 병합 할 수 있는지 여부를 모르겠습니다. 곧 확인하겠습니다
누군가가 ident에 대한 "man gitattributes"섹션을 지적했습니다.
신분
속성 ident가 경로로 설정되면, git은 blob 객체의 $ Id $를 $ Id :로 대체하고 그 뒤에 40 자 16 진 blob 객체 이름이오고 그 뒤에 달러 기호 $가옵니다. 작업 트리 파일에서 $ Id :로 시작하고 $로 끝나는 모든 바이트 시퀀스는 체크인시 $ Id $로 바뀝니다.
당신이 그것에 대해 생각하면, 이것은 CVS, Subversion 등이하는 일입니다. 저장소를 보면 저장소의 파일에 항상 $ Id $가 포함되어 있음을 알 수 있습니다. 그것은 그것의 확장을 포함하지 않습니다. 텍스트가 펼쳐지는 것은 체크 아웃시에만 가능합니다.
ident
커밋의 서두가 아니라 파일 자체의 해시입니다. 에서 git-scm.com/book/en/... : "하지만, 그 결과는 제한적으로 사용 당신이 CVS에서 키워드 대체를 사용했습니다 또는 파괴, 당신은 날짜 스탬프를 포함 할 경우 - SHA는 모두 도움이되지 않습니다. 왜냐하면 그것은 상당히 임의적이며 하나의 SHA가 다른 SHA보다 오래되었거나 새로운 것인지 알 수 없기 때문입니다. " filter
작동하지만 커밋 정보를 파일에 넣을 수 있습니다.
gitattributes 의 filter
속성 을 사용하면 됩니다. 커밋 ID를 삽입 하는 명령과smudge
clean
삭제합니다, 그것은 삽입있어 파일이 단지 때문에 변경하지 않을 것이라고 등이 ID를 커밋 명령을 사용합니다.
따라서 커밋 ID는 파일의 Blob에 저장되지 않습니다. 작업 복사본에서 확장되었습니다. 실제로 커밋 ID를 Blob에 삽입하면 무한 재귀 작업이됩니다. ☺)이 트리를 복제하는 사람은 자신을 위해 속성을 설정해야합니다.
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]}
기본적으로는에서 반환 한 메시지에 대해 sha1 체크섬을 실행합니다 git cat-file commit HEAD
. 이 메시지를 살펴보면 즉시 두 가지 문제가 발생합니다. 하나는 트리 sha1이고 두 번째는 커밋 시간입니다.
이제 커밋 시간은 메시지를 변경하고 특정 시간에 커밋 또는 일정을 예약하는 데 걸리는 시간을 추측하여 쉽게 처리 할 수 있습니다. 진정한 문제는에서 얻을 수있는 트리 sha1입니다 git ls-tree $(git write-tree) | git mktree
. 기본적으로 ls-tree의 메시지에서 모든 파일과 해당 sha1 체크섬의 목록 인 sha1 체크섬을 수행하고 있습니다.
따라서 커밋 sha1 체크섬은 트리 sha1 체크섬에 의존하며,이 파일은 sha1 체크섬 파일에 직접 의존하며, 원을 완성하고 커밋 sha1에 의존합니다. 따라서 나 자신이 사용할 수있는 기술에 대한 순환 문제가 있습니다.
덜 안전한 체크섬을 사용하면 무차별 강제로 파일의 체크섬을 파일 자체에 쓸 수 있습니다. 그러나 sha1을 사용하여 해당 작업을 수행 한 작업에 대해서는 알지 못합니다. 이것은 불가능하지는 않지만 현재의 이해로는 불가능합니다 (그러나 몇 년 후에 누가 알 수 있는지는 사소한 것입니다). 그러나 (blob) 체크섬의 (트리) 체크섬에 대한 (커밋) 체크섬을 파일에 써야하기 때문에 여전히 무차별 대입하기가 더 어렵습니다.