2008년 9월 25일 목요일

Windows 에서 git 사용

Cygwin? msysGit?

Cygwin 을 쓰던 사람이라면 Cygwin 으로 배포되는 git 을, git 이외에 Cygwin 류의 것을 쓸 일이 없다는 사람은 msysGit 을 추천한다.

(Cygwin 홈 페이지 자신을 "a Linux-like environment for Windows" 라고 소개하고 있다.)

Cygwin 팁

Windows 폴더 팝업 메뉴에서 Cygwin shell 을 바로 띄우는 방법이다. fvue.nl/wiki/Bash_and_Windows 에 자세한 내용이 있다. (msysGit 은 설치하면 "Git Gui Here"와 "Git Bash Here" 메뉴 아이템을 추가한다.)

C:\cygwin\cygwin_here.bat (Window2000 이상)

 @echo off
 REM --- cygwin_here.bat ------------------------------------------------------
 REM function: Start Cygwin in current directory
 REM args:     - 1..9

 REM Setting `CHERE_INVOKING' prevents /etc/profile from issuing `cd $HOME'
 set CHERE_INVOKING=1
 C:\cygwin\bin\bash --login -i %1 %2 %3 %4 %5 %6 %7 %8 %9

registry 수정

 HKEY_CLASSES_ROOT
 |-Folder
   |-shell
     |-Shell to Cygwin   "Shell to Cyg&win"
       |-command         "C:\cygwin\cygwin_here.bat"

혹시 권한을 탓하며 실행을 거부하는 경우에는 Cygwin 을 실행하고 권한을 주면 된다.

 cd /
 chmod +x cygwin_here.bat

(Cygwin 에서 cat 으로 cygwin_here.bat 을 만들었는데 실행권한이 없었다. 그냥 다른 Windows 에디터를 사용했었다면 이런 일이 안 생겼을지도 모르겠다.)

원활한 원격 작업을 위한 설정

원격 저장소와 통신에 사용하는 디폴트 프로토콜은 ssh 이다. 보통 아무 작업도 해주지 않으면 push 나 pull 할 때 암호를 물어오게 되어 있다. 암호를 입력해 주면 되는데, 문제는 그렇게 두면 git gui 에서는 원격 작업을 할 수 없다는 것이다.

작업 머신에서 서버에 암호 입력 없이 접근할 수 있게 해주는 방법이 있다.

 ssh-keygen.exe -C "you@your.email.com" -t dsa

 scp ~/.ssh/id_dsa.pub  you@yourgitserver:~/.ssh/authorized_keys

(이 때 한 번 로그인 암호를 입력하게 된다.)

ssh-keygen 시에 passphrase 를 물어 오는데 입력을 하지 않는 것이 편하다. 입력을 하고 나중에 ssh-agent, ssh-add 를 이용하면 많이 불편하지는 않지만, 입력을 하지 않는 것 보다는 불편하다.

ssh-agent, ssh-add 사용하기

만일 주인이 없는 사이에 누군가 개발 머신을 켜고 원격 저장소를 엑세스하는 것을 막고자 한다면, 아니면 누군가 id_dsa 를 복사해 가서 원격 저장소를 엑세스 할 가능성을 없애려면, 매번 암호 입력을 하거나 passphrase 를 사용해서 ssh-keygen 을 해야만 한다.

아래는 ssh-agent 와 ssh-add 를 사용하는 방법이다. 먼저 Cygwin 이나 Git-Bash 를 실행하고

 eval `ssh-agent -s`
 ssh-add

passphrase 를 입력해준다.

이제 마음껏 작업한다.

 git pull
 git push
 git gui
 ...

다른 사람이 자리에 앉아서 서버에 접속할 가능성을 차단하기 위해 ssh-agent 를 죽인다.

 ssh-agent -k

물론 컴퓨터를 끄고 집에 가려 한다면 마지막 명령은 필요없다.

2008년 9월 24일 수요일

Git - CVS 에서 전환

첫번째 문서 중 중요 내용 요약, 약간의 내용

단어들

저장소
repository
중앙 저장소
central repository
개별 저장소, 작업본 저장소
local repository
작업본
working copy
bare 저장소
작업본이 없는 저장소
SHA1-number
git 은 모든 object 에 SHA1 hash number 를 생성한다. 이것은 어떤 파일이나 특정 commit 등을 지정하는데 사용할 수 있다.

처음

이름과 이메일 설정

 git config --global user.name "Your Name"
 git config --global user.email "my@email.com"

원할 경우, conflicts 해결을 위해 머지(merge) 툴을 설정할 수 있다.

 git config --global merge.tool meld

CVS 에서 하던 것처럼

괜히 더 복잡하다고 생각할 수도 있다.

중앙 저장소를 두는 셋팅의 경우.

가져오기
 cvs checkout

 git clone <server>:/path/to/repos/project.git
