git : 두 가지 병합 : 어떤 방향?
우리는 다음과 같은 상황이 있습니다.
A --- B --- C --- ... --- iphone
/
... --- last-working --- ... --- master
마지막 작업과 iPhone 사이에 32 개의 커밋이 이루어졌습니다. 마지막 작업과 마스터 사이 에 많은 커밋이 이루어졌습니다.
지금 내가 원하는 것은 아이폰과 현재 마스터가 합쳐진 새로운 브랜치입니다. 그리고 나중에 이것은 마스터로 병합되어야합니다.
먼저 다음과 같이 계획했습니다.
git checkout iphone -b iphone31
git merge master
하지만 그렇게하는 것이 더 낫다면 다음과 같이 생각했습니다.
git checkout master -b iphone31
git merge iphone
이제 궁금합니다. 결과의 차이는 무엇입니까? 병합이 다르게 작동합니까?
나는 이미 두 가지를 모두 시도했으며 예상대로 아이폰이 마스터에 비해 정말 오래 되었기 때문에 많은 충돌이 발생했습니다. 이제 가장 쉬운 병합 방법이 궁금합니다.
마스터로 시작하여 아이폰의 각 커밋을 병합하는 것이 더 쉬울까요? 이렇게 :
git checkout master -b iphone31
git merge A
git merge B
git merge C
...
git merge iphone
마지막에이 병합이 완료되면 (즉 모든 충돌이 해결되고 작동 중임) 다음과 같이하고 싶습니다.
git checkout master
git merge iphone31
대안에 관하여
git checkout iphone -b iphone31
git merge master
과
git checkout master -b iphone31
git merge iphone
그들은 똑같은 용이함이나 어려움을 가질 것입니다. 그것은 마치 유리 잔이 반쯤 찼는 지 반이 비어 있는지 논쟁하는 것과 같습니다.
버전 트리 인식
버전 트리를 보는 방법은 어떤면에서 우리의 임의적 인식 일뿐입니다. 다음과 같은 버전 트리가 있다고 가정 해 보겠습니다.
A----------+
| |
| |
\_/ \_/
B X
| |
| |
\_/ \_/
C Y
|
|
\_/
D
|
|
\_/
E
그리고 C에서 E 로의 변경 사항을 기반으로 Y에서 체크 아웃 된 새 버전 Z를 작성하려고하지만 A에서 C 로의 변경 사항은 포함하지 않으려 고합니다.
"아, 공통된 출발점이 없기 때문에 어려울 것입니다." 글쎄,별로. 이와 같이 그래픽 레이아웃에서 개체를 약간 다르게 배치하면
/
C+---------+
| \ |
| |
\_/ |
D B
| / \
| |
\_/ |
E A
|
|
\_/
X
|
|
\_/
Y
이제 상황이 유망 해 보이기 시작했습니다. 여기서는 어떤 관계도 변경하지 않았고, 화살표는 모두 이전 그림과 같은 방향을 가리키며 버전 A는 여전히 공통 기반입니다. 레이아웃 만 변경됩니다.
하지만 이제 다른 나무를 상상하는 것은 사소한 일입니다.
C'---------+
| |
| |
\_/ \_/
D B'
| |
| |
\_/ \_/
E A
|
|
\_/
X
|
|
\_/
Y
작업은 일반적으로 버전 E를 병합하는 것입니다.
따라서 원하는 것을 병합 할 수 있습니다. 용이성 또는 난이도에 영향을 미치는 유일한 것은 시작점 또는 공통 기반으로 선택한 위치와 병합하는 위치 사이에 수행 된 변경 사항의 집합입니다. 버전 관리 도구가 제안하는 자연스러운 시작점을 사용하는 데 국한되지 않습니다.
This might not be simple with some version control systems/tools, but if all else fails there is nothing that stops you from doing this manually by checking out version C and save the file as file1, checking out version E and save the file as file2, checking out version Y and save the file as file3, and run kdiff3 -o merge_result file1 file2 file3
.
Answer
Now for your specific situation it is difficult to say exactly what strategy that will produce the least amount of problems, but if there are many changes that create some kind of conflict it probably is easier to split up and merge smaller parts.
My suggestion would be that since there are 32 commits between last-working and iphone, you could for instance start by branching of master and then merge in the first 16 commits. If that turns out to be too much trouble, revert and try to merge the 8 first commits. And so on. In worst case you end up merging each of the 32 commits one by one, but it would probably be easier than having to handle all the accumulated conflicts in one single merge operation (and in that case you are working with a really diverging code base).
Tips:
Draw on paper a version tree and note with arrows what you want to merge. Cross off things as they are done if you split up the process in several steps. This will give you a clearer picture of what you want to achieve, what you have done so far and what is left.
I can really recommend KDiff3, it is an excellent diff/merge tool.
There is a difference.
Always check out the target branch during a merge (i.e. if merging A into B, checkout B).
Folks often say that the merge direction does not matter, but this is wrong. While the resulting content will be the same regardless of the merge direction, there are several aspects that are different:
- The diffs listed in the resulting merge-commit will be different depending on the direction.
- Most branch visualizers will decide which branch is "primary" using the merge direction.
To elaborate, imagine this exaggerated example:
- You branched off from MASTER at 1000 commits behind, and named it DEVELOP (or in a tracking-branch scenario, you have not fetch for quite some time).
- You add one commit into DEVELOP. You know there are no conflicts for this change.
- You want to push your changes into MASTER.
- You incorrectly merge MASTER into DEVELOP (i.e. DEVELOP is checked out during the merge). Then, you push DEVELOP as the new MASTER.
- The diffs in the resulting merge-commit will show all 1000 commits that happened in MASTER, because DEVELOP is the reference point.
Not only is this data useless, it's hard to read what's going on. Most visualizer will make it look like your DEVELOP line was the primary all along, with 1000 commits brought into it.
My suggestion is this: Always check out the target branch during a merge (i.e. if merging A into B, checkout B).
- If you are working on a parallel branch and want to periodically bring in changes from a main branch, then checkout your parallel branch. The diffs will make sense -- you will see the changes done in the main branch w.r.t to your branch.
- When you are done working in parallel and wish to merge your changes into the main branch, checkout the main branch and merge with your parallel branch. The diff again will make sense -- it will show what your parallel changes are w.r.t to the main branch.
The readability of the log, in my opinion, matters.
The best approach really depends on whether other people have remote copies of your code. If the master branch is only on your local machine, you can use the rebase command to interactively apply the commits from the feature branch into master:
git checkout master -b iphone-merge-branch
git rebase -i iphone
Note that this alters the commit history of your new iphone-merge-branch branch, which may cause problems for anyone else trying to pull your changes into their checkout later on. By contrast, the merge command applies the changes as a new commit, which is safer when collaborating because it doesn't affect the branch history. See this article for some useful tips on using rebase.
If you need to keep your commit history in sync, you are better off performing a merge. You can use git mergetool to interactively fix conflicts one-by-one using a visual diff tool (a tutorial on this can be found here):
git checkout master -b iphone-merge-branch
git merge iphone
git mergetool -t kdiff3
A third option, if you want absolute control over the process, would be to use git cherry-pick. You can use gitk (or your favourite history viewer) to view the commit hashes in the iphone branch, note them down, and cherry pick them individually into the merging branch - fixing conflicts as you go. An explanation of this process can be found here. This process will be the slowest, but might be the best fall-back option if the other methods do not work out:
gitk iphone
<note down the 35 commit SHA hashes in this branch>
git checkout master -b iphone-merge-branch
git cherry-pick b50788b
git cherry-pick g614590
...
You say:
iphone branch is very old compared to master
Do you really want to merge them both forming a new branch?
The purpose of master and iphone branches would now have been very different ( because iphone is very old ). A new branch merging iphone with an ancestor of master would be better? Think about it.
I highly recommend that you read Fun with merges and purposes of branches.
After reading that article if you still feel you want to merge iphone and master then @seanhodges explains how to handle the conflicts really well.
You may want to make a local backup of your work before experimenting, so you can restart, if you stop understanding what has happened.
Make a backup branch of your work so not lose it during rebase, if you want to keep it for reference.
git checkout iphone -b iphone_backup
Create a new branch from master
git checkout master -b iphone31
then rebase on top of it.
git rebase -i --onto iphone31 iphone
Sean above is correct about rebase applying one commit at a time. But don't worry about existing commits on the branch you rebase onto - they will not be changed. Rebase puts new (adapted) commits on top of them. While done one commit at a time you have better control over conflicts. What is important though, you must rebase your work on top of the master and not vice versa, so the history of master won't change.
Alternatively, you can do only
git rebase -i master iphone
if you don't care about backing up the iphone branch. Look into rebase documentation for details and alternatives http://git-scm.com/docs/git-rebase.
참고URL : https://stackoverflow.com/questions/2351108/git-merge-two-branches-what-direction
'Nice programing' 카테고리의 다른 글
SQL Server로 Lucene.Net 구성 (0) | 2020.12.05 |
---|---|
유사한 텍스트가있는 기사를 찾는 알고리즘 (0) | 2020.12.05 |
jQuery의 작은 따옴표 또는 큰 따옴표 (0) | 2020.12.05 |
고정 헤더가있는 CSS 전용 스크롤 가능 테이블 (0) | 2020.12.05 |
C # 클래스 이름에는 어떤 문자가 허용됩니까? (0) | 2020.12.04 |