달력

52024  이전 다음

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
Android 에서는 Git 를 내부적으로 사용하면서 Repo 를 Wrapper 로 이용한다.
.repo 안에 어떻게 되어 있는 건지 궁금해서 들여다 봤다.
앞으로 더 봐야겠지만 오늘 분석한 것을 정리한다.

<download>
Android Source 전체를 받을 필요는 없고, repo sync 까지만 해서 .repo 안에 구조를 본다.

mkdir mydroid
cd mydroid/
repo init -u git://android.git.kernel.org/platform/manifest.git

<.repo>
.repo 안에 repo command 를 구현한 repo directory 가 있고,
.repo 내 프로젝트 설정 정보를 담고 있는 manifest.xml 파일이 있다.
그런데 manifest.xml 는 symbolic link 이고 실제 파일은 manifest directory 에 있는 default.xml 이다.

$ tree -L 1 .repo
.repo
|-- manifests
|-- manifests.git
|-- manifest.xml -> manifests/default.xml
`-- repo

그런데 manifest.git 는 어떤 directory 인지 궁금했는데,
manifest.xml 을 git 로 관리하는 것이다.

참고적으로 repo sync 를 통해 Source 를 받고 나니,
project 에 대한 정보가 있는 파일이 더 생겼다.
이 부분은 나중에 확인해 봐야겠다.

// would be like this after repo sync
$ tree -L 1 .repo/
.repo/
|-- manifests
|-- manifests.git
|-- manifest.xml -> manifests/default.xml
|-- project.list
|-- projects
`-- repo

<manifests VS manifests.git>
directory가 두 개가 있는데 왜 두 개인지 궁금했다.

안을 들여다 보기 전에 우선 용량부터 확인했더니,
둘 다 용량이 작은데, manifests 가 훨씬 작았다.

$ du -sh .repo/manifests
104K    .repo/manifests
$ du -sh .repo/manifests.git/
1.4M    .repo/manifests.git/

ls 로 파일을 보니, manifests 에는 파일이 몇 개 있고,
.git 가 있는 것을 보니 Git 로 관리하고 있는 것으로 보인다.

$ ls -l .repo/manifests
total 100
drwxr-xr-x 3 jaewon jaewon  4096 2011-07-29 20:48 .
drwxr-xr-x 6 jaewon jaewon  4096 2011-08-13 22:46 ..
-rw-r--r-- 1 jaewon jaewon 21776 2011-07-29 20:46 3.0-base.xml
-rw-r--r-- 1 jaewon jaewon 22340 2011-07-29 20:46 3.1-base.xml
-rw-r--r-- 1 jaewon jaewon 23240 2011-07-29 20:46 3.2-base.xml
-rw-r--r-- 1 jaewon jaewon 14378 2011-07-29 20:46 default.xml
drwxr-xr-x 2 jaewon jaewon  4096 2011-08-13 22:21 .git

그런데 .git 안을 보니 주요 파일들이 Symbolic Link 일 뿐 실제 파일이 아니고,
manifest.git 에 있는 것이 실제 파일이다.
심지어 packed-refs 와 svn 는 target 이 없는 broken link 이다.

$ ls -l .repo/manifests/.git/
total 8
lrwxrwxrwx 1 jaewon jaewon  26 2011-08-13 23:10 config -> ../../manifests.git/config
lrwxrwxrwx 1 jaewon jaewon  31 2011-08-13 23:10 description -> ../../manifests.git/description
-rw-r--r-- 1 jaewon jaewon  24 2011-08-13 23:10 HEAD
lrwxrwxrwx 1 jaewon jaewon  25 2011-08-13 23:10 hooks -> ../../manifests.git/hooks
-rw-r--r-- 1 jaewon jaewon 385 2011-08-13 23:10 index
lrwxrwxrwx 1 jaewon jaewon  24 2011-08-13 23:10 info -> ../../manifests.git/info
lrwxrwxrwx 1 jaewon jaewon  24 2011-08-13 23:10 logs -> ../../manifests.git/logs
lrwxrwxrwx 1 jaewon jaewon  27 2011-08-13 23:10 objects -> ../../manifests.git/objects
lrwxrwxrwx 1 jaewon jaewon  31 2011-08-13 23:10 packed-refs -> ../../manifests.git/packed-refs
lrwxrwxrwx 1 jaewon jaewon  24 2011-08-13 23:10 refs -> ../../manifests.git/refs
lrwxrwxrwx 1 jaewon jaewon  28 2011-08-13 23:10 rr-cache -> ../../manifests.git/rr-cache
lrwxrwxrwx 1 jaewon jaewon  23 2011-08-13 23:10 svn -> ../../manifests.git/svn

