덜 번잡하게 git branch를 지울 방법이 없을까?

현재 상황:

  • git + gerrit 사용 중
  • submit 할 때 rebase 해서 merge가능하면 자동으로 rebase (gerrit 옵션)

문제:

  • 다른 커밋들과 거의 무관해서 일련의 내 커밋이 git rebase 되어서 mainline에 “rebase + fast-forward” 됨.
  • 해당 기능의 로컬 branch를 지우려고 하면 merge되지 않았다고 “git branch -D {branch}” 하라고 나옴
  • git show {branch} 해서 대략적으로 바뀐 부분을 찾고, git diff master..{branch} — {바뀐 위치} 로 겹치지 않는 diff가 있나 확인하고 나서 지움; 매우 번잡함

원하는 해결책:

  • git branch -d {branch} 정도로 지워지면 best지만 이건 불가능함
  • “안전하게 지울 수 있다”가 내가 코드를 살펴보지 않고도 가능하면 좋겠음
  • 아마 그 creteria는 “지우려는 branch의 gerrit 용 UUID가 다 mainline에 있는지” 체크하면 됨. (거의 됨?)

뭐 이런 script어디 없나 -_-;;

NDC 2013: DVCS와 코드리뷰, 자동화를 통한 쾌속개발

https://speakerdeck.com/reinkim/ndc-2013-dvcswa-kodeuribyu-jadonghwareul-tonghan-kwaesoggaebal

 

올해 NDC에서 발표한 내용. Slideshare에 업로드 실패를 반복해서 (원인은 용량인듯; pdf로 한 48MiB쯤?) 스피커덱을 한 번 써봤다.
다만 WordPress에 임베드가 잘 안되어서 오늘에야 플러그인 찾아서 블로그에도 게시.

같이 쓰는 사람 수만 좀 많으면 참 좋겠는데 (…).

gerrit 남은 리뷰 수 시각화하기

회사에서 gerrit 이라는 git 기반의 코드 리뷰 도구를 쓴다.

gerrit 최근 버전들이 RESTful API를 제공하기 시작했는데, 이를 이용해서 각 날짜 별로 남아있는 리뷰 수를 보여주는 스크립트를 작성했다.

예를 들어 android 프로젝트의 하위 프로젝트인 platform/sdk 에 대해서 그려보면 이런 그래프가 나온다.

gerrit-graph

대략 작년 1월부터 오늘까지 남은 리뷰 수 통계다 — 실제론 merge 된 것만 계산해서 최근 통계는 좀 안 맞을 수도 있다.

해당 코드는 https://github.com/reinkim/gerrit-graph 에 올려두었다. 좀 naive하긴하지만 svg로 그리니 그리긴 참 편하다 (…).

git 통계 / jenkins 통계 / gerrit 통계가지고 조금 손보면 적당히 발표할만한 주제를 잡을 수 있을 것 같다.

신규 웹 서비스 뒷조사(?)해보기

며칠 전 트위터 타임라인에서 https://urigit.com 이란 서비스에 대해 초대권 받는다는 글이 보여서 뒷조사(?)한 후기.

내가 쓰는 방식이 상식적인 방법인진 모르겠지만, 여하튼 대략 다음과 같은 걸 읽어본다.

1. DNS 주소 정보

urigit.com은 올해 1/19에야 등록이 되었고 (그러니까 최종적인 서비스 명칭은 이 시점에야…),
등록자는 애조로 스튜디오란 이름이었다.

소개 페이지의 내용도 그렇고 메일 주소가 daum.net 인걸로 봐선 다음 제주 본사에 근무 중인 개발자가 주축인 것으로 보인다.

그리고 DNS 서버는 AWSDNS-* 이다. 서버도 AWS 위에서 돌리고 있음.
다음에서 직접 준비한 서비스가 아니거나 다음이 AWS를 테스트베드로 쓰고 있거나인듯. (누가 다른 정보 좀…)

근데 이 정보는 아예 막혀있는 경우도 많다. godaddy나 gabia 등도 registar 주소만 보이는 경우가 더 많음…

2. SSL 인증서 정보

인증서가 1/30에 발행된듯하다. 아마 twitter  계정으로 해당 초대권을 알리기 시작한 날과 무관하지 않은 듯.

