git 에서, 특정한 변경 내역만 한쪽 저장소에만 유효하게 두고 싶은데...

raymundo의 이미지

전에 git 책 하나(pro git 번역)를 볼 때는 이것저것 알 것 같았는데 막상 실전에 쓰려니 여전히 어렵군요.
(인간적으로 git는 너무 옵션이나 개별 명령이 많고 복잡하지 않나라는 생각도...)

상황은 이렇습니다.

리눅스 서버에서 사용하는 펄 스크립트들이 저장소 하나에 있습니다. (저장소 이름이 linux라고 하죠)

이 중에 집의 윈도우에서 쓸만한 것들도 있는데, 그냥 복사하면 나중에 수정할 때 일관성이 없어서,
저 저장소를 통채로 clone 명령어로 가져왔습니다. (편의상 저장소 이름을 win이라고 하면)

그런데 스크립트 내용 일부는 윈도우에서 쓰려면 고쳐야 합니다. ("/home/raymundo" 를 "D:/work"로 고치는 등)

linux: A---B---C    master
 
win:   A---B---C    master
                |
                M   수정되고 커밋은 안 된 상태

이 상태에서 뭐가 문제냐 하면...

1. 리눅스에서 스크립트를 고쳐도, 윈도에서 그걸 가져올 수 없음

linux: A---B---C---D    master
 
win:   A---B---C        master
                |
                M   수정되고 커밋은 안 된 상태
 
D를 가져오기 위해 git pull 하면, 로컬에 변경사항이 있으니 이걸 커밋하거나 stash한 후에 pull하라고 함

M을 일단 git-stash로 임시보관하고, pull한 후, 다시 stash에서 빼면 될 것 같긴 합니다. (해결책1)

linux: A---B---C---D    master
 
win:   A---B---C---D    master
                   |
                   M    수정내용이 D에 적용

그런데 매번 이러자니 귀찮고... 나중에 윈도우쪽에서 다른 부분을 고치고 커밋할 때마다 M을 따로
챙겨줘야 할 것 같습니다.

2. 그렇다고 커밋을 하자니, 윈도우 쪽에서 다른 부분을 고친 후 리눅스로 push를 할 때마다 저 M을 빼줘야 합니다.

linux: A---B---C        master
 
win:   A---B---C---M    master
 
git push 하면 M이 linux 쪽에서도 붙어 버릴 것임

3. 그렇다고 별도의 브랜치로 빼자니

linux: A---B---C        master
 
win:   A---B---C        master
               |
               ---M     window_only

리눅스에서 고친 걸 가져와서 pull할 때는 그냥 merge 하면 된다지만

linux: A---B---C---D        master
 
win:   A---B---C---D        master
               |    |
               --M--o       window_only

반대로 윈도우에서 뭔가 고칠 때는...
- master 브랜치에서는 고칠 수가 없습니다. M이 적용되어 있어야 동작할 테니
- windows_only 브랜치에서 고치면, 이걸 linux 에 master로 넘기려면...

linux: A---B---C---D        master
 
win:   A---B---C---D        master
               |    |
               --M--o---E   여기서 고쳐서 테스트하고
 
 
linux: A---B---C---D        master
 
win:   A---B---C---D----E'  master 여기로 rebase를 하든지 하고
               |    |
               --M--o
 
 
linux: A---B---C---D----E'  master  push로 전달한 다음에
 
win:   A---B---C---D----E'  master
               |    |
               --M--o
 
linux: A---B---C---D----E'  master
 
win:   A---B---C---D----E'  master
               |    |    |
               --M--o----o  windows_only 윈도우에서는 또 merge해서 써야 하고

제가 제대로 이해했다면 저래야 한다는 건데... 이건 또 너무 귀찮습니다 -_-;

요컨데,

- 두 저장소 중 이쪽 저장소에만 반영이 되어 있되,

- 반대편 저장소에서 고친 걸 가져올 때도 지장이 없으면서

- 이쪽에서 고친 다른 부분을 저쪽으로 넘길 때는 같이 넘어가지 않는

그런 수정사항을 만들려면... 어떻게 해야 할까요.

