git의 스테이지 영역(stage area)은 왜 필요할까?

전에 만들어 올려 두었던 'svn 능력자를 위한 git 개념 가이드' PT 자료에 오류를 지적하는 댓글이 올라와서 그에 대해 답변글을 적었는데 너무 길어진데다가 혹여나 다른 분들도 궁금해하실 수 있겠다 싶어 이 곳에도 올려둡니다.

문제를 제기해주신 부분은 다음과 같았습니다:
20페이지에서 'SVN에서는 변경된 파일들이 모두 커밋대상이 되기 때문'에 커밋 전에 login.php를 revert해야 된다고 하셨는데 틀린것 같습니다. SVN도 원하는 파일만 골라서 커밋할수 있거든요..

'기본적으로'라는 표현이 빠졌기 때문에 분명히 제 표현의 실수입니다. 하지만, 그냥 간단히 단답을 하고 넘어가기에는 그 한 문장이 내포하는 의미가 너무 길어서 부득이하게 긴 답변글이 되고 말았습니다.

아래에 그 분께 남겨드린 답변을 그대로 옮겨놓습니다:




네. 말씀대로 svn 역시 파일들을 골라서 커밋 할 수 있습니다. 이해를 돕기 위해 표현을 간단히 하다보니 의도치 않게 부정확한 표현이 되어 버렸네요. 조금 정정하자면, git은 commit 명령만으로 stage area에 추가된 파일들만 골라서 커밋하지만 svn의 commit 명령은 변경 된 모든 파일들을 커밋시킨다는 것입니다.

svn으로 특정 파일들만 커밋하기 위해서는 실제로 commit 명령뒤에 대상이 되는 파일 목록을 파라메터로 붙여 적어주어야 합니다. 우리가 보통 사용하는 svn 클라이언트 소프트웨어들은 체크박스등을 선택하여 이를 간단히 도와주지만 리눅스 콘솔 등을 이용하는 유저들에게 이는 매우 곤욕스러운 일입니다.

svn commit -m 'multiple files' a.txt b.doc c.cpp *.hpp temp/test.php

참고가 되실까 싶어 조금만 부연 설명을 드리자면, git은 커밋을 하기 전에 커밋 대상을 담는 공간(stage)을 따로 구분하는 방법으로 커밋을 보다 융통성있도록 만들어 주었습니다. 어떤 점인지 살펴보면요,

svn은 커밋을 하는 순간에 커밋 대상을 선택합니다. (커밋 명령 뒤 파라메터로 붙인다고 아까 말씀드렸듯이...) 이로 인해 생기는 단점은 파일 이름만으로 커밋 대상 여부를 판단해야 한다는 것입니다. 매번 커밋을 시도 할 때 마다 각각의 변경 파일들이 어떤 수정을 거쳤는지에 대해 작업자가 인지하고 있어야 합니다.

이런 귀찮음을 해소하기 위해 일부 작업자들은 애매한 꼼수를 쓰기도 합니다. A작업을 진행중인 작업자가 갑자기 B작업을 해야 할 때, 아직 A작업이 원하는 수준으로 완료되지 않았지만 임시로 커밋을 하고 작업사본을 깨끗한 상태로 만들어버립니다. 이후,  B작업이 완료되어 커밋을 한 뒤에 A작업을 이어서 하게 되죠. 파일 이름만으로 각각 어떤 작업의 변경 내역인지 가려내야 하는 수고로움을 덜기 위해 만들어내는 꼼수입니다.

만약 이러한 수고도 하기 싫은 작업자라면 A작업이 진행중인 작업 사본에 B작업을 동시에 진행한 후 A와 B 작업을 동시에 커밋합니다. 결국 이후에 이러한 작업물들의 svn 로그를 살펴보면 이도저도 아닌 애매한 커밋들이 무수하게 보여집니다.

이는 변경내역을 서버에 저장하는 최소 단위가 commit인 svn이 가지는 한계입니다.

하지만 git은 작업을 진행하는 도중에 수시로 커밋 대상에 추가 혹은 삭제를 할 수 있습니다. 심지어는 하나의 변경 파일 내에서도 특정한 줄들만 커밋 대상에 추가 할 수도 있습니다. 이 덕분에 특정한 작업을 위해 수정한 파일들을 작업자가 직접 기억하는게 아니라 git이 기억해주는 것이죠.

이런 것들에 대한 종합적인 의미로 svn에서는 변경된 파일들이 모두 커밋대상이 된다고 뭉툭하게 표현해버리고 말았습니다. 의도가 잘 전달되었는지 궁금하네요.

0 comments:

댓글 쓰기

Powered by Blogger.

Popular Posts