2014-11-23 3 views
0

here으로 설명한 대화식 리베이스 모드를 시도하면 이상한 점은 noop입니다.하지만 그 이유는 알 수 없습니다.git rebase -i foo/dev noop

나는 내 컴퓨터에 임시 지점 내부와 나는 사이의 차이를 보려고 할 때,이 얻을 : 나는 다음과 같은 명령을 실행할 때, 나는 무 조작을 얻고있다, 그러나

 
[email protected] /D/Dropbox/AppsPublic/gulp-aspnet-k (temp-a) 
$ git log --pretty=oneline temp-a..ajryan/dev 
f0ef4ee40fde4de5360515fd556de9c3ed40431c update readme with new optionsfcba1ae3306ae041a1d82647e4cf65a0c96fe2f7 do not loop for build, restore8bedd238660908f06d698815ef12fce786d716ed fix command concat 
e2e3a0d00e3950911c00c0e6e51a671f5f2ac2d3 bump version 
d65923ff91eb9d6b9782bc2bf5ab606d19733203 add quiet option 
91a1faff0a3aa1ca552df2151190a3ecd87cfc6f allow caller to loop all comma962c55854457314324d81457c42913532875cc85 trailing whitespace, tabs > sp 

을 :

 
[email protected] /D/Dropbox/AppsPublic/gulp-aspnet-k (temp-a) 
$ git rebase -i ajryan/dev 

왜 내가 뭘 잘못하고 있는거야?

+0

만약'temp-a'가'ajryan/dev'의 조상이라면 나는 이것이 가능하다고 생각합니다. –

답변

2

git log 명령은 ajryan/dev에는 있지만 temp-a에는없는 커밋을 표시합니다. rebase 명령은 temp-a에있는 커밋을 리베이스하지만, ajryan/dev에는 커밋되지 않은 커밋을 리베이스하라는 명령을 받았지만 커밋이없는 것으로 추정됩니다. 그림으로 :

... - o - o - o     <-- HEAD=temp-a 
       \ 
        o - o - o - * <-- ajryan/dev 

따라서, 픽업하여이 나는 스타 * 표시 한 커밋에 리베이스 할 커밋이 없습니다. 따라서 rebase -i은 단일 no-op 명령을 생성합니다.

당신은 어떤 조합이의 REBASE 작업이 *를 저지하기 위해 temp-a 지점을해야하는 마지막이 * 이후에 추가 된 커밋을 가리 키도록 temp-a를 이동하여 결론없는 것을 실행합니다. (그런 일이 발생하지 않으면 rebase의 작은 버그입니다.) 아무 작업도 삭제하지 않으면 rebase 작업이 중단되고 temp-a은 이동되지 않습니다. 당신 그랬다면은 당신이 그들을 리베이스, 또는 다른 지점을 리베이스 수 temp-a에 다른 항목을 가지고


참고. 여기 ajryan/dev에없는 거의 동일한 기본부터 시작하여 두 개 더 그림은,하지만 하나의 커밋으로 그 temp-a에있다 :

이 경우
... - o - o - o - @    <-- HEAD=temp-a 
       \ 
        o - o - o - * <-- ajryan/dev 

, 당신은 @이 다른 커밋의 상부에 커밋 넣을 수 있습니다 :

... - o - o - o 
       \      (illustration 1) 
        o - o - o - * - @ 

또는 다른 커밋 아래 바닥에

: 내가 레이블을 떠난

다음
... - o - o - o 
       \      (illustration 2) 
        @ - o - o - o - * 

(및 ajryan/dev). 이것은 의도적으로 : git에서, 브랜치 레이블은 쉽게 옮겨 질 수 있습니다 (실제로는 "forward"방식 인 한 으로 이동해야합니다); 모든 실제 branch-iness는 커밋 자체에 저장됩니다. git rebase이 실제로하는 일은 사본입니다. 오래된 것은 새로운 것으로 커밋되므로 부모의 연령 및/또는 콘텐츠를 변경할 수 있습니다.

일러스트레이션 # 1에서 우리는 @ 커밋을 다시 적용했습니다 : 이제는 *을 부모로 커밋했습니다. 다른 모든 커밋은 변경되지 않으므로 @ 커밋 만 복사해야합니다.