제 3의 bare 저장소 같은 걸 만들어서... linux 저장소와 win 저장소가 다 그 제3의 저장소와만 연결되는
걸 고려해봤는데... 그래도 M이 win에만 남아 있도록 하면서 push하려면 또 막막할 것 같습니다.

쉬운 방법이 있는데 제가 놓치는 것 같기도 합니다만... 조언 주시면 감사하겠습니다.

raymundo의 이미지

몇 시간째 구글링을 하고 있는데...

* 파일 하나를 통채로 git 관리에서 제외하거나 (.gitignore 에 넣는다거나)

* 로컬에서 특정 파일에 한 수정 모두를 마치 없는 척 하거나 (assume-unchanged 또는 skip-worktree)

* merge 할 때 행여 충돌이 나면 무조건 내 쪽의 상태를 반영시키는 얘기나 (merge 전략 중 ours 나 고유의 merge driver)

(위 세 가지는 로컬에서 파일에 가해진 수정 내역 중에서도 일부만 빼돌릴 수는 없었음)

* 그냥 별도의 브랜치에 그 수정을 넣고, 그때그때 rebase 하라는 거나 (그게 싫었던 거라...)

이렇게밖에 못 찾겠네요. 아예 "방법 없음"이라고 확정을 할 수만 있다면 더 고민도 안 할 텐데 말이죠.

좋은 하루 되세요!

M.W.Park의 이미지

저도 예전에 비슷한 문제를 아주 잠깐 고민했었는데요.
그때는 테스트용이라 그냥 쓰고 버렸던 것으로 기억합니다.

현상황에서는 그냥 stash해서 로컬 변경을 분리하는 것이 맞는 방법으로 생각됩니다.

다만 한가지, raymundo님의 코드에서 OS 종속적인 부분을 제거(외부 설정으로 뺀다든지, OS를 runtime에 체크한다든지)해서
code를 개선하는 방법이 code base를 유지하는데 더 도움이 될것같다는 생각이 드네요.

그리고 제 경험상으로는 날(raw) git을 쓰는 것보다는 gitflow를 사용하는 것이 workflow를 일관되게 유지하는데 많은 도움이 되었던 것으로 기억합니다.

-----
오늘 의 취미는 끝없는, 끝없는 인내다. 1973 法頂

raymundo의 이미지

관심 가져주셔서 감사합니다 ^^

일단은 윈도우 쪽에서는 다른 브랜치를 만들어서 저 수정사항 M은 거기다 놓고,
나중에 다른 부분을 고쳐서 리눅스 쪽으로 보낼 때는 master 브랜치에 rebase 해서 보내는 형태로
하려고 하고 있습니다.

stash를 쓰는 게 저 변경사항 하나만 있을 때는 상관이 없는데, 이 상태에서 다른 부분을 고치려니
- M과 추가 수정 내역이 합쳐진 상태에서 추가 수정 내역만 뽑는 방법도 (있을 것 같긴 하지만) 모르겠고,
- M을 stash하고 고치자니 애초에 M이 없으면 윈도우에서 돌릴 수가 없으니 말이 안 되어서,
이 방법은 안 되겠더라고요.

그리고 gitflow나 좀 더 체계적으로 설정 파일을 분리하거나 하는 건... 이게 무슨 본격적으로 개발-사용-배포 등을 하는 게 아니라 저 혼자 쓰는 잡다한 스크립트들인데 너무 과하다 싶더라고요. ^^;

그리고 그 종속적인 부분을 제거하는 문제 말인데요, 제가 전에 시도해봤더니, 재귀적인 문제에 빠지는 것 같던데, 혹시 이건 어떤 식으로 해결들 하시는지 여쭈고 싶습니다.

_

예를 들어 제가 본문에 적은 홈디렉토리 설정을 스크립트에서 빼어서 별도의 config 파일에 저장했다고 치면요. 이걸 git로 관리하지 않도록 .gitignore 에 넣어두고 리눅스 서버와 집PC 두 곳에서 서로 다른 config 파일을 만들면 되겠죠.

# 리눅스 서버의 config 파일
homedir: /home/raymundo

# 윈도우 PC의 config 파일
homedir: D:/Work

그런데 스크립트를 수정하다보니 이런 설정 항목이 추가가 된다면:

