Git의 다른 지점에서 선택적으로 병합하거나 변경 사항을 선택하는 방법은 무엇입니까?


1449

두 개의 병렬이지만 현재 실험적인 개발 분기가있는 새 프로젝트에서 git을 사용하고 있습니다.

  • master: 기존 코드베이스 및 일반적으로 확신하는 몇 가지 모드 가져 오기
  • exp1: 실험 지점 # 1
  • exp2: 실험 지점 # 2

exp1그리고 exp2두 개의 매우 다른 건축 방법을 나타냅니다. 더 나아갈 때까지 어느 쪽이 작동하는지 알 방법이 없습니다. 한 브랜치에서 진행하면서 다른 브랜치에 유용한 편집 내용이 있고 그 지점 만 병합하려고합니다.

다른 모든 것을 남겨두고 한 개발 지점에서 다른 개발 지점으로 선택적 변경 사항을 병합하는 가장 좋은 방법은 무엇입니까?

내가 고려한 접근법 :

  1. git merge --no-commit 브랜치 사이에서 공통적으로 만들고 싶지 않은 많은 편집 내용을 수동으로 언 스테이징했습니다.

  2. 공통 파일을 임시 디렉토리로 git checkout수동 복사 한 후 다른 분기로 이동 한 다음 임시 디렉토리에서 작업 트리로 수동 복사를 더 수동으로 복사합니다.

  3. 위의 변형. exp지금 지점을 포기하고 실험을 위해 두 개의 추가 로컬 저장소를 사용하십시오. 이렇게하면 파일을 수동으로 훨씬 간단하게 복사 할 수 있습니다.

이 세 가지 방법 모두 지루하고 오류가 발생하기 쉬운 것 같습니다. 더 나은 접근 방식이 있기를 바랍니다. git-merge더 선택적인 필터 경로 매개 변수와 유사한 것 입니다.


5
실험 브랜치의 변경 사항이 별도의 커밋으로 잘 구성되어 있으면 선택적 파일 대신 선택적 커밋 을 병합하는 관점에서 생각하는 것이 좋습니다 . 아래의 대부분의 답변은 이것이 사실이라고 가정합니다.
akaihola

2
git merge -s ours --no-commit뒤에 몇 가지 조합이 git read-tree좋은 해결책이 아닐까요? 참조 stackoverflow.com/questions/1214906/...
VonC

34
보다 최근의 질문은 한 줄의 잘 작성된 답변이 있습니다 : stackoverflow.com/questions/10784523/…
brahn

특정 파일을 병합이 블로그를 체크 아웃 jasonrudolph.com/blog/2009/02/25/...
아슈 Chamoli

답변:


475

cherry-pick 명령을 사용하여 한 분기에서 개별 커밋을 가져옵니다.

원하는 변경 사항이 개별 커밋에없는 경우 여기에 표시된 방법을 사용 하여 커밋을 개별 커밋으로 분할하십시오 . 대략적으로 말하면 git rebase -i원래 커밋을 편집하고 git reset HEAD^변경 사항을 선택적으로 되 돌린 다음 git commit해당 비트를 기록에서 새 커밋으로 커밋하는 데 사용됩니다.

Red Hat Magazine 에는 또 다른 멋진 방법이 있습니다. 여기서는 다른 변경 사항을 개별 파일로 분할하려는 경우 (이 페이지에서 "분할"검색) 덩어리의 일부만 추가 git add --patch하거나 git add --interactive추가 할 수 있습니다.

변경 사항을 나누면 원하는 항목 만 체리 픽 선택할 수 있습니다.


14
내가 이해 한 바에 따르면, 이것은 투표율이 높은 답변보다 불필요하게 더 복잡합니다.
Alexander Bird

