git pull--rebase origin 개발 이해 및 사용

11598 단어 Git

일의 시작


선배: "git pull-rebase로"
나는 "네! (뭔지는 전혀 모르겠지만)"
리베이스에 대해 전혀 모르기 때문에 이참에 잘 보기로 했어요.

실제로 동작을 보세요.


실제적으로 팀 개발의 예로 확인해 보자.
로컬이 개발자 지점에서 피처/something-1 지점을 끊었다고 가정합니다. (원격으로 미루지 않았습니다.)

다른 한편, 원격에서 누군가가 작업을 하는 라식 요청이 통합된 상태이다.

이 상태에서 로컬 응용 프로그램으로 변경된 경우 git pullgit pull --rebase 이 어떻게 다른지 확인합니다.

git pull


리모트의 개발자 지점을pull합니다.
% git pull origin develop
git log를 통해 확인합니다.
% git log
commit 2076b38bd7801d0271485fdb3baed5b074769397 (HEAD -> feature/something-1)
Merge: a25f40f 2db3d26
Author: dys <[email protected]>
Date:   Sun Jul 14 16:50:20 2019 +0900

    Merge branch 'develop' of github.com:dys6/git-practice into feature/something-1

commit 2db3d260a29b2f44fcc72c716bc4d7ec972335a8 (origin/develop)
Merge: f1d0035 f4f2e6e
Author: dys <[email protected]>
Date:   Sun Jul 14 16:45:23 2019 +0900

    Merge pull request #1 from dys6/feature/something-2

    Implement something-2

commit f4f2e6efdad3aab6d7d5330bbdef7fd9abadf4bd
Author: dys <[email protected]>
Date:   Sun Jul 14 16:45:11 2019 +0900

    Implement something-2

commit a25f40faef493d2f4c0589d2ad8ed5027fb4756d
Author: dys <[email protected]>
Date:   Sun Jul 14 16:44:12 2019 +0900

    Implement something-1

commit f1d0035dee3a67d8f2ecd1d22bad2a31613298b2 (develop)
Author: dys <[email protected]>
Date:   Sun Jul 14 16:42:31 2019 +0900

    first commit

git pull --rebase


remote의 개발 지점에 대해pullreabse를 진행합니다.
% git pull --rebase origin develop
% git log
commit c7d2da23a86f81db2f5c01fa445b9fc604beba8d (HEAD -> feature/something-1)
Author: dys <[email protected]>
Date:   Sun Jul 14 16:44:12 2019 +0900

    Implement something-1

commit 2db3d260a29b2f44fcc72c716bc4d7ec972335a8 (origin/develop)
Merge: f1d0035 f4f2e6e
Author: dys <[email protected]>
Date:   Sun Jul 14 16:45:23 2019 +0900

    Merge pull request #1 from dys6/feature/something-2

    Implement something-2

commit f4f2e6efdad3aab6d7d5330bbdef7fd9abadf4bd
Author: dys <[email protected]>
Date:   Sun Jul 14 16:45:11 2019 +0900

    Implement something-2

commit f1d0035dee3a67d8f2ecd1d22bad2a31613298b2 (develop)
Author: dys <[email protected]>
Date:   Sun Jul 14 16:42:31 2019 +0900

    first commit

구체적으로 무엇이 다른가


그러나 git pull 합병 시fast forward를 진행할 수 있을 때 합병 제출은 일어나지 않는다.이번 예는nonfast forward입니다.

커밋 병합

git pull 때 "Merge branch'develop'of github.com:dys6/git-practice into feature/something-1"메시지가 제출되었습니다.한편 git pull --rebase 때는 발생하지 않았다.
그러나 git pull 합병 시fast-forward를 진행할 때 합병 제출은 일어나지 않는다.이번 예는non-fast-forward입니다.

something-1 제출 역사 위치 및 산열 값 실시