그러나 일러스트레이션 # 2에서는 원래 ajryan/dev에만 있었던 커밋 체인 전체를 다시 사용했습니다. Commit @ 그 자체는 변경되지 않았지만 원래 o - o - o - * 커밋 4 개 모두를 복사해야했습니다. 첫 번째 o을 복사하여 부모를 @으로 설정했습니다. 이 새로운 커밋에는 새롭고 다른 SHA-1 ID가 있으므로 두 번째 o을 복사하여 새 커밋의 ID를 부모로 사용합니다. 이 두 번째 사본은 강제로 세 번째 사본을 강제 실행 한 후 *의 마지막 사본을 강제 실행합니다. 그것에 대해 나쁠 수있는 것에 관해서 다음 섹션을보십시오. 커밋의 두 개의 서로 다른 체인에 가입 자식에


, 당신은 일반적으로 git merge을 사용합니다 : 여기
  A - B 
     /  \ 
... - o   M <-- HEAD=branch 
     \  /
      C - D 

Mo으로부터 포크 두 체인 A - BC - D에 가입 커밋 병합합니다. A에서 D까지 모두 존재하고 새로운 커밋 M을 만들면 A에서 D까지 아무 일도 일어나지 않습니다. 이전과 여전히 동일합니다.

단순한 개발을 위해 CDA - B의 "맨 위에"앉게 만드는 것이 더 일반적입니다. 하지만 당신은 을 복사해야합니다. 왜냐하면 git에서의 커밋은 영구적이고 변하지 않기 때문입니다. C을 새 것으로 약간 다른 C'으로 복사하고 으로 약간 다른 D으로 복사합니다. REBASE 복사가 완료되면

  A - B - C' - D' <-- HEAD=branch 
     /
... - o 
     \ 
      C - D   [abandoned] 

, 당신을 : C' 다른 점 중요한 것은 부모가 B하지 o, 약 D' 부모가 C'하지 C 점이다 다르다 중요한 것은 때문이다 단순히 이전 CD 커밋을 포기하고 C' 척 시작하고 D' 원래 커밋했다 :

  A - B - C - D <-- HEAD=branch 
     /
... - o 

이제 우리는 더 긴하지 어 우리가 원래 CD에 대한 모든 잊어 버린 이후 그래프에서 약간의 꼬임을해야하고, 역사는 바로 다음과 같습니다

... - o - A - B - C - D <-- HEAD=branch 

더러운 비밀 (그래서 비밀하지가 아니라 그 더러운)이라는 원래 CD은 여전히 ​​입니다.은 (당신에게) 보이지 않습니다. 실제로 더럽혀지는 부분은 누군가 다른 사람은 원래 두 CD 커밋을가집니다. Git 커밋 ID는 부모 SHA-1 ID를 포함하여 콘텐츠의 암호화 체크섬이므로 원래 CD은 여전히 ​​존재하며 은 과 D에서 다른과 다릅니다.

다른 사람으로부터 커밋을 가져올 때 이것은 중요합니다. 커밋을 작업에 리베이스하면 으로 변경됩니다.새 사본을 만들 때 원본이 있다는 것을 잊어 버릴 수도 있지만 새 사본은 아직 알지 못하며 은 원래 ID를 잊어 버리지 않았습니다.

나중에 커밋의 리베이스 복사본을 제시하면 커밋 복사본을 선택하고 수행 한 추가 작업을 이동해야합니다. 간단히 말해, 사전에 누군가와 계약을 맺지 않았다면 일러스트레이션 # 2에 표시된 것과 같은 rebase는 일반적으로 좋은 생각이 아닙니다.


"빨리 감기"는 어떤가요? 음, 일러스트레이션 # 1을 다시 한번 살펴 보겠습니다. o - o - o - @ 체인이 다른 누군가 ("pull request")로부터 왔다고 가정하고, 자신의 작업을 리베이스하여 그 위에 * 커밋을 추가한다고 가정 해 봅시다. 또 하나 개의 꼬임을 추가의 너무 그래프를 다시 그려 보자, 다시 ajryan/dev 라벨을 넣어 :

