블로그 이미지
Every unexpected event is a path to learning for you.


분류 전체보기 (2196)N
Unity3D (517)N
Programming (460)
Unreal (2)
Gamebryo (56)
Tip & Tech (174)
협업 (29)
3DS Max (3)
Game (12)
Utility (104)N
Etc (91)
Link (29)
Portfolio (19)
Subject (90)
iOS,OSX (34)
Android (3)
Linux (5)
잉여 프로젝트 (2)
게임이야기 (1)
Memories (19)
Interest (37)
Thinking (34)
한글 (25)
PaperCraft (5)
Animation (408)
Wallpaper (2)
재테크 (16)
Exercise (3)
나만의 맛집 (2)
냥이 (9)
육아 (2)
Statistics Graph


« » 2018.07
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        



Tistory Cumulus Flash tag cloud by BLUEnLIVE requires Flash Player 9 or better.

I love Git. I was very much a TFS purist up until the last year or so, but after using Git for a while now, I’m hooked. Whilst TFS certainly isn’t bad, I love the flexibility and the fact I can muck about to my hearts content in a DVCS without affecting anyone (unless I choose to). That doesn’t mean I love everything though, one of my biggest headaches recently has been tags.

Tags in Git are simply textual markers against specific commits, very much like branches (although tags don’t move). Generally they’re used to mark points in your commit history (i.e. versions etc), but they can – being just text – be used to mark anything really.

So what’s the problem? Well, the issue isn’t with tags themselves, it’s more with the fact they’re very, very annoying to kill. I purposefully say kill and not delete, because deleting a tag is actually very simple, it’s making sure that tag staysdeleted/dead that’s the problem. Once a tag has been pushed to a remote, it is automatically retrieved during any subsequent pulls, at this point the tag exists in the user’s local repository until they choose to delete it. But it also means that said user can also then re-push a single tag – or even worse, all their local tags – to a remote when doing a push.

To illustrate this, consider the following example:

  1. Bob creates the tag ‘foo’ against a commit and pushes this to a remote
  2. Fred pulls from the remote to update his local copy of a branch he’s working on with Jane
  3. Jane does the same as Fred, meaning both Fred and Jane now have Bob’s tag ‘foo’ in their local repos
  4. Bob realises that ‘foo’ is a terrible name for a tag and wants to delete it, so he deletes the tag locally and pushes the delete to the remote
  5. Fred has written some more code he wants to share with Jane, so – using his handy Atlassian SourceTree app – he pushes his changes. But; Fred doesn’t 100% understand what he’s doing, so he checks the “Push all tags” checkbox when doing his push, thus re-pushing the tag which Bob just deleted!
  6. Bob does a further pull later that day, and lo and behold, his poorly named tag ‘foo’ has reappeared in his local repository!
  7. Jane pulls again and also pulls down the once deleted tag, much to Bob’s annoyance

Alright, so the answer here is probably to give Fred some guidance about how to use Git, but it does illustrate the real life problem I had recently, the only difference was that in my situation there were lots more developers involved.

So how do you solve this? Well, the Git documentation states that – by default – tags are not pushed unless you specify otherwise (using the “tags” switch). So actually, Git does a pretty good job of preventing people from automatically sharing all their tags, but tools like SourceTree, which provide a seductive “Push all tags” checkbox when pushing – are clearly too tempting for developers to pass up:


Another option – and probably a better one than just relying on your developers to not push their tags – is to implement a pre-receive server side hook to check whether tags are being pushed and reject the push it the user doesn’t have permission. Unfortunately, if you’re using a hosted Git repository like GitHub or Bitbucket, you’re out of luck as they don’t currently provide the ability for you to edit hooks and unfortunately don’t allow you to apply permissions to tags. This is a real shame as the functionality is already there to control access to branches.

Of course, the final option is just to accept that tags are not really meant to be deleted after they’re pushed, which is all well and good if you and your developers understand this from the start, not so good if not!

[출처] http://thecurlybracket.com/2014/10/11/git-zombie-tags-from-hell/

'협업 > Git' 카테고리의 다른 글

