예비 메모
여기서 관찰 한 내용은 작업을 시작한 후에 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 push
Git 버전 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
branch1
git rev-parse branch1:P
branch1
P
git rev-parse
branch-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
과 일치합니다 . 이 변경 사항은 커밋을 위해 준비되지 않았으므로 여기에 표시됩니다.branch2
branch1
git 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
와 색인 변경 사항을 새로운 체크 아웃에 병합하는을 제공합니다.