3. Twitter 등의 SNS 페이지

이건 큰 참고는 안되고, 대략 public하게 행동한게 언젠지 알게 해주는 정도. 대략 DNS 등록한 날짜랑 큰 차이가 없음.

 

사실 이런 걸 까본 이유는 다음과 같은 점이 궁금해서:

1. git 호스팅 서비스가 큰 의미가 있는가?

한국에선 최초로 하는 서비스 일 것 같다. 근데 git 기반이면 지연시간이 짧다는 것 하나만으론 큰 의미가 없을 것 같다.

git 의 remote operation을 할 일 자체가 자주 없는데 그럼에도 호스팅 서비스가 의미가 큰 가?
특히 github, bitbucket, google-code 같은 다른 서비스들이랑 비교해서?

2. 사업 모델이 뭘까?

단순 호스팅 서비스를 판매하는 거라면 이게 의미가 클까? 상대적으로 연동할 수 있는 툴 수도 제한적일텐데.
github 처럼 연동 도구를 선점하거나, bitbucket처럼 배후에 아틀라시안을 깔고 있는 건 아닐텐데. (배후에 있는 회사가 다음이면 잘 모르겠다)

github 처럼 설치 버전을 판다면 이게 몇몇 스타트업들이 이용하는 gitlab이나, 규모가 좀 되는 회사들(예를 들어 카카오?)이 도입하기도 하는  github enterprise보다 큰 가치가 무엇일까?

2012년 git 통계 (@work)

현재 일하고 있는 곳에서는 소스 저장소로 git을 이용하고 있다. 오늘 오후에 심심풀이로 (???) 적당한 스크립트를 돌려서 내가 commit 한 것에 대한 통계를 내봤다. (gitstats 를 이용해서 통계를 냈다.) 예전 회사에서 SVN stats 던가 하는 걸로 통계 낼 때는 천년 쯤 걸렸던 것 같은데, 로컬에 데이터가 다 있으니 금방 되더라. (상대적으로 history도 적고)

월 별 통계:

4월에 입사한 이후의 통계.

work2012_month_of_year_

올해는 여러 가지로 다사다난했던 것 같다. 중간중간 움푹 들어간 커밋 량을 보니 Orz.

내년엔 12월의 페이스로 진행할 수 있게 되길(…)

 

요일/시간대 별 통계 (heat map):

work2012_hours

목, 금이 평소보다 커밋을 더 많이 하는 듯. 그리고 주로 점심 먹고 온 후에 커밋을 하게 되는 것 같은데 … (점심 시간이 오후 1~2 사이)

커밋 로그에 따르면 주말 출근은 1회 (…).

 

스크립트:

git filter-branch 의 man page에 나오는 commit-filter 예제 – 특정 사용자의 커밋을 지우는 걸 조건을 바꿔서 – 를 수정해서 사용했다.

#!/bin/bash -ex
skip_commit()
{
  shift;
  while [ -n "$1" ];
  do
    shift;
    map "$1";
    shift;
  done;
}

git filter-branch --commit-filter '
  if [ "$GIT_AUTHOR_NAME" = "Jinuk Kim" ];
  then
    git commit-tree "$@";
  else
    skip_commit "$@";
  fi' HEAD

프로그래머의 일상: git 저장소 권한 관리

지금 일하는 곳에선 linux 개발환경을 쓰고, 소스 저장소로는 git을 쓴다.  그리고 여기에 코드 리뷰 도구인 gerrit2를 이용하는데, 이 조합으로 작업하면서 느낀 점을 간단히 써본다.

git이 DVCS이긴 하지만 그래도 canonical 저장소는 있어야 한다. 근데 git 특성(?)상 권한관리의 개념이 희박하다.[1] 저장소가 전체 쓰기가 가능하거나/읽기만 가능하거나/접근할 수 없거나 정도의 권한 수준만 있다. 그래서 많은 프로젝트의 canonical git 저장소는 linux kernel처럼 hierachical하게 패치/메일로 merge하거나, github.com의 pull request처럼 한 명, 혹은 소수가 gate-keeper의 역할을 맡아서 이를 대신한다.

