Git에서 내 마스터 브랜치가 "이미 최신 상태"라고 말하는 이유는 무엇입니까?


118

기본적인 문제

내 프로젝트의 파일에서 모든 코드를 삭제하고 로컬 git에 변경 사항을 커밋했습니다. 나는했다

git pull upstream master

업스트림에서 가져오고 병합합니다 (이론상 삭제 된 코드는 다시 있어야 함).

Git은 모든 것이 최신 상태라고 알려줍니다.

모든 것이 최신 상태가 아닙니다. 삭제 된 모든 코드는 여전히 삭제됩니다.

기타 관련 정보

"마스터"라는 브랜치가 하나뿐입니다.

최근에 다음과 같이 업스트림을 추적하도록 "마스터"를 설정했습니다.

업스트림에서 원격 분기 마스터를 추적하도록 설정 한 분기 마스터.

명령 git branch -vv은 다음을 생성합니다.

* master 7cfcb29 [upstream/master: ahead 9] deletion test

왜 이런 일이 발생합니까? 코드에 대한 변경 사항을 프로젝트 관리자에게 전자 메일로 보내기 직전입니다.

최신 정보

나는 그것이 명백하다고 생각했지만 어쨌든 이것이 내 목표입니다.

내 시스템에서 최신 코드를 가져옵니다.

내 분노를 실례합니다. 그런데 왜 그렇게 간단한 일이 그렇게 힘들어 야합니까?


1
소스를 삭제하면 git이 로컬 변경 사항 (이 경우 삭제)을 덮어 쓰지 않고 로컬 변경 사항을 덮어 쓰지 않는 간단한 "pull"을 사용해보십시오. 첫 번째 대답은 어떻게 할 수 있는지 정확하게 설명하는 것 같습니다.
CashCow 2011

답변:


209

나는 여기서 당신의 기본적인 문제는 당신이 git이하는 일과 그것이하는 이유를 오해하거나 오해하고 있다는 것입니다.

다른 저장소를 복제 할 때 git은 "저기"에있는 모든 항목의 복사본을 만듭니다. 또한 같은 "그들의"지점 라벨을 소요 master하고, "이름"에서 라벨의 복사본을 만드는 당신의 자식 트리 (일반적으로)입니다 remotes/origin/master(하지만 경우에 remotes/upstream/master). 대부분의 경우 remotes/부분도 생략 하므로 원본을 upstream/master.

이제 일부 파일을 변경하고 커밋하면 해당 변경 사항이있는 유일한 사람입니다. 한편 다른 사람들은 (당신이 복제 한) 원본 저장소를 사용하여 다른 복제를 만들고 그 복제를 변경할 수 있습니다. 물론 그들은 그들의 변화를 가진 유일한 사람들입니다. 하지만 결국 누군가가 ( "푸시"또는 패치 등을 통해) 원래 소유자에게 다시 보내는 변경 사항을 가질 수 있습니다.

git pull명령은 대부분 git fetch뒤에 git merge. 이 두 작업이 실제로 수행하는 작업을 이해해야하기 때문에 중요합니다.

git fetch명령은 복제 한 곳 (또는 가져올 장소로 설정 한 곳)으로 돌아가 "다른 사람이 추가하거나 변경하거나 제거한 새 항목"을 찾도록합니다. 이러한 변경 사항은 복사되어 이전에 가져온 내용의 복사본에 적용 됩니다 . 그것들은 당신 자신의 일에만 적용 되지 않습니다 .

git merge명령은 더 복잡하고 비스듬히가는 곳입니다. 그것이하는 일은 "당신이 당신의 사본에서 변경 한 것"을 "당신이 다른 누군가로부터 가져 와서 당신의 사본에 추가 된 것"과 비교하는 것입니다. 변경 사항과 변경 사항이 충돌하지 않는 것 같으면 merge작업이이를 하나로 묶어 개발과 개발을 함께 연결하는 "병합 커밋"을 제공합니다 (비록없는 매우 일반적인 "쉬운"경우가 있지만 변경하고 "빨리 감기").