중앙 저장소에 바뀐 부분 가져오기
 cvs update

 git pull origin master
수정한 것을 중앙 저장소로
 cvs update
 cvs checkin file1 file2 ...

 git pull origin
 git commit file1 file2 ...
 git push origin master

여기에서 git 과 CVS 의 차이가 확연히 나타난다. git 의 commit 은 개별 저장소에만 commit 을 하는 것이다. (git 의 경우 작업본마다 개별 저장소를 가지고 있다.) 중앙 저장소에 push 하는 것은 별개의 작업이다.

좀 더 유용한 작업 방식은 아래 처럼.

 ... 작업
 git commit file1 file2 ...
 ... 작업
 git commit fileN dir2 ...
 ... 작업
 git commit -a  # (수정 사항 모두 commit)
 ... 새로운 기능 완성!
 git pull origin master
 git push origin master
기타 작업
 cvs add file1 ...
 git add file1 ...

 cvs remove file1
 git rm file1

파일 이동이나 이름 바꾸기

 [cvs remove, add 각각]
 git mv file1 file

지운 파일 살리기

 cvs update
 git checkout file1

commit 을 자주

git 과 CVS 의 가장 큰 차이 두가지:

  • 작업본이 완전한 저장소 - commit 과 commit 들을 보내는 차이가 존재함
  • 각각의 파일 상태를 추적하는 것이 아니라 전체 상태를 추적함

git 의 commit 은 CVS 의 그것과 같다. 다만 push 하기 전까지 그것은 개발자의 작업본 저장소에만 적용된다. 중앙 저장소로 push 하면 개발자의 저장소와 중앙 저장소는 같은 상태가 된다. 마지막 push 이후 12번의 commit 을 했다면 12번의 commit 이 중앙 저장소로 push 된다. CVS 에서라면 서버에 직접 12번 commit 을 했어야 한다. git 에서는 원하는 만큼 commit 하고 됐다고 생각될 때 서버로 작업한 것을 올릴 수 있다.

결론 : git 은 자주 commit 하는데 부담이 없다.

Branch

git 에서 branch 와 merge 는 (CVS에 비해서) 아주 간단하다. 사실 각각의 개별 저장소는 각각의 branch 라고 할 수 있다.

branch 만들기

 git branch <branch>

특정 지점 으로 branch 만들기

 git branch <branch> <지점>

<지점> - 다른 branch, tag, SHA1-number 등이 올 수 있다.

branch 목록 보기

 git branch

작업 branch 바꾸기

 git checkout <branch>

git checkout 은 branch, tag 등 지점을 가져오는데도 사용되고 파일이나 디렉토리를 가져오는데도 사용된다.

branch 지우기 - commit 들이 현재 branch 에서 추적 가능한 경우에만

 git branch -d <branch>

branch 지우기 - commit 들이 추적 불가능한 경우에도 지워버림

 git branch -D <branch>
작은 오류 수정 push

작은 오류 수정을 해야할 필요가 있는데, 많은 commit 을 했고 push 할만한 상태가 아닐 경우, branch 가 유용할 수 있다.

  • 아직 수정하지 않은 경우 - 임시 branch (fix 라고 이름 지었다고 가정)를 만들고 checkout 한다. 문제를 해결하고 commit, 서버에 push 한다. 작업 branch 를 chekout 하고 수정사항을 서버에서 pull 한다. fix branch 를 지운다.
  • 문제를 이미 해결하고 commit 해둔 경우 - 임시 branch (fix)를 만든다. 오류 수정한 commit 의 SHA1-number 를 찾는다. (gitk 나 git log 사용) git cherry-pick SHA1-number 로 해당 commit 만을 fix branch 에 반영한다. push 하고 작업 branch 를 checkout 한다. fix branch 를 삭제한다.
기타 유용한 경우
  • 실험 branch
  • 둘 이상의 release 관리
  • 특화 기능 추가 요청
  • 등등 …

submodule

git 은 파일 하나 하나의 변화를 추적하는 대신 전체의 변화를 한 commit 으로 관리한다. 부분별 관리가 따로 필요할 경우를 위해서 만들어진 기능이 submodule 기능이다.

Manual 참조.

기타

  • push 는 bare 저장소에 쓰기 위한 것이다. 작업본이 있는 저장소에도 push 를 할 수 있기는 하지만 작업본까지 바꾸지는 않기 때문에 개발자를 혼란에 빠뜨릴 것이다.
  • GUI 가 있다. "git gui". pull은 없고 fetch 와 merge 를 해야한다.
  • git bisect - 버그가 들어온 경우, 어떤 commit 때문인지를 2진 검색(binary search) 으로 찾을 때 사용.

2008년 9월 21일 일요일

Git #0 - git?

  • git - Fast Version Control System

