[git] 자식 분기, 포크, 가져 오기, 병합, 리베이스 및 복제의 차이점은 무엇입니까?
Git의 브랜치, 포크 및 클론의 차이점을 이해하고 싶습니까?
마찬가지로,에 git fetch
반대하여을 할 때 무엇을 의미 git pull
합니까?
또한 ? rebase
와 비교하여 merge
무엇을 의미 합니까?
개인 커밋을 함께 스쿼시하려면 어떻게해야합니까?
그들은 어떻게 사용되며 왜 사용되며 무엇을 상징합니까?
GitHub는 어떻게 파악됩니까?
답변
복제본은 단순히 저장소의 사본입니다. 표면적으로 결과는 svn checkout
다른 리포지토리에서 소스 코드를 다운로드하는와 같습니다. Subversion과 같은 중앙 집중식 VCS와 Git과 같은 DVCS의 차이점은 Git에서 복제 할 때 실제로 모든 히스토리 및 분기를 포함하여 전체 소스 저장소를 복사한다는 것입니다. 이제 시스템에 새 저장소가 있으며 커밋이 있으면 해당 저장소로 이동합니다. 커밋을 다른 리포지토리 (또는 원래 리포지토리)로 푸시하거나 공개적으로 액세스 할 수있는 누군가가 리포지토리에서 커밋을 가져 오기 전까지는 아무도 변경 내용을 볼 수 없습니다.
브랜치는 리포지토리 내에있는 것입니다. 개념적으로 개발 스레드를 나타냅니다. 일반적으로 마스터 분기가 있지만 일부 기능 xyz를 작업하는 분기와 버그 abc를 수정하는 분기가있을 수도 있습니다. 지점을 체크 아웃하면 커밋 한 커밋은 해당 지점에 남아 있고 해당 지점과 병합하거나 리베이스 할 때까지 다른 지점과 공유되지 않습니다. 물론, Git은 브랜치 구현 방식의 기본 모델을 볼 때까지 브랜치와 관련하여 약간 이상하게 보입니다. 직접 설명하지 않고 (나는 이미 너무 많이 말했지만, methinks), Git 웹 사이트에서 가져온 Git 모델 브랜치 및 커밋 방법에 대한 “컴퓨터 과학”설명에 연결합니다.
http://eagain.net/articles/git-for-computer-scientists/
포크는 실제로 Git 컨셉이 아니라 정치적 / 사회적 아이디어입니다. 즉, 어떤 사람들이 프로젝트가 진행되는 방식에 만족하지 않으면 소스 코드를 가져 와서 원래 개발자와 별도로 작업 할 수 있습니다. 그것은 포크로 간주 될 것입니다. Git은 모든 사람이 이미 소스 코드의 “마스터”복사본을 가지고 있기 때문에 쉽게 포크 할 수 있으므로, 원래 프로젝트 개발자와의 관계를 끊는 것만 큼 간단하고 SVN과 관련하여 공유 저장소에서 히스토리를 내보낼 필요가 없습니다. .
편집 : GitHub와 같은 사이트에서 사용되는 “포크”에 대한 현대적인 정의를 알지 못했기 때문에 자세한 내용은 아래 의 의견과 Michael Durrant의 답변 을 참조하십시오.
답변
힘내
이 답변에는 많은 사람들이 그것에 대해 물었던 GitHub도 포함됩니다.
로컬 리포지토리
힘내 (로컬)에는 .git
파일을 커밋 하는 디렉토리 ( )가 있으며 이것이 로컬 저장소입니다. 이것은 원격 저장소에 즉시 추가하고 커밋하는 SVN과 같은 시스템과 다릅니다.
Git은 전체 파일을 저장하여 변경되는 파일의 각 버전을 저장합니다. 델타 변경을 통해 ‘재 작성’하지 않고 개별 버전으로 이동할 수 있으므로 SVN과 다릅니다.
Git은 파일을 전혀 ‘잠그지’않으므로 편집을위한 ‘독점 잠금’기능을 피할 수 있으므로 (pvcs와 같은 구형 시스템을 염두에 두어야 함) 오프라인 상태에서도 모든 파일을 항상 편집 할 수 있습니다. 실제로 GitHub와 같은 원격 저장소로 가져 오거나 가져 오기 / 푸시하는 동안 파일 변경 사항을 동일한 파일 내에서 병합하는 놀라운 작업을 수행합니다. 수동 변경 (실제로 파일 편집)을 수행해야하는 유일한 경우는 두 변경에 동일한 코드 줄이 포함 된 경우입니다.
지점
브랜치를 사용하면 기본 코드 ( ‘마스터’브랜치)를 보존하고 사본 (새 브랜치)을 만든 다음 새 브랜치 내에서 작업 할 수 있습니다. 브랜치가 작성된 이후 작업이 오래 걸리거나 마스터가 많은 업데이트를 얻는 경우, 마스터 브랜치에 대해 병합 또는 재베이스 (종종 더 나은 히스토리를 선호하고 충돌을 쉽게 해결하기 위해)해야합니다. 완료하면 지점에서 변경 한 사항을 다시 마스터 리포지토리에 병합합니다. 많은 조직은 기능, 버그 또는 집안일 항목이든 각 작업에 대해 지점을 사용합니다. 다른 조직에서는 버전 업그레이드와 같은 주요 변경 사항에 대해서만 지점을 사용합니다.
포크 : 브랜치를 사용하면 브랜치를 제어하고 관리하는 반면, 다른 사람은 다른 사람이 코드를 다시 수락하도록 제어합니다.
광범위하게 말하면, 가지를 수행하는 두 가지 주요 접근 방식이 있습니다. 첫 번째는 마스터 브랜치에서 대부분의 변경 사항을 유지하는 것입니다. 버전 요구 사항과 같이 필요에 따라 두 개의 브랜치를 사용할 수있는 버전 변경과 같이 더 크고 더 오래 실행되는 항목에 대해서만 브랜치를 사용합니다. 두 번째는 기본적으로 모든 기능 요청, 버그 수정 또는 잡일에 대한 분기를 만든 다음 실제로 해당 분기를 기본 마스터 분기에 병합 할시기를 수동으로 결정하는 것입니다. 이것이 지루한 것처럼 들리지만 이것은 일반적인 접근 방식이며 현재 사용하고 추천하는 방법입니다. 이는 마스터 브랜치를 더 깨끗하게 유지하고 프로덕션으로 홍보하는 마스터이기 때문에 rebasing을 통해 완성되고 테스트 된 코드 만 원합니다. 가지의 병합.
지점에 ‘in’을 가져 오는 표준 방법은을 수행하는 것 merge
입니다. 지점은 “정리”하여 기록을 ‘정리’할 수도 있습니다. 현재 상태에는 영향을주지 않으며 ‘보다 깨끗한’기록을 제공하기 위해 수행됩니다.
기본적으로 아이디어는 특정 지점 (일반적으로 마스터)에서 분기한다는 것입니다. 분기 한 이후 ‘마스터’자체가 해당 분기 지점에서 앞으로 이동했습니다. 지점에서 수행 한 모든 변경 사항이 최신 변경 사항과 함께 현재 마스터 상태에 대해 재생되는 경우 ‘깨끗한'(문제를 해결하기 쉽고 기록을 더 쉽게 이해할 수 있음)됩니다. 따라서 프로세스는 다음과 같습니다. 변경 사항을 저장하십시오. ‘새’마스터를 얻은 다음 변경 사항을 다시 적용하십시오 (이 부분은 rebase 부분입니다). 병합과 마찬가지로 리베이스는 수동으로 해결해야하는 충돌 (예 : 편집 및 수정)을 초래할 수 있습니다.
참고 사항 :
지점이 로컬이고 아직 원격으로 푸시하지 않은 경우에만 리베이스하십시오!
다른 사람이 자신의 커밋을 포함 할 수있는 역사를 바꿀 수 있기 때문입니다.
추적 지점
이것들은 이름이 붙은 가지입니다 origin/branch_name
(단지 반대로 branch_name
). 원격 리포지토리로 코드를 밀거나 당기는 경우 실제로 이것이 발생하는 메커니즘입니다. 예를 들어, git push
이라는 building_groups
지점이 있으면 지점이 먼저 이동 origin/building_groups
한 다음 원격 저장소로 이동합니다. 마찬가지로을 수행하면 git fetch building_groups
검색된 파일이 origin/building_groups
분기에 배치됩니다 . 그런 다음이 분기를 로컬 사본에 병합하도록 선택할 수 있습니다. 우리의 관행은 항상 ( git fetch
단 git pull
하나의 단계에서 위의 두 가지를 수행 하는 것)보다는 수동 병합을 수행하는 것 입니다.
새 가지를 가져 오는 중입니다.
새 가지 얻기 : 복제 초기에 모든 가지가 있습니다. 그러나 다른 개발자가 분기를 추가하고 원격으로 푸시하는 경우 분기를 로컬로 끌어 올릴 수 있도록 해당 분기와 해당 이름을 ‘알 수있는’방법이 필요합니다. 이는 git fetch
추적 분기 (예 :)를 사용하여 모든 새 분기 및 변경된 분기를 로컬 저장소로 가져 오는를 통해 수행됩니다 origin/
. fetch
ed가 되면 git branch --remote
추적 분기를 나열하고 git checkout [branch]
실제로 지정된 분기 로 전환 할 수 있습니다.
합병
병합은 서로 다른 브랜치 또는 동일한 브랜치의 다른 버전 (예 : 로컬 브랜치와 원격이 동기화되지 않은 경우)의 코드 변경 사항을 결합하는 프로세스입니다. 지점에서 작업을 개발했으며 작업이 완료, 준비 및 테스트 된 경우 master
지점 으로 병합 될 수 있습니다 . 이는 지점 git checkout master
으로 전환 master
한 다음에 수행 git merge your_branch
됩니다. 병합하면 다른 모든 파일과 동일한 파일에 대한 다른 변경 사항이 함께 제공됩니다. 이것은 실제로 모든 변경 사항을 병합하기 위해 파일 내부의 코드를 변경한다는 것을 의미합니다.
할 때 checkout
의 master
그도를 할 것을 추천 git pull origin master
리모트 마스터의 최신 버전을 얻으려면 로컬 마스터에 병합. 리모트 마스터가 변경 한 경우, 즉 moved forward
, 그 동안 저를 반영하는 정보를 볼 수 있습니다 git pull
. 이런 경우 (마스터 변경) 당신이하는 것이 좋습니다 git checkout your_branch
다음 rebase
은 변경 사항이 실제로 얻는 ‘새로운’마스터의 상단에 ‘재생’너무 마스터. 그런 다음 다음 단락과 같이 마스터를 최신 상태로 유지하십시오.
충돌이없는 경우 master에 새로운 변경 내용이 추가됩니다. 충돌이있는 경우 동일한 파일이 유사한 코드 줄에 대해 자동으로 병합 할 수없는 변경 사항이 있음을 의미합니다. 이 경우 git merge new_branch
해결해야 할 충돌이 있음을보고합니다. 파일을 편집하고 (두 가지 변경 사항이 모두 있음) 원하는 변경 사항을 선택하고, 원하지 않는 변경 내용을 문자 그대로 삭제 한 다음 파일을 저장하여 파일을 ‘해결’합니다. 변경은 예컨대 세퍼레이터로 표시되어 ========
하고 <<<<<<<<
.
당신이 다시 한번 것 충돌 해결되면 git add
및 git commit
병합을 계속 변경 사항을 (이 과정을 안내하는 동안 자식의 피드백을 얻을 것이다).
프로세스가 제대로 작동하지 않으면 git merge --abort
재설정하기가 매우 편리합니다.
대화식 리베이스 및 스쿼시 / 재정렬 / 커밋 제거
예를 들어, 매일 ‘진행중인 작업’으로 코드를 커밋하는 등 많은 작은 단계로 작업을 수행 한 경우 이러한 많은 작은 커밋을 몇 개의 커밋으로 ‘스쿼시’할 수 있습니다. 동료와 코드 검토를 수행 할 때 특히 유용합니다. 커밋을 통해 수행 한 모든 ‘단계’를 재생하고 싶지 않고 여기에서 한 번의 커밋 으로이 작업에 대한 모든 변경 사항의 최종 효과 (diff)가 있다고 말하고 싶습니다.
이 작업을 수행할지 여부를 고려할 때 평가해야 할 핵심 요소는 여러 커밋이 동일한 파일 또는 여러 파일에 대해 두 번 이상 수행되는지 여부입니다 (이 경우 스쿼시 커밋보다 낫습니다). 이것은 대화식 리베이스 도구로 수행됩니다. 이 도구를 사용하면 커밋 스쿼시, 커밋 삭제, 메시지 변경 등을 수행 할 수 있습니다. 예를 들어 git rebase -i HEAD~10
( 참고 :이 ~
아닌 a-
)는 다음을 나타냅니다.
하지만 조심해서이 도구를 ‘진저하게’사용하십시오. 한 번에 한 번 스쿼시 / 삭제 / 재주문을 수행하고 해당 커밋을 종료하고 저장 한 다음 도구를 다시 입력하십시오. 커밋이 연속적이지 않으면 다시 정렬 할 수 있습니다 (필요에 따라 스쿼시). 실제로 커밋도 여기서 삭제할 수 있지만 그렇게 할 때 실제로 무엇을하고 있는지 확인해야합니다!
포크
Git 리포지토리에는 협업에 대한 두 가지 주요 접근 방식이 있습니다. 위에서 자세히 설명한 첫 번째는 사람들이 끌어 당기는 지점을 통해 직접 가져온 것입니다. 이 공동 작업자는 SSH 키가 원격 저장소에 등록되어 있습니다. 이를 통해 해당 저장소로 직접 푸시 할 수 있습니다. 단점은 사용자 목록을 유지 관리해야한다는 것입니다. 다른 접근 방식 (forking)은 누구나 저장소를 ‘포크’하여 기본적으로 자체 Git 저장소 계정에 로컬 사본을 만듭니다. 그런 다음 변경을 수행하고 완료되면 ‘풀 요청'(실제로 리포지토리 관리자의 ‘푸시’및 실제 리포지토리 관리자에 대한 ‘풀’요청에 해당)을 보내 코드를 수락합니다.
포크를 사용하는이 두 번째 방법 에서는 누군가 저장소의 사용자 목록을 유지 보수 할 필요 가 없습니다 .
깃 허브
GitHub (원격 리포지토리)는 이러한 리포지토리가 있거나 추가 된 경우 커밋 된 변경 사항을 일반적으로 푸시하고 가져 오는 원격 소스이므로 로컬과 원격은 실제로 매우 다릅니다. 원격 저장소를 생각하는 또 다른 방법은 원격 저장소에있는 .git
디렉토리 구조라는 것입니다.
당신이 ‘포크’경우 – GitHub의 웹 브라우저 GUI에서 당신이 버튼을 클릭 할 수 있습니다 – 당신의 코드의 사본 ( ‘클론’)를 생성 하여 GitHub의 계정. 처음에는 약간 미묘 할 수 있으므로 코드 소유자가 원래 소유자 또는 ‘forked’아래에 나열된 저장소를 확인하십시오.
로컬 복사본이 있으면 원하는대로 로컬 컴퓨터로 당겨서 변경할 수 있습니다. 완료되면 원래 저장소 소유자 / 관리자에게 ‘풀 요청’을 제출하십시오 (멋지게 들리지만 실제로 이것을 클릭하십시오 :).
코드를 함께 공동 작업하는 팀에게는 리포지토리를 ‘복제’하는 것이 더 일반적입니다 (리포지토리 기본 화면에서 ‘복사’아이콘 클릭). 그런 다음 로컬로 입력 git clone
하여 붙여 넣습니다. 로컬로 설정되며 (공유) GitHub 위치로 밀고 당길 수도 있습니다.
클론
GitHub 섹션에 표시된 것처럼 클론은 리포지토리의 복사본입니다. 원격 저장소가있는 경우 git clone
해당 URL에 대해 명령을 실행 한 다음 저장소의 로컬 사본 또는 복제본으로 끝납니다. 이 클론은 모든 파일, 마스터 브랜치, 다른 브랜치, 모든 기존 커밋, 전체 shebang을 갖습니다. 추가 및 커밋을 수행하는 것이이 복제본이며 원격 저장소 자체가 커밋을 푸시합니다. SVN, PVCS, CVS 등과 같은 전통적인 CVS (코드 버전 관리 시스템)와 반대로 Git (및 Mercurial과 유사한 시스템)을 DVCS ( 분산 버전 제어 시스템)로 만드는 것은이 로컬 / 원격 개념입니다 . 원격 저장소에 직접 커밋합니다.
심상
핵심 개념의 시각화는
http://marklodato.github.com/visual-git-guide/index-en.html 및 http://ndpsoftware.com/git-cheatsheet.html#loc=index 에서 볼 수 있습니다.
변경 사항이 어떻게 작동하는지 시각적으로 표시하려면 ‘지하철 맵'(런던 지하철)이라고하는 GUI를 사용하여 시각적 도구 gitg
( gitx
macOS 용)를 이길 수 없습니다 . 사물이 어떻게 바뀌고 분기되고 병합되는지 등
또한이를 사용하여 변경 사항을 추가, 커밋 및 관리 할 수 있습니다!
gitg / gitx는 매우 작지만 GUI 도구의 수는 계속 확장됩니다. 많은 Mac 사용자는 brotherbard의 gitx 포크와 Linux를 사용하며, 직관적이지만 강력한 인터페이스를 갖춘 스마트 git 옵션이 있습니다.
GUI 도구를 사용하더라도 명령 행에서 많은 명령을 수행 할 수 있습니다.
이를 위해 ~/.bash_aliases
파일에 다음과 같은 별칭이 있습니다 ( ~/.bashrc
각 터미널 세션마다 파일 에서 호출 됨 ).
# git
alias g='git status'
alias gcob='git checkout -b '
alias gcom='git checkout master'
alias gd='git diff'
alias gf='git fetch'
alias gfrm='git fetch; git reset --hard origin/master'
alias gg='git grep '
alias gits='alias | grep "^alias g.*git.*$"'
alias gl='git log'
alias gl1='git log --oneline'
alias glf='git log --name-status'
alias glp='git log -p'
alias gpull='git pull '
alias gpush='git push '
그리고 내 ~/.gitconfig
파일 에 다음과 같은 “git aliases”가 있습니다. 왜 이런 것들이 있습니까?
그래서 분기 완료 (TAB 키 사용)가 작동합니다!
따라서 이들은 :
[alias]
co = checkout
cob = checkout -b
사용법 예 : git co [branch]
분기의 <-탭 완성이 작동합니다.
GUI 학습 도구
https://learngitbranching.js.org/ 는 기본 개념을 배우는 데 유용 할 수 있습니다 . 스크린 샷 :
비디오 : https://youtu.be/23JqqcLPss0
마지막으로, 7 가지 주요 생명의 은인!
-
변경, 추가 및 커밋 (하지만 밀지 않음) 한 다음 아! 당신은 당신이 마스터에 있다는 것을 알고 있습니다!
git reset [filename(s)] git checkout -b [name_for_a_new_branch] git add [file(s)] git commit -m "A useful message" Voila! You've moved that 'master' commit to its own branch !
-
로컬 브랜치에서 작업하는 동안 일부 파일을 엉망으로 만들고 마지막으로 수행 한 작업으로 돌아가고 싶습니다
git pull
.git reset --hard origin/master # You will need to be comfortable doing this!
-
로컬에서 변경을 시작하고 6 개 파일을 편집 한 다음 여전히 마스터 (또는 다른) 브랜치에 있습니다.
git checkout -b new_branch_name # just create a new branch git add . # add the changes files git commit -m"your message" # and commit them
-
현재 브랜치에서 하나의 특정 파일을 엉망으로 만들고 해당 파일을 원격 저장소에서 마지막으로 가져간 마지막 방법으로 기본적으로 해당 파일을 ‘재설정'(변경 사항 잃어 버림)하려고합니다.
git checkout your/directories/filename
이것은 실제로 파일을 재설정합니다 (많은 Git 명령과 마찬가지로 여기에서 수행중인 작업의 이름이 잘못되었습니다).
-
로컬에서 약간의 변경을 수행
git reset
하거나 또는 수행하는 동안 변경 사항을 잃지 않도록하고 싶습니다 .Git에서 엉망이되거나 중요한 것을 잃을 지 확실하지 않을 때rebase
종종 전체 프로젝트의 수동 사본을 만듭니다 (cp -r ../my_project ~/
) 변화. -
당신은 rebasing하지만 상황이 엉망이됩니다 :
git rebase --abort # To abandon interactive rebase and merge issues
-
Git 브랜치를
PS1
프롬프트에 추가하십시오 ( https://unix.stackexchange.com/a/127800/10043 참조 )지점은
selenium_rspec_conversion
입니다.
답변
올리버 스틸 (Oliver Steele)의 이미지가 모두 잘 어울리는 모습은 다음과 같습니다.
답변
포크 대. 복제-두 단어 모두 복사를 의미
이 다이어그램을 참조하십시오 . (원래 http://www.dataschool.io/content/images/2014/Mar/github1.png에서 )
.-------------------------. 1. Fork .-------------------------.
| Your GitHub repo | <-------------- | Joe's GitHub repo |
| github.com/you/coolgame | | github.com/joe/coolgame |
| ----------------------- | 7. Pull Request | ----------------------- |
| master -> c224ff7 | --------------> | master -> c224ff7 (c) |
| anidea -> 884faa1 (a) | | anidea -> 884faa1 (b) |
'-------------------------' '-------------------------'
| ^
| 2. Clone |
| |
| |
| |
| |
| | 6. Push (anidea => origin/anidea)
v |
.-------------------------.
| Your computer | 3. Create branch 'anidea'
| $HOME/coolgame |
| ----------------------- | 4. Update a file
| master -> c224ff7 |
| anidea -> 884faa1 | 5. Commit (to 'anidea')
'-------------------------'
(a) - after you have pushed it
(b) - after Joe has accepted it
(c) - eventually Joe might merge 'anidea' (make 'master -> 884faa1')
포크
- Joe ‘s에 연결하는 원격 저장소 (클라우드)에 사본
- 그런 다음 사본을 로컬 리포지토리에 복제하고 F * % $-up
- 완료되면 리모컨으로 다시 밀 수 있습니다.
- 그런 다음 풀 요청을 클릭하여 Joe에게 프로젝트에서 사용할 것인지 묻습니다.
클론
- 로컬 리포지토리 (하드 드라이브)
답변
다른 사람들에게 추가하기 위해, 포크 관련 메모.
기술적으로 repo를 복제하고 repo를 포크하는 것은 동일한 것임을 인식하는 것이 좋습니다. 하다:
git clone $some_other_repo
등을 두드리면서 다른 레포를 갈았습니다.
VCS로서 Git은 실제로 복제 복제 에 관한 것 입니다. 그렇다 같은 CGIT로 원격 UI를 사용하여 “단지 검색”에서, 포함하지 않는 자식의 repo와 함께 할 거의가 분기 어느 시점에서의 repo를 복제.
하나,
-
누군가가 repo X를 포크 했다고 말하면 , 다른 실험 에 노출 시키 거나 다른 접근 제어 메커니즘을 적용하기 위해 (예 : Github 액세스하지만 회사 내부 계정을 사용하여 공동 작업).
사실 : repo는 아마도 다른 명령으로 작성되었을 가능성이 높으며
git clone
, 아마도 누군가의 랩톱과는 달리 서버의 어딘가에서 호스팅 될 것이고 아마도 약간 다른 형식을 가질 것입니다 (예 : 작업 트리가없는 “맨손의 repo”입니다) 기술적 인 내용 일뿐입니다.아마도 다른 브랜치, 태그 또는 커밋 세트를 포함한다는 사실은 아마도 그들이 처음에 그것을했던 이유 일 것입니다.
( “포크”를 클릭 할 때 Github의 기능은 설탕을 추가하여 복제하는 것입니다. 리포지토리를 복제하고 계정에 저장하며 어딘가에 “포크”를 기록하고 “업스트림”이라는 이름의 원격을 추가하며 가장 중요한 것은 멋진 애니메이션을 재생합니다.)
-
누군가 repo X를 복제 했다고 말하면 랩톱이나 데스크탑에서 로컬로 repo 복제본을 작성하여 연구, 재생, 기여 또는 소스 코드로 무언가를 빌드했음을 의미합니다.
Git의 장점은 이것이 모두 완벽하게 적합하다는 것입니다.이 모든 리포지토리는 블록 커밋 체인 의 공통 부분을 공유 하므로 원하는대로 모든 리 포지션 사이에서 변경 사항을 안전하게 (아래 참고 참조) 병합 할 수 있습니다.
참고 : 체인의 공통 부분을 다시 작성하지 않고 변경 사항이 충돌하지 않는 한 “안전”합니다.