git push-리스와 포스 대-포스


182

나는 차이점을 이해하려고 노력하고있다.

git push --force

git push --force-with-lease

내 추측은 원격에 로컬 분기가없는 커밋이없는 경우 후자가 원격으로 푸시 한다는 것입니다 .


"로컬 원격 추적 지점 " 기본적으로 리모컨은 클라이언트가 원하는 모양과 같아야합니다. git help push의 목적을 설명하는 유스 케이스가 있습니다 (기본적으로 누군가가 방금 밀어 낸 변경 사항을 휴지통에 버리지 않도록). 약간 불분명 한 것은 원격 추적 지점의 작동 방식입니다. 그러나 아마도 일반적으로 지난 번에 fetch또는 pull새로운 커밋없이 마지막으로 어떻게 보 였는지 정확하게 볼 필요 가 있습니다.
zzxyz

4
@zzxyz : 실제 구현은 --force-with-lease최신 CPU의 비교 및 ​​스왑 명령의 구현과 유사합니다. 스왑을 원하는 사람은 예상 값과 새 값을 제공합니다. 스왑을 수행하는 시스템은 예상 값을 실제 현재 값과 비교하고 둘이 동일한 경우에만 스왑을 수행합니다. 로 git push예상 값은 원격 추적 이름에있는 값입니다. 예를 들어, 원하는 새 값과 함께 git push --force-with-lease origin X자신 origin/X을 보냅니다 . originGit은 교환 여부를 알려줍니다.
torek

1
Git at origin교환이 완료되면 완료된 것입니다. 그렇지 않은 경우 실행 git fetch origin하여 현재 값 을 선택하고 필요한 경우 변경 사항을 재 작업 한 후 임대와 비교 및 ​​스왑을 다시 실행하여 다시 시도 할 수 있습니다.
torek

답변:


172

force 원격 지점을 로컬 지점으로 덮어 씁니다.

--force-with-lease더 많은 커밋이 원격 지사에 추가 된 경우 (다른 팀 구성원이나 동료 또는 다른 사용자가) 지사에 대한 작업을 덮어 쓰지 않는보다 안전한 옵션입니다. 강제로 밀어서 다른 사람의 작업을 덮어 쓰지 않도록합니다.

나는 명령을 둘러싼 일반적인 생각이 맞다고 생각합니다. 원격 지사가 로컬 컴퓨터의 원격 지사와 동일한 값을 갖는 경우 원격을 덮어 씁니다. 값이 같지 않으면 코드 작업 중에 다른 사람이 원격 지사에서 변경 한 것을 나타내므로 코드를 덮어 쓰지 않습니다. 분명히 원격에 추가 커밋이 있으면 값이 동일하지 않습니다.

--force-with-lease팀원 코드를 덮어 쓰지 않도록 할 때 사용할 옵션으로 생각 합니다. 회사의 많은 팀 --force-with-lease이 안전 장치의 기본 옵션으로 사용 합니다. 대부분의 상황에서 불필요하지만 다른 사람이 원격에 기여한 것을 덮어 쓰면 두통을 많이 줄입니다.

나는 당신이 문서를 보았을 것이라고 확신하지만 여기에 더 많은 설명이 포함될 수 있습니다.

https://git-scm.com/docs/git-push


38

신뢰할 수있는 공식 출처에서 답변을 찾고 있습니다.

의견그의 다른 답변 에서 torek 이 언급 한 "비교 및 교환" 은 Git 자체출처에 의해 더 설명 됩니다 .

후자는 원격에 로컬 브랜치에없는 커밋이없는 경우에만 원격으로 푸시합니까?

이 기능은 이 커밋 에 도입되었습니다 (2013 년 12 월, Git v1.8.5-rc0)

--force-with-lease 달리 명시되지 않는 한, 현재 값이 합리적인 기본값과 동일하도록 요구하여 업데이트 될 모든 원격 참조를 보호합니다.

