로컬 git 커밋 중 일부만 어떻게 푸시합니까?


160

5 개의 로컬 커밋이 있다고 가정합니다. SVN 스타일 워크 플로를 사용하여 두 개만 중앙 저장소에 푸시하고 싶습니다. 어떻게해야합니까?

이것은 작동하지 않았다 :

git checkout HEAD~3  #set head to three commits ago
git push #attempt push from that head

결과적으로 5 개의 로컬 커밋이 모두 완료됩니다.

실제로 커밋을 취소하기 위해 git reset을 수행하고 git stash와 git push를 수행 할 수 있다고 가정하지만 이미 커밋 메시지를 작성하고 파일을 정리했으며 다시 실행하고 싶지 않습니다.

내 느낌은 밀거나 재설정하기 위해 전달 된 일부 플래그가 작동한다는 것입니다.

도움이된다면 여기 내 자식 설정이 있습니다.

[ramanujan:~/myrepo/.git]$cat config 
[core]
        repositoryformatversion = 0
        filemode = true
        bare = false
        logallrefupdates = true
[remote "origin"]
        url = ssh://server/git/myrepo.git
        fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
        remote = origin
        merge = refs/heads/master

답변:


192

커밋이 마스터 분기에 있고 원격 마스터 분기로 푸시하려는 경우 :

$ git push origin master~3:master

git-svn을 사용하는 경우 :

$ git svn dcommit master~3

git-svn의 경우 커밋을 기대하고 있기 때문에 HEAD ~ 3을 사용할 수도 있습니다. 스트레이트 git의 경우 HEAD가 참조 사양에서 올바르게 평가되지 않으므로 분기 이름을 사용해야합니다.

더 긴 접근 방식을 취할 수도 있습니다.

$ git checkout -b tocommit HEAD~3
$ git push origin tocommit:master

이러한 유형의 작업 흐름을 습관화하는 경우 별도의 지점에서 작업을 수행하는 것을 고려해야합니다. 그런 다음 다음과 같은 작업을 수행 할 수 있습니다.

$ git checkout master
$ git merge working~3
$ git push origin master:master

"origin master : master"부분은 설정에서 선택 사항 일 수 있습니다.


14
참고 :을 사용할 필요는 없습니다 master~3. 원하는 "최대"커밋에 대한 참조 (예 : HEAD~3또는) HEAD~~~, 특정 SHA 또는 해당 커밋 레이블이 지정된 태그 가 동일하게 유효합니다 .
Kaz