하지만 회사 환경에서 쓰기엔 이런 방법들은 좀 불합리(?)한 듯 싶다. 위의 방법을 써서 gate-keeper에게 부하가 걸리거나, 아니면 권한이 열려 있어서 권한 관리가 잘 안되거나일 것 같다. 그래서인지 여기서는 다음의 방법으로 권한 관리를 대체(?)한다.

  • 모든 개발자는 읽기 권한만 갖는다
  • 개발자들은 메인 저장소가 아닌 코드 리뷰 도구(여기서는 gerrit2)에 push한다.
  • 리뷰 결과 수정할 부분은 수정하고 다시 push
  • 리뷰 결과가 좋으면 gerrit2이 canonical 저장소에 commit

이러면 코드 리뷰를 통과한 것만 실제 canonical 저장소에 들어가는 식으로 권한 관리가 이루어진다.

예를 들어 나는 somelib만 관리하는데 anotherlib에 이상한 수정 사항을 넣었다 치자. 그 쪽 코드 관리하는 사람이 리뷰에서 탈락(…) 시키는 형태로 권한 관리하면 끝이다. 코드 리뷰가 중간에 끼인 거라 당연히도 코드 리뷰의 장점도 전부 포함하게 됨.

덤으로 gerrit2설정에 따라 다르겠지만, canonical 저장소의 이력(history)을 branch가 매우 많은 DVCS 특유의 모습이 아니라, svn 이나 p4에서 흔히 볼 수 있는 선형적인 이력으로 유지할 수도 있다.

 

PS. git을 소스 저장소 시스템으로 사용하는게 난이도가 좀 있을지도 모른다고 생각했었다. 하지만 내가 입사한 이후에 합류한 분들이나, 여름 방학 기간 중에 인턴으로 들어오신 분들도 간단한 git 소개 페이지를 읽고 gerrit을 통해 커밋할 수 있게 되는데는 일주일 이하의 시간이 걸린 것 같다.

그러니 그런 이유로 git 저장소 도입을 망설일 필요는 없을 것 같다. gerrit2 처럼 중간에 gate-keeping하는 녀석이 있으면 실제로 삽질할 수 있는 일의 가짓수도 줄어들어서 git 에 익숙한 사용자가 한 두명 있으면 어떻게든 진행할 수 있을 것이다.[2]

  1. 인증 자체는 ssh나 signed-commit으로 대체 가능하다. []
  2. 사실 git처럼 저장소가 append-only이면 할 수 있는 실수에도 한계가 있다. []

svnserve를 흉내내는 git 저장소를 만들 수 있을까?

git 저장소 (혹은 git 호환 구현체)에서 svn 서버인척하려면 필요한 걸 리스팅 하는 중.

최근에 알게된 dulwich 프로젝트 덕분에 svn 프로토콜 일부를 구현하면 아마 기존 저장소를 git으로 옮기고, svn 클라이언트 쓰는 사람들에겐 ‘여전히 svn 저장소로 보이도록’ 만드는게 가능하지 않을까 싶다.

일단 떠오르는 것만 간단히. 잘못된 부분이나 추가할 사항 있으면 댓글로 좀(…).

svn은 revision 번호가 존재함. git에서 (내부적으로) 적당히 tag달아서 그걸 기준으로 해석해서 보내주면 되려나? (클라이언트 동작이긴하지만 git svn을 생각하면 어렵지 않을듯)

svn은 몇 가지 (미리 정해놓은) svn:… 형식의 프로퍼티를 지원한다. 이걸 어떻게 흉내낼까? link 가 없다고 가정(…)하면 상당히 쉬울 것 같긴한데…
(물론 여기서도 svn:externals 문제가 생길 거 같긴 하다)
executable mode야 별도로 처리하니까 (파일 퍼미션은 별도로 저장하긴하니까) svn:executable은 처리해줄 수 있고, svn:ignore 도 .gitignore나 .git/info/exclude 생각하면 어찌 되겠지. (.gitignore에 가깝군…)

svn:keywords 같이 서버 수준에서 처리하는 기능은 GG. 이건 어찌 해볼 도리가 없다.