[펌] Git: Zombie tags from hell  (0) 2018.02.21
[펌] Synology As A Git LFS Server  (0) 2017.11.14
[펌][SourceTree] 갑자기 실행이 안될때  (0) 2017.10.23
[링크] Pro Git[ebook]  (0) 2017.07.29
[Bug] SourceTree for Mac  (0) 2017.06.29
[Util] GitKraken  (0) 2017.06.29
Posted by blueasa
TAG Git, tag, Zombie

댓글을 달아 주세요

Last Christmas I bought my wife and myself a Synology NAS to store our pictures on. Given that I’d spent a lot of time over the last few years working on Git LFS, I always thought it would be pretty cool if you could use the NAS as an LFS server.

Like everything else these days, the thing can run apps. I looked around for what it would take to make an app for it and what I found seemed to be mostly a bunch of flaming hoops to jump through. I’m pretty lazy, so I dropped it.

The other day I was checking out Home Assistant and noticed it could be installed on the Synology via Docker. Wait … what? You can run Docker on it‽ Far out! It is Linux, so I guess that makes sense. Now it should be easy to set up an LFS server on it. We have a reference server that’ll do just fine for this.

To get running, first install the Docker app from Package Center. Start the app and head to the Registrytab. It’s hooked up to DockerHub by default. The search seems to love returning results for things you didn’t ask for, so it’s best to just search for rubyist. Searching for rubyist/git-lfs-server is far too specific, I guess, but that’s what you’re looking for. Click Download for download.

Once it’s downloaded, it’ll appear in the Image tab. Click Launch to launch.

This brings up the Docker app’s container wizard. It’s actually quite nice. Click the Advanced Settingsbutton. Set the following options in their respective tabs:

  • Advanced Settings: Enable auto-restart
  • Volume: Add a folder on the drive at a Mount Path of /var/git-lfs
  • Network: Select “Use the same network as Docker Host”
  • Environment: Configure any environment vars for the server

The full set of supported environment variables can be found in the lfs-test-server README, here are the ones you’ll need to set:

  • LFS_HOST: The host name of your NAS
  • LFS_ADMINUSER: The username of the admin user
  • LFS_ADMINPASS: The admin password

When setting LFS_HOST you’ll need to include the port that the LFS server is running on, which will be ":8080". For example, "foobar.localdomain:8080".

Once you’re done there, close the advanced settings and click the Next button. You’ll see a summary of the config. Click Apply.

Your LFS server is now running! Configure LFS by adding the following to the .lfsconfig file in the root of your repo:


If you have questions, tweet at @rubyist, I might answer.

[출처] https://killring.io/post/synology-for-lfs/

'협업 > Git' 카테고리의 다른 글

[펌] Git: Zombie tags from hell  (0) 2018.02.21
[펌] Synology As A Git LFS Server  (0) 2017.11.14
[펌][SourceTree] 갑자기 실행이 안될때  (0) 2017.10.23
[링크] Pro Git[ebook]  (0) 2017.07.29
[Bug] SourceTree for Mac  (0) 2017.06.29
[Util] GitKraken  (0) 2017.06.29
Posted by blueasa

댓글을 달아 주세요

NAS를 살 때 많은 고민을 하고 Synology 제품을 선택했다.

FTP 같은 기능은 당연한 것이고,

CloudStation 은 참 만족스러운 기능으로 사용을 했다.


최근에 주변 사람을 통해서 소스 형상관리툴 Git을 알게 되었다.

나의 NAS에서 Git을 설치할 수 있다는 것을 알게 되고는

구글링등의 많은 방법을 통하여 설치하는 방법을 알게 되었다.


이걸 정리를 해 놓아야지 다음에 다시 설치하더라고 유용할꺼 같아서 정리를 해 보았다.


● 설치 환경

Synology NAS DS212J

DSM 5.2


● 사용환경

Visual Studio 2013


● 설정방법


1.NAS에서 SSH서비스를 활성화해야 한다.


제어판에 들어가서 응용 프로그램란에 [터미널 및 SNMP]를 선택한다. 



SSH 서비스를 활성화 시켜준다. 