2
좋은 물건. 경고 :이 예제는 원점 마스터로 푸시됩니다. 이 솔루션을 복사하여 붙여 넣는 경우 실수로 마스터 분기가 업데이트 될 수 있습니다. (물론, 당신은 항상주의를 git push
기울이고

이것은 커밋을 푸시하지만 분기를 원격으로 추가하지 않는 것으로 보입니다.
Nateowami 2012

@Nateowami는 Refspec master의 원격 측 이외의 다른 것을 지정해야합니다.git push origin tocommit:newbramch
Ryan Graham

내가 참조. 분기 이름이 이미 로컬로 존재했습니다. 나는 그것이 마음에 들지 않았다고 생각합니다. 리모컨은 아직 지점 이름이 없었습니다.
Nateowami

16

내가하는 일은 "work"라는 로컬 지점에서 일하는 것입니다. 이 분기에는 업스트림 리포지토리로 푸시하지 않을 모든 임시 커밋 (해결 방법 또는 개인 빌드 옵션 등)이 포함됩니다. 나는 내가하는 적절한 커밋 체리 - 선택, 마스터 분기로 전환 커밋 할 때 그때, 그 지점에 떨어져 작동 다음 주인을 밀어 커밋합니다.

업스트림에서 마스터 브랜치로 변경 사항을 가져온 후 I git checkout workgit rebase master. 그러면 내 로컬 변경 사항이 기록이 끝날 때까지 다시 작성됩니다.

실제로이 git svn워크 플로와 함께 사용 하고 있으므로 "푸시"작업에 관련이 git svn dcommit있습니다. 또한 tig멋진 텍스트 모드 GUI 저장소 뷰어를 사용하여 마스터에 적절한 커밋을 선택합니다.


git svn dcommit을 사용하면 dcommit까지 커밋을 지정할 수 있으므로 원하는 효과는 git-svn에서는 매우 사소합니다.
Ryan Graham

이 접근법에는 단점이 있습니다 (여기서는 stackoverflow.com/a/881014/1116674 ). 좋은 대안은 작업중인 모든 기능에 대한 분기와 분기를 만드는 것 work입니다. 그런 다음 특정 지점을 병합 master하여 기록을 잃지 않도록합니다. 작업시 work모든 분기를 병합합니다. 더 많은 오버 헤드가 있지만 경우에 따라 가치가있을 수 있습니다.
Hudon

16

기본적으로 git-push는 모든 분기를 푸시합니다. 이렇게하면 :

 git checkout HEAD~3  #set head to three commits ago
 git push #attempt push from that head

분리 된 HEAD (지점에 있지 않음)로 이동 한 다음 로컬 마스터 (아직 있던 위치)를 포함하여 모든 분기를 원격 마스터로 푸시합니다.

수동 솔루션은 다음과 같습니다.

 git push origin HEAD:master

혼란스럽고 위험한 모든 브랜치를 푸시하는 기본 동작을 찾으면 ~ / .gitconfig에 추가하십시오.

 [remote.origin]
    push = HEAD

그런 다음 현재 연결된 지점 만 푸시됩니다. 귀하의 예 (분리 된 헤드)에서 실수로 잘못된 커밋을 푸시하지 않고이 오류 메시지가 나타납니다.

 error: unable to push to unqualified destination: HEAD

10

짧은 답변:

git push <latest commit SHA1 until you want commits to be pushed>

예 :

git push fc47b2

git push HEAD~2

긴 대답 :

커밋은 부모 / 자식 메커니즘을 사용하여 체인으로 연결됩니다. 따라서, 커밋 밀어 것은 사실 또한 밀어 모든 부모 커밋 이에 원격 알려지지 않은 곳 커밋합니다. 이것은 git push현재 커밋 시 내재적으로 수행됩니다 git push HEAD. 이 명령이와 같으므로 모든 이전 커밋도 푸시됩니다 .

따라서 질문은 특정 커밋을 푸시하는 방법에 다시 쓰여질 수 있으며이 특정 커밋은 HEAD ~ 2 일 수 있습니다.

푸시하려는 커밋이 연속적이지 않은 git rebase -i경우, 특정 푸시 이전에 커밋을 다시 정렬 하십시오 .


5

1) 원하는 경우 "git rebase"를 사용하여 커밋을 재정렬하십시오.

git rebase -i

이 명령은 편집기에 다음과 같이 표시됩니다 (vim을 사용하고 있습니다)

pick 4791291 commitA
pick a2bdfbd commitB
pick c3d4961 commitC
pick aa1cefc commitD
pick 9781434 commitE

# Rebase ..............
#
# Commands:
#  p, pick = use commit
#  r, reword = use commit, but edit the commit message
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit
#  f, fixup = like "squash", but discard this commit's log message
#  x, exec = run command (the rest of the line) using shell
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out




^G Get Help         ^O WriteOut         ^R Read File        ^Y Prev Page                ^K Cut Text         ^C Cur Pos
^X Exit             ^J Justify          ^W Where Is         ^V Next Page            ^U UnCut Text       ^T To Spell

2) 간단한 잘라 내기 붙여 넣기로 원하는대로 커밋을 다시 정렬하십시오. 새로운 주문이

9781434 commitE 선택

c3d4961 commitC를 선택하십시오

4791291 commitA를 선택하십시오

aa1cefc commitD를 선택하십시오

a2bdfbd commitB를 선택하십시오

편집기에서 변경 한 후 ctrl + O (writeOut)를 누르십시오.

또는 당신은 또한 사용할 수 있습니다

git rebase -i HEAD~<commitNumber>

당신은 새로운 순서를 확인할 수 있습니다

git log

3) 이제 사용

git push <remoteName> <commit SHA>:<remoteBranchName>

원격 (원점)에 하나의 지점과 로컬 (마스터)에 하나의 지점 만있는 경우

git push <commit SHA>
git push aa1cefc

그러면 commitB와 commitD가 푸시됩니다.

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