svn branch (copy?)를 어떻게 처리할까? git 브랜치 처럼 처리하면 망하지 않을까?

MIME 타입 처리?
http://stackoverflow.com/questions/3537575/can-git-store-the-mime-type-of-a-file-like-svn-does-for-browsing-html
로 보아서는 잘 안될듯하다.

svn은 (대부분의 응답으로) unified diff를 보낸다. git에서 diff를 딸 때 unified diff로 따는 게 있었던 것 같으니 이건 큰 문제가 안될 것 같다.

svn은 저장소를 재귀적으로 정의한다. git은 저장소를 `하나로’ 본다. svn의 서브 디렉터리 요청이 오면 이걸 잘 처리할 방법이 필요한 듯. git에 이런 명령어(혹은 object 접근 방법)이 있던가?; log 랑 diff는 적당히 제한할 수 있었던 것 같으니 큰 문제 아닌가?

SVN 에서 서버 접근할 때 일반적으로 쓰는 명령이 뭐가 있을까?

update, commit, ls, copy, move, rm, … 정도인가?

git svn 동작이 거지같게 느껴지던 이유

실제론 svn으로 버젼관리를 하는 상황에서, git을 그 위에 쓰다보니 몇 가지 문제를 겪어야 했다.사실 몇 가지 점에서 git 의 동작을(혹은 git-svn의 동작을) 이해할 수가 없었는데, 최근에 Pragmatic Version Control using Git 을 구입해서 읽고나니 약간은 이해할 수 있게 되었다.

svn은 본질적으로 선형적인(linear) 이력(history) 를 갖는다. 즉,

  1. 최초의 repository 상태가 있고,
  2. 이 위에 새로운 변경 rev 2
  3. 그 위에 새로운 변경이 더해져 rev 3
  4. 마지막 변경이 가해져서 rev n

이 되는 형태다.

반대로 git은 각 개별 repository(DVCS니까)가 브랜치처럼 인지되고 / 변경 사항이 merge 되는 것 처럼 동작한다. 이에 따라 svn update에 대응되는 git 동작은 git pull이 아니라 git svn rebase (사실상은 git rebase) 만 가능해던 거다. 선형 이력이 아니라 브랜치간 merge 이력인 git이 svn 쪽에는 정상적인 svn 복사본인양 보여야하기에 이런 뻘짓(…)을 해야하는 거 -_-;[1]

그리고 rebase 이기 때문에 커밋되지 않은 변경사항이 있으면 안되던 것 — 보통 git stash로 잠시 패치를 만들어 빼둔다 — 도 이해가 가게 되었다; svn update는 로컬에 변경사항이 있다면 묵시적인 머지를 시도하는 거지만,  git의 경우엔 그런 머지를 git의 관점에서 추적할 수단이 없기에 -_-;

개인적인 해결책(?)은 그냥 svn 브랜치 / 개발 브랜치 따로 쓰면서 git svn을 쓰는게 답이 아닐까 싶지만 -_-; 그럼 git svn이 복잡하기도 하고 merge/fast-forward 가 난무하게 되는 것도 사용자 입장에선 꽤나 귀찮은 일이 될테니 역시 이것도 답이 없나?

결국 git-svn의 동작이 이해안가고 / 맘에 안들던 이유는 git과 svn의 이력관리의 차이…때문인듯하다;

ps. 여튼 책을 읽으면서 커밋되지 않은 변경 사항이 branch 딸 때 어떻게 된다거나 / 써보지 않은 signing이나 k-merge 전략 같은 내용도 개념을 잡게 해줬다는 점에서는 괜찮았다. 그렇지만 책 자체가 튜토리얼치곤 양이 많고 / 리퍼런스치곤 볼륨이 부족하다는 점은 좀 아쉬비;

  1. git이 선형 이력이 안되는 이유…라기보단 git 사용 방식의 문제가 있는데. git은 기본적으로 branching이 매우 쉽다. 그리고 모든 류의 커밋은 merge 처럼 간주해서 처리한다. (분산인 이상은 당연한듯?) 그래서 이력 자체가 선형으로 생길래야 생길 수가 없다. 그래서 이걸 꽉 눌러짜서(…) git svn rebase로만 업데이트 해야 한다 []