예비 메모
여기서 관찰 한 내용은 작업을 시작한 후에 branch1( branch2먼저 다른 지점으로 전환하는 것이 좋은지 잊어 버리거나 알지 못함 ) 다음을 실행 한다는 것입니다 .
git checkout branch2
때때로 Git은 "OK, 당신은 이제 branch2에 있습니다!"라고 말합니다. 때때로 Git은 "나는 그렇게 할 수 없다. 나는 당신의 변화를 잃을 것이다"라고 말한다.
Git 이 허용하지 않으면 변경 사항을 커밋하고 영구적으로 저장해야합니다. 그것들을 저장하기 위해 사용할 수도 git stash있습니다. 이것이 설계된 것 중 하나입니다. 하는 것으로 git stash save나 git stash push실제로는 의미 "모든 변경 사항을 커밋하지만 전혀 지점에, 나는 지금있는 곳에서 제거합니다." 그러면 전환이 가능해집니다. 이제 진행중인 변경 사항이 없습니다. 그런 다음 git stash apply전환 후 사용할 수 있습니다 .
사이드 바 : git stash save이전 구문입니다. git stash pushGit 버전 2.13에서 도입되어 git stash새로운 옵션에 대한 인수 문제를 해결합니다 . 기본 방식으로 사용될 때 둘 다 동일한 작업을 수행합니다.
원하는 경우 여기에서 읽기를 중단 할 수 있습니다!
망할 놈의 경우 하지 않습니다 당신이 전환 할 수, 당신은 이미 구제가 : 사용 git stash또는 git commit; 또는 변경 사항이 재현하기에 사소한 경우이를 사용하여 변경 git checkout -f하십시오. 이 답변은 약간의 변경을 시작하더라도 Git이 언제 당신을 허락 할 것인지에 관한 것 git checkout branch2입니다. 왜 다른 시간이 아닌 때때로 작동 합니까?
여기서의 규칙은 한 가지 방법으로 간단하고 다른 방법으로는 복잡하거나 설명하기 어렵습니다.
상기 전환이 그러한 변경을 방해 할 필요가없는 경우에만 작업 트리에서 커밋되지 않은 변경 사항으로 분기를 전환 할 수 있습니다.
즉 — 이것은 여전히 단순화되어 있습니다. 무대 git add, 무대 git rm등 이있는 매우 어려운 코너 케이스 가 있습니다 branch1. A git checkout branch2는 이것을해야합니다 :
- 모든 파일의 경우 입니다 에
branch1와 하지 에 branch2, 1 개 파일이 삭제.
- 모든 파일에 들어 있습니다 에
branch2와 하지 에 branch1, (적절한 내용) 해당 파일을 만들 수 있습니다.
- 두 분기에있는 모든 파일에 대해 버전
branch2이 다르면 작업 트리 버전을 업데이트하십시오.
이러한 각 단계는 작업 트리에서 무언가를 방해 할 수 있습니다.
- 작업 트리의 버전이의 커밋 된 버전과 동일한 경우 파일을 제거하는 것이 "안전"합니다
branch1. 변경 한 경우 "안전하지 않은"것입니다.
- 파일이
branch2존재하지 않는 경우 파일을 만드는 방법 은 "안전"합니다. 2 현재 존재하지만 "잘못된"내용이있는 경우 "안전하지 않은"것입니다.
- 물론 작업 트리 버전이 이미 커밋 된 경우 파일의 작업 트리 버전을 다른 버전으로 바꾸는 것이 "안전"합니다
branch1.
새 분기 ( git checkout -b newbranch)를 만드는 것은 항상 "안전한"것으로 간주됩니다.이 프로세스의 일부로 작업 트리에서 파일이 추가, 제거 또는 변경되지 않으며 인덱스 / 스테이징 영역도 변경되지 않습니다. (주의 : 새로운 지점의 시작 지점을 변경하지 않고 새로운 지점을 만들 때 안전하지만, 다른 인수를 추가하면 (예 :) git checkout -b newbranch different-start-point변경해야 할 수도 있습니다 different-start-point. Git은 평소와 같이 체크 아웃 안전 규칙을 적용합니다 .)
1 이것은 우리가 파일이 차례로 단어의 정의가 필요한 지점에 있어야하는 것이 무엇을 의미하는지 정의가 필요 분기를 제대로. (참조 정확하게 우리가 "가지"가 무슨 뜻 이죠? ) 여기서, 정말 뜻이 무엇인지 커밋되는 지점 이름의 결의 : 그 경로에있는 파일 인 의 경우 해시를 생성합니다. 그 파일이 아닙니다 에 대신 오류 메시지가 있다면. 이 특정 질문에 대답 할 때 색인 또는 작업 트리 에 경로 가 존재 하지 않습니다. 따라서 여기서 비밀은 각각에 대한 결과를 검사하는 것입니다P branch1git rev-parse branch1:Pbranch1Pgit rev-parsebranch-name:path. 파일이 최대 하나의 브랜치에 "in"있기 때문에 실패하거나 두 개의 해시 ID를 제공합니다. 두 개의 해시 ID가 동일한 경우 파일은 두 분기에서 동일합니다. 변경할 필요가 없습니다. 해시 ID가 다른 경우 파일은 두 분기에서 다르며 분기를 전환하도록 변경해야합니다.
여기서 중요한 개념은 커밋의 파일 이 영원히 동결 된다는 것입니다. 편집 할 파일은 고정 되지 않습니다 . 우리는 적어도 처음에는 고정 된 두 커밋 사이의 불일치 만보고 있습니다. 불행하게도, 우리 또는 힘내-또한 파일을 처리 할 필요가 없습니다 당신이 멀리 전환 가고있는 커밋에 있는 (가) 당신이 스위치에거야 커밋. 파일이 인덱스 및 / 또는 작업 트리에 존재할 수 있기 때문에 나머지 복잡한 문제가 발생합니다.
2 "올바른 내용"과 함께 이미 존재하는 경우 "안전 정렬"로 간주 될 수 있으므로 Git이이를 생성 할 필요가 없습니다. 적어도 Git의 일부 버전은 이것을 허용하지만, 테스트 결과 Git 1.8.5.4에서 "안전하지 않은"것으로 간주됩니다. 전환 대상 분기와 일치하도록 수정되는 수정 된 파일에 동일한 인수가 적용됩니다. 다시, 1.8.5.4는 단지 "덮어 쓰기 될 것"이라고 말합니다. 기술 노트의 끝 부분도 참조하십시오 .1.5 버전에서 Git을 처음 사용하기 시작한 이후 읽기 트리 규칙이 변경되지 않았다고 생각하면 메모리가 잘못되었을 수 있습니다.
변경 사항이 준비되어 있는지 또는 준비되어 있지 않은지가 중요합니까?
그렇습니다. 특히 변경을 준비한 다음 작업 트리 파일을 "수정 취소"할 수 있습니다. 여기에 다른의 두 지점에있는 파일,의 branch1와는 branch2:
$ git show branch1:inboth
this file is in both branches
$ git show branch2:inboth
this file is in both branches
but it has more stuff in branch2 now
$ git checkout branch1
Switched to branch 'branch1'
$ echo 'but it has more stuff in branch2 now' >> inboth
이 시점에서 작업 트리 파일 은에 있지만 파일의 파일 inboth과 일치합니다 . 이 변경 사항은 커밋을 위해 준비되지 않았으므로 여기에 표시됩니다.branch2branch1git status --short
$ git status --short
M inboth
space-then-M은 "수정되었지만 준비되지 않음"을 의미합니다 (보다 정확하게는 작업 트리 복사본이 준비 / 인덱스 복사본과 다릅니다).
$ git checkout branch2
error: Your local changes ...
이제 작업 트리 사본을 준비해 봅시다. 이미 알고있는 사본과 일치합니다 branch2.
$ git add inboth
$ git status --short
M inboth
$ git checkout branch2
Switched to branch 'branch2'
여기에서 준비 및 작업 사본이 모두와 일치 branch2하므로 결제가 허용되었습니다.
다른 단계를 시도해 봅시다 :
$ git checkout branch1
Switched to branch 'branch1'
$ cat inboth
this file is in both branches
체크 아웃이 스테이징 영역을 통해 쓰기 때문에 이제 스테이징 영역에서 변경 한 내용이 손실됩니다. 이것은 약간의 경우입니다. 변화는 사라지지 않았지만 내가 무대에 놓았다는 사실 은 사라졌습니다.
분기 복사와는 다른 파일의 세 번째 변형을 준비한 다음 현재 분기 버전과 일치하도록 작업 복사본을 설정합니다.
$ echo 'staged version different from all' > inboth
$ git add inboth
$ git show branch1:inboth > inboth
$ git status --short
MM inboth
두 M여기에 평균들 :에서 파일 다릅니다 개최 HEAD파일 과 에서 작업 트리 파일 다르다 파일을 개최. 작업 트리 버전은 branch1(일명 HEAD) 버전 과 일치합니다 .
$ git diff HEAD
$
그러나 git checkout체크 아웃을 허용하지 않습니다.
$ git checkout branch2
error: Your local changes ...
branch2버전을 작업 버전으로 설정하십시오 .
$ git show branch2:inboth > inboth
$ git status --short
MM inboth
$ git diff HEAD
diff --git a/inboth b/inboth
index ecb07f7..aee20fb 100644
--- a/inboth
+++ b/inboth
@@ -1 +1,2 @@
this file is in both branches
+but it has more stuff in branch2 now
$ git diff branch2 -- inboth
$ git checkout branch2
error: Your local changes ...
현재 작업중인 사본이의 branch2파일 과 일치하더라도 준비된 파일은 일치 하지 않으므로 git checkout해당 사본이 손실되고 git checkout는 거부됩니다.
기술 노트 — 미심쩍은 호기심 만 :-)
이 모든 것에 대한 기본 구현 메커니즘은 Git 's index 입니다. 당신이 구축 곳 또한 "준비 영역"이라고 인덱스는,이다 다음 당신이 체크 아웃 한대로 지금 즉, 현재의 커밋을, 일치 밖으로 시작하고 때마다 당신에게 : 커밋 git add파일, 당신은 대체 인덱스 버전을 작업 트리에있는 모든 것을
기억 작업 트리가 당신이 당신의 파일에 일하는 곳입니다. 여기, 커밋과 인덱스에서와 같이 Git 형식 만 사용하는 것이 아니라 일반적인 형식을 사용합니다. 당신은 파일을 추출 그래서 에서 A가 커밋 을 통해 작업 트리에에서 다음 인덱스합니다. 변경 한 후에 git add는 색인으로 이동합니다. 따라서 각 파일에는 현재 커밋, 인덱스 및 작업 트리의 세 위치가 있습니다.
당신이 실행하면 git checkout branch2, 힘내 커버 아래 않습니다 무엇을 비교하는 것이다 끝이 커밋 의 branch2현재 커밋 지금은 인덱스 모두에서 무엇이든 할 수 있습니다. 현재 존재하는 것과 일치하는 모든 파일은 Git에서 그대로 둘 수 있습니다. 모두 손대지 않았습니다. 두 커밋 모두에서 동일한 파일 인 Git은 단독으로 남겨 둘 수 있으며 분기를 전환 할 수있는 파일입니다.
커밋 전환을 포함한 Git의 대부분은 이 인덱스로 인해 비교적 빠릅니다 . 실제로 색인에있는 것은 각 파일 자체가 아니라 각 파일의 해시 입니다. 파일 자체의 복사본은 Git이 blob 객체 라고 부르는 저장소로 저장소에 저장됩니다. 이것은 파일이 커밋에 저장되는 방식과 비슷합니다. 커밋은 실제로 파일을 포함하지 않으며 , Git을 각 파일의 해시 ID로 연결합니다. 따라서 Git은 해시 ID (현재 160 비트 길이의 문자열)를 비교하여 커밋 X 와 Y 의 파일 이 같은지 여부를 결정할 수 있습니다. 그런 다음 해당 해시 ID를 색인의 해시 ID와 비교할 수도 있습니다.
이것이 위의 모든 홀수 볼 코너 사례로 이어집니다. 우리는 둘 다 file을 갖는 X 와 Y 를 커밋 하고에 path/to/name.txt대한 색인 항목을 가지고 path/to/name.txt있습니다. 세 개의 해시가 모두 일치 할 수 있습니다. 어쩌면 두 개가 일치하고 하나는 일치하지 않을 수 있습니다. 세 가지 모두 다를 수도 있습니다. 그리고, 우리는 또한있을 수 있습니다 another/file.txt그 단지에의 X 또는에서만 Y 및 또는 현재 인덱스가 아닙니다. 이러한 다양한 경우 각각 별도의 고려 사항이 필요 합니다 . Git 은 커밋에서 인덱스로 파일을 복사하거나 인덱스에서 제거하여 X 에서 Y 로 전환 해야 합니까? 그렇다면, 그것은 또한 에있다파일을 작업 트리에 복사하거나 작업 트리에서 제거하십시오. 만약 그 '사건이야, 인덱스와 작업 트리 버전이 더 적합 커밋 된 버전 중 적어도 하나를했다; 그렇지 않으면 Git은 일부 데이터를 방해합니다.
(이 모든 것에 대한 완전한 규칙 git checkout은 예상 한 git read-tree문서가 아니라 "Two Tree Merge"섹션 의 문서에 설명되어 있습니다.)
git checkout -m와 색인 변경 사항을 새로운 체크 아웃에 병합하는을 제공합니다.