54
이것은 기술적으로 정답이며 정답은 "뒤틀린"것으로 나타납니다. --- 높을수록 대답은 대부분의 사람들에게 그들에 대해 모두 "트릭 않습니다"대답 인 단지 신속하고 더러운 투표 (:
야곱

3
@akaihola : HEAD ^이 맞습니다. man git-rev-parse 참조 : 개정 매개 변수의 접미사 ^는 해당 커밋 객체의 첫 번째 부모를 의미합니다. 접두사 ^ 표기법은 커밋에서 도달 가능한 커밋을 제외하는 데 사용됩니다.
Tyler Rick

13
: 난 그냥 또 다른 깨끗한 덜 모두의 뒤얽힌 보인다 접근 공유하기를 원해요 jasonrudolph.com/blog/2009/02/25/... 총 단순하고 멋진
superuseroi

14
어떤 접근 방식이 '올바른'것인지에 대한 논쟁으로 혼란스러워? 파일과 커밋의 차이점을 고려 하십시오 (아래 설명 참조) . OP는 파일을 병합하고 COMMITS를 언급하지 않습니다. 높은 투표 응답은 파일에 따라 다릅니다. 허용되는 답변은 커밋에 특정한 cherry-pick을 사용합니다. Cherry-pick은 커밋을 선택적으로 병합하는 데 중요하지만 파일을 한 브랜치에서 다른 브랜치로 옮기는 데는 매우 고통 스러울 수 있습니다. 커밋은 git의 힘의 핵심이지만 파일이 여전히 역할을한다는 것을 잊지 마십시오!
Kay V

970

위에서 언급 한 것과 똑같은 문제가있었습니다. 그러나 나는 대답을 설명하는 것이 더 명확 하다는 것을 알았습니다 .

요약:

  • 병합하려는 지점에서 경로를 확인하십시오.

    $ git checkout source_branch -- <paths>...
    

    힌트 : --링크 된 게시물에서 볼 수있는 것처럼 작동하지 않습니다 .

  • 또는 덩어리를 선택적으로 병합

    $ git checkout -p source_branch -- <paths>...
    

    또는 reset을 사용하고 옵션을 추가하십시오 -p.

    $ git reset <paths>...
    $ git add -p <paths>...
    
  • 마지막으로 커밋

    $ git commit -m "'Merge' these changes"
    

9
Bart J의 링크 된 기사가 가장 좋습니다. 명확하고 간단하며 하나의 명령입니다. 내가 사용하려고하는 것입니다. :)
Pistos

256
이것은 실제 병합이 아닙니다. 커밋 대신 파일별로 변경 사항을 선택하면 기존 커밋 정보 (작성자, 메시지)가 손실됩니다. 물론, 일부 파일의 모든 변경 사항을 병합하려면 모든 커밋을 다시 수행해야합니다. 그러나 파일에 병합 변경 사항과 폐기 할 변경 사항이 모두 포함되어 있으면 다른 답변에 제공된 방법 중 하나가 더 효과적입니다.
akaihola 2012

10
@mykhal 및 기타 : 인덱스의 파일을 자동으로 스테이징하므로 체크 아웃 foo.c하면 git reset HEAD foo.c해당 파일의 스테이징을 해제하고 diff 할 수 있습니다. 나는 그것을 시도하고 이것에 대한 답을 찾기 위해 여기로 돌아온 후에 이것을 발견했다
michiakig

12
다음과 같은 변경 사항을 사용할 수도 있습니다.git diff --cached
OderWat

9
답변 에 따르면 git checkout -p <revision> -- <path>당신이 설명한 처음 세 명령을 실행하는 것과 동일합니다 :)
7hi4g0

338

한 지점에서 다른 지점으로 파일을 선택적으로 병합하려면 다음을 실행하십시오.

git merge --no-ff --no-commit branchX

branchX현재 브랜치로 병합하려는 브랜치가 어디에 있습니까 ?

--no-commit옵션은 실제로 커밋하지 않고 Git에 의해 병합 된 파일을 준비합니다. 이렇게하면 병합 된 파일을 수정할 수 있지만 원하는대로 커밋 할 수 있습니다.

파일 병합 방법에 따라 다음과 같은 네 가지 경우가 있습니다.

1) 당신은 진정한 합병을 원합니다.

이 경우 Git이 자동으로 병합 한 방식으로 병합 된 파일을 수락 한 다음 커밋합니다.

2) 병합하고 싶지 않은 파일이 있습니다.

예를 들어, 현재 분기에 버전을 유지하고 병합하려는 분기의 버전을 무시하려고합니다.

현재 분기에서 버전을 선택하려면 다음을 실행하십시오.

git checkout HEAD file1

이것은 file1현재 브랜치에서 버전을 검색하고 file1Git에 의해 자동 병합 된 것을 덮어 씁니다 .

3) branchX의 버전을 원할 경우 (진정한 병합이 아님).

운영:

git checkout branchX file1

이것은 Git에 의해 자동 병합 된 file1in branchX및 덮어 쓰기 버전을 검색합니다 file1.

4) 마지막 경우는에서 특정 병합 만 선택하려는 경우입니다 file1.

이 경우 수정 된 내용을 file1직접 편집 하고 원하는 버전으로 업데이트 file1한 다음 커밋 할 수 있습니다.

Git이 파일을 자동으로 병합 할 수 없으면 파일을 " 병합되지 않은 " 것으로보고 하고 충돌을 수동으로 해결해야하는 사본을 생성합니다.



예제를 통해 더 자세히 설명하기 위해 branchX현재 브랜치 로 병합하고 싶다고 가정 해 봅시다 .

git merge --no-ff --no-commit branchX

그런 다음 git status명령을 실행하여 수정 된 파일의 상태를보십시오.