# 리눅스 서버의 config 파일
homedir: /home/raymundo
key1   : value-common   # 여기가 추가. 양쪽에서 공통의 값일 수도 있고 다를 수도 있겠지만

그러면 집PC의 config 파일에다가는 제가 손으로 두번째 라인을 추가해줘야 되잖아요? 그게 싫어서 config 파일을 git로 관리시키면, 또 처음과 동일한 상황이 되고 말이죠.
(수정 내역을 잘 조절하면 conflict 를 만든 상황에서 merge 전략을 잘 써서 어찌할 수 있을 것 같기도 합니다만)

_

그러면 이번엔
* 일단 설정 파일의 키-값 항목을 config.template 파일로 만들어 git로 관리를 하고
* 양쪽 컴퓨터에서는 그걸 config 파일(git로 관리하지 않는)로 복사해서 값을 각각 자신에 맞게 고친다
이러면 또 config.template 에 항목이 추가되었을 때 config 파일에 그 항목을 일일이 수작업으로 추가...

_

또 한가지 방법은
* git로 관리하는 config.default 파일을 두고, 스크립트는 일단 이걸 읽어서 설정값을 읽고
* git로 관리하지 않는 config.local 파일을 각각 두고, 여기엔 로컬에서 따로 값을 지정해야 하는 항목만 넣고, 스크립트는 이걸 추가로 읽어서 default값을 덮어쓰게 함
이러면 항목이 추가될 때 config.default 에만 추가해주면, 딱히 로컬에서 수정된 값을 넣을 필요가 없다면 config.local 파일을 건드리지 않아도 되겠군요.

그런데 이쯤되면 이건 스크립트에서 일을 하는 부분보다 설정 읽는 부분의 코드가 더 커질지도...

_

이거 답변 하나 듣고나서 더 귀찮게 해드리는 것 같아 죄송하네요ㅠ

좋은 하루 되세요!

M.W.Park의 이미지

예시하신 방법들을 적절히 쓰시면 될것같네요.
OS에 종속적인 불변값들은 SCM으로 관리해도 되지만, user config에 가까운 것들은 그냥 예시하신 것처럼 템플릿을 제공하는 것이 좋을 것같습니다.
그리고 간단히 환경변수에서 얻어올 수 있는 것들(user home 등)은 그냥 코드 내에서 얻어오는 방법도 있겠지요.

정리하자면, "버전관리 하에 있는 코드 쪽에는 가능한 실행환경 독립적인 것들만 유지하자" 정도가 되겠습니다.

본격적인 제품이라면 개발 완료 후 배포 이전에 assembly 단계나 또는 deploy 단계에서 실행환경에 맞춰주는 작업(수동 or 자동)이 필요하겠지요.

-----
오늘 의 취미는 끝없는, 끝없는 인내다. 1973 法頂

raymundo의 이미지

아 네. 제가 그래도 가능한 건 거의 다 생각한 거군요. :) 감사합니다.

좋은 하루 되세요!

nzer0의 이미지

저도 git을 쓴지 얼마 되지는 않아 정확하진 않지만 Hook을 쓰면 어떨까요

OS종속적인 부분을 config파일로 빼놓고,
pre-commit, post-commit, post-checkout 등 Hook을 이용하면 될듯도 합니다.

윈도우에서 Checkout할 때 post-checkout을 걸어서 window config로 바꾸어주고,
커밋 할 때 pre-commit에서 다시 리눅스쪽 config로 바꾸고, post-commit에서 다시 윈도우 config로 바꾸면
(...)
더러울 것 같긴 하지만;; 어느 정도 되지 않을까요?

raymundo의 이미지

앗 답글 달아주신 걸 이제야 봤습니다. 답변 감사드립니다.

hook 같은 걸 생각해보지 않은 건 아닌데,
그냥 대충 개념만 알고 있는 상태였는데, 말씀하신 대로 더러울(;;) 것 같아서... 좀 아닌 듯 싶더라고요.

일단은 그 특정 변경 내역만 그냥 별개 브랜치에 두고, master에서 새로 고칠 때 그걸 rebase 로 master 끝에 붙이는 형태로 두고 있습니다.

좋은 하루 되세요!

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.