현재로서는 "일부 합리적인 기본값"을 " 업데이트중인 원격 참조에 대한 원격 추적 분기의 값 "으로 임시로 정의하고 있으며, 이러한 원격 추적 분기가없는 경우 오류가 발생합니다.

따라서 "임대"는 다음을 의미합니다.

" force-with-lease": 리베이스 내역을 가져 오기 위해 가져 왔을 때 심판에 임대를했다고 가정하고 임대가 중단되지 않은 경우에만 되돌릴 수 있습니다.

소스는 여전히 "cas"를 언급합니다.

  • 이 옵션은 원래 " cas"( "비교 및 스왑"의 경우) 라고 불 렸습니다 . 너무 기술적이기 때문에 아무도 좋아하지 않는 이름입니다.
  • 두 번째 시도는 "lockref"라고 불렀지 만 (잠금 후 푸시하는 것과 같은 개념이기 때문에) "lock"이라는 단어는 다른 사람의 푸시를 거부 할 수 있기 때문에 미워했습니다.
  • 이 라운드는 "리스 임대"라고합니다.
    가져 와서 리베이스 히스토리가 무엇인지 결정하기 위해 심판에서 임대를했다고 가정하고 임대가 중단되지 않은 경우에만 되돌릴 수 있습니다.

" git push --force-with-lease--force"

" push --force-with-lease기본적으로 " 에서 언급했듯이 Git 2.13 (Q2 2017)에서 언급 했듯이 백그라운드 프로세스 (Git 플러그인이있는 IDE에서 찾은 프로세스와 같은)가 실행되면 이 옵션 --force-with-lease무시할 수 있습니다 git fetch origin.
이 경우에 --force우선합니다.


29

git push --force 는 원격 저장소를 로컬에있는 것으로 무조건 덮어 쓰기 때문에 파괴적입니다. git의 push --force 는 이미 공유 저장소에 푸시 된 다른 커밋을 파괴 할 수 있으므로 권장하지 않습니다. 힘 푸시의 가장 일반적인 원인 중 하나는 지점을 리베이스해야 할 때입니다.

예를 들어. Alice와 Bob이 작업 할 기능 분기가있는 프로젝트가 있습니다. 그들은이 저장소를 복제하고 작업을 시작합니다. Alice는 처음에 기능의 일부를 완성하고이를 기본 리포지토리로 푸시합니다. 이 모든 것이 좋고 좋습니다. 밥은 또한 그의 작업을 마치지만, 밀어 붙이기 전에 일부 변경 사항이 마스터로 병합되었음을 알 수 있습니다. 깨끗한 나무를 유지하기 위해 마스터 브랜치에 대해 리베이스를 수행합니다. 물론, 그는이 rebased branch를 푸시하려고 할 때 거부됩니다. 그러나 Alice가 이미 자신의 작업을 추진했다는 사실을 알지 못했지만 그는 추진력을 발휘합니다. 불행하게도, 이것은 중앙 저장소에서 Alice의 모든 변경 기록을 삭제합니다.

무엇 --force-와-임대가 하는 일은 우리가 기대하는 상태가 아닌 지점을 업데이트하는 쓰레기입니다; 즉, 아무도 업스트림 지점을 업데이트하지 않았습니다. 실제로 이것은 참조가 해시이기 때문에 업스트림 참조가 예상 한 것인지 확인하고 부모 체인을 암시 적으로 값으로 인코딩함으로써 작동합니다.

다음 은 git push --force 및 git push --force-with-lease에 관한 좋은 게시물입니다.


2
내가 이해하지 못하는 것-당신이 master와 rebase하면, 당신은 없이 밀어 넣을 수 있어야 --force-with-lease합니까? --force-with-lease마스터와의 관계를 유지 한 후에 왜 필요한가 ?
Alexander Mills