당연하겠지만 그래서 .git 가 차지하는 용량도 무척 작다.

$ du -sh .repo/manifests/.git/
12K    .repo/manifests/.git/

Symbolic Link 라서 이건 껍데기려니 하고,
그냥 diff 로 차이가 있는 파일을 봤다.
다른 건 그럭저럭 눈에 안 뜨이는데 HEAD 파일이 다르다는 것이 이상하다.

$ diff -qr .repo/manifests/.git .repo/manifests.git
Only in .repo/manifests.git: branches
Only in .repo/manifests.git: FETCH_HEAD
Files .repo/manifests/.git/HEAD and .repo/manifests.git/HEAD differ
Only in .repo/manifests/.git: index
Only in .repo/manifests/.git: packed-refs
Only in .repo/manifests.git: .repopickle_config
Only in .repo/manifests/.git: svn

<manifest>
manifest directory 를 좀 더 들여다 봤다.

$ cd .repo/manifests

config 파일을 열어 환경 설정을 보니,
origin remote 와 default branch 를 가진 일반적인 형태다.
다른 파일들이 Symbolic Link 이지만 config 파일은 mainifest.git 의 config 와 같은 내용이었다.

.repo/manifests$ cat .git/config
[core]
    repositoryformatversion = 0
    filemode = true
[remote "origin"]
    url = git://android.git.kernel.org/platform/manifest.git
    fetch = +refs/heads/*:refs/remotes/origin/*
[branch "default"]
    remote = origin
    merge = refs/heads/master

본 김에 HEAD commit 을 봤다.
Log Message 를 보니 새 project 를 만들었나 보다.

.repo/manifests$ git log --oneline HEAD^!
dc01e28 Add new projects

예상대로 HEAD 는 정상적으로 heads/default 즉 local default branch 를 의미했다.

.repo/manifests$ cat .git/HEAD
ref: refs/heads/default

remote branch 를 포함해서 전체 branch 를 보니,
default 는 origin/master 즉 origin remote 에서 master branch 를 upstream 으로 하고 있다.
그밖에 Android 각 version 별로 branch 를 따로 만들어서 사용했던 것 같다.
내부적으로 최신 version 으로 merge 했을 것 같지만.

.repo/manifests$ git branch -avv
* default                                  dc01e28 [origin/master] Add new projects
  remotes/origin/android-1.5               1b4d95f fixed duplicate entry
  remotes/origin/android-1.5r2             2de7a11 Manifest for 1.5r2
  (생략)
  remotes/origin/master                    dc01e28 Add new projects
  (생략)

<manifest.git>
그럼 manifest.git directory 는 어떻게 되어 있을까?

$ cd .repo/manifests.git/

branch 정보를 봤는데, manifest 와 같은 것 같다.
아라? 그런데 local default branch 에 현재 branch 를 가리키는 * 가 없다.
HEAD 값이 어떻게 되어 있길래?

.repo/manifests.git$ git branch -avv
  default                                  dc01e28 [origin/master] Add new projects
  remotes/origin/android-1.5               1b4d95f fixed duplicate entry
  remotes/origin/android-1.5r2             2de7a11 Manifest for 1.5r2
  ...
  remotes/origin/master                    dc01e28 Add new projects
  ...

우선 config 를 봤다.
특별한 사항은 없다.

.repo/manifests.git$ cat config
[core]
    repositoryformatversion = 0
    filemode = true
[remote "origin"]
    url = git://android.git.kernel.org/platform/manifest.git
    fetch = +refs/heads/*:refs/remotes/origin/*
[branch "default"]
    remote = origin
    merge = refs/heads/master

그럼 HEAD 는 어떻게 되어 있을까?
default branch 가 아니라 master branch 로 되어 있다!!!
왜 이렇게 해 놨을까??

.repo/manifests.git$ cat HEAD
ref: refs/heads/master

heads 즉 local branch 중에 master 는 없는데 말이다.

.repo/manifests.git$ ls refs/heads/
default

이렇게 HEAD가 잘못 되어 있으니까,
git log 와 같은 것도 안 되는 것이 당연하다.

.repo/manifests.git$ git log
fatal: bad default revision 'HEAD'

테스트용으로 master ref 를 만들어본다면,
git log 가 잘 된다.
manifest.git 내에서 git command 를 하지 못 하도록 일부러 막았을지도 모르겠다.

.repo/manifests.git$ cp refs/heads/default refs/heads/master
.repo/manifests.git$ git log --oneline HEAD^!
dc01e28 Add new projects
.repo/manifests.git$ git branch -vv
  default dc01e28 [origin/master] Add new projects
* master  dc01e28 Add new projects
.repo/manifests.git$ rm refs/heads/master


Posted by neodelicious
|