git pull에서 git log로 표시될 때 실제 제출 순서로 제출을 표시합니다.산열 값도 변하지 않았다.한편git pull --rebase에 따르면'Implement something-1'의 제출 산열 값은 a25f40faef493d2f4c0589d2ad8ed5027fb4756d에서 c7d2da23a86f81db2f5c01fa445b9fc604beba8d로 다른 제출 처리가 되었다.또 이력서의 위치도 시작이 된다.
원격에서 변경이 없는 상태git pull --rebase에서도 이력서는 변하지 않고 제출한 산열치도 변하지 않는다.

뭐 공부 해요?

git pull를 사용하여 자신의 업무 지점에 최신 개발자 지점의 변경을 적용하면 변경이 있을 때마다 통합된 제출이 발생합니다.최종적으로 개발자 지점에 합병하면 개발자의 역사를 더럽힐까요?됐어.사용git pull --rebase을 통해 불필요한 합병 제출 없이 이력서를 깨끗하게 유지할 수 있다.

실제 사용


git pull--rebase git push


기본적으로 자신의 지점에서 작업을 하고 제출한 후git push 이전git pull --rebase에 로컬에서 원격 변경을 적용하는 동시에 작업을 진행한다.
단, 원격으로 한 번 전송한 후 같은 지점에서 다시 제출하면 원격에 변경이 있는 상태git pull --rebase 이후에 시도git push하면 다음과 같이 욕을 먹는다.
% git push origin feature/something-3
To github.com:dys6/git-practice.git
 ! [rejected]        feature/something-3 -> feature/something-3 (non-fast-forward)
error: failed to push some refs to '[email protected]:dys6/git-practice.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
선배: "이럴 때는git push-force-with-lease를 사용하세요."
저는 "네! (전혀 모르지만)"
force 옵션은 매우 위험한 인상을 주고 전혀 사용하지 않았고 조사도 하지 않았기 때문에 이를 계기로 이해합니다.

도대체 왜 욕을 먹었을까.

git pull --rebase 때문에,fast-forward를 통해origin/feature/something-3을 업데이트할 수 없습니다.욕을 먹은 내용 중에는 git push --help도 있다. Note about fast-forwards에 관한 항목을 읽고 제출 이력을 잃지 않기 위해서도 fast-forward를 통해 로컬 변경을 가져와야 한다.
//git push-help 참조
When an update changes a branch (or more in general, a ref) that used to point at commit A to point at another commit B, it is called a fast-forward update if and only if B is a descendant of A.
지점 (일반적으로 ref) 이 제출 A에서 다른 제출 B로 바뀌었을 때, B가 A의 후손일 때만fast-forward 업데이트라고 합니다.
원격 상태에서 Fix something-3을 다시 제출하고 실행git pull --rebase하면 로컬 상태가 됩니다.

이때 something-3지점의 원격과 현지의 역사적 지점이 다르기 때문에 현지의 제출과 원격의 제출은 더 이상 자손 관계가 아니다.따라서fast-forward를 통해 업데이트할 수 없습니다. 앞에서 열거한 오류가 발생했습니다.

이러한 상황이 발생할 때, 다른 사람이 원격'Fix something-3'을 읽지 않았을 때만 실행할 수 있습니다 git push --force. 로컬 역사로 원격 역사를 덮어쓸 수 있습니다.
상황은 다르지만 git push --help 에는 다음과 같은 내용이 적혀 있다.
//git push-help 참조
There is another common situation where you may encounter non-fast-forward rejection when you try to push, and it is possible even when you are pushing into a repository nobody else pushes into.After you push commit A yourself (in the first picture in this section), replace it with "git commit --amend"to produce commit B, and you try to push it out, because forgot that you have pushed A out already. In such a case, and only if you are certain that nobody in the meantime fetched your earlier commit A (and started building on top of it), you can run "git push --force"to overwrite it. In other words, "git push --force"is a method reserved for a case where you do mean to lose history.
다른 사람이 같은 저장소로 미루지 않았더라도non-fast-forward가 거절할 수 있습니다.
A를 제출한 후 이를 잊어버리고'gitcommit--amend'로 B를 작성하고 제출할 때.이 경우, 이전의 제출 A를 받지 못한 사람이 확실할 때만 "gitpush-force"를 실행해서 덮어쓸 수 있습니다.다시 말하면'gitpush-force'는 역사를 잃는 것을 의미하는 일을 하기 위한 방법이다.