3
@AlexanderMills 문제를 일으킬 가능성이있을 수 있습니다. 당신이 이것을 마스터하도록 강요하는 마지막 사람이라면 아무런 문제가 없지만 다른 일을하는 다른 사람이 있다면 심각한 문제를 일으킬 수 있습니다. 처음에 A-B-C가 마스터에 있다고 말하고, 처음에 Alice가 그것을 A-B-C-D-E로 만들고 동시에 Bob이 그것을 A-B-C-F-G로 만듭니다. Alice가 마지막 사람이라면 푸시 A-B-C-D-E-F-G를 리베이스 한 후 마스터에서 아무런 문제가 발생하지 않지만 다른 사람 Tom은 마스터 재난시 동시에 A-B-C-D-E-R을 푸시하려고 시도합니다! !
Shakil

3
--force커밋을 잃지 않고 그냥 분리합니다. 원격 저장소의 관리자가 GC 또는 정리 작업을 수행하지 않는다고 가정 git checkout <SHA>하거나 또는 에서와 같이 해시로 부활 할 수 있습니다 git reset --hard <SHA>.
Keith Russell

1
"git의 push --force는 이미 공유 리포지토리에 푸시 된 다른 커밋을 삭제할 수 있으므로 권장하지 않습니다." 강제 푸시는 일반적인 git rebase 코드 검토 워크 플로우의 일부입니다. 또한 이미 언급 했듯이이 작업을 수행 한 후에도 커밋을 검색 할 수 있습니다.
에티엔

9

서버의 사전 수신 후크가 푸시를 승인한다고 가정하면 항상 성공합니다.

git push --force

진행하기 전에 특정 클라이언트 측 검사를 실행하는 반면 :

git push --force-with-lease

특정 확인을 직접 실행할 수 있습니다. "임대 점검"알고리즘은 다음과 같습니다.

  1. 현재 지점을 파악하십시오.

  2. 를 실행하십시오 git for-each-ref refs/remotes. git 클라이언트가 현재 브랜치의 업스트림 상태에 해당한다고 생각하는 commit-id를 기록하십시오.

예를 들어, "foo"분기에있는 경우 "refs / remotes / origin / foo"와 연관된 commit-id를 기록하십시오.

  1. 지금 업스트림 git 서버에서 원격 브랜치의 실제 commit-id를 결정하십시오.

  2. 2 단계와 3 단계에서 추출한 commit-id가 일치하는 경우에만 "git push"를 진행하십시오. 즉, 로컬 git clone의 업스트림 개념이 실제 업스트림과 일치하는 경우에만 진행하십시오.

여기에는 슬픈 의미가 있습니다. git fetch"refs / remotes / origin / *"아래의 모든 참조를 최신 버전으로 업데이트하므로이 명령 조합은 기본적으로 다음과 같습니다 git push --force.

git fetch

# The command below behaves identically to "git push --force"
# if a "git fetch" just happened!

git push --force-with-lease

이 본질적인 약점을 해결하기 위해 git push --force-with-lease나는 결코 도망치려 고하지 않는다 git fetch. 대신 참조 / 원격에서 단일 참조 만 업데이트하므로 "임대"를 유용하게 유지하기 git pull --rebase때문에 항상 업스트림과 동기화해야 할 때마다 실행 git pull됩니다 --force-with-lease.


1
수표가 고객 측인 경우 경쟁 조건이 발생할 가능성이 있습니까? 즉, 다른 사람은 확인 후 강제 푸시 전에 변경 사항을 푸시합니까?
craq

2

임대 계약은 반드시 안전 할 필요는 없습니다. Sylvie가 말한대로 작동합니다. 참고 사항 : 자식에서 분기는 커밋의 포인터 일뿐입니다. 그리고 커밋은 0 개 이상의 부모 커밋을 가리 킵니다. 하드 git 리셋과 강제 푸시 또는 원치 않는 강제 푸시로 분기를 완전히 변경하더라도 큰 문제는 아닙니다. 로컬 git reflog를 사용하여 브랜치의 로컬 팁 (그 당시 HEAD는 어디에 있었습니까?)이 어떻게 바뀌 었는지 확인하고 브랜치를 다시 푸시 할 수 있습니다. 그런 다음 원격 지점에서 새 커밋 만 잃지 만 팀 구성원이 복원 할 수도 있습니다.

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