예를 들면 다음과 같습니다.

git status

# On branch master
# Changes to be committed:
#
#       modified:   file1
#       modified:   file2
#       modified:   file3
# Unmerged paths:
#   (use "git add/rm <file>..." as appropriate to mark resolution)
#
#       both modified:      file4
#

어디에서 file1, file2그리고 file3성공적으로 자동 합병이 자식 파일입니다.

이것이 의미하는 것은 masterbranchX세 파일 모두에 대한 변경 사항이 충돌없이 함께 결합되었다는 것입니다.

git diff --cached; 를 실행하여 병합이 수행 된 방식을 검사 할 수 있습니다 .

git diff --cached file1
git diff --cached file2
git diff --cached file3

병합이 바람직하지 않은 것을 발견하면

  1. 파일을 직접 편집하십시오
  2. 저장
  3. git commit

병합하지 않고 file1현재 분기에서 버전을 유지하려는 경우

운영

git checkout HEAD file1

병합하지 않고 file2버전 만 원하는 경우branchX

운영

git checkout branchX file2

당신이 원하는 경우 file3자동으로 병합 할, 아무것도하지 않습니다.

Git은 이미이 시점에서 병합했습니다.


file4위의 Git 병합 실패입니다. 이는 동일한 라인에서 발생하는 두 가지 모두에 변경이 있음을 의미합니다. 여기서 충돌을 수동으로 해결해야합니다. 파일을 직접 편집하거나 원하는 브랜치에서 버전에 대한 체크 아웃 명령을 실행하여 병합 된 내용을 버릴 수 있습니다 file4.


마지막으로 잊지 마세요 git commit.


10
주의 사항 : 만약 이것이 git merge --no-commit branchX빨리 감기라면, 포인터가 업데이트 될 것이고 --no-commit는 자동적으로 무시된다
cfi

16
@cfi --no-ff그 행동을 막기 위해 추가 하는 것은 어떻습니까?
Eduardo Costa

5
이 답변을 Eduardo의 "--no-ff"옵션으로 업데이트하는 것이 좋습니다. 나는 병합이 빨리 진행되도록 모든 것을 읽었습니다 (그렇지 않으면 좋았습니다).
Funktr0n

7
이 솔루션은 최상의 결과와 유연성을 제공합니다.
Thiago Macedo

20
가장 많은 표를 얻은 답변과 달리이 솔루션은 병합 기록을 보존했습니다. 이는 분기 전체에서 부분 커밋을 앞뒤로 짜는 데 중요합니다. 다른 제안 된 솔루션을 모두 시도하지 않았으므로 일부 솔루션 도이 작업을 수행합니다.
ws_e_c421 12

107

위의 접근 방식이 마음에 들지 않습니다. cherry-pick을 사용하면 단일 변경을 선택하는 것이 좋지만 일부 변경을 제외하고 모든 변경을 가져 오려면 고통입니다. 여기 내 접근 방식이 있습니다.

--interactivegit merge에 전달할 수있는 인수 는 없습니다 .

대안은 다음과 같습니다.

'feature'브랜치에 일부 변경 사항이 있고 일부를 전부는 아니지만 부주의하게 '마스터'로 가져 오려고합니다 (즉, 각각 체리 선택하고 커밋하고 싶지는 않습니다)

git checkout feature
git checkout -b temp
git rebase -i master

# Above will drop you in an editor and pick the changes you want ala:
pick 7266df7 First change
pick 1b3f7df Another change
pick 5bbf56f Last change

# Rebase b44c147..5bbf56f onto b44c147
#
# Commands:
# pick = use commit
# edit = use commit, but stop for amending
# squash = use commit, but meld into previous commit
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#

git checkout master
git pull . temp
git branch -d temp

따라서 쉘 스크립트로 래핑하고 master를 $ to로 변경하고 기능을 $ from으로 변경하면 좋습니다.

#!/bin/bash
# git-interactive-merge
from=$1
to=$2
git checkout $from
git checkout -b ${from}_tmp
git rebase -i $to
# Above will drop you in an editor and pick the changes you want
git checkout $to
git pull . ${from}_tmp
git branch -d ${from}_tmp

서식을 고쳤습니다. 커밋을 선택하고 싶을 때이 방법은 아주 좋은 방법입니다.
1800 INFORMATION

나는이 기술을 사용하고 있으며 실제로 효과가있는 것으로 보입니다.
dylanfm

4
당신은 변경할 수 있습니다 git rebase -i $togit rebase -i $to || $SHELL사용자가 호출 할 수 있습니다 그래서, git --skipREBASE이 실패 할 경우 필요에 따라 등. 또한 줄 &&바꿈 대신 줄을 묶을 가치가 있습니다.
sircolinton

