git의 "rebase --reserve-merges"가 정확히 무엇을 하는 것입니까 (그리고 그 이유는 무엇입니까?)
--preserve-merges
Instead of ignoring merges, try to recreate them.
This uses the --interactive machinery internally, but combining it
with the --interactive option explicitly is generally not a good idea
unless you know what you are doing (see BUGS below).
그래서 당신이 사용할 때 실제로 일어나는 일은--preserve-merges이 플래그가 없는 기본 동작과 어떻게 다릅니까?병합 등을 "재작성"한다는 것은 무엇을 의미합니까?
일반적인 깃베이스와 마찬가지로, 깃베이스는--preserve-merges먼저 커밋 그래프의 한 부분에서 수행된 커밋 목록을 식별한 다음 다른 부분 위에 해당 커밋을 재생합니다.와의 --preserve-merges재생을 위해 선택된 커밋과 병합 커밋에 대해 재생이 작동하는 방식과 관련이 있습니다.
일반 리베이스와 병합 보존 리베이스의 주요 차이점을 보다 명확하게 설명하려면 다음과 같이 하십시오.
- 병합 보존 리베이스는 병합 커밋을 재생(일부)할 수 있지만 일반 리베이스는 병합 커밋을 완전히 무시합니다.
- 병합 커밋을 재생할 의향이 있으므로 병합 보존 기본 재배치는 병합 커밋을 재생하는 것이 무엇을 의미하는지 정의하고 추가 주름을 처리해야 합니다.
- 개념적으로 가장 흥미로운 부분은 아마도 새로운 커밋의 병합 부모가 되어야 하는 것을 선택하는 것입니다.
- 커밋을 .
git checkout <desired first parent>)), 하지 되는 반면에, 반에일반인리적는스그베없대필다습니요걱가면정할해.
- 병합 보존 리베이스는 재생을 위해 더 얕은 커밋 집합을 고려합니다.
- 특히, 가장 최근의 병합 기준(즉, 가장 최근에 두 분기가 분기된 시간) 이후에 만들어진 커밋을 재생하는 것만 고려할 것이며, 일반적인 리베이스는 두 분기가 처음 분기된 시간으로 거슬러 올라가는 커밋을 재생할 수 있습니다.
- 잠정적이고 불분명하게 말하자면, 이것은 궁극적으로 이미 병합 커밋에 "통합"된 "이전 커밋"을 다시 재생하는 것을 걸러내는 수단이라고 생각합니다.
" 을 기본으로 하는지 설명해 .--preserve-merges그렇습니다, 그리고 몇 가지 예가 있을 것입니다.물론 그것이 더 유용해 보인다면, 예들로 시작할 수 있습니다.
"Brief"의 알고리즘
, git 하고 git 해 보세요.git-rebase--interactive.sh(베이스는 Git의 C 코어의 일부가 아니라 bash로 작성됩니다.그리고 배후에서는 "대화형 리베이스"와 코드를 공유합니다.)
하지만 여기서 저는 그것의 본질이 무엇이라고 생각하는지 스케치할 것입니다.생각해야 할 것들의 수를 줄이기 위해, 저는 몇 가지 자유를 택했습니다.(예: 계산이 이루어지는 정확한 순서를 100% 정확하게 캡처하려고 하지 않으며, 일부 덜 중심적인 주제(예: 분기 간에 이미 선택된 커밋에 대해 어떻게 해야 하는지)를 무시합니다.
첫째, 비 병합 보존 리베이스는 다소 단순합니다.어느 정도입니다.
Find all commits on B but not on A ("git log A..B")
Reset B to A ("git reset --hard A")
Replay all those commits onto B one at a time in order.
재배치--preserve-merges비교적 복잡합니다.여기 꽤 중요해 보이는 것들을 잃지 않고 해낼 수 있었던 간단한 방법이 있습니다.
Find the commits to replay:
First find the merge-base(s) of A and B (i.e. the most recent common ancestor(s))
This (these) merge base(s) will serve as a root/boundary for the rebase.
In particular, we'll take its (their) descendants and replay them on top of new parents
Now we can define C, the set of commits to replay. In particular, it's those commits:
1) reachable from B but not A (as in a normal rebase), and ALSO
2) descendants of the merge base(s)
If we ignore cherry-picks and other cleverness preserve-merges does, it's more or less:
git log A..B --not $(git merge-base --all A B)
Replay the commits:
Create a branch B_new, on which to replay our commits.
Switch to B_new (i.e. "git checkout B_new")
Proceeding parents-before-children (--topo-order), replay each commit c in C on top of B_new:
If it's a non-merge commit, cherry-pick as usual (i.e. "git cherry-pick c")
Otherwise it's a merge commit, and we'll construct an "equivalent" merge commit c':
To create a merge commit, its parents must exist and we must know what they are.
So first, figure out which parents to use for c', by reference to the parents of c:
For each parent p_i in parents_of(c):
If p_i is one of the merge bases mentioned above:
# p_i is one of the "boundary commits" that we no longer want to use as parents
For the new commit's ith parent (p_i'), use the HEAD of B_new.
Else if p_i is one of the commits being rewritten (i.e. if p_i is in R):
# Note: Because we're moving parents-before-children, a rewritten version
# of p_i must already exist. So reuse it:
For the new commit's ith parent (p_i'), use the rewritten version of p_i.
Otherwise:
# p_i is one of the commits that's *not* slated for rewrite. So don't rewrite it
For the new commit's ith parent (p_i'), use p_i, i.e. the old commit's ith parent.
Second, actually create the new commit c':
Go to p_1'. (i.e. "git checkout p_1'", p_1' being the "first parent" we want for our new commit)
Merge in the other parent(s):
For a typical two-parent merge, it's just "git merge p_2'".
For an octopus merge, it's "git merge p_2' p_3' p_4' ...".
Switch (i.e. "git reset") B_new to the current commit (i.e. HEAD), if it's not already there
Change the label B to apply to this new branch, rather than the old one. (i.e. "git reset --hard B")
▁an로 --onto C인수는 매우 유사해야 합니다.B의 HEAD에서 커밋 재생을 시작하는 대신 C의 HEAD에서 커밋 재생을 시작합니다. (그리고 B_new 대신 C_new를 사용합니다.)
예 1
예를 들어 커밋 그래프를 사용합니다.
B---C <-- master
/
A-------D------E----m----H <-- topic
\ /
F-------G
m은 부모 E와 G와의 병합 커밋입니다.
일반적으로 병합되지 않는 기본 재배치를 사용하여 마스터(C) 위에 주제(H)를 기반으로 했다고 가정합니다. (예: 체크아웃 주제; 기본 재배치 마스터)이 경우 git는 재생을 위해 다음 커밋을 선택합니다.
- D를 골라라
- 픽 E
- F를 선택합니다.
- G를 골라라
- H를 골라 H
그런 다음 커밋 그래프를 다음과 같이 업데이트합니다.
B---C <-- master
/ \
A D'---E'---F'---G'---H' <-- topic
(D'는 D 등의 재생된 등가물입니다.)
병합 커밋이 재생에 대해 선택되지 않았습니다.
만약 우리가 대신 한다면,--preserve-mergesC 위에 H의 기본 재배치(예: 체크아웃 항목; 기본 재배치 --preserve-merges master).이 새로운 경우 git는 재생을 위해 다음 커밋을 선택합니다.
- D를 골라라
- 픽 E
- F를 선택합니다('하위 항목' 분기에서 'D'로).
- G를 선택합니다('하위 항목' 분기에서 F로).
- 분기 '하위 항목'을 항목에 병합 선택
- H를 골라 H
이제 m이 재생을 위해 선택되었습니다.또한 병합 커밋 전에 병합 부모 E와 G가 포함되도록 선택되었습니다.
다음은 커밋 결과 그래프입니다.
B---C <-- master
/ \
A D'-----E'----m'----H' <-- topic
\ /
F'-------G'
다시 말하지만, D'는 D의 체리로 선택된 (즉, 재작성된) 버전입니다.E' 등도 마찬가지입니다.마스터에 없는 모든 커밋이 재생되었습니다.E와 G(m의 병합 부모)가 모두 E'와 G'로 재생성되어 m'의 부모 역할을 합니다(리베이스 후에도 트리 히스토리는 그대로 유지됨).
예 2
일반적인 리베이스와 달리 병합 보존 리베이스는 업스트림 헤드의 자식을 여러 개 만들 수 있습니다.
예를 들어, 다음을 생각해 보십시오.
B---C <-- master
/
A-------D------E---m----H <-- topic
\ |
------- F-----G--/
C(마스터) 위에 H(항목)를 기본으로 하면, 기본 재배치를 위해 선택된 커밋은 다음과 같습니다.
- D를 골라라
- 픽 E
- F를 선택합니다.
- G를 골라라
- 픽엠
- H를 골라 H
그 결과는 다음과 같습니다.
B---C <-- master
/ | \
A | D'----E'---m'----H' <-- topic
\ |
F'----G'---/
예 3
위의 예에서 병합 커밋과 두 부모 모두 원래 병합 커밋이 가진 부모가 아닌 재생된 커밋입니다.그러나 다른 기본값에서 재생된 병합 커밋은 병합 전에 이미 커밋 그래프에 있던 부모로 끝날 수 있습니다.
예를 들어, 다음을 생각해 보십시오.
B--C---D <-- master
/ \
A---E--m------F <-- topic
만약 우리가 주제를 마스터에 기초한다면(머징 보존), 재생할 커밋은
- 병합 커밋 선택
- F를 선택합니다.
다시 작성된 커밋 그래프는 다음과 같습니다.
B--C--D <-- master
/ \
A-----E---m'--F'; <-- topic
여기서 재생된 병합 커밋'은 커밋 그래프에 미리 존재하는 부모, 즉 D(마스터의 HEAD) 및 E(원래 병합 커밋의 부모 중 하나)를 가져옵니다.
예 4
병합 보존 기본 재배치는 특정 "빈 커밋" 사례에서 혼동될 수 있습니다.적어도 이것은 일부 이전 버전의 git(예: 1.7.8)에만 해당됩니다.
다음 커밋 그래프를 사용합니다.
A--------B-----C-----m2---D <-- master
\ \ /
E--- F--\--G----/
\ \
---m1--H <--topic
commit m1과 m2 모두 B와 F의 모든 변경 사항을 포함했어야 합니다.
우리가 하려고 한다면,git rebase --preserve-mergesH(주제)에서 D(마스터)로 이동하면 재생을 위해 다음 커밋이 선택됩니다.
- m1 선택
- H를 골라 H
m1에 통합된 변경사항(B, F)은 이미 D에 통합되어야 합니다. (m2는 B와 F의 자식들을 병합하기 때문에 이러한 변경사항은 이미 m2에 통합되어야 합니다.)따라서 개념적으로 D 위에서 m1을 재생하는 것은 아마도 no-op이거나 빈 커밋(즉, 연속적인 리비전 사이의 차이가 비어 있는 커밋)을 만들어야 합니다.
그러나 Git는 D 위에서 m1을 재생하려는 시도를 거부할 수 있습니다.다음과 같은 오류가 발생할 수 있습니다.
error: Commit 90caf85 is a merge but no -m option was given.
fatal: cherry-pick failed
깃에 플래그를 전달하는 것을 잊은 것처럼 보이지만 근본적인 문제는 깃이 빈 커밋을 만드는 것을 싫어한다는 것입니다.
2는 Git 2.18 (2018년 2분기)를 개선할 입니다.--preserve-merge새 옵션을 추가하여 선택할 수 있습니다.
"git rebase학식이 있는"--rebase-merges커밋 그래프의 전체 토폴로지를 다른 곳에 이식합니다.
(참고: Git 2.22, 2019년 2분기는 실제로 더 이상 사용하지 않으며, Git 2.25, 2020년 1분기는 ""git rebase --help 출력에서 광고를 중단합니다.
커밋 25cff9f, 커밋 7543f6f, 커밋 1131ec9, 커밋 7cdf65, 커밋 537e7d6, 커밋 a9be29c, 커밋 8f6aed7, 커밋 1644c73, 커밋 1e8b01, 커밋 4c68e7d, 커밋 9055e40, 커밋 cb5206e, 커밋 commit 01c2a5, 커밋 2f1d1d1d1(4), bf5, commit 5, commit 5, bf5,dscho commit 2018년 4월 25
Stefan Beller()stefanbeller의 commit f431d73(2018년 4월 25일)을 참조하십시오.
필립 우드()phillipwood의 커밋 2429335(2018년 4월 25일)를 참조하십시오.
(주니오 C 하마노에 의해 합병되었습니다 -- -- 커밋 2c18e6a, 2018년 5월 23일)
pull락수를--rebase-merges만듭니다.
합니다.
preserve모드를 단순히 통과합니다.--preserve-merges에 대한rebase령명,merges는 모는단순히통다니합과드▁the▁passes다▁simply▁mode를 간단히 통과합니다.--rebase-merges선택.이를 통해 사용자는 새 커밋을 풀 때 단순하지 않은 커밋 토폴로지를 평평하게 만들지 않고 편리하게 재배치할 수 있습니다.
git rebaseman 페이지에는 이제 병합으로 기록을 재구성하는 전체 섹션이 있습니다.
추출:
개발자가 병합 커밋을 다시 생성하려는 정당한 이유가 있습니다. 즉, 상호 관련된 여러 분기에서 작업할 때 분기 구조(또는 "커밋 토폴로지")를 유지하는 것입니다.
다음 예제에서 개발자는 단추가 정의된 방식을 리팩터링하는 항목 분기와 "버그 보고" 단추를 구현하기 위해 리팩터링을 사용하는 다른 항목 분기에서 작업합니다.
의 출력.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-merges선택.
작은 예는 커밋 1644c73을 참조하십시오.
rebase-helper--make-script병합의 기본을 바꾸기 위해 깃발을 도입합니다.
시퀀서는 분기 구조를 재현하기 위한 새로운 명령어를 방금 배웠습니다(정신적으로는 와 비슷하지만 상당히 덜 부서진 설계임).
다음을 허용합니다.
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?
Commit 8f6aed7은 다음을 설명합니다.
옛날에 이 개발자는 이렇게 생각했습니다. 예를 들어, 코어 Git 위에 있는 Windows용 Git의 패치를 여러 개의 분기로 표현하고, 체리 픽 가능한 패치 시리즈를 유지하기 위해 코어 Git 위에 기반을 바꿀 수 있다면 좋지 않을까요?
이에 대한 최초의 답변은 다음과 같습니다.
git rebase --preserve-merges.하지만, 그 실험은 결코 대화형 옵션으로 의도된 것이 아니었고, 그것은 단지 돼지 등에 의지했을 뿐입니다.
git rebase --interactive명령어의 은 이미입니다. 이는 왜하면 그명이매미우구은현때친보, 다니문였기입설: ▁same▁▁who▁person'▁designed다▁by▁designed▁the니▁was:▁it▁already▁that▁command를 설계한 동일한 사람이 설계했습니다.--preserve-merges당신의 진심입니다.
그리고 작가는 "당신의 진실"을 통해 자신을 다음과 같이 언급합니다.Johannes Schindelin()dscho은 (Hannes, Steffen, Sebastian 등의 다른 영웅들과 함께) Git For Windows를 갖게 된 주된 이유입니다(비록 그 시절인 2009년에도 불구하고).
그는 2015년 9월부터 마이크로소프트에서 일하고 있는데, 마이크로소프트가 현재 Git를 많이 사용하고 있고 그의 서비스가 필요하다는 것을 고려하면 말이 됩니다.
이 추세는 2013년에 TFS를 통해 시작되었습니다.그 이후로, 마이크로소프트는 지구상에서 가장 큰 Git 저장소를 관리하고 있습니다!그리고 2018년 10월부터 마이크로소프트는 깃허브를 인수했습니다.
2018년 4월 Git Merge 2018을 위한 이 비디오에서 요하네스가 말하는 것을 볼 수 있습니다.
후,안드레아스,는 너를 ! 가 허락하는 했습니다.
--preserve-merges…과--interactive포함 그리고 깃 주니오가 깃 했고, (경고함께음와자는유!)의이 그리깃지고유고동의했깃자다니그매입바력지로그즉임것이동없시의안주는가니오▁the▁()음),는그매바다니▁the입▁cave▁and▁theats▁when력!with로▁andor이▁(것▁g그경▁(▁glam▁thatitweller▁is▁maintain동▁of의,▁agreed▁g고그,(했리자.--preserve-merges디자인은 다소 빠르고 보기 흉하게 무너지기 시작했습니다.
여기 조나단이 Suse의 Andreas Schwab에 대해 이야기하고 있습니다.
여러분은 2012년에 있었던 그들의 토론 중 일부를 볼 수 있습니다.
그 이유는?모드에서 병합 커밋의 부모(또는 이와 관련하여 모든 커밋의 부모)는 명시적으로 명시되지 않았지만 명령에 전달된 커밋 이름에 의해 암시되었습니다.
이로 인해 커밋을 다시 정렬할 수 없습니다.
분기 간에 커밋을 이동하거나 주제 분기를 두 개로 나누는 것은 말할 것도 없습니다.아아, 이러한 단점들은 또한 모드(원래 목적은 Windows용 Git를 제공하는 것이었고 다른 사람들에게도 유용할 수 있다는 추가적인 희망)가 Windows용 Git를 제공하는 것을 막았습니다.
이 없는 를 Git for Windows에 해졌을 때,이 좋지 않은 5.5인치 ). Git for Windows에 부분적으로 관련이 있고 부분적으로 관련이 없는 패치를 Git for Windows에 하나씩 포함하는 것이 정말로 불가능해졌을 때, 이는 때때로 핵심 Git의 태그에 기반을 두고 있었습니다(운명이 나쁜 개발자의 부당한 분노를 샀습니다).
git-remote-hg처음에 Git for Windows의 경쟁적인 접근 방식을 폐지한 시리즈는 나중에 유지 관리자 없이 포기되었습니다.) 실제로 "Git garden shears"가 탄생했습니다. 대화형 리베이스 위에 피기백 방식으로 배치되는 스크립트로, 우선 재배치할 패치의 분기 토폴로지를 결정합니다.추가 편집을 위해 유사 작업관리 목록을 만들고, 결과를 실제 작업관리 목록으로 변환합니다.exec명령을 사용하여 누락된 작업관리 목록 명령을 "실행"하고 마지막으로 새 기본 커밋 위에 패치 시리즈를 다시 만듭니다.
(Git garden shears 스크립트는 이 패치에서 commit 9055e40에서 참조됩니다.)
그것은 2013년이었습니다.
그리고 그 디자인을 고안하고 그것을 나무 밖의 스크립트로 구현하는 데 약 3주가 걸렸습니다.물론 설계 자체가 건전하다는 것이 입증되는 동안 구현은 안정화되기까지 몇 년이 걸렸습니다.이 패치로 깃 정원 가위의 장점이 저절로 나타납니다.
옵션을 전달하면 쉽게 이해할 수 있고 커밋을 다시 정렬하는 방법이 명확한 작업관리 목록이 생성됩니다.
삽입하여 새 분기를 도입할 수 있습니다.label및 " 명및호출"merge <label>.
일단 이 방식이 안정적이고 보편적으로 받아들여지면, 우리는 디자인 실수를 더 이상 사용하지 않을 수 있습니다.
Git 2.19(2018년 3분기)는 새로운 기능을 향상시킵니다.--rebase-merges사용할 수 있도록 설정하는 옵션--exec.
더 "--exec옵션: "git rebase --rebase-mergesexec 명령을 잘못된 위치에 배치했습니다. 이 명령은(는)
커밋 1ace63b(2018년 8월 9일), 커밋 f0880f7(2018년 8월 6일)을 요하네스 쉰들린()dscho 참조.
(주니오 C 하마노에 의해 합병 -- 750eb11, 2018년 8월 20일 커밋)
rebase --exec와 잘 해나가다--rebase-merges
의 생각
--exec를 추가하는 것입니다.exec차례차례로 부르다pick.의 도입 이후로
fixup!/squash!커밋, 이 아이디어는 "픽(pick), 그 다음에 픽업/디렉싱 체인(fixup/fix-chain)"에 적용되도록 확장되었습니다. 즉, 실행자는 다음 사이에 삽입되지 않습니다.pick그리고 그에 상응하는 모든 것.fixup또는squash줄들.현재 구현에서는 이를 달성하기 위해 더티 트릭을 사용합니다. 즉, pick/fixup/squash 명령만 있는 것으로 가정하고 다음을 삽입합니다.
exec앞줄pick하지만 첫 번째, 그리고 마지막 하나를 추가합니다.에서 생성된 작업관리 목록을 사용
git rebase --rebase-merges이 간단한 구현은 문제를 보여줍니다: 그것은 정확하게 잘못된 것이 있을 때 생성됩니다.label,reset그리고.merge명령을 실행합니다.원하는 대로 구현을 변경합니다. 라인을 찾고 픽스업/스쿼시 체인을 건너뛰고 라인을 삽입합니다.거품을 내고, 헹구고, 반복합니다.
참고: 빈 커밋은 주석이 달린 선택 라인으로 표시되기 때문에 가능한 한 주석 라인 앞에 삽입하려고 합니다(그리고 앞에 있는 선택의 실행 라인을 나중이 아닌 앞에 삽입하고 싶습니다).
사용 중에 추가할 수 있습니다.
exec뒤의 행.merge명령, 왜냐하면 그것들은 정신적으로 비슷하기 때문입니다.pick명령: 새 커밋을 추가합니다.
Git 2.22 (2019년 2분기)는 refs/rewrite/계층 구조의 사용을 수정하여 기본 중간 상태를 저장하며, 이는 본질적으로 워크트리별 계층 구조를 만듭니다.
커밋 b9317d5, 커밋 90d31ff, 커밋 09e6564(2019년 3월 7일)를 Nguyễn Thai Ngọc Duy()pclouds의 커밋을 참조하십시오.
(주니오 C 하마노에 합병 -- -- 커밋 917f2cd, 2019년 4월 9일)
참조/재작성/작업 트리별인지 확인합니다.
a9be29c(시퀀서: ref를 생성합니다.label명령 worktree-local, 2018-04-25, Git 2.19) 추가refs/rewritten/작업 트리 기준 공간으로 표시됩니다.
안타깝게도 (내가 잘못한) 실제로 작업 트리별인지 확인하기 위해 업데이트가 필요한 곳이 몇 군데 있습니다.
add_per_worktree_entries_to_dir()참조가 작업 트리별로 확인되도록 업데이트되었습니다.refs/rewritten/1인당 대신에
common_list[]다음과 같이 업데이트됩니다.git_path()올바른 위치를 반환합니다.여기에는 "가 포함됩니다.rev-parse --git-path".이 난장판은 제가 만든 것입니다.
저는 그것을 고치려고 하기 시작했습니다.refs/worktree,여기서 모든 참조는 특별한 처리 없이 작업 트리별로 이루어집니다.
유감스럽게도 refs/worktree 이전에 refs/rewrite가 발생했기 때문에 이것이 우리가 할 수 있는 전부입니다.
Git 2.24 (2019년 4분기), "git rebase --rebase-merges다양한 합병 전략을 추진하고 전략별 옵션을 전달하는 방법을 배웠습니다.
엘리야 뉴렌()newren의 커밋 476998d(2019년 9월 4일)를 참조하십시오.
위원회1fac53, commit a63f990, commit a63f990, commit 5dd74, commit 145d99, commit 4e6023b, commit f67336d, commit a9c7107, commit b8c6f24, commit c248d32, commit 8c1e240, commit 5e0e, commit 68b54f6, commit 6180bac, 6180b20, d581(Julit)을 dschoSchelinit 2019 Schelinit (Julinit
(주니오 C 하마노에 의해 합병되었습니다 -- -- 커밋 917a319, 2019년 9월 18일)
Git 2.25(2020년 1분기)에서는 워크트리 로컬 및 리포지토리 글로벌 참조를 구분하는 데 사용되는 논리가 고정되어 보존-합병을 용이하게 합니다.
커밋 f45f88b, 커밋 c72fc40, 커밋 8a64881, 커밋 7cb8c92, 커밋 536b1f(2019년 10월 21일) by SZEDER Gavor()szeder 참조.
(주니오 C 하마노에 의해 합병 -- -- 2019년 11월 10일 커밋 db806d7에서)
path.c전화하지 마match에 가치가 없는 기능trie_find()사인 오프 바이: SZEDER Garbor
'logs/refs'는 작업 트리별 경로가 아니지만 commit b9317d55a3(refs/rewrite/가 작업 트리별인지 확인, 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가 발생했을 때, 그것만큼 오래된 버그를 트리거했습니다.
trie4e09cf2acf에 추가된 구현 자체("pathoptimize common dir checking", 2015-08-31, Git v2.7.0-rc0 -- 배치 #2에 나열된 병합.
다음을 설명하는 코멘트에 따라
trie_find()주어진 일치 함수를 "/또는 트리가 값을 포함하는 키의 종료 접두사"에 대해서만 'fn'이라고 불러야 합니다.
이것은 사실이 아닙니다. trie_find()가 일치 함수를 호출하는 세 곳이 있지만 그 중 하나는 값의 존재를 확인하지 못합니다.b9317d55a3는 두개의 새로운 키를 추가했습니다.
trie:'
logs/refs/rewritten그리고'
logs/refs/worktree이미 존재하는 ' 옆에logs/refs/bisect'.
이로 인해 다음과 같은 결과가 발생했습니다.trie경로가 '인 노드logs/refs/이전에는 존재하지 않았고, 가치가 붙어 있지 않은 것입니다.
'에 대한 쿼리logs/refs/이 노드를 찾은 다음 하나의 콜 사이트를 누릅니다.match값의 존재를 확인하지 않고, 따라서 호출하는 함수match와 함께 일하는.NULL가치로서그 때.
match기능.check_common()를 사용하여 호출됩니다.NULLvalue는 0을 반환합니다. 이는 쿼리된 경로가 공통 디렉터리에 속하지 않음을 나타냅니다. 따라서 위에 표시된 가짜 경로가 생성됩니다.누락된 조건 추가
trie_find()따라서 존재하지 않는 값으로 일치 함수를 호출하지 않습니다.
check_common()그러면 더 이상 NULL이 아닌 값을 받았는지 확인할 필요가 없으므로 해당 조건을 제거합니다.저는 유사한 허위 산출물을 야기할 수 있는 다른 경로는 없다고 생각합니다.
일치 함수를 호출하는 유일한 다른 키는 AFICT입니다.
NULL값은 '입니다.co(키 때문에)common및 'config').그러나 공통 디렉토리에 속하는 디렉토리에 없기 때문에 작업 트리별 경로가 필요합니다.
메모리 누수를 방지하기 위해 Git 2.34(Q4 2021)를 사용해야 합니다.
커밋 6e65854, 커밋 0c52cf8(2021년 10월 13일) 및 커밋 5a917f(2021년 10월 7일)를 Aevar Arnförd Bjarmason()avar의 커밋을 참조하십시오.
주니오 C 하마노()gitster의 커밋 9d05b45(2021년 10월 7일)를 참조하십시오.
(주니오 C 하마노에 의해 합병 -- -- 2021년 10월 25일 커밋 bfa646c에서)
sequencer메모리 누수를 고치다do_reset()사인 오프 바이: 애바르 아르뇌르드 비야르마손
9055e40에 도입된 메모리 누수를 해결합니다(").
sequencer개정을 재설정하기 위한 새로운 명령을 도입합니다.", 2018-04-25, Git v2.18.0-rc0 -- merge listed in batch #6).setup_unpack_trees_porcelain()에의 연락 없이.clear_unpack_trees_porcelain().
Git 2.41 (2023년 2분기) 간소화--rebase-merges명령줄 옵션 처리 및 소개rebase.merges구성 변수입니다.
커밋 6605fb7, 커밋 33561f5, 커밋 7e5dec(2023년 3월 25일)alexhenrie 참조.
(주니오 C 하마노에 의해 합병 -- -- 2023년 4월 4일 9142fce 커밋에서)
rebase구성 옵션 추가--rebase-merges사인 오프 바이: 알렉스 헨리
새로운 옵션의 목적은 다음과 같은 사용자를 수용하는 것입니다.
--rebase-merges기본적으로 켜져 있고 쉽게 켜집니다.--rebase-mergesGit의 향후 버전에서는 구성하지 않고 기본적으로.명령줄 옵션의 이름과 일관성을 유지하고 다음에서 값을 스크롤할 때 명확하도록 새 옵션의 이름을 지정합니다.
[rebase]의 일부..gitconfig.서포트 설정
rebase.rebaseMerges비특이적인 값으로 "true기본값 재지정과 기본값 비지정의 차이에 대해 배울 필요가 없거나 알고 싶지 않은 사용자를 위해 사용됩니다.만들다
--rebase-merges명령줄에서 인수 없이 모든 값을 재정의합니다.rebase.rebaseMerges연결된 구성 옵션이 있는 선택적 인수를 사용하여 다른 명령줄 플래그와의 일관성을 유지합니다.
git config이제 관리 페이지에 다음 항목이 포함됩니다.
rebase.rebaseMerges설정 여부 및 방법
--rebase-merges기본 옵션입니다.수 있습니다.rebase-cousins,no-rebase-cousins또는 부울 값입니다.true 또는 로 설정no-rebase-cousins와 동등합니다.--rebase-merges=no-rebase-cousins설정rebase-cousins와 동등합니다.--rebase-merges=rebase-cousins그리고 false로 설정하는 것은 다음과 같습니다.--no-rebase-merges.
패싱--rebase-merges명령행에서 인수가 있든 없든 모든 명령어를 재정의합니다.rebase.rebaseMerges배열.
git rebase이제 관리 페이지에 다음 항목이 포함됩니다.
반대와 양쪽 모두
rebase.rebaseMerges구성 옵션 및 이전 버전--rebase-merges.
그들이 그 메시지를 끌어서 받았다는 이유만으로 여기서 끝나는 사람들을 위해:
git pull
(...)
warning: git rebase --preserve-merges is deprecated. Use --rebase-merges instead.
~/.gitconfig 및 /etc/gitconfig를 살펴보고 이 옵션을 검색합니다.
[pull]
rebase = preserve
그런 다음 해당 문서로 이동하여 필요한 사항을 이해하고 해결하십시오. https://www.git-scm.com/docs/git-config#Documentation/git-config.txt-pullrebase
언급URL : https://stackoverflow.com/questions/15915430/what-exactly-does-gits-rebase-preserve-merges-do-and-why
'programing' 카테고리의 다른 글
| UI 레이블 주위에 테두리를 그리는 방법은 무엇입니까? (0) | 2023.06.03 |
|---|---|
| SQL Server Reporting Services(VB)에서 이전 달력 달의 첫째 날과 마지막 날을 찾습니다.네트) (0) | 2023.05.09 |
| Git 저장소에서 디렉토리의 이름을 올바르게 변경하는 방법은 무엇입니까? (0) | 2023.05.09 |
| Xcode 4 - 새 Macintosh 설치에서 프로파일 프로비저닝 시 "유효한 서명 ID를 찾을 수 없음" 오류 (0) | 2023.05.09 |
| pgadmin4: postgresql 응용 프로그램 서버에 연결할 수 없습니다. (0) | 2023.05.09 |