2.Git Server 설치


NAS바탕화면에 있는 패키지 센터를 실행해서, [모두] 또는 [유틸리티]화면을 열어보면 아래와 같이 Git Server라는게 보인다.

서버가 설치되기 전에는 버튼이 [설치]라고 되어 있어 설치하고 나서 보면 아래와 같이 [열기]로 보여진다. 



Git Server 설치 후 설치됨 메뉴를 선택해보면 아래와 같이 설치가 되었음을 알 수가 있다.



Git Server를 선택하여 들어가서 Git Server 서비스를 활성화 시켜준다. 



3.NAS에 사용자 계정을 추가해야 한다.


다시 제어판에 가서 사용자 메뉴를 선택한다.

사용자 메뉴에서 [생성] 버튼을 클릭한다.



사용자 정보를 입력한다.

사용자 계정을 gituser라고 했다.



gituser의 그룹은 users로 선택한다.



gituser는 homes만 접근권한을 줬다.



그 이후는 모두 다음 .. 다음 넘어가면 되고 혹시나 싶어서 WebDav는 허용하였다. 




4.Repository 생성


NAS에서의 작업은 끝이 난거 같다.

Windows 를 사용하는 관계로 PuTTY를 이용해서 Repository를 생성해야 되겠다.

PuTTY를 실행하고 root로 로그인을 한다.




키보드를 두드릴 시간이 왔다.


NAS에 disk가 하나가 있어 그 놈은 volume1인데 그 놈의 이름이 /var/services 이라는것 같다.(리눅스를 잘 모름)

아뭏튼 gituser라고 만든 계정의 홈은 /var/services/homes/gituser가 된다.


여기에 project.git 이라는 폴더를 생성고

그 폴더로 들어가서 Repository 초기화(?)라나 뭐 그렇게 해준다.

그리고 cd .. 하여 상위 폴더로 올라와서

project.git 이란 폴더의 하위 전체의 권한을 gituser에 넘긴다.


chown -R (git사용자 계정):(git 사용자가 속한 그룹)  (사용자 디렉토리)


여기까지 하면 Git Server의 설정이 끝이다.




5.Windows 에서의 설정


이것도 참 고생을 했다.

개념 모르고 덤비니 가시밭길이 이만 저만이 아니다.

그래도 다 왔다.


참고로 Windows에서의 Git 에 대한 사용법은 http://backlogtool.com/git-guide/kr/ 여기를 참고했다.


TortoiseGit 프로그램을 설치를 한다.

그리고 나서 Windows 원하는 경로에 repository를 생성한다.




그리고는 다시 TortoiseGit의 Settings 화면에서 사용자를 저장한다.

이 때 사용자는 NAS에 만든 gituser가 아닌 개발자를 의미한다.(개발자마다의 개별 설정)



제일 중요한 마지막 설정이다.

URL 은 http로는 성공을 못했다. 그래서 ssh로 했다.

ssh://(NAS에 생성했던 계정)@(NAS의 DNS):(포워딩한 port)/volume1/homes/(사용자 계정 폴더)/(Repository 폴더 명)