최근 많은 오픈소스 프로젝트들(특히 RoR(Ruby on Rails) 관련 프로젝트들)이 버젼 관리 툴을 git 으로 옮겨갔다는 것을 알게 되었다. RoR 개발 자체가 git 으로 옮겨간 것이 관련 프로젝트들의 이동에 영향을 미쳤던 것 같다.

근래에 새로운 프로젝트를 시작할 계획을 하면서 어떤 버젼 관리 툴을 쓸 것인가 고민 중이었는데, git 이 어떤지 한 번 둘러보기로 했다.

처음 git 이 만들어지고 사용되기 시작했을 때, 별 관심이 가지 않았던 것은 Linux 개발을 염두에 두고 만들어졌을 것이라는 생각이 들었기 때문일 것이다. 아마도 Linux 처럼 큰 규모이고 개발자들이 흩어져 있는 프로젝트를 염두에 두고 작성된 것을 간단한 프로젝트나 문서 관리에 사용하기에는 불필요하게 복잡하지 않을까 했던 것 같다.

Git 은 분산형 버젼 관리 툴이고, 성능에 중점을 두고 개발하였다고 한다. 분산형 버젼 관리에 대해서 한글 블로그 글이 있다.

whiteship.me/1826 와 포함된 링크들이 도움이 될 것이다.

Linus 가 2007년에 Google Talk 에서 한 강연도 git 을 이해하는데 도움이 된다. 다만, CVS(SVN 포함)와 그 사용자들을 무지하게 비난하기 때문에 CVS 나 SVN 사용자들은 기분이 나쁠 수도 있다.

분산형 버젼 관리 툴이라하면 개인 프로젝트에 사용하기에는 다른 툴에 비해 쓰기가 더 불편할 것 같지만 개인 프로젝트의 경우에도 git 이 CVS 나 Subversion 보다 사용하기에 더 간편하다는 느낌이 들었다. CVS 나 Subversion 을 쓸 때는 중앙 저장소를 어떻게 구성해야 할 것인지 먼저 고민을 해야한다. 게다가 프로젝트 디렉토리 이름이라도 바꾸려면 (개인 프로젝트 단계라 할지라도) 성가신 작업을 거치거나 중앙 저장소의 명칭과 불일치한 상태로 작업을 해야한다. 이에 반해 git은 working copy 와 저장소가 함께 있기 때문에 작명 작업을 뒤로 미루거나 후에 이름을 바꾸는 일에 대한 부담이 적다. (물론 개인 프로젝트 단계에 있거나 작은 팀의 경우이다. 공개 되었거나 큰 팀이 작업한다면 중앙 집중형이건 분산형이건 이름을 바꾸지 않는 것이 상책일 것이다.)

팀에서 CVS 대신 git 을 사용하는 것을 검토해 보기로 하였다. 말을 꺼낸 내가 그 일을 맡게 되었다. 아마도 몇 개의 git 사용에 관한 글을 더 쓰게 될 것 같다.

2008년 9월 8일 월요일

Java.next

JtestR 에 관한 글을 쓴 이후에 아래 질문에 대해서 좀 써 봐야겠다고 생각했었다.

  • 왜 Java 프로젝트에서 Ruby 를?

충분하지 않은 간단한 답은 간결함 이랄까? 어쨌든 설명이 수월치 않았다.

그러던 와중에 웹 서핑을 하다가 실마리가 될만한 시리즈를 발견했다. Stuart Halloway 가 쓴 것으로 JVM 을 기반으로 차세대 언어에 관한 글이다. Clojure, Groovy, JRuby, Scala, 이 네개의 언어가 소개된다.

첫번째 글은 차세대 언어들의 Java 와 대비되는 공통점들에 대해서 이야기하고 있다. 이글이 위 질문에 대한 답을 어느정도는 해줄 수 있다고 생각한다.

같은 것을 표현 하는 코드는 (readablity 를 해치지 않는 범위 안에서) 짧을 수록 좋다. Java 는 같은 일을 하는데 군더더기 코드가 많이 필요하다.

또 한가지, 첫번째 글의 결론에 나오는 데로 Java.next 언어들은 Java 에 비해서 좀 더 Domain 에 잘 맞는 DSL(Domain-Specific Languages) 을 개발하기가 용이하다. JtestR 에 포함된 RSpec 이 한가지 예로 BDD(Behavior Driven Development) DSL 이라고 말할 수 있다. 물론, Java 에도 BDD 를 지원하는 페키지들이 개발되어 있기는 하다. 그렇지만, 각각의 예제를 RSpec 의 예제와 비교해 본다면 어떤 것이 읽기 좋은지 금방 결정할 수 있을 것이다.

질문의 범위를 좁혀서 ‘왜 JtestR 을 쓰려고 했나?’ 라는 질문을 해보자. 그러면 ‘테스트 코드만이라도 간결하게 짜고 싶어서’, 그리고 ‘RSpec 을 쓰고 싶어서’ 라는 말이 대부분의 이유를 설명해 주는 대답이 될 것이다.