본문 바로가기

Tools

깃허브 잔디 조작해서 아스키 아트 그리기

 

로컬에만 커밋을 해 두고 푸시 안 하고 있다가

며칠이 지난 나중에 푸시하니 로컬에 커밋한 시간에 깃허브 잔디가 심어진것을 보았다.

 

그걸 본 나는 이상한 생각이 들었다

깃 커밋 구조를 파악하면 깃허브 잔디로 재미좀 보겠는걸?

 

 

그러기 위해서는 github 가 어떤 정보를 보고 잔디를 생성해 주는지 알아보아야 한다.

 

먼저 알아야 할 것은 git이 데이터를 관리하는 위치는. git/objects 디렉터리인데

여기에는 파일 해시, 커밋 해시 등 git 이 특정 상태를 기록하기 위한 모든 것을 해시로 관리하고 있다

 

먼저 문제의 커밋이다

commit 0f6f8949e6dbc748b098d88377c806dbd341e196 (HEAD -> main, origin/main)
Author: birariro <vps32@naver.com>
Date:   Mon Dec 4 13:50:48 2023 +0900

    feat: spring batch init

 

커밋 메시지와 작성자, 이메일, 시간 정보 등이 있었으며

 

타임스탬프로 이루어진 시간을 보기 쉽게 변환해 보면

2023-12-04T04:50:48

 

잔디가 심어졌던 과거의 날짜인 12월 4일 즉 github는 이 시간 정보를 가지고 잔디를 심어주고 있는 것이다.

 

그렇다면 위와같은 커밋을 직접 생성할 수 있다면 타임스탬프값을 자유롭게 변경이 가능할 것이다.

위에서 말한 것처럼 모든 것을 objects에서 해시로 관리하고 있기에 저 해시를 통해 자세한 내용을 자세히 확인할  수 있다

$ git cat-file -p 0f6f8949e6dbc748b098d88377c806dbd341e196

tree 664f501868770f3e087f074a5cc095489cabb63d
parent 63bf5144c9c8bcea94fc2fdea3a250a90d273096
author birariro <vps32@naver.com> 1701665448 +0900
committer birariro <vps32@naver.com> 1701665448 +0900

feat: spring batch init

 

커밋 기준 파일의 상태를 관리하는 스냅샷 tree의 해시, 이전 커밋 해시 번호의 정보를 추가로 얻을 수 있었다.

 

tree 해시도 자세히 확인해 보면

$ git cat-file -p 664f501868770f3e087f074a5cc095489cabb63d

100644 blob 0de153ff612082629718fa17e9552a95fd6fe720    .gitignore
100644 blob 189d2e5f1483a95e9ed841b8dae0e2c49e9bfaf2    .java-version
100644 blob 10a8ad46be1387c814f94456868e07144e4b7ae2    README.md
100644 blob 7318b6bf46336eb6fa20bcde8b2901c7e9ee91fa    build.gradle
040000 tree 26f39dea09152e3ddca2358a63b639cfe82ee9d2    gradle
100755 blob 1aa94a4269074199e6ed2c37e8db3e0826030965    gradlew
100644 blob 6689b85beecde676054c39c2408085f41e6be6dc    gradlew.bat
100644 blob 67eeb94f6ab958d090bae581c5c2dcf7a5bd2d52    settings.gradle
040000 tree e13fc2ea3cdfad52f2b4711ad8e144db33eea129    src
040000 tree d71160b9d81024c09b32409c9ebf21544753e703    tools

관리되는 파일별 스냅샷 상태가 확인 가능했다

 

변경 사항의 기본단위는 blob, 그리고 그들의 집합인 tree로 이루어져 있으며

유닉스 파일모드에 의해 100644는 일반파일, 100755는 실행파일, 12000 은 심볼릭 파일 등을 나타내고 있다

 

커밋을 강제 만드는 건 크게 어려운 게 아니었다.

  1. 변경 사항을 만든다
  2. 변경 사항을 .git/objects에 해시로 등록한다
  3. 변경 사항 해시를 통해 tree 해시를 등록한다
  4. tree 해시를 이용하여 과거의 타임스탬프를 가지고 있는 commit 해시를 등록한다
  5. push 한다

 

먼저 정상적으로 해시값을 도출하고 있는지 확인하기 위해

git add, commit와 같은 고수준 명령을 사용하고 그다음에 저수준 명령으로 같은 해시가 도출되는지 확인하면서

commit의 타임스탬프 을 마음대로 조작하려 한다.

 

고수준 명령으로 정상 해시 확인

note.txt 파일의 내용을 변경

git add. 실행

git commit -m "second commit" 실행

 

커밋 메시지 해시 확인(git log)

9613c407f47fb8918606678638e0716b29e4851e

커밋의 트리 해시 확인(git cat-file -p )

64aaeb047944bac09608e517db19add35ffa982c

 

변경된 파일 해시 확인(git cat-file -p) 

ac50d0ca4089368d0f4268cfa32e90960685194a

 

이제 저수준으로 같은 작업을 해보면서 고수준 명령의 해시값과 같은 결과가 나오는지 확인하면서 진행한다.

 

저수준 명령으로 커밋 조작

note.txt 파일의 내용을 변경

 

변경된 파일 해시 생성 및 확인 ( git hash-object -w {file name} ) 

트리를 만들기 위한 인덱스 생성( git update-index --add --cacheinfo {file mode} {file hash} {file name} )

트리 해시 생성 및 확인 ( git write-tree )

 

으로 진행한다.

위처럼 저수준 명령으로 트리까지 생성한 결과가 위의 고수준으로 얻은 해시와 일치한다.

 

여기 까지는 모두 일치하니 이제 커밋메시지만 조작한다

echo -n "tree 64aaeb047944bac09608e517db19add35ffa982c
parent d3ef9c16c83c3d3c8d9f1be8096d3a085a889a46
author birariro <vps32@naver.com> 1701927980 +0900
committer birariro <vps32@naver.com> 1701927980 +0900

second commit
" | git hash-object -t commit --stdin -w

 

tree 해시, 이전 커밋 해시를 넣고 타임스탬프를 원하는 시간으로 넣는다.

 

이 상태에는 git log로 해도 나오지 않는다 HEAD를 만들어낸 해시로 이동해야 한다

git reset 4d523a7ca2636f7a5916e55010b5ce0ef5ba62c5

 

 

이제 푸시하면 원하는 시간으로 잔디가 심어진다

 

 

 

 

조작된 커밋이 인식되어 잔디가 심어졌다.

 

도구로 만들기

https://github.com/birariro/git-commit-syringe

 

GitHub - birariro/git-commit-syringe: 깃허브 잔디 탈모 치료제

깃허브 잔디 탈모 치료제. Contribute to birariro/git-commit-syringe development by creating an account on GitHub.

github.com

 

원하는 시간의 커밋을 생성해주는 스크립트를 js 로 작성하여 2019 년 1월의 커밋을 채워 넣어보기도 하고

 

 

 

글씨를 써보기도 하고..

 

 

즐겁다 이거

'Tools' 카테고리의 다른 글