병합시 밀어 넣기가 발생하지 않으므로 git merge
(물론, pull
)에서 발생하지만 실제로는 병합 + 병합이므로 병합시 병합됩니다. pull
는 fetch
가 (지금에있는 모든 새로운 커밋을 얻을 의미하기 때문에,
<get copy from origin/develop>
<wait around for remote's origin/develop to acquire new commits>
git checkout develop # get onto (local) develop branch
<edit>
git commit -m message # create some new commit(s)
git push origin develop # attempt to push -- but this fails!
git pull
그것은 병합 (위 M
를) 커밋 만듭니다 마지막 단계입니다 :
그것은 당신이 이런 일을했다는 가능성이 보인다 origin/develop
), merge
(로컬 develop
을 가져 와서 방금 가져온 새로운 커밋과 병합하십시오.) 당신이하지 git push
에디션이 새로운 결과가있는 경우
, 다음 원격 REPO는 중 해당 지역의 커밋, 사람이 분류 한 C*
및 M
이 없습니다. 이 경우, 당신은 좋은 모습입니다! (다시 원격에서 하나, 다음에 무엇을 볼 수 git log origin/develop
을하고 해당 지역의 repo의 origin/develop
일치하는지 확인하기 위해 git fetch
을 실행하여 확인할 수 있습니다.)
그것은 두 개의 완전히 분리 된 자식의 repos 여기에 있다는 것을 기억하는 데 도움이 될 수 있습니다 당신의 물건들; 그리고 전화 한 사람 origin
여기. (그 기계를 X
라고 부르 자.) 만약 X
에 로그온했다면, 그것 자신의 별도의 커밋 내역과 브랜치 이름 등을 가지고있다. 저기서 디렉토리를 repo로 변경하고 git log -1 develop
을 실행하고 해당 분기의 끝 부분에있는 내용을 확인하십시오.
이제 X
에서 로그 오프하고 다시 자신의 컴퓨터에있는 경우 git log -1 origin/develop
을 실행할 수 있습니다. 그 내용이 X
에서 본 것과 같으면 git fetch
은 실제로 X
에 로그온하여 develop
에있는 내용을보고 있기 때문에 아무 것도 업데이트하지 않습니다. X
에 origin/develop
, fetch
이 없으면 origin/develop
에 추가됩니다.이제 X
과 동기화되었습니다. X
님은 내 콘텐츠가 없지만 나만 보유하고 있습니다.
당신은 다음이 할 경우, 병합 커밋합니다 ...을 A (pull
에 의해 암시 포함) merge
, 자식을하는 별도의 조치를 취할하지만이 모든에서, 당신의의 repo에있는 경우 가지의 끝 (여전히이 경우 develop
). 이 병합 커밋을 X
(또는 누군가 X
에있는 사용자가 커밋을 가져 오지만 지금은 무시합니다 .-))까지 밀어 넣기 전까지는 X
에 커밋되지 않습니다.
어쨌든 리모컨 (여기서는 X
)에 병합 완료가없는 한 사용자는 황금색입니다. 부터이 없으므로 다른 사람도 마찬가지입니다. develop
지점의 rebase
을 수행하여 origin/develop
위에 커밋 (C*
)을 올릴 수 있습니다. 그러면 병합 커밋 (M
)이 제거되고 간단한 빨리 감기를 origin/develop
으로 푸시 할 수 있습니다.
하면 X
않습니다이 병합 커밋 - 즉, 당신이 pull
에드 후 밀어 얻은 경우 그 병합 - 당신은 아마도 다른 사람이 X
에 액세스 할 수 있으며 현재 사용하고 있기 때문에 (어느 정도) 막히다 병합 커밋. git reset
및 git rebase
등으로 자신의 저장소에서 수행 할 수있는 것과 비슷한 방식으로 X
에있는 저장소를 롤백 할 수는 있지만 일반적으로 좋지 않습니다.
지금, 당신은 사실이
가정은 (기계 X
에) 다른 REPO에 푸시,하지만 당신은 다른 확신 아무도 아직 변경 사항을 볼 수 없다있어, 당신은 확실히 그들을 다시 것보다는 되 돌리는 것 그들 (되돌리기는 "fessing up"에 이르고 screwup-record는 뒤에 남겨 두어 다른 사람들이 쉽게 복구 할 수있게하지만 오류를 볼 수도 있습니다 :-)). 여기에 1 트릭 : 당신이 먼저 C7 이전에서 당신의 고유의 다이어그램에서 "지점 devel
의 끝이 C7을 커밋한다"고 말을 기계 X의 REPO를 얻을 필요가, 단지 있도록 다시 번호 I 각 커밋의 이름을 다르게 지정할 수 있습니다.
--------------------------- C*--- M
--- C4 --- C5 --- C6 --- C7 ----/
그래서 어떻게 할 수 있습니까? 음, 한 가지 방법은 X
, cd
에 로그인하여 (--bare
인 경우에도) Repo에 로그인하고 git update-ref
을 사용하는 것입니다. C7의 SHA1이 실제로 50db850
("git log"에 표시된 것처럼)이라고 가정 해 보겠습니다.
localhost$ ssh X
X$ cd /path/to/repo.git
X$ git update-ref refs/heads/develop 50db850
을하지만 X
에 로그인 할 수없는 경우, 또는 그냥 당신이 git push -f
과 같은 작업을 수행 할 수 있습니다 싶지 않은 : 그럼 당신은이 작업을 수행 할 수 있습니다. 3는 (이것은 다른 장점이 있습니다 특히, 당신의 자식의 repo는 push -f
이 성공적으로 완료되면 origin/develop
가, 되감기되었음을 알 수 있습니다.) 그냥 오른쪽을 가리키는 로컬 가지 팁 커밋합니다 4
localhost$ git branch resetter 50db850
localhost$ git log resetter # make sure it looks right
...
localhost$ git push -f origin resetter:develop
Total 0 (delta 0), reused 0 (delta 0)
To ssh://[redacted]
+ 21011c9...50db850 resetter -> develop (forced update)
localhost$ git branch -d resetter # we don't need it anymore
이 작업을 완료하면 컴퓨터 X가 원하는 상태로 돌아오고 원하지 않는 병합을 푸시 한 적이없는 것처럼 계속 진행할 수 있습니다.당신이 push -f
을 수행 할 때 다른 사람이 M
의 상단에 새로운 커밋을 만든 경우, 사람들은 도는 "기술적으로 커밋 병합과 함께, 거기에 아직도 있지만, 그들이 (보이지 않는 될 것으로
는 주 잃어버린 "은 lost+found
의 느낌이 git fsck --lost-found
이고, 몇 달 후에 그들은 정말로 영원히 사라질 것입니다. 5
다시 매우 중요한: "공유의 repo의 롤백"이런 종류의 그래서 당신이 그것을하기 전에 괜찮아요 정말 반드시 해당 공유 REPO의 다른 사용자에게 큰 고통이다.
1도 되돌릴 필요가없는 사소한 병합 이런 종류의. 거기에 병합을 남기는 것이 근본적으로 잘못된 것은 아닙니다. 더 심각한 실수 합병을 다루는 경우, "oops"기록 외에 병합을 되 돌리는 데 또 다른 단점이 있습니다. 나중에 "병합"에서 변경 사항을 "다시 실행"하는 것이 조금 더 어렵습니다. 목적에 따라 "이전 합병과 생각을 볼 수 있습니다 : 확인을 다시 병합 할 필요가 없습니다 그 변경. 대신 "되돌리기 되돌리기"를해야합니다. 보기 (git log
) 당신은 당신이 추진하려고하는 것은 당신이 밀어 의도가 무엇인지 확인하기 위해을 밀어 넣기 전에 :
나는 여기에 바로 테이크 아웃의 교훈이라고 생각합니다. 더 쉽고 간단 : git ls-remote
. 이것은 원격 프로토콜의 내용을보기 위해 fetch protocol 코드를 사용합니다. 그러나 그것은 내가 여기에서 할 주제를 숨 깁니다. 리모콘은 당신처럼 레포입니다!
3 곧 자식 버전이 출시 git push -f
으로 가능한 것입니다 새로운 "안전 기능"을 가지고있다. 그러나 그들은 아직 빠져 나오지 않았으므로 도움이되지 않습니다. 나는 이것을 나중에 다시 편집 할 것입니다. 그때까지는 이 실제로입니다. 공유 저장소에 새로운 항목을 푸시하려고하는 다른 사용자와 경쟁하고 있습니다.
원시 SHA-1 ID로도이 작업을 수행 할 수 있습니다. 분기 이름은 한 번에 여러 번 올바르게 입력하는 것이 더 쉽습니다.
보유 및 만료는 git의 "reflogs"를 통해 이루어집니다. 공유 서버가 모든 참조 업데이트를 로깅하지 않을 수 있습니다. 그렇지 않다면, 새로운 커밋을 이미 가지고있는 private repos만이 그 커밋을 유지할 것입니다. 가장 짧은 기본 만료 기간은 분기 팁에서 더 이상 도달 할 수없는 커밋에 대해 30 일 (약 1 개월)입니다. 하지만 공유 저장소에서 강제로 "작업을 잃어 버린"후 "잃어버린"커밋에 대해 저장소를 통해 모든 사람이 검색 할 수 있도록 만드는 것은 재미없고 놀랄만 한 스크램블입니다.
와우, 덕분에이 광범위한 답변을 많이. 불행히도 X로 밀어 넣었습니다. 아무도 새로운 가져 오기를 만들지 않았으므로이 변경 사항을 취소 할 수 있는지 궁금합니다. 정말 명확하지 않은 한 가지 : 다시 두 걸음을 다시 설정하면 분기 중 하나 또는 두 가지 모두를 남겨두고 있습니까? – dmeu
좋아, 음, 밀고 난 후에, 정말로 확실하다면 : *) ... 당신이하고 싶은 것은 분기의 끝점에 대한 X의 생각을 조금 뒤로 되 감는 것이다. 대답을 수정하겠습니다 ... – torek
아, 그리고 :'git reset HEAD ~ 2'를 "두 걸음 뒤로"이동 시키려면, 이것은 정말 자식에게 말하고 있습니다 : "내가 지금 가고있는 가지의 끝을 설정하십시오"- 아마도 이것은 당신의' 개발 "-"HEAD ~ 2를 보면서 얻을 수있는 커밋 ID로 이동 " 커밋이 무엇인지 확인하려면 'git show HEAD ~ 2'를 먼저 실행하십시오. 위의 그림에서'M'을 선택하면'HEAD ~ 2'는'M'과'C * '를 모두 백업하는'M ~ 2'입니다. 아마도 당신이 원하는 것이 아닙니다. – torek