지금 당신이 직면하고있는 상황은 당신이 변경하고 커밋 한 상황입니다 (사실 9 번, 따라서 "앞서 9") . 그들은 변경 하지 않았습니다 . 따라서 fetch성실하게 아무것도 가져 오지 않고 merge변경 사항이 없는 것을 가져오고 아무것도 하지 않습니다.

원하는 것은 "자신의"버전의 코드를 보거나 "재설정"하는 것입니다.

단순히보고 싶다면 해당 버전을 확인하면됩니다.

git checkout upstream/master

그러면 git에게 현재 디렉토리를 전체 이름이 실제로 인 브랜치로 이동하려고합니다 remotes/upstream/master. 마지막으로 실행 git fetch하고 최신 코드를 받았을 때의 코드가 표시됩니다.

자신의 변경 사항을 모두 버리고 싶다면 레이블 master이름을 지정해야하는 개정판에 대한 git의 아이디어를 변경 해야합니다. 현재 가장 최근 커밋의 이름을 지정합니다. 해당 지점으로 돌아 가면 :

git checkout master

그런 다음 git reset명령을 사용하면 "레이블을 이동"할 수 있습니다. 남은 유일한 문제는 (당신이 가진 모든 것을 버릴 준비가되어 있다고 가정 할 때) 레이블이 가리키는 위치를 찾는 것입니다.

git log7cfcb29영구적 인 (절대 변경되지 않는) 이름 인 숫자 이름을 찾을 수 있으며 이름 을 지정하는 다른 방법은 엄청나게 많지만이 경우에는 이름을 원합니다 upstream/master.

자신의 변경을 닦아 레이블을 이동하려면 (당신이 저지른 모든 것을 아주 잠시 동안 실제로 복구 할 수 있지만, 그렇게 할 많이 힘들어이 이후의 매우 확실) :

git reset --hard upstream/master

--hard주어진 커밋을 체크 아웃 한 후, 당신이하고있다 무엇을 쓸어 현재 지점 레이블을 이동하고 이눔 알려줍니다.

많은 일을 정말로git reset --hard하고 지우는 것은 드문 일이 아닙니다 . 보다 안전한 방법 (일부가 가치가 있다고 판단한 경우 해당 작업을 훨씬 쉽게 복구 할 수 있도록하는 방법)은 기존 브랜치의 이름을 바꾸는 것입니다.

git branch -m master bunchofhacks

그런 다음 master"tracks" 라는 이름의 새 로컬 브랜치를 만듭니다 (사람들을 혼란스럽게한다고 생각하므로이 용어가 마음에 들지 않지만 git 용어입니다 :-)) 원점 (또는 업스트림) 마스터 :

git branch -t master upstream/master

그런 다음 다음과 같이 할 수 있습니다.

git checkout master

마지막 세 개의 명령이 수행하는 작업 (단지 두 개의 명령을 만드는 단축키가 있음)은 기존 레이블에 붙여 넣은 이름을 변경 한 다음 새 레이블을 만든 다음 전환하는 것입니다.

무엇이든하기 전에 :

C0 -    "remotes/upstream/master"
    \
     \- C1 --- C2 --- C3 --- C4 --- C5 --- C6 --- C7 --- C8 --- C9    "master"

이후 git branch -m:

C0 -    "remotes/upstream/master"
    \
     \- C1 --- C2 --- C3 --- C4 --- C5 --- C6 --- C7 --- C8 --- C9    "bunchofhacks"

이후 git branch -t master upstream/master:

C0 -    "remotes/upstream/master", "master"
    \
     \- C1 --- C2 --- C3 --- C4 --- C5 --- C6 --- C7 --- C8 --- C9    "bunchofhacks"

다음 C0은 .NET Framework를 처음 수행했을 때 얻은 최신 커밋 (전체 소스 트리)입니다 git clone. C1에서 C9는 커밋입니다.

을했다면 마지막 사진이 git checkout bunchofhacks다음 git reset --hard HEAD^^과 같이 변경됩니다.

C0 -    "remotes/upstream/master", "master"
    \
     \- C1 --- C2 --- C3 --- C4 --- C5 --- C6 --- C7 -    "bunchofhacks"
                                                      \
                                                       \- C8 --- C9