... - o - o - o  [your original '@' commit, before rebasing, was here] 
       \ 
        o - o - o - *  <-- ajryan/dev 
           \ 
            @ <-- HEAD=(something, maybe "dev") 

을 이제 더 그들은, 그들이 누구든지, 자신의 dev 분기에 o - o - o - * 순서를 가지고하지 않은 것으로 가정하자 어떤 추가 작업, 그들의 물건은 *이라고 표시된 커밋에서 끝납니다. 이 커밋 시퀀스를 사용할 수있게되면 dev 레이블을 아래쪽 및 오른쪽으로 이동하여 @ 레이블을 가리 키도록 dev 브랜치에 커밋 @을 추가 할 수 있습니다. 이제 ajryan/dev 레이블을 지우고이 도면의 꼬임을 곧게 자르고 dev 레이블을 사용하십시오.

... - o - o - o - o - o - o - * - @ <-- HEAD=dev 

그들이이있을 것이다 것입니다, 당신은 동기화 모두있어 일단 당신이,이 무슨 다음은 결과입니다. 실제 개발 과정에서 약간 벗어난 경우에도 매우 간단합니다. *으로 끝나는 체인을 처음 보지 않고 커밋 @을 작성했습니다. 그러나 이것은 개발 작업을 훨씬 쉽게 수행 할 수있게 해주는 일종의 "리베이스 (rebase)"이며 일반적으로 사람들이 원하는 일입니다.

레이블 "오른쪽으로"(위 그림과 같이 오른쪽 아래 또는 오른쪽 포함) 슬라이딩은 "빨리 감기"조작입니다. --ff-only을 사용하여 git merge을 실행하면 실제로 이러한 종류의 병합되지 않은 빨리 감기 인 경우에만 "병합"을 수행합니다.


결론 : 나는 당신이 @ajryan/dev 작업에 커밋 리베이스 싶었지만, 그렇지 @이 리베이스 커밋해야했다 생각합니다. 그래서 rebase가 noop을주었습니다. 이 경우 간단한 병합되지 않은 빨리 감기 git merge 만 있으면 레이블을 해당 레이블과 일치시킬 수 있습니다.


또한 이것에 대해 생각하는 가치 : 당신이 git log X..Y을 할 때 내가 여기처럼 그래프를 그릴 자식을 요구하고 :

... - o - o - o  <-- X 
     \ 
      o - o - o <-- Y 

X..Y 개념은 본질적으로 말한다 :이 그래프로 시작, 형광펜을 꺼내서 X이 가리키는 커밋을 강조 표시하고 커밋을 모두 왼쪽에서 및/또는 위 또는 아래로 커밋합니다.그러면 3 개의 o이 지정되고 Y의 표시가 해제됩니다. 그런 다음 강조 표시되지 않은 Y이 가리키는 모든 커밋을 찾아서 기록하십시오. 당신이 git log Y..X에서와 XY, 반대 경우

, 당신은 X에만 두 o 유일의 잎 Y로 표시 커밋에 "하이 라이터를 실행"을 자식에게, 그리고 모든 지적-에 커밋 로그 X에 의해 강조 표시되어 있지 않습니다. 그래서 여기 X에서 두 개의 o을 얻습니다.

+0

무엇보다 명령이어야합니까? 'git rebase -i -onto temp-b ajryan/dev'? 작동하지 않습니다. s – tugberk

+0

어떤 결과를 원하십니까? 'ajryan/dev'에없는'temp-a'에 대한 커밋은 없습니다. 'git merge -ff-only ajryan/dev' 명령을 사용하여'temp-a' 브랜치가'ajryan/dev'을 따라 잡을 수 있도록 할 수 있습니다. 진정한 합병 (나는 사실이라고 믿는다. 그러나 나는 당신의 레포를 가지고 있지 않다)을 만든다. – torek

+0

내가하려고하는 것은 리모트 pull-request 브랜치 내부에서 변경된 내용을 대화 형 리베이스 세션을 가진'temp-a' 브랜치에 넣는 것입니다. – tugberk