자식 분기, 포크, 가져 오기, 병합, 리베이스 및 복제의 차이점은 무엇입니까?
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)은 누구나 저장소를 '포크 (fork)'할 수있게하여 기본적으로 자체 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 에서 볼 수 있습니다.
변경 사항이 어떻게 작동하는지 시각적으로 표시하려면 '지하철 맵'(Ep. London Underground)이라고하는 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 !
You mess up some files while working in a local branch and simply want to go back to what you had the last time you did a
git pull
:git reset --hard origin/master # You will need to be comfortable doing this!
You start making changes locally, you edit half a dozen files and then, oh crap, you're still in the master (or another) branch:
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
You mess up one particular file in your current branch and want to basically 'reset' that file (lose changes) to how it was the the last time you pulled it from the remote repository:
git checkout your/directories/filename
This actually resets the file (like many Git commands it is not well named for what it is doing here).
You make some changes locally, you want to make sure you don't lose them while you do a
git reset
orrebase
: I often make a manual copy of the entire project (cp -r ../my_project ~/
) when I am not sure if I might mess up in Git or lose important changes.You are rebasing but things gets messed up:
git rebase --abort # To abandon interactive rebase and merge issues
Add your Git branch to your
PS1
prompt (see https://unix.stackexchange.com/a/127800/10043), e.g.The branch is
selenium_rspec_conversion
.
Here is Oliver Steele's image of how it all fits together:
Fork Vs. Clone - two words that both mean copy
Please see this diagram. (Originally from 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')
Fork
- A copy to your remote repo (cloud) that links it to Joe's
- A copy you can then clone to your local repo and F*%$-up
- When you are done you can push back to your remote
- You can then ask Joe if he wants to use it in his project by clicking pull-request
Clone
- a copy to your local repo (harddrive)
Just to add to others, a note specific to forking.
It's good to realize that technically, cloning the repo and forking the repo are the same thing. Do:
git clone $some_other_repo
and you can tap yourself on the back---you have just forked some other repo.
Git, as a VCS, is in fact all about
cloning
forking. Apart from "just browsing" using remote UI such as cgit, there is very little to do with git repo that does not involve
forking
cloning the repo at some point.
However,
when someone says I forked repo X, they mean that they have created a clone of the repo somewhere else with intention to expose it to others, for example to show some experiments, or to apply different access control mechanism (eg. to allow people without Github access but with company internal account to collaborate).
Facts that: the repo is most probably created with other command than
git clone
, that it's most probably hosted somewhere on a server as opposed to somebody's laptop, and most probably has slightly different format (it's a "bare repo", ie. without working tree) are all just technical details.The fact that it will most probably contain different set of branches, tags or commits is most probably the reason why they did it in the first place.
(What Github does when you click "fork", is just cloning with added sugar: it clones the repo for you, puts it under your account, records the "forked from" somewhere, adds remote named "upstream", and most importantly, plays the nice animation.)
When someone says I cloned repo X, they mean that they have created a clone of the repo locally on their laptop or desktop with intention study it, play with it, contribute to it, or build something from source code in it.
The beauty of Git is that it makes this all perfectly fit together: all these repos share the common part of
block
commit chain so it's possible to safely (see note below) merge changes back and forth between all these repos as you see fit.
Note: "safely" as long as you don't rewrite the common part of the chain, and as long as the changes are not conflicting.
'Programing' 카테고리의 다른 글
새로운 TTY로 이미 실행중인 Docker 컨테이너에 입력하는 방법 (0) | 2020.02.13 |
---|---|
JSLint는 "missing radix parameter"라고 말합니다. (0) | 2020.02.13 |
Python 3으로 pip를 설치하는 방법은 무엇입니까? (0) | 2020.02.13 |
vim에서“다음 찾기” (0) | 2020.02.13 |
XML 파일을 어떻게 구문 분석합니까? (0) | 2020.02.13 |