그 이유는 즉 HEAD^^이름 (리셋이 될 것 바로 전에 현재 지점의 머리에서 개정이 최대 bunchofhacks)와 reset --hard다음 레이블을 이동합니다. 커밋 C8 및 C9는 이제 거의 보이지 않습니다 (reflog와 같은 것을 사용 git fsck하여 찾을 수 있지만 더 이상 사소한 것은 아닙니다). 레이블은 원하는대로 이동할 수 있습니다. 이 fetch명령은로 시작하는 항목을 처리합니다 remotes/. "yours"를 "theirs"와 일치시키는 것이 일반적 이지만 (그러므로 만약 remotes/origin/mauve당신이 당신의 이름을 붙인다면 mauve) "그들로부터"받은 커밋의 이름을 짓거나보고 싶을 때마다 "theirs"를 입력 할 수 있습니다. ( "하나의 커밋"은 전체 소스 트리임을 기억하십시오. 하나의 커밋에서 하나의 특정 파일을 선택할 수 있습니다. git show예를 들어,


12
나는 당신의 훌륭한 대답에서 많은 것을 배웠습니다. 그러나 업스트림 리포지토리가 현재 리포지토리보다 몇 번 커밋 된 경우 "귀하의 브랜치가 'origin / master'로 최신 상태입니다. '라는 git 상태 메시지를받는 이유에 대해 여전히 혼란 스럽습니다. git pull에 대한 최신 정보를 얻을 수 있지만 메시지에 최신 상태라는 메시지가 표시되면 가져와야한다는 것을 어떻게 알 수 있습니까?
Christopher Werby

@ChristopherWerby : git merge명령 줄 명령으로 실행중인 것 같습니다 (내가 직접 수행하는 작업이며 합리적인 방법입니다). 참고하지만 것을 git pull먼저 실행하여 시작되면 git fetch, 다음 실행 git merge(또는 git rebase대신 그렇게하도록 지시하는 경우). 병합 할 새 커밋을 실제로 가져 오는 것은 가져 오기 단계입니다 (또는 리베이스 전용).
torek

@torek git status업스트림 저장소가 현재 저장소보다 앞서 있는지 확인하는 데 사용할 수있는 이외의 명령 이 있습니까? 내가 함께 얻을 메시지 git status즉, "당신의 지사가 최신 '원산지 / 마스터'와"라고 내가하지 않는 경우 나, 최신 변경 사항을 가지고 생각으로 나를 혼란. 때로는 "origin / master is 5 commits before your branch"(패러 프레이징)와 같은 메시지를받습니다. 하지만 일관성이 없습니다.
Christopher Werby

1
이것은 git status즉각적 git fetch으로 100 개 이상의 객체를 끌어 내고 거의 100 개의 델타를 해결하고 몇 개의 새 브랜치와 몇 개의 새 태그를 언급하고 메인 (원격 추적) 브랜치 헤드 커밋-그리고 또 다른 git 상태가 경쾌하고 솔직하게 "귀하의 브랜치가 최신 상태입니다"라고 말합니다. 분명히 많은 것이 원산지에서 내려 왔지만 지점은 전후 모두 "원산지와 함께 최신 상태"였습니까?
NeilG 19

1
git pullgit fetch먼저 실행 한 다음 git merge(또는 선택한 다른 두 번째 명령). git fetch단계는 업데이트 당신 의 망할 놈의 메모리를 자신의 최대 호출하여 망할 놈의 상태를, 망할 놈을하고 그들로부터 새로운 것을 얻고. 당신은 git status그들의 망할 놈의 당신의 망할 놈의 메모리를 확인합니다.
torek

18

당신과 같은 문제가있었습니다.

나는 git status git fetch git pull했지만 내 지부는 여전히 원산지에 뒤쳐져 있었다. 폴더와 파일을 원격으로 푸시했고 웹에서 파일을 보았지만 내 로컬에서는 누락되었습니다.

마지막으로 다음 명령은 내 로컬의 모든 파일과 폴더를 업데이트했습니다.

git fetch --all
git reset --hard origin/master 

또는 지점을 원하는 경우

git checkout your_branch_name_here
git reset --hard origin/your_branch_name_here

1
감사! 이것은 실제로 작동했습니다. 브랜치 이름은 대소 문자를 구분합니다.
André Ramon 19

4

모든 프로젝트 파일 삭제와 같이 커밋 한 모든 변경 사항은 가져 오기 후에도 그대로 유지됩니다. 풀이하는 일은 다른 곳의 최신 변경 사항을 자신의 브랜치로 병합하는 것이며, 브랜치가 모든 것을 삭제 한 경우 업스트림 변경 사항이 삭제 한 파일에 영향을 미칠 때 기껏해야 병합 충돌이 발생합니다. 즉, 모든 것이 최신 상태입니다.

"모든 파일 삭제"대신에 원하는 결과를 설명하면 누군가 적절한 조치를 제안 할 수 있습니다.

최신 정보:

내 시스템에서 가장 최근의 코드 가져 오기

당신이 이해하지 못하는 것은 당신이 이미 가장 최근의 코드를 가지고 있다는 것입니다. 정말로 원하는 것이 마스터 브랜치에있는 다른 사람의 가장 최근 작업 을 보는 것이라면 다음과 같이하십시오 .

git fetch upstream
git checkout upstream/master

이것이 바로 자신의 작업을 (다시) 시작할 수있는 위치에 있지는 않습니다. 수행 한 작업을 실행 취소하거나 본인 또는 다른 사람이 변경 한 사항을 되 돌리는 방법을 알아야하는 경우 세부 정보를 제공하십시오. 또한 기본 목적을 오해하는 것처럼 보이기 때문에 버전 제어가 무엇인지 읽어보십시오.


사실 내 시스템에서 다른 사람의 코드의 최신 버전을 원합니다. 그러나이 두 명령은 그렇게하지 않았습니다. 내가 얻는 것은 "이미 분기 마스터에"입니다. 내 파일의 코드가 다른 사람의 코드를 반영하지 않습니다.
user1971506

죄송합니다 upstream/master. 내 대답을 업데이트했습니다.
Ryan Stewart

3

다른 포스터가 말했듯이 풀은 업스트림에서 저장소로 변경 사항을 병합합니다. 저장소에있는 항목을 업스트림에있는 항목으로 바꾸려면 몇 가지 옵션이 있습니다. 커프에서 벗어난 나는 함께 갈거야

git checkout HEAD^1  # Get off your repo's master.. doesn't matter where you go, so just go back one commit
git branch -d master  # Delete your repo's master branch
git checkout -t upstream/master  # Check out upstream's master into a local tracking branch of the same name

1

제공된 정보의 폭과 깊이 측면에서 가장 좋은 대답은 훨씬 낫지 만 문제가 거의 즉시 해결되기를 원하고 버전 제어의 기본 원칙 중 일부를 밟아도 괜찮다면 ...

  1. 마스터로 전환

    $ git checkout upstream master
    
  2. 원하지 않는 분기를 삭제하십시오. (참고 : 브랜치가 마스터보다 많은 커밋을 수행하므로 일반 -d 플래그 대신 -D가 있어야합니다.)

    $ git branch -d <branch_name>
    
  3. 새 브랜치 생성

    $ git checkout -b <new_branch_name>
    

1

이 답변 중 어느 것도 나를 위해 일하지 않았지만 다음 명령을 사용하여 문제를 해결할 수있었습니다.

git fetch origin

이것은 나를위한 속임수였습니다.


0

당신은 GitHub의에없는 로컬 파일이 아직 귀하의 경우 그냥 알려드립니다 git status말한다

지점이 '원산지 / 마스터'로 최신 상태입니다. 커밋 할 것이없고 트리를 깨끗하게

파일이있는 경우 발생할 수 있습니다. .gitignore

실행 해보세요

cat .gitignore 

이 파일이 거기에 표시되는지 확인합니다. 그것은 git이 원격으로 옮기고 싶지 않은 이유를 설명합니다.

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