가장 먼저 구현한 기능은 'git init' 이었다.
https://git-scm.com/docs/git-init
Git - git-init Documentation
-q --quiet Only print error and warning messages; all other output will be suppressed. --bare Create a bare repository. If GIT_DIR environment is not set, it is set to the current working directory. --object-format= Specify the given object (hash algorithm
git-scm.com
git init 은 git 에 사용할 로컬 저장소를 만드는 기능으로 특정 위치에 .git 이라는 폴더를 생성하여 해당 위치가 git 저장소로 활용되도록 한다. .git 폴더에는 버전 관리를 위한 폴더 및 파일들이 포함되어 있는데, 대표적으로 objects 폴더, refs 폴더, HEAD 파일이 있다.
objects 폴더
버전 관리되는 파일들의 정보가 담겨있는 Git Object 파일들이 저장되는 폴더이다.
Git Object 는 blob, tree 등 용도에 따른 종류가 있던데, 차차 진행해나가면서 하나씩 정리할 것이다.
refs 폴더
외우기 힘든 SHA-1 값을 외우기 쉬운 이름으로 된 포인터로 연결한 것을 Git Refs 라고 하는데, 쉬운 이름과 연결된 SHA-1 값을 저장하는 폴더이다.
예) 특정 커밋을 구분하는 해시값인 1a410efbd13591db07496601ebc7a059dd55cfe9 대신 .git/refs/heads/master 에 해시값을 저장하여 head/master 라는 이름만으로 해당 커밋을 찾을 수 있도록 만들어준다. 실제로 해당 경로에서 master 파일을 열어보면 40자의 SHA-1 해시값이 기록되어 있다.
HEAD 파일
Git 이 마지막 커밋의 SHA-1 을 값을 알기 위한 정보가 담겨있는 파일이다.
위의 refs 와 다르게 간접(symbolic) refs 라서 직접 특정한 SHA-1 값을 가리키는게 아닌 다른 Refs 를 가리키므로 고유한 SHA-1 값이 존재하지 않는다. 이 파일을 열어보면 다음과 같이 마스터 브랜치의 마지막 커밋을 가리키는 Refs 가 명시되어 있으며 기본적으로는 다음과 같이 마스터의 마지막 커밋의 refs를 가리키고 있다. (이 값은 git init 구현에 사용될 예정)
ref: refs/head/master
구현할 기능은 다음과 같다.
1) .git 폴더를 생성한다.
2) 그외 필요한 폴더(objects, refs) 를 생성한다.
3) .git 폴더 안에 HEAD 파일을 생성하고 마스터의 헤드를 가리키는 간접 레퍼런스를 기록한다.
특별한 알고리즘이나 라이브러리 없이 대부분 언어에서 표준으로 지원하는 파일 입출력으로 구현할 수 있다.
codecrafters 에서는 처음에 이걸 굳이 고민하면서 구현할 가치가 없다고 생각했는지, 초기 코드에서 주석만 해제하도록 만들어뒀다.
아래는 C++ 로 작성된 코드이며, codecrafters 서비스 특성상 bash, cmake, vckpkg 를 사용하여 빌드와 테스트를 하므로
사용법에 익숙해져야 할 것 같다.
std::string command = argv[1];
if (command == "init") {
try {
std::filesystem::create_directory(".git");
std::filesystem::create_directory(".git/objects");
std::filesystem::create_directory(".git/refs");
std::ofstream headFile(".git/HEAD");
if (headFile.is_open()) {
headFile << "ref: refs/heads/main\n";
headFile.close();
} else {
std::cerr << "Failed to create .git/HEAD file.\n";
return EXIT_FAILURE;
}
std::cout << "Initialized git directory\n";
} catch (const std::filesystem::filesystem_error& e) {
std::cerr << e.what() << '\n';
return EXIT_FAILURE;
}
}
(다음 글에 계속)
'주제별 모험기 > Build Your Own X' 카테고리의 다른 글
| [Build your own git] #5 write-tree 명령어 만들기 (0) | 2025.01.07 |
|---|---|
| [Build your own git] #4 ls-tree 명령어와 tree objects (0) | 2025.01.07 |
| [Build your own git] #3 git hash-object 명령어 만들기 (0) | 2025.01.06 |
| [Build your own git] #2 cat-file 명령어와 Git Object (0) | 2025.01.02 |
| [Build your own git] #0 시작 (0) | 2025.01.01 |