[git] Git 버전 해시를 자동으로 인쇄하도록 C 코드를 얻으려면 어떻게해야합니까?

Git 버전 해시에 액세스 할 수있는 C 코드를 작성하는 쉬운 방법이 있습니까?

실험실 환경에서 과학 데이터를 수집하기 위해 C로 소프트웨어를 작성했습니다. 내 코드는 수집 한 데이터를 나중에 분석하기 위해 .yaml 파일에 기록합니다. 내 실험은 매일 바뀌고 종종 코드를 수정해야합니다. 개정을 추적하기 위해 git 저장소를 사용합니다.

내 .yaml 데이터 파일에 주석으로 Git 개정 해시를 포함하고 싶습니다. 이렇게하면 .yaml 파일을보고 해당 파일에 표시된 데이터를 생성하는 데 사용 된 코드를 정확히 알 수 있습니다. 이 작업을 자동으로 수행하는 쉬운 방법이 있습니까?



답변

내 프로그램에서 git 버전 번호와 빌드 날짜를라는 별도의 파일에 보관 version.c합니다.

#include "version.h"
const char * build_date = "2009-11-10 11:09";
const char * build_git_sha = "6b54ea36e92d4907aba8b3fade7f2d58a921b6cd";

다음과 같은 헤더 파일도 있습니다.

#ifndef VERSION_H
#define VERSION_H
extern const char * build_date; /* 2009-11-10 11:09 */
extern const char * build_git_sha; /* 6b54ea36e92d4907aba8b3fade7f2d58a921b6cd */
#endif /* VERSION_H */

헤더 파일과 C 파일은 모두 다음과 같은 Perl 스크립트에 의해 생성됩니다.

my $git_sha = `git rev-parse HEAD`;
$git_sha =~ s/\s+//g;
# This contains all the build variables.
my %build;
$build{date} = make_date_time ();
$build{git_sha} = $git_sha;

hash_to_c_file ("version.c", \%build, "build_");

여기에 hash_to_c_file만드는 모든 작업 수행 version.cversion.hmake_date_time같이 문자열을 만든다.

메인 프로그램에는 루틴이 있습니다.

#include "version.h"

// The name of this program.
const char * program_name = "magikruiser";
// The version of this program.
const char * version = "0.010";

/* Print an ID stamp for the program. */

static void _program_id_stamp (FILE * output)
{
    fprintf (output, "%s / %s / %s / %s\n",
             program_name, version,
             build_date, build_git_sha);
}

나는 git에 대해 잘 알지 못하기 때문에 더 나은 방법이 있다면 의견을 환영합니다.


답변

make 기반 빌드를 사용하는 경우 Makefile에 넣을 수 있습니다.

GIT_VERSION := "$(shell git describe --abbrev=4 --dirty --always --tags)"

( 스위치의 기능 은 man git describe 참조 )

그런 다음 CFLAGS에 다음을 추가하십시오.

-DVERSION=\"$(GIT_VERSION)\"

그런 다음 #define처럼 프로그램에서 직접 버전을 참조 할 수 있습니다.

printf("Version: %s\n", VERSION);

기본적으로 이것은 축약 된 git commit id를 인쇄하지만 선택적으로 특정 릴리스에 다음과 같은 태그를 지정할 수 있습니다.

git tag -a v1.1 -m "Release v1.1"

그러면 다음과 같이 인쇄됩니다.

Version: v1.1-2-g766d

즉, “766d”로 시작하는 git commit id로 v1.1 이전에 2 번 커밋됩니다.

트리에 커밋되지 않은 변경 사항이 있으면 “-dirty”를 추가합니다.

종속성 검사가 없으므로 make clean버전을 강제로 업데이트 하려면 명시 적으로 수행해야합니다 . 그러나 이것은 해결할 수 있습니다 .

장점은 간단하고 perl 또는 awk와 같은 추가 빌드 종속성이 필요하지 않다는 것입니다. 이 접근 방식을 GNU automake 및 Android NDK 빌드와 함께 사용했습니다.


답변

@Kinopiko의 답변과 매우 유사한 것을 사용했지만 perl 대신 awk를 사용했습니다. 이것은 mingw의 특성상 awk가 설치되어 있지만 perl이 아닌 Windows 시스템에 붙어있는 경우 유용합니다. 작동 방식은 다음과 같습니다.

내 makefile에는 git, date 및 awk를 호출하여 ac 파일을 만드는 줄이 있습니다.

