로컬 전용 브랜치에 다음 커밋 기록이 있다고 가정합니다.
A -- B -- C
A
과 사이에 새 커밋을 어떻게 삽입 B
합니까?
답변
OP의 답변보다 훨씬 쉽습니다.
git rebase -i <any earlier commit>
. 구성된 텍스트 편집기에 커밋 목록이 표시됩니다.- 삽입하려는 커밋을 찾습니다 (라고 가정 해 보겠습니다
a1b2c3d
). 편집기에서 해당 줄에pick
대해edit
. - 텍스트 편집기를 닫아 리베이스를 시작하십시오 (변경 사항 저장). 이렇게하면 방금 커밋 된 것처럼 이전에 선택한 커밋 (
a1b2c3d
) 이있는 명령 프롬프트가 표시 됩니다. - 변경하고
git commit
( 대부분 의 경우와 달리 수정 하지 않음edit
). 이렇게 하면 선택한 커밋 뒤에 새 커밋이 생성 됩니다. git rebase --continue
. 그러면 연속 커밋이 재생되고 새 커밋이 올바른 위치에 삽입됩니다.
이것은 역사를 다시 쓰게 될 것이고, 당기려고하는 다른 사람을 깨뜨릴 것이라는 점에주의하십시오.
답변
여기에 있는 답은 매우 간단 합니다 . 지점에 있다고 가정합니다 branch
. 다음 단계를 수행하십시오.
-
새 커밋 (이 경우 commit
A
) 을 삽입하려는 후 커밋에서 임시 분기를 만듭니다 .git checkout -b temp A
-
변경 사항을 수행하고 커밋하고 커밋을 생성하고 호출합시다
N
.git commit -a -m "Message"
(또는
git add
뒤에git commit
) -
새 커밋 이후에 원하는 커밋 (이 경우에는 커밋
B
및C
)을 새 커밋으로 리베이스합니다 .git rebase temp branch
(아마도 ciekawy에 의해 더 이상 존재하지 않는 주석-p
덕분에 병합을 보존 하기 위해 사용해야 합니다 )
-
임시 분기를 삭제하십시오.
git branch -d temp
그 후의 역사는 다음과 같습니다.
A -- N -- B -- C
물론 리베이스하는 동안 일부 충돌이 나타날 수 있습니다.
지점이 로컬 전용이 아닌 경우 다시 쓰기 기록이 발생하므로 심각한 문제가 발생할 수 있습니다.
답변
더 쉬운 솔루션 :
-
마지막에 새 커밋 D를 만듭니다. 이제 다음을 수행합니다.
A -- B -- C -- D
-
그런 다음 다음을 실행하십시오.
$ git rebase -i hash-of-A
-
Git이 편집기를 열면 다음과 같이 표시됩니다.
pick 8668d21 B pick 650f1fc C pick 74096b9 D
-
이렇게 D를 맨 위로 옮기고 저장하고 종료
pick 74096b9 D pick 8668d21 B pick 650f1fc C
-
이제 다음을 갖게됩니다.
A -- D -- B -- C
답변
커밋 히스토리가라고 가정하고 와 preA -- A -- B -- C
사이에 커밋을 삽입하려는 경우 단계는 다음과 같습니다.A
B
-
git rebase -i hash-of-preA
-
Git이 편집기를 엽니 다. 내용은 다음과 같을 수 있습니다.
pick 8668d21 A pick 650f1fc B pick 74096b9 C
첫 번째
pick
를edit
다음으로 변경하십시오 .edit 8668d21 A pick 650f1fc B pick 74096b9 C
저장하고 종료.
-
코드를 수정 한 다음
git add . && git commit -m "I"
-
git rebase --continue
이제 Git 커밋 기록은 preA -- A -- I -- B -- C
충돌이 발생하면 Git은이 커밋에서 중지됩니다. 를 사용 git diff
하여 충돌 마커를 찾아 해결할 수 있습니다. 모든 충돌을 해결 한 후에는을 사용 git add <filename>
하여 충돌이 해결되었음을 Git에 알리고 git rebase --continue
.
rebase를 실행 취소하려면 git rebase --abort
.
답변
내가 읽은 다른 답변에서 볼 수있는 리베이스 동안 “편집 해킹”을 피하는 전략이 있습니다.
를 사용 git rebase -i
하면 해당 커밋 이후 커밋 목록을 얻을 수 있습니다. 파일 상단에 “중단”을 추가하면 해당 지점에서 리베이스가 중단됩니다.
break
pick <B's hash> <B's commit message>
pick <C's hash> <C's commit message>
일단 시작되면 git rebase
이제 “휴식”지점에서 멈 춥니 다. 이제 파일을 편집하고 정상적으로 커밋을 만들 수 있습니다. 그런 다음을 사용하여 리베이스를 계속할 수 있습니다 git rebase --continue
. 이로 인해 해결해야 할 충돌이 발생할 수 있습니다. 길을 잃은 경우 항상 사용을 중단 할 수 있음을 잊지 마십시오 git rebase --abort
.
이 전략은 커밋을 어디에 든 삽입하도록 일반화 할 수 있습니다. 커밋을 삽입하려는 지점에 “중단”을두기 만하면됩니다.
역사를 다시 쓴 후에는 git push -f
. 브랜치를 가져 오는 다른 사람들에 대한 일반적인 경고가 적용됩니다.
답변
여기에 이미 많은 좋은 답변이 있습니다. 간단한 4 단계로 “리베이스 없음”솔루션을 추가하고 싶었습니다.
요약
git checkout A
git commit -am "Message for commit D"
git cherry-pick A..C
git branch -f master HEAD
설명
(참고 :이 솔루션의 한 가지 장점은 최종 결과에 대해 100 % 확신 할 때 최종 단계까지 분기를 건드리지 않으므로 매우 편리한 “사전 확인”단계가 있다는 것입니다. AB 테스트 허용 .)
초기 상태 ( master
지점 이름으로 가정 했습니다)
A -- B -- C <<< master <<< HEAD
1) 올바른 위치에서 HEAD를 가리키는 것으로 시작
git checkout A
B -- C <<< master
/
A <<< detached HEAD
(선택적으로 여기에서 HEAD를 분리하는 대신을 사용하여 임시 분기를 만들 수 있습니다.이 분기 git checkout -b temp A
는 프로세스가 끝날 때 삭제해야합니다. 다른 모든 변형은 동일하게 유지되므로 원하는대로 작동합니다.)
2) 삽입 할 새 커밋 D 생성
# at this point, make the changes you wanted to insert between A and B, then
git commit -am "Message for commit D"
B -- C <<< master
/
A -- D <<< detached HEAD (or <<< temp <<< HEAD)
3) 그런 다음 마지막 누락 된 커밋 B와 C의 복사본을 가져옵니다 (커밋이 더 있으면 같은 줄이됩니다).
git cherry-pick A..C
# (if any, resolve any potential conflicts between D and these last commits)
B -- C <<< master
/
A -- D -- B' -- C' <<< detached HEAD (or <<< temp <<< HEAD)
(필요한 경우 여기에서 편안한 AB 테스트)
이제 요구 사항을 테스트 할 것을 코드, 테스트 아무것도를 검사하는 순간, 당신은 또한 DIFF / 비교 / 검사 할 수 있습니다 당신이 무엇을했다 및 무엇을 얻을 것입니다 작업 후.
4)C
와 사이의 테스트에 따라 C'
OK 또는 KO입니다.
(어느 한 쪽) 4-OK) 마지막으로master
git branch -f master HEAD
B -- C <<< (B and C are candidates for garbage collection)
/
A -- D -- B' -- C' <<< master
(또는) 4-KO) 그냥 떠날 master
변경
임시 브랜치를 생성했다면 git branch -d <name>
,하지만 당신은 분리 된 HEAD 경로에 들어갑니다 경우,이 시점에서 전혀 필요하지 동작은 새로운 커밋은 다시 연결 직후 가비지 컬렉션을받을 수 없습니다 HEAD
로모그래퍼git checkout master
두 경우 모두 (OK 또는 KO)이 시점에서 master
다시 체크 아웃 하여 HEAD
.