2
불행히도, 답변의 링크가 죽은 것으로 보입니다.
ThomasW

링크가 죽었을뿐만 아니라 WOT의 평판이 좋지 않습니다. 따라서 제거했습니다.
Jean-François Corbett

93

갈 다른 방법이 있습니다.

git checkout -p

그것은 사이의 혼합 git checkout이며 git add -p정확히 당신이 찾고있는 것일 수 있습니다.

   -p, --patch
       Interactively select hunks in the difference between the <tree-ish>
       (or the index, if unspecified) and the working tree. The chosen
       hunks are then applied in reverse to the working tree (and if a
       <tree-ish> was specified, the index).

       This means that you can use git checkout -p to selectively discard
       edits from your current working tree. See the “Interactive Mode”
       section of git-add(1) to learn how to operate the --patch mode.

10
병합 할 수있는 변경 횟수 만있는 한이 방법이 가장 쉽고 간단한 방법입니다. 더 많은 사람들이이 답변을보고 찬성하기를 바랍니다. 예 : 자식 체크 아웃 --patch EXP1 file_to_merge
타일러 릭

1
이 질문에 비슷한 답변이 게시되었습니다. stackoverflow.com/a/11593308/47185
Tyler Rick

아, 나는 체크 아웃에 패치가 있다는 것을 몰랐다! 대신 체크 아웃 / 재설정 / 추가 -p를 수행했습니다.
Daniel C. Sobral

2
정말 가장 간단한 방법입니다. git checkout -p featurebranch 파일 이름. 그리고 가장 좋은 것은 명령이 실행될 때 ay / n / e /? / ... 등을 제공하는 것입니다. 파일을 병합하는 방법을 결정하는 옵션입니다. 나는 e로 시도했고 적용하기 전에 패치를 편집 할 수도 있습니다 ... 얼마나 멋진가요. 다른 브랜치의 선택적 파일을 병합하기위한 진정한 하나의 라이너.
infoclogged가

55

이러한 답변 중 일부는 꽤 좋지만 실제로는 실제로 지점의 특정 파일을 선택하는 OP의 원래 제약 조건에 아무도 대답하지 않은 것 같습니다. 이 솔루션은 그렇게하지만 파일이 많은 경우 지루할 수 있습니다.

당신이이 말을하자 master, exp1exp2지점. 각 실험 분기에서 하나의 파일을 마스터로 병합하려고합니다. 나는 이런 식으로 할 것입니다 :

git checkout master
git checkout exp1 path/to/file_a
git checkout exp2 path/to/file_b

# save these files as a stash
git stash
# merge stash with master
git merge stash

이렇게하면 원하는 각 파일에 대한 파일 내 차이점이 제공됩니다. 더 이상 없습니다. 그 이하도 아닙니다. 버전마다 파일이 완전히 다른 경우 유용합니다. 필자의 경우 앱을 Rails 2에서 Rails 3으로 변경하는 것이 좋습니다.

편집 : 파일을 병합하지만 스마트 병합을 수행합니다. 파일 내 diff 정보를 얻는 데이 방법을 사용하는 방법을 알 수 없었습니다 (아마도 여전히 큰 차이가있을 것입니다.이 -s recursive -X ignore-all-space옵션 을 사용하지 않으면 공백과 같은 성가신 작은 것들이 다시 병합됩니다 )


4
또한 참고 : 주어진 분기에서 모든 인라인으로 여러 파일을 수행 할 수 있습니다. 예 :git checkout exp1 path/to/file_a path/to/file_x
EMiller