$(MyLibs)/version.c: FORCE
    $(GIT) rev-parse HEAD | awk ' BEGIN {print "#include \"version.h\""} {print "const char * build_git_sha = \"" $$0"\";"} END {}' > $(MyLibs)/version.c
    date | awk 'BEGIN {} {print "const char * build_git_time = \""$$0"\";"} END {} ' >> $(MyLibs)/version.c

코드를 컴파일 할 때마다 awk 명령은 다음과 같은 version.c 파일을 생성합니다.

/* version.c */
#include "version.h"
const char * build_git_sha = "ac5bffc90f0034df9e091a7b3aa12d150df26a0e";
const char * build_git_time = "Thu Dec  3 18:03:58 EST 2009";

다음과 같은 정적 version.h 파일이 있습니다.

/*version.h*/
#ifndef VERSION_H_
#define VERSION_H_

extern const char * build_git_time;
extern const char * build_git_sha;


#endif /* VERSION_H_ */

이제 나머지 코드는 단순히 version.h 헤더를 포함하여 빌드 시간과 git 해시에 액세스 할 수 있습니다. 모든 것을 마무리하기 위해 .gitignore 파일에 한 줄을 추가하여 git에게 version.c를 무시하도록 지시합니다. 이런 식으로 git은 지속적으로 병합 충돌을 일으키지 않습니다. 도움이 되었기를 바랍니다!


답변

프로그램은 git describe런타임에 또는 빌드 프로세스의 일부로으로 쉘 아웃 할 수 있습니다 .


답변

다음 두 가지를 수행 할 수 있습니다.

  • Git 이 파일에 일부 버전 정보를 포함 하도록 만들 수 있습니다 .

    간단한 방법은 사용하는 것입니다 ident 속성 (예를 들어) 퍼팅 의미,

    *.yaml    ident
    

    에서 .gitattributes파일 및 $Id$적절한 장소이다. 파일 내용의 SHA-1 식별자 (blob id) 로 자동 확장됩니다 . 이것은 파일 버전이 아니거나 마지막 커밋입니다.

    Git은 이러한 방식으로 $ Id $ 키워드를 지원하여 분기 전환, 분기 되감기 등에서 변경되지 않은 파일을 건드리지 않도록합니다. 정말로 Git이 파일에 커밋 (버전) 식별자 또는 설명을 입력하도록하려면 (남용) 사용할 수 있습니다. filter결제시 일부 키워드 (예 : $ Revision $)를 확장하기 위해 clean / smudge filter를 사용하고 커밋을 위해 정리합니다.

  • Linux 커널이나 Git 자체처럼 빌드 프로세스 를 만들 수 있습니다 .

    봐 가지고 GIT-VERSION-GEN 스크립트 및 힘내에서의 사용 메이크 파일 이 메이크가 생성 / 구성 중에 버전 정보를 내장하는 방법, 또는 예를 들어 gitweb/gitweb.cgi파일을.

    GIT-VERSION-GEN은 git describe 를 사용하여 버전 설명을 생성합니다. 프로젝트의 릴리스 / 마일스톤에 태그 (서명 / 주석 태그 사용)를 태그하는 것이 더 잘 작동해야합니다.


답변

이 작업을 수행해야 할 때 같은 태그를 사용합니다 RELEASE_1_23. SHA-1을 몰라도 태그가 무엇인지 결정할 수 있습니다. 나는 다음 태그를 커밋합니다. 원하는대로 프로그램에 해당 태그를 저장할 수 있습니다.


답변

njd27의 답변에 따라 코드가 다른 방식으로 빌드 될 때 기본값이있는 version.h 파일과 함께 종속성 스캔이있는 버전을 사용하고 있습니다. version.h를 포함하는 모든 파일이 다시 빌드됩니다.

또한 개정 날짜를 별도의 정의로 포함합니다.

# Get git commit version and date
GIT_VERSION := $(shell git --no-pager describe --tags --always --dirty)
GIT_DATE := $(firstword $(shell git --no-pager show --date=short --format="%ad" --name-only))

# recompile version.h dependants when GIT_VERSION changes, uses temporary file version~
.PHONY: force
version~: force
    @echo '$(GIT_VERSION) $(GIT_DATE)' | cmp -s - $@ || echo '$(GIT_VERSION) $(GIT_DATE)' > $@
version.h: version~
    @touch $@
    @echo Git version $(GIT_VERSION) $(GIT_DATE)