gitpush-force와gitpush-force-with-lease의 차이


둘 다 역사를 덮어쓰고 강제로 밀어붙인다는 점은 변하지 않았다.예를 들어feature/something-3에서 다른 사람도 일하고 있다고 가정하면'Fix something-3by otherperson'을 제출하고 원격으로 전송합니다.자신의 로컬에서 제출이 전송되기 전git pull --rebase.이 경우 git push --force 은 실행할 수 있지만 git push --force-with-lease 은 실행할 수 없습니다.실행git push --force하면 원격 "Fix something-3by other person"제출은 "Fix something-3"으로 덮어쓰지 않습니다.git push --force-with-lease 이를 막을 수 있을 것 같다.

//git push--help 참조
Usually, "git push"refuses to update a remote ref that is not an ancestor of the local ref used to overwrite it. This option overrides this restriction if the current value of the remote ref is the expected value. "git push"fails otherwise.
Imagine that you have to rebase what you have already published. You will have to bypass the "must fast-forward"rule in order to replace the history you originally published with the rebased history. If somebody else built on top of your original history while you are rebasing, the tip of the branch at the remote may advance with her commit, and blindly pushing with --force will lose her work.This option allows you to say that you expect the history you are updating is what you rebased and want to replace. If the remote ref still points at the commit you specified, you can be sure that no other people did anything to the ref. It is like taking a "lease" on the ref without explicitly locking it, and the remote ref is pdated only if the "lease"is still valid.
자꾸 force 옵션이 위험해요. 사용하면 안 돼요!이런 인식이지만 나만 일하는 지점, 필요한 부분을 덮어쓰고 싶을 때 등 적당한 장소에서 사용하면 위험하지 않다고 생각해요.

충돌!

% git pull --rebase origin develop
From github.com:dys6/git-practice
 * branch            develop    -> FETCH_HEAD
First, rewinding head to replay your work on top of it...
Applying: Implement something-6
Using index info to reconstruct a base tree...
Falling back to patching base and 3-way merge...
CONFLICT (add/add): Merge conflict in something-6.md
Auto-merging something-6.md
error: Failed to merge in the changes.
Patch failed at 0001 Implement something-6
hint: Use 'git am --show-current-patch' to see the failed patch
Resolve all conflicts manually, mark them as resolved with
"git add/rm <conflicted_files>", then run "git rebase --continue".
You can instead skip this commit: run "git rebase --skip".
To abort and get back to the state before "git rebase", run "git rebase --abort"
충돌이 잦지만 수동 해제git addgit rebase --continue만 하면 된다.왠지 엉망이야. 역시 포기하고 싶을 때 git rebase --abort 리베스 앞으로 돌아갈 수 있어.git rebase --skip 충돌이 해결된 후 원격의 최신 제출과 차이가 없음 git rebase --continue 을 사용할 수 없습니다.
% git add something-6.md
% git rebase --continue
Applying: Implement something-6
No changes - did you forget to use 'git add'?
If there is nothing left to stage, chances are that something else
already introduced the same changes; you might want to skip this patch.
Resolve all conflicts manually, mark them as resolved with
"git add/rm <conflicted_files>", then run "git rebase --continue".
You can instead skip this commit: run "git rebase --skip".
To abort and get back to the state before "git rebase", run "git rebase --abort"

마지막


나는 이해하는 것을 조심스럽게 썼지만, 틀리면 부드럽게 말해 주세요.

참고 문헌


리베이스 전에 메르지와fetch는 솔직히 잘 몰랐지만 여기를 보니 이해가 됐어요.이해하기 쉬워요. 많이 배웠어요!
  • git pull과 git pull – rebase의 차이점은?그림으로 설명!
  • 좋은 웹페이지 즐겨찾기