2
이것은 아름답다. 내가 그랬어 git checkout feature <path>/*파일 그룹을 얻을 수 있습니다.
isherwood

이것은 정상적으로 작동하지만 두 개의 추가 커밋 객체가 추가되었습니다. 큰 거래가 아니라 약간 지저분하다
MightyPork

@MightyPork 당신이 맞아요. 불행히도, 오래 전에 이것을 작성했기 때문에 "git commit"대신 "git stash"및 "git merge stash"단계가 왜 더 이상 있는지 잘 모르겠습니다.
Eric Hu

2
아, 분명합니다. 이 방법으로 대상 브랜치의 이전 변경 사항을 반드시 덮어 쓰지는 않아도 하나의 파일을 병합합니다.
MightyPork

48

1800 INFORMATION의 답변이 완전히 맞습니다. git noob으로서, "git cherry-pick 사용"은 인터넷에서 조금 더 파지 않고 이것을 알아 내기에 충분하지 않았으므로 다른 사람이있는 경우 더 자세한 가이드를 게시 할 것이라고 생각했습니다. 비슷한 보트.

내 유스 케이스는 다른 사람의 github 브랜치에서 내 자신의 변경 사항을 선택적으로 가져오고 싶었습니다. 변경 사항이있는 로컬 지점이 이미있는 경우 2 단계와 5-7 단계 만 수행하면됩니다.

  1. 가져올 변경 사항을 사용하여 로컬 브랜치를 작성하십시오 (작성되지 않은 경우).

    $ git branch mybranch <base branch>

  2. 그것으로 전환하십시오.

    $ git checkout mybranch

  3. 상대방의 계정에서 원하는 변경 사항을 풀다운하십시오. 아직 원격으로 추가하지 않으려는 경우.

    $ git remote add repos-w-changes <git url>

  4. 지점에서 모든 것을 끌어 내십시오.

    $ git pull repos-w-changes branch-i-want

  5. 커밋 로그를보고 원하는 변경 사항을 확인하십시오.

    $ git log

  6. 변경 사항을 가져 오려는 지점으로 다시 전환하십시오.

    $ git checkout originalbranch

  7. 체리는 해시로 커밋을 하나씩 선택합니다.

    $ git cherry-pick -x hash-of-commit

모자 팁 : http://www.sourcemage.org/Git_Guide


3
팁 : 먼저 git cherry명령을 사용하여 (먼저 수동 참조) 아직 병합하지 않은 커밋을 식별하십시오.
akaihola

이것은 작동합니다 .. 1. 새 브랜치를 만들었습니다 2. 일부 파일을 만들거나 변경했습니다 3. 커밋 4. 마스터 브랜치를 체크 아웃 5. git cherry-pick -x 커미트 해시를 실행하고 병합 충돌을 해결하십시오 토고.
RamPrasadBismil

귀하의 링크가 더 이상 작동하지 않습니다. 업데이트 하시겠습니까?
creep3007

42

다음은 대체 할 수있는 방법입니다 Myclass.java있는 파일 master과 분기 Myclass.javafeature1분기합니다. 에 Myclass.java없는 경우에도 작동 합니다 master.

git checkout master
git checkout feature1 Myclass.java

이것은 병합하지 않고 덮어 쓰고 마스터 브랜치의 로컬 변경 사항을 무시합니다.


6
병합되지 않습니다. feature1 브랜치의 변경 사항으로 마스터의 변경 사항을 덮어 씁니다.
Skunkwaffle

3
완벽하게, 나는 theirs덮어 쓰기 ours=> +1 Cheers;) 에서 이런 종류의 병합을 찾고있었습니다 .
olibre

1
때로는 전체 파일을 교체하기 만하면되기 때문에 이것이 내가 원하는 것입니다. 그러나이 파일에서 변경 한 내용을 모두 잃어 버리도록해야합니다.
MagicLAMP

1
OP가 전체 파일을 다른 지점의 해당 파일로 대체하려는 경우 가장 깨끗한 솔루션 :2. Manual copying of common files into a temp directory followed by ...copying out of the temp directory into the working tree.
Brent Faust

29

특정 파일을 다른 브랜치의 파일로 바꾸는 것이 아니라 실제로 두 개의 브랜치에서 특정 파일을 병합 하는 간단한 방법 입니다.

1 단계 : 분기 차이

git diff branch_b > my_patch_file.patch

현재 branch와 branch_b의 차이점에 대한 패치 파일을 만듭니다.

2 단계 : 패턴과 일치하는 파일에 패치 적용

git apply -p1 --include=pattern/matching/the/path/to/file/or/folder my_patch_file.patch

옵션에 대한 유용한 참고 사항

*포함 패턴에서 와일드 카드로 사용할 수 있습니다 .

슬래시를 피할 필요가 없습니다.

또한 --exclude를 대신 사용하여 패턴과 일치하는 파일을 제외한 모든 항목에 적용하거나 패치를 -R로 되돌릴 수 있습니다.

-p1 옵션은 * 유닉스 패치 명령에서 홀드 및 패치 파일의 내용이 각 파일 이름 앞에 추가 사실이다 a/b/(이상 패치 파일이 생성 된 방법에 따라) 당신이 그것을 알아낼 수 있도록 제거해야하는 패치를 적용해야하는 파일의 경로에 대한 실제 파일

더 많은 옵션은 git-apply 매뉴얼 페이지를 확인하십시오.

3 단계 : 3 단계가 없습니다.

분명히 변경 사항을 커밋하고 싶지만 누가 커밋하기 전에 수행해야 할 다른 관련 조정 사항이 없다고 말하는 사람은 분명합니다.


1
current_branch에 보존해야 할 "추가"변경 사항이 많은 경우에 매우 유용했습니다. git diff HEAD ... branch_b와 같이 branch_b에 의해 가져온 변경 사항의 차이를 얻었습니다 (예-3주기는 마술을 수행합니다).
Saad Malik

@masukomi, 2 단계에서 1 단계에서 작성된 패치 파일을 인수로 추가해서는 안됩니까?
Spiralis

나를 위해 모든 변경 사항이 거부되었습니다. 왜 그런지 알아?
LinusGeffarth

@LinusGeffarth의 초기 생각은 패치를 만들 때 가지를 거꾸로했을 것입니다. 우리가 알아낼 수 있는지 확인하기 위해 SO 외부의 후속 조치를 취할 것입니다.
masukomi

24

"단순한"병합으로 원하지 않는 많은 변경 사항을 가져 왔더라도 다른 지점의 파일 몇 개만 따라가는 기록을 얻는 방법은 다음과 같습니다.

먼저, 커밋하려는 것이 합병이며, git이 작업 디렉토리의 파일에 대해 전혀 아무것도하지 않고 미리 선언하는 특별한 단계를 수행합니다.

git merge --no-ff --no-commit -s ours branchname1

. . . 여기서 "branchname"은 병합한다고 주장하는 것입니다. 즉시 커밋하면 변경되지 않지만 다른 지점의 조상은 계속 표시됩니다. 더 많은 지점 / 태그 / 등을 추가 할 수 있습니다. 필요한 경우 명령 줄에 이 시점에서 커밋 할 변경 사항이 없으므로 다른 개정판에서 파일을 가져옵니다.

git checkout branchname1 -- file1 file2 etc

둘 이상의 다른 브랜치에서 병합하는 경우 필요에 따라 반복하십시오.

git checkout branchname2 -- file3 file4 etc

이제 다른 브랜치의 파일이 색인에 있으며 커밋 준비가되었습니다.

git commit

커밋 메시지에서 설명해야 할 것이 많습니다.

확실하지 않은 경우, 이것은 엉망인 일입니다. 그것은 "지점"의 목적이 아니며 체리 픽은 당신이 여기서하고있는 일을하는 더 정직한 방법입니다. 지난 번에 가져 오지 않은 동일한 지점의 다른 파일에 대해 다른 "병합"을 수행하려는 경우 "이미 최신"메시지가 표시됩니다. 우리가 가져야 할 때 분기하지 않는 증상입니다. "보낸 사람"분기에서 둘 이상의 다른 분기 여야합니다.


3
첫 번째 명령 ( git merge --no-ff --no-commit -s outs branchname1)은 내가 찾던 것입니다! 감사!
RobM

1
여러 분기, 필요한 기록, 단일 파일을 병합하고 푸시하기 전에 파일의 내용을 변경 해야하는 경우 이는 적절한 대안으로 보입니다. 예를 들어 dev => master이지만 master로 푸시하기 전에 호스트 정의 등을 변경하려고합니다.
timss

15

조금 늦었다는 것을 알고 있지만 이것은 선택적 파일을 병합하기위한 워크 플로입니다.

#make a new branch ( this will be temporary)
git checkout -b newbranch
# grab the changes 
git merge --no-commit  featurebranch
# unstage those changes
git reset HEAD
(you can now see the files from the merge are unstaged)
# now you can chose which files are to be merged.
git add -p
# remember to "git add" any new files you wish to keep
git commit

나는 이것에 약간의 변형을 사용했다. 병합하는 대신 나는 체리 피킹했다. 그것은 일을한다. 이 방법의 유일한 단점은 원래 커밋 해시에 대한 참조를 잃는 것입니다.
Matt Florence

15

가장 쉬운 방법은 리포지를 병합하려는 지점으로 설정하고 실행하는 것입니다.

git checkout [branch with file] [path to file you would like to merge]

당신이 실행하는 경우

git status

파일이 이미 준비된 것을 볼 수 있습니다 ...

그런 다음 실행

git commit -m "Merge changes on '[branch]' to [file]"

단순한.


3
이것은 내가 찾은 거의 최고의 답변입니다. jasonrudolph.com/blog/2009/02/25/… 를 참조하십시오 . 너무 명확하고 간결하며 작동합니다!
superuseroi

1
병합하지 않고 소스 브랜치의 파일 내용을 완전히 대체합니다
Amare

나는 이렇게 대답하려고했지만, 아직 답변되지 않은 새로운 것들을 발명했다고 생각했습니다! 그러나 이것이 가장 간단한 방법 입니다. 이 위에 있어야합니다!
Irfandy Jip

15

내가 찾은 이 게시물을 간단한 답을 포함 할 수 있습니다. 꼭해라 :

$ #git checkout <branch from which you want files> <file paths>

예:

$ #pulling .gitignore file from branchB into current branch
$ git checkout branchB .gitignore

자세한 내용은 게시물을 참조하십시오.


3
이것은 실제로 병합되지 않으며 현재 분기의 파일을 덮어 씁니다.
Igor Ralic

1
@igrali 이것은 유용한 의견이지만, "적절한"방법으로 어려움을 겪는 것과 비교하면 좋은 해결 방법입니다. 하나는 매우 조심해야합니다.
owensmartin

12

자식이 여전히 편리한 도구를 가지고 있지 않다는 것은 이상하다. 현재 버전 분기의 일부 버그 수정으로 일부 이전 버전 분기 (여전히 많은 소프트웨어 사용자가 있음)를 업데이트 할 때 많이 사용합니다 . 이 경우 트렁크의 파일에서 줄의 코드 를 빠르게 가져 와서 많은 다른 변경 사항 (이전 버전으로 들어 가지 않아야 함)을 무시하고 종종 대화 형 3 방향 병합 이 경우에 필요 git checkout --patch <branch> <file path>하며이 선택적 병합 목적으로 사용할 수 없습니다.

당신은 쉽게 할 수 있습니다 :

이 행을 [alias]글로벌 .gitconfig또는 로컬 .git/config파일의 섹션에 추가 하십시오.

[alias]
    mergetool-file = "!sh -c 'git show $1:$2 > $2.theirs; git show $(git merge-base $1 $(git rev-parse HEAD)):$2 > $2.base; /C/BCompare3/BCompare.exe $2.theirs $2 $2.base $2; rm -f $2.theirs; rm -f $2.base;' -"

Beyond Compare를 사용한다는 의미입니다. 필요한 경우 원하는 소프트웨어로 변경하십시오. 또는 대화식 선택적 병합이 필요하지 않은 경우 3 방향 자동 병합으로 변경할 수 있습니다.

[alias]
    mergetool-file = "!sh -c 'git show $1:$2 > $2.theirs; git show $(git merge-base $1 $(git rev-parse HEAD)):$2 > $2.base; git merge-file $2 $2.base $2.theirs; rm -f $2.theirs; rm -f $2.base;' -"

그런 다음 다음과 같이 사용하십시오.

git mergetool-file <source branch> <file path>

이것은 다른 브랜치에있는 파일 의 진정한 선택적 트리-웨이 병합 기회를 제공합니다.


10

정확히 당신이 찾고있는 것이 아니지만 나에게 유용했습니다.

git checkout -p <branch> -- <paths> ...

몇 가지 답변이 혼합되어 있습니다.


2
이것은 실제로 유용하며 나에게 가장 좋은 대답 인 @alvinabad의 대답에 추가 될 수 있습니다. 수행 할 때 : git checkout HEAD file1현재 버전을 유지하고 파일을 병합 해제 file1하려면 -p옵션을 사용 하여 병합 할 파일의 일부 를 선택할 수 있습니다 . 트릭 주셔서 감사합니다!
Simon C.

이것은 나의 마음에 드는 답변입니다. 간단하고 요점과 작품
Jesse Reza Khorasanee

8

나는 할 것이다

자식 diff commit1..commit2 파일 패턴 | git-apply --index && 자식 커밋

이 방법으로 브랜치에서 파일 패턴에 대한 커밋 범위를 제한 할 수 있습니다.

도난 : http://www.gelato.unsw.edu.au/archives/git/0701/37964.html


어떤 상황에서는 매우 유용 할 수 있습니다. 그러나 변경 사항이 다른 지점에있는 경우 위의 Bart J의 답변과 같이 해당 지점의 끝에서 체크 아웃 할 수 있습니다.
cdunn2001

Bart Js는 누구입니까?
Black

8

위에서 언급 한 것과 똑같은 문제가있었습니다. 그러나 나는 이 자식 블로그 가 답을 설명하는 것이 더 명확 하다는 것을 알았습니다 .

위 링크에서 명령 :

#You are in the branch you want to merge to
git checkout <branch_you_want_to_merge_from> <file_paths...>

이것을 테스트 했습니까? 파일이 병합되지 않고 <branch_you_want_to_merge_from>에서 대체 될 것입니다
Amare

7

위의 'git-interactive-merge'답변이 마음에 들지만 더 쉬운 방법이 있습니다. git이 대화 형과 rebase의 rebase 조합을 사용 하여이 작업을 수행하도록하십시오.

      A---C1---o---C2---o---o feature
     /
----o---o---o---o master

따라서 '기능'분기 (분기점 'A')에서 C1과 C2를 원하지만 나머지는 없습니다.

# git branch temp feature
# git checkout master
# git rebase -i --onto HEAD A temp

위와 같이 C1 및 C2에 대한 'pick'라인을 선택하는 대화식 편집기로 이동합니다 (위와 같이). 저장하고 종료하면 rebase가 진행되고 master + C1 + C2에 분기 'temp'와 HEAD가 표시됩니다.

      A---C1---o---C2---o---o feature
     /
----o---o---o---o-master--C1---C2 [HEAD, temp]

그런 다음 master를 HEAD로 업데이트하고 임시 분기를 삭제하면 좋습니다.

# git branch -f master HEAD
# git branch -d temp

7

무엇에 대해 git reset --soft branch? 아직 아무도 언급하지 않은 것에 놀랐습니다.

나를 위해, 그것은 다른 브랜치에서 변경 사항을 선택적으로 선택하는 가장 쉬운 방법입니다.이 명령은 내 작업 트리에 모든 차이 변경 사항을 넣고 필요한 것을 쉽게 선택하거나 되돌릴 수 있기 때문입니다. 이런 식으로 커밋 된 파일을 완전히 제어 할 수 있습니다.


6

나는이 질문이 오래되었고 다른 많은 대답이 있다는 것을 알고 있지만 디렉토리를 부분적으로 병합하기 위해 'pmerge'라는 자체 스크립트를 작성했습니다. 진행중인 작업이며 여전히 git 및 bash 스크립팅을 배우고 있습니다.

이 명령은 git merge --no-commit제공된 경로와 일치하지 않는 변경 사항을 사용 하고 적용하지 않습니다.

사용법 : git pmerge branch path
예 :git merge develop src/

나는 그것을 광범위하게 테스트하지 않았습니다. 작업 디렉토리에는 커밋되지 않은 변경 사항과 추적되지 않은 파일이 없어야합니다.

#!/bin/bash

E_BADARGS=65

if [ $# -ne 2 ]
then
    echo "Usage: `basename $0` branch path"
    exit $E_BADARGS
fi

git merge $1 --no-commit
IFS=$'\n'
# list of changes due to merge | replace nulls w newlines | strip lines to just filenames | ensure lines are unique
for f in $(git status --porcelain -z -uno | tr '\000' '\n' | sed -e 's/^[[:graph:]][[:space:]]\{1,\}//' | uniq); do
    [[ $f == $2* ]] && continue
    if git reset $f >/dev/null 2>&1; then
        # reset failed... file was previously unversioned
        echo Deleting $f
        rm $f
    else
        echo Reverting $f
        git checkout -- $f >/dev/null 2>&1
    fi
done
unset IFS

4

read-tree주어진 원격 트리를 읽거나 현재 색인으로 병합 하는 데 사용할 수 있습니다 ( 예 :

git remote add foo git@example.com/foo.git
git fetch foo
git read-tree --prefix=my-folder/ -u foo/master:trunk/their-folder

병합을 수행하려면 -m대신 사용하십시오.

참조 : git에서 하위 디렉토리를 어떻게 병합합니까?


3

파일별로 선택적으로 병합 / 커밋하는 간단한 방법 :

git checkout dstBranch git merge srcBranch // make changes, including resolving conflicts to single files git add singleFile1 singleFile2 git commit -m "message specific to a few files" git reset --hard # blow away uncommitted changes


3

변경된 파일이 너무 많지 않으면 추가 커밋이 없습니다.

1. 일시적으로 브랜치 복제
$ git checkout -b temp_branch

원하는 마지막 2. 재설정 커밋
$ git reset --hard HEAD~n 곳, n다시 갈 필요가 커밋의 수는

3. 원래 지점에서 각 파일을 체크 아웃하십시오.
$ git checkout origin/original_branch filename.ext

필요한 경우 이제 원격으로 덮어 쓰기 위해 커밋하고 강제로 푸시 할 수 있습니다.


3

특정 디렉토리 만 병합하고 다른 모든 것을 그대로 유지하면서 기록을 보존해야하는 경우 시도해 볼 수 있습니다 . 실험하기 전에 새로운 target-branch것을 만들어보십시오 master.

아래 단계에서는 두 개의 분기가 target-branch있고 를 병합하려는 source-branch디렉토리 dir-to-merge가에 있다고 가정 합니다 source-branch. 또한 dir-to-retain히스토리를 변경하고 유지하지 않으려는 대상 과 같은 다른 디렉토리가 있다고 가정하십시오 . 또한에 병합 충돌이 있다고 가정합니다 dir-to-merge.

git checkout target-branch
git merge --no-ff --no-commit -X theirs source-branch
# the option "-X theirs", will pick theirs when there is a conflict. 
# the options "--no--ff --no-commit" prevent a commit after a merge, and give you an opportunity to fix other directories you want to retain, before you commit this merge.

# the above, would have messed up the other directories that you want to retain.
# so you need to reset them for every directory that you want to retain.
git reset HEAD dir-to-retain
# verify everything and commit.

2

두 분기의 현재 커밋 사이에서 몇 개의 파일 만 변경되면 다른 파일을 통해 변경 사항을 수동으로 병합합니다.

git difftoll <branch-1>..<branch-2>

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.