Git 2.18 (2018 년 2 분기)은 --preserve-merge
새로운 옵션을 추가 하여 옵션을 상당히 개선 할 것 입니다.
커밋 그래프의 전체 토폴로지를 다른 곳에 이식하기위한 " git rebase
"학습 된 " --rebase-merges
" .
(참고 : Git 2.22, Q2 2019는 실제로 더 이상 사용되지 않으며 --preserve-merge
Git 2.25, Q1 2020 은 " git rebase --help
"출력 에서 광고를 중단 합니다. )
참조 25cff9f 커밋 , 7543f6f 커밋 , 1131ec9 커밋 , 7ccdf65 커밋 , 537e7d6 커밋 , a9be29c 커밋 , 8f6aed7 커밋 , 1644c73 커밋 , d1e8b01 커밋 , 4c68e7d 커밋 , 9055e40 커밋 , cb5206e 커밋 , a01c2a5 커밋 , 2f6b1d1 커밋 , bf5c057 커밋 (2018 4월 25일를) Johannes Schindelin (에dscho
의해 ) . Stefan Beller의 커밋 f431d73 (2018 년 4 월 25 일)
참조 ( )stefanbeller
.
Phillip Wood ( )의 commit 2429335 (2018 년 4 월 25 일)를
참조하십시오 . (가 합병 Junio C 하마노 - - 에 2c18e6a을 투입 , 2018 (23) 월)phillipwood
gitster
pull
: --rebase-merges
브랜치 토폴로지를 다시 작성하도록 승인
preserve
단순히 --preserve-merges
옵션을 rebase
명령에 전달 하는 모드 와 마찬가지로 모드는 단순히 옵션을 merges
전달합니다
--rebase-merges
.
이를 통해 사용자는 새 커밋을 풀지 않고 간단하게 커밋 할 수 있습니다.
git rebase
매뉴얼 페이지는 이제 병합을 통해 히스토리를 리베이스하기 위한 전체 섹션을 갖습니다 .
추출물:
개발자가 병합 커밋을 다시 만들려는 합법적 인 이유가 있습니다. 여러 관련 분기에 대해 작업 할 때 분기 구조 (또는 "커밋 토폴로지")를 유지하는 것입니다.
다음 예제에서 개발자는 단추가 정의 된 방식을 리팩토링하는 토픽 브랜치 및 해당 리팩토링을 사용하여 "버그보고"버튼을 구현하는 다른 토픽 브랜치에서 작업합니다.
출력 git log --graph --format=%s -5
은 다음과 같습니다.
* Merge branch 'report-a-bug'
|\
| * Add the feedback button
* | Merge branch 'refactor-button'
|\ \
| |/
| * Use the Button class for all buttons
| * Extract a generic Button class from the DownloadButton one
개발자는에 그 커밋을 리베이스 할 수도 있습니다 새로운 master
첫 번째 주제 분기가 통합 될 것으로 예상되는 경우, 예를 들어, 분기 토폴로지를 유지하면서 master
훨씬 이전에 두 번째, 말보다 변경으로 해결 병합 충돌,
DownloadButton
만든 클래스 로 master
.
이 rebase는 --rebase-merges
옵션을 사용하여 수행 할 수 있습니다 .
작은 예제는 commit 1644c73 을 참조하십시오 .
rebase-helper
--make-script
: 병합을 리베이스하는 플래그 소개
시퀀서는 단지 (새 명령을 재 작성 가지 구조로 구성 배운 정신에는 변함이 --preserve-merges
있지만 실질적으로 덜 깨진 디자인, ).
rebase--helper
새로운 --rebase-merges
옵션 에 의해 트리거되는 이러한 명령을 사용 하여 할 일 목록을 생성 할 수 있도록하겠습니다 .
이와 같은 커밋 토폴로지의 경우 (HEAD가 C를 가리키는 경우) :
- A - B - C (HEAD)
\ /
D
생성 된 할 일 목록은 다음과 같습니다.
# branch D
pick 0123 A
label branch-point
pick 1234 D
label D
reset branch-point
pick 2345 B
merge -C 3456 D # C
차이점은 무엇입니까 --preserve-merge
?
커밋 8f6aed7 는 다음과 같이 설명합니다.
옛날 옛적에, 여기에 개발자는 이렇게 생각했습니다 : 예를 들어, 핵심 Git 위에있는 Windows 용 Git 패치는 굵은 가지로 표현 될 수 있고 핵심 Git 위에 기반을두고 Cherry-pick'able 패치 시리즈 세트를 유지합니까?
이에 대한 최초의 시도는 다음과 같습니다 git rebase --preserve-merges
.
그러나이 실험은 대화식 옵션으로 의도 된 것이 아니며 git rebase --interactive
명령 구현이 이미 매우 친숙해 보였기 때문에 피기 백 되었습니다 --preserve-merges
. 실제로 설계 한 사람이 설계했습니다 .
그리고 "당신의 진실"이라고 저자는 자신을 말합니다 : Johannes Schindelin ( dscho
) , 우리가 Git For Windows를 가지고있는 주된 이유 (Hannes, Steffen, Sebastian 등 ...) 2009 년 당시에는 쉽지 않았습니다 .)
그는 2015 년 9 월부터 Microsoft에서 근무하고 있으며 , 현재 Microsoft가 Git을 많이 사용하고 있으며 서비스가 필요하다는 점을 고려하십시오.
이러한 추세는 실제로 2013 년 TFS와 함께 시작되었습니다 . 그 이후로 Microsoft는 지구상에서 가장 큰 Git 저장소를 관리 합니다 ! 그리고 2018 년 10 월부터 Microsoft는 GitHub를 인수했습니다 .
2018 년 4 월에 Git Merge 2018의 비디오에서 Johannes가 말하는 것을 볼 수 있습니다 .
얼마 후 다른 개발자 (Andreas! ;-)를보고 있음 )와 Git 관리자 (Git 관리자) (Gim 관리자)를 --preserve-merges
함께 사용하는 것이 좋은 생각이라고 생각했습니다 --interactive
. Junio가 부재하는 동안, 즉 동의), 그리고 --preserve-merges
디자인 의 매력이 오히려 빠르고 매끄럽게 떨어지기 시작했습니다.
여기 Jonathan은 Suse의 Andreas Schwab 에 대해 이야기하고 있습니다. 2012 년에 토론 내용을 다시
볼 수 있습니다 .
이유? 에서 --preserve-merges
(의, 또는 그 문제에 대한 모드, 병합의 부모가 커밋 어떤 커밋) 명시 적으로 언급되지 않은,하지만 한
암시 받는 전달 된 커밋 이름으로 pick
명령 .
예를 들어 커밋을 재정렬하는 것이 불가능했습니다 .
브랜치간에 커밋을 이동하거나 토픽 브랜치를 두 개로 나누는 것을 금지하는 것은 말할 것도 없습니다.
아아, 이러한 단점은 또한 모드 (Windows의 요구에 Git을 제공하는 원래 목적이 다른 사람들에게도 유용 할 것이라는 추가 희망)가 Windows의 요구에 Git을 제공하는 것을 막았습니다.
5 년 후, 때때로 Git for Windows에서 핵심적인 Git의 태그에 기반을 둔 부분적으로 관련이없고 부분적으로 관련이없는 하나의 다루기 힘든 큰 hodge-podge 패치 시리즈를 가질 수 없게되었을 때 git-remote-hg
처음에는 쓸모없는 Git for Windows의 경쟁 접근 방식이 나중에 관리자 가 아닌 경우에만 버려지 는 잘못된
시리즈 중 하나는 실제로는 불가능했습니다. " Git garden shears " 가 탄생했습니다 : 스크립트, 대화 형 rebase 위에 피기 백, 먼저 리베이스 할 패치의 브랜치 토폴로지를 결정하고 추가 편집을위한 의사 작업 목록을 생성하고 결과를 실제 작업 목록으로 변환합니다 (exec
명령을 누락 된 할 일 목록 명령을 "구현"하고 마지막으로 새 기본 커밋 위에 패치 시리즈를 다시 만듭니다.
(Git garden shears 스크립트는 커밋 9055e40 의이 패치에서 참조됩니다 )
2013 년에 시작되었습니다.
그리고 디자인을 작성하고이를 트리 외부 스크립트로 구현하는 데 약 3 주가 걸렸습니다. 말할 필요도없이, 구현 자체가 안정화되는 데 몇 년이 걸렸으며, 디자인 자체는 그 자체가 건전한 것으로 입증되었습니다.
이 패치로, 힘내 정원 가위의 선 (善)은 오는 git
rebase -i
자체 . 옵션을
전달하면 --rebase-merges
쉽게 이해할 수있는 할 일 목록과 커밋을 재정렬하는 방법이 분명한 곳이 생성됩니다 . 명령
을 삽입 label
하고을 호출 하여 새 분기를 도입 할 수 있습니다 merge <label>
.
그리고이 모드가 안정적이고 보편적으로 받아 들여지면 디자인 실수를 더 이상 사용하지 않을 수 있습니다--preserve-merges
.
Git 2.19 (Q3 2018)는와 --rebase-merges
함께 작동 하여 새로운 옵션을 개선합니다 --exec
.
" --exec
"옵션 " git rebase --rebase-merges
"은 (는) 수정 된 잘못된 위치에 exec 명령을 배치했습니다.
참조 1ace63b 커밋 (2018년 8월 9일)를, 그리고 f0880f7 커밋 으로 (06 년 8 월 2018) 요하네스 Schindelin ( dscho
) .
( Junio C gitster
Hamano 에 의해 합병 -- 커밋 750eb11 , 2018 년 8 월 20 일)
rebase --exec
: 작동하도록 --rebase-merges
아이디어는 각각 후에 전화 --exec
를 추가하는 것 입니다.exec
pick
의 도입 이후 fixup!
/ s의 quash!
커밋,이 아이디어는 간부가 사이에 삽입되지 않을 것 즉, "아마도 픽스 업 / 스쿼시 체인 다음, 선택"에 적용하도록 확장되었다 pick
및 해당의
fixup
또는 squash
라인.
현재 구현에서는 더티 트릭을 사용하여이를 달성합니다. pick / fixup / squash 명령 만 있다고 가정 한 다음 첫 번째 명령 앞에 행 을
삽입 하고 마지막 명령을 추가합니다.exec
pick
에 의해 생성 된 할 일 목록과 함께 git rebase --rebase-merges
,이 간단한 구현 프로그램의 문제 : 그것은 정확한 잘못이있는 것은 생산 label
, reset
및 merge
명령.
우리가 원하는 것을 정확하게 수행하도록 구현을 변경해 봅시다 : 라인을 찾고
pick
, 수정 / 스쿼시 체인을 건너 뛰고, exec
라인 을 삽입하십시오 . 오히려 헹구고 반복하십시오.
참고 : 우리가 삽입 고통을 하기 전에 주석 행 가능한 빈 커밋에 의해 표현으로 주석 처리 된 선 선택 (우리는 앞의 선택의 간부 라인을 삽입 할 전에 하지 이후, 같은 라인).
그 동안 명령과 유사하기 때문에 명령 exec
뒤에 줄 을 추가하십시오. 새로운 커밋을 추가합니다.merge
pick
Git 2.22 (Q2 2019)는 기본적으로 작업 트리 당 계층 구조를 만드는 rebase 중간 상태를 저장하기 위해 refs / rewritten / 계층 구조의 사용법을 수정합니다.
참조 b9317d5 커밋 , 90d31ff 커밋 , 09e6564 커밋 에 의해 (07 3 월 2019) 응웬 타이 응옥 두이 ( pclouds
) .
(의해 병합 - Junio C 하마노 gitster
- 에 917f2cd 커밋 2,019 09 사월)
refs / rewritten /가 작업 트리 당인지 확인하십시오
a9be29c (시퀀서 : label
worktree-local, 2018-04-25, Git 2.19 명령으로 생성 된 심판 refs/rewritten/
참조 )는 워크 트리 별 참조 공간으로 추가 합니다.
불행히도 (나쁜) 워크 트리마다 실제로 업데이트하려면 몇 가지 장소가 필요합니다.
- add_per_worktree_entries_to_dir()
참조 목록이 리포지토리 refs/rewritten/
대신 워크 트리 를 확인하도록 업데이트되었습니다 .
common_list[]
git_path()
올바른 위치 를 반환 하도록 업데이트됩니다 . 여기에는 " rev-parse --git-path
"가 포함됩니다 .
이 혼란은 나에 의해 만들어졌습니다.
나는 refs/worktree,
모든 처리가 특별한 처리없이 작업 트리 당 될 위치를 소개하여 문제를 해결하기 시작했습니다 .
불행한 refs / rewritten는 refs / worktree 앞에 왔으므로 이것이 우리가 할 수있는 전부입니다.
Git 2.24 (2019 년 4 분기)를 통해 " git rebase --rebase-merges
"는 다양한 병합 전략을 추진하고 전략 별 옵션을 전달하는 방법을 배웠습니다.
Elijah Newren ( )의 commit 476998d (2019 년 9 월 04 일)를 참조하십시오 .
참조 e1fac53 커밋 , a63f990 커밋 , 5dcdd74 커밋 , e145d99 커밋 , 4e6023b 커밋 , f67336d 커밋 , a9c7107 커밋 , b8c6f24 커밋 , d51b771 커밋 , 커밋 c248d32 , 8c1e240 커밋 , 커밋 5efed0e , 68b54f6 커밋 , 2e7bbac 커밋 , 6180b20 커밋 , d5b581f 커밋 (31 2019 년 7 월)newren
요하네스 Schindelin (dscho
) .
(의해 병합 Junio C 하마노 - gitster
- 에 917a319 커밋 2,019 9월 18)
Git 2.25 (Q1 2020)에서는 보존 트리 병합을 용이하게하기 위해 worktree 로컬 및 저장소 전역 참조를 구별하는 데 사용되는 논리가 고정되어 있습니다.
참조 f45f88b 커밋 , c72fc40 커밋 , 8a64881 커밋 , 7cb8c92 커밋 , e536b1f 커밋 에 의해 (2019년 10월 21일)를 SZEDER 가보 ( szeder
) .
( Junoio C gitster
Hamano 에 의해 병합 - 커밋 db806d7 , 2019 년 11 월 10 일)
path.c
: match
값이없는 함수를 호출하지 마십시오 .trie_find()
서명자 : SZEDER Gábor
'logs / refs'는 작동하는 트리 별 경로가 아니지만 커밋 b9317d55a3 이후로 (refs / rewritten /가 작업 트리 당인지 확인하십시오, 2019-03-07, v2.22.0-rc0) ' git rev-parse --git-path
'는 가짜 경로를 반환했습니다 후미 ' /
'가있는 경우 :
$ git -C WT/ rev-parse --git-path logs/refs --git-path logs/refs/
/home/szeder/src/git/.git/logs/refs
/home/szeder/src/git/.git/worktrees/WT/logs/refs/
trie
데이터 구조를 사용하여 경로가 공통 디렉토리에 속하는지 또는 작동중인 트리에 속하는지 여부를 효율적으로 결정합니다.
공교롭게도 b9317d55a3이 는 AS 오래된 같다 버그 트리거 trie
에 추가 구현 자체 4e09cf2acf을 ( " path
: 최적화 공통의 디렉토리 검사", 2015년 8월 31일은, 힘내 v2.7.0-RC0 - 병합 에 나열된 배치 # 2 ).
설명하는 주석에 따르면 trie_find()
, "trie가 값을 포함하는 키의 // 또는 \ 0- 종료 된 접두사"에 대해 지정된 일치 함수 'fn'만 호출해야합니다.
이것은 사실이 아닙니다. trie_find ()가 match 함수를 호출하는 세 곳이 있지만 그중 하나에 값이 있는지 확인하지 않습니다.
b9317d55a3 는 trie
:
- '
logs/refs/rewritten
'및
- '
logs/refs/worktree
', 기존 ' logs/refs/bisect
' 옆에 있습니다.
그 결과 trie
경로가 ' logs/refs/
'인 노드가 생겼으며 이전에는 존재하지 않았으며 값이 첨부되지 않았습니다.
' logs/refs/
'에 대한 쿼리 는이 노드를 찾은 다음 match
값의 존재를 확인하지 않는 함수 의 호출 사이트 하나를 히트 하여 값으로 match
함수를 호출합니다 NULL
.
match
함수 check_common()
가 NULL
값을 사용하여 호출 되면 0을 반환합니다. 이는 쿼리 된 경로가 공통 디렉토리에 속하지 않음을 나타내며 결국 위의 가짜 경로를 나타냅니다.
trie_find()
존재하지 않는 값으로 일치 함수를 호출하지 않도록 누락 된 조건을 추가하십시오 .
check_common()
그런 다음 더 이상 NULL이 아닌 값을 가지고 있는지 확인할 필요가 없으므로 해당 조건을 제거하십시오.
비슷한 가짜 출력을 일으킬 수있는 다른 경로가 없다고 생각합니다.
AFAICT NULL
값 으로 호출되는 일치 함수를 초래하는 다른 키 는 ' co
'( ' common
'및 ' config
' 키로 인해 )입니다.
그러나 이들이 공통 디렉토리에 속하는 디렉토리에 없으므로 결과적인 작업 트리 특정 경로가 예상됩니다.
git --rebase-merges
부터는 이전을 대체 할 것git --preserve-merges
입니다. 아래 내 답변