(예 ssh://gituser@nas.familyds.com:9112/volume1/homes/gituser/project.git)


- ssh의 표준 포트는 SSH 서비스 활성화에서처럼 22이다.

  세상이 무서워서 port forwading을 하는게 좋을꺼 같다. 임의의 숫자로


- /volume1 대신 /var/services 라고 써도 되는거 같은데 다음에 설정할 일이 있으면 그렇게 해 보아야겠다.




이렇게 해서 NAS에서의 Git 사용에 관련된 모든 설정을 완료한거 같다.

많은 시간을 들여서 해 놓은 삽질을 잊어버리기 전에 이렇게 정리한 번 해 보았다.

[출처] http://kongzz.tistory.com/14

Posted by blueasa

댓글을 달아 주세요

처음에는 Rebase를 왜 해야 하고 언제 어떻게 해야 하는지 좀 헷갈린다. 헷갈리는 이유는 정답이 없고 미묘함이 있어서인데 그래도 대략적인 가이드가 있으면 좋겠다 싶어서 정리해보았다.


Social Coding Platform

svn이나 다른 VCS 도구 말고 git을 사용해야 하는 이유는 커뮤니케이션이다. 개발이라는 작업은 혼자 하는 게 아니라서 코드를 공유하고, 리뷰하고, 피드백을 받아야 하는데 Git으로 하면 일이 좀 쉬워진다(Git이 쉽다는 것은 아니다).

git과 github의 인기는 VCS 본연의 기능뿐만 아니라 커뮤니케이션을 원활하게 할 수 있는 플랫폼이 함께 필요하다는 것을 보여준다. git은 소스관리에도 뛰어난 도구지만 그게 Git만의 장점은 아니다.

git은 단순히 VCS가 아니다. 소스관리뿐만 아니라 커뮤니케이션에 필요한 모든 것이 들어 있다. 특히 코드를 공유하는 것은 정말 끝내 준다. Git 이외에 필요한 도구가 별로 없다. 나는 히스토리를 엉망으로 관리하는 프로젝트을 살펴보고자 gitx를 가끔 사용하고 차이를 살펴보고자 diffmerge를 아주 가끔 사용한다. 정말 아주 가끔이다. 한 달에 한 번도 실행하지 않는다.

그 외에는 항상 콘솔에서 작업한다. git은 아직도 발전 중이고 코드를 쉽게 공유하는 방법이 계속 통합될 것으로 생각한다. git에는 정말 필요한 모든 것이 통합되고 있어서 언젠가 git으로 문자 메시지로 코드를 보낼 수 있는 날이 올지도 모른다는 상상을 하고 있다.


동료는 그녀와 같다. 배려 없이 초대에 응하는 그녀는 없다. 최대한 친절을 베풀어야 그녀를 내 저장소로 초대할 수 있다. 공포를 조장하거나 무턱대고 돈만 살포해서는 진심을 이끌어 낼 수 없다. 스스로 응할 때까지 배려하고 인내해야 한다.

코드는 당연히 잘 짜야 한다. 버그는 없을수록 좋고, 주석은 간략하고 명확해야 하고, 변수나 함수이름, 파일이나 디렉토리 구조나 이름 등등…. 중요하지 않은 것이 없다. 좋은 글에는 좋은 문장도 많은 법이다.

git도 마찬가지다. 변수 이름을 잘 짓듯이 브랜치 이름도 잘 지어야 한다. 커밋 메시지도 표준 포멧에 따라 잘 지어야 한다. 그리고 히스토리도 예쁘게 만들어야 한다.

Merge vs Rebase

Rebase는 히스토리를 단장하는 데 필요하다. 나 혼자 쓰는 저장소에서도 Rebase가 없으면 지저분해서 히스토리를 읽을 수가 없다.

잘 정리한 히스토리를 엿보고 싶다면 npm 저장소를 구경해보는 것이 좋다. @izs님은 완전 git타쿠:


히스토리가 정말 보기 좋다. github의 'pull request'도 사용하지 않고 죄다 손으로 Merge하는 것 같다.

커밋 vs Merge 커밋

Merge와 Rebase를 살펴보기 전에 커밋부터 다시 살펴보자.

커밋은 의미의 단위다. 지금 하는 일을 적당하게 한 조각으로 나눠서 커밋한다. 10줄, 100줄처럼 정량적인 단위가 아니다. 고기를 사듯이 '커밋 한 근 주세요.'라고 말할 수 없다. 커밋 하나는 의미 하나다.

커밋 하나하나에도 의미가 있지만 어떤 모듈을 개발한다면 여러 개를 하나로 묶어서 처리할 필요도 있다. 그러니까 여러 개의 커밋을 묶음으로 표현할 수 있는 커밋이 필요하다. 그게 Merge 커밋이다. Merge 커밋은 일종의 커밋 묶음이다

npm 저장소에 @izs님이 만들어 놓은 Merge 커밋을 보자:


1ecd0eb는 gyp를 구현한 커밋들을 묶어 놓은 Merge 커밋이다. gyp 브랜치를 만들어 gyp를 구현하고 master 브랜치로 Merge했다.

Merge 커밋은 사실 커밋 묶음 나타내는 것이 아니다. 보통 커밋은 Parent가 하나인데 Merge 커밋은 Parent가 여러 개다. 하지만, Parent가 여러 개인 점을 이용해서 커밋 묶음으로 다룰 수 있다:


C6는 Merge 커밋으로 Parent가 두 개다.

Merge 커밋을 Reset하면 관련 커밋이 전부 Reset된다:


C3와 C5가 같이 Reset되기 때문에 master 입장에서는 커밋 묶음이 Reset된 것이다.

npm 저장소에서 master 브랜치가 Merge 커밋인 1ecd0eb를 가리키는 상태에서 'HEAD~1'으로 Reset하면 gyp 브랜치가 통째로 Reset된다. 그래서 master는 c4eb2fd를 가리킨다.

Merge vs Rebase

다음과 같은 브랜치를 Merge, Rebase해보고 그 결과를 비교해보자:


git merge iss1 명령으로 iss1를 Merge한다. 노란색인 C1은 Merge Base이다:


git merge iss2 명령으로 iss2를 Merge한다:


git merge iss3 명령으로 iss3를 Merge한다:


iss1, iss2, iss3를 Merge 했다. C9, C10, C11은 Merge 커밋이다. 이 그림에서는 히스토리가 복잡하지 않다고 생각할 수 있지만, 이정도 되는 내용도 콘솔에서 보면 헷갈린다. 한눈에 들어오지 않는다. 이제 Rebase 후 Merge해보자.

헷갈릴 수 있으니 원본 브랜치를 다시 한번 보고:


git checkout iss1과 git rebase master를 차례대로 실행해서 Rebase한다 그러면 Merge Base가 C1이 아니라 C4가 된다:


git checkout master과 git merge iss1를 차례대로 실행해서 Merge한다. Rebase를 하면 항상 Fast-Forward Merge가 가능해진다. 하지만, 무턱대고 Fast-Forward Merge를 하는 것이 아니라 앞서 얘기했듯이 커밋을 묶음으로 관리하고 싶지 않을 때만 Fast-Forward Merge한다. 이 경우는 커밋이 하나이므로 그냥 Fast-Forward Merge한다:


git checkout iss2과 git rebase master를 차례대로 실행해서 Rebase한다 그러면 Merge Base가 C3가 아니라 C2'가 된다:


git checkout master과 git merge --no-ff iss2를 차례대로 실행해서 Merge한다.--no-ff 옵션은 강제로 Merge 커밋을 남기려고 주는 것이다. iss2 브랜치는 커밋이 두 개고 이 커밋은 iss2를 처리한 결과이므로 커밋 묶음으로 처리하는 것이 낫다(물론, 내용상 --no-ff 옵션을 주는 게 틀릴 수도 있다.):


git checkout iss3과 git rebase master를 차례대로 실행해서 Rebase한다 그러면 Merge Base가 C3에서 C9이 된다:


git checkout master과 git merge --no-ff iss3를 차례대로 실행해서 Merge한다:


다음 그림은 위에서 Rebase 없이 Merge한 결과다. 한번 비교해보자:


Rebase를 하고 나서 Merge한 것이 훨씬 보기 좋다. 아무리 복잡한 과정을 거쳤어도 한눈에 들어오게 할 수 있다.


Git처럼 히스토리를 다중으로 관리하는 시스템에서 Rebase는 필수다. Mercurial도 Git의 영향을 받아 Rebase를 지원한다. 이글에서는 Rebase가 왜 필요하고 언제 어떻게 해야 하는지 알아봤다.

UPDATE: 20121122

Merge Commit은 Commit을 묶음으로 관리하는데도 유용하지만 Release Note에 넣을 만한 것을 미리 Merge Commit으로 만들어 놓으면 편리할 것 같다. 배포할 때 Merge Commit만 추려볼 수 있으니 Release Note를 따로 작성하지 않아도 된다.

Posted by blueasa
TAG Git, Rebase

댓글을 달아 주세요

Posted by blueasa

댓글을 달아 주세요