git remote prune, git prune, git fetch --prune 등의 차이점은 무엇입니까?


358

내 상황은 이것입니다 ... 같은 리포지토리에서 일하는 사람이 로컬 및 원격 리포지토리에서 지점을 삭제했습니다 ...

Stack Overflow 또는 다른 사이트에서 이러한 종류의 문제에 대해 질문 한 사람들은 대부분 git branch -a맨 아래 의 원격 추적 분기 목록 에 분기 문제가 여전히 표시됩니다 .

* master
  develop
  feature_blah
  remotes/origin/master
  remotes/origin/develop
  remotes/origin/feature_blah
  remotes/origin/random_branch_I_want_deleted

그러나 내 상황에서 거기에 없어야하는 지점은 로컬입니다.

* master
  develop
  feature_blah
  random_branch_I_want_deleted
  remotes/origin/master
  remotes/origin/develop
  remotes/origin/feature_blah

다음 중 하나를 수행하면 로컬로 제거되지 않습니다.

$ git prune

나는 또한 시도했다 :

$ git remote prune origin
$ git fetch --prune

더 유용한 정보 : 확인 git remote show origin하면 다음과 같습니다.

* remote origin
Fetch URL: utilities:homeconnections_ui.git
Push  URL: utilities:homeconnections_ui.git
HEAD branch: master
Remote branches:
 master                        tracked
 develop                       tracked
 feature_blah                  tracked
 other123                      tracked
 other444                      tracked
 other999                      tracked
Local branches configured for 'git pull':
 develop                      merges with remote develop
 feature_blah                 merges with remote other999
 master                       merges with remote master
 random_branch_I_want_deleted merges with remote random_branch_I_want_deleted
Local refs configured for 'git push':
 develop         pushes to develop     (local out of date)
 master          pushes to master      (up to date)
 feature_blah    pushes to feature_blah(up to date)

이 섹션은 제목이있는 섹션에만 있습니다. Local branches configured for 'git pull':

왜?


git branch -d the_local_branch
krsteeve

1
고맙지 만, 왜 그런 일이 있었는지 궁금합니다.
gogogadgetinternet

분기 계층 구조 ( x/y)를 다룰 때 미묘한 차이가있었습니다 : 수정되었습니다 ( 아래 답변 참조 )
VonC

답변:


664

나는 이것에 대해 좌절했다고 당신을 비난하지 않습니다. 가장 좋은 방법은 이것입니다. 모든 원격 지점에는 세 가지 버전이 있습니다.

  1. 원격 저장소에 실제 지점
    (예를 들어, 원격 REPO에서 https://example.com/repo.git , refs/heads/master)
  2. 로컬 해당 분기의 스냅 샷 (저장 아래 refs/remotes/...)
    (예를 들면, 지역의 repo, refs/remotes/origin/master)
  3. 그리고 원격 지점을 추적 할 수있는 로컬 지점
    (예 : 로컬 저장소 refs/heads/master)

로 시작하겠습니다 git prune. 이 제거합니다의 객체 참조되지 않게되고, 그것은 참조를 제거하지 않습니다. 귀하의 경우 지역 지점이 있습니다. 즉 random_branch_I_want_deleted, 해당 분기의 히스토리를 나타내는 일부 오브젝트를 나타내는 ref라는 이름 이 있습니다. 따라서 정의상을 git prune제거하지 않습니다 random_branch_I_want_deleted. 실제로 git pruneGit에 축적되었지만 아무 것도 참조하지 않는 데이터를 삭제하는 방법입니다. 일반적으로 지점에 대한 귀하의 견해에는 영향을 미치지 않습니다.

git remote prune origin그리고 git fetch --prune둘 다 아래의 참조에서 작동합니다 refs/remotes/...(이는 원격 참조라고 부릅니다). 현지 지사에는 영향을 미치지 않습니다. 이 git remote버전은 특정 원격에서 원격 참조 만 제거하려는 경우에 유용합니다. 그렇지 않으면 두 사람은 정확히 같은 일을합니다. 요컨대,git remote prune 그리고 git fetch --prune위의 2 번에서 작동합니다. 예를 들어, git web GUI를 사용하여 브랜치를 삭제했는데 더 이상 로컬 브랜치 목록에 표시하지 않으려면 ( git branch -r), 이것이 사용해야하는 명령입니다.

로컬 브랜치를 제거하려면 git branch -d(또는 -D병합되지 않은 경우) 를 사용해야합니다 . FWIW에는 원격 분기가 사라지면 로컬 추적 분기를 자동으로 제거하는 git 명령이 없습니다.


22
이것은 적절한 차이점을 설명함으로써 전반적인 문제를 해결하는 데 더 효과적입니다. 또한 위의 질문에서 얻은 추가 질문에 답변합니다.
gogogadgetinternet

14
이 명령은 해당 원격 분기가없는 모든 로컬 분기 목록을 표시합니다. 당신은 할 수 파이프 이것 xargs git branch -D만 참고 사용자가 만든 있지만 서버에 푸시 적이없는 새로운 지점이 삭제 될 수 있음을, 그래서 트레드주의 : git branch -r | awk '{print $1}' | egrep -v -f /dev/fd/0 <(git branch -vv | grep origin) | awk '{print $1}'
제이슨 월튼

4
@Seed 아니요 그렇지 않습니다. :-( 로컬 원격 추적 참조 만 삭제합니다. 방금 버전 2.7.0으로이를 다시 확인했습니다.
John Szakmeister

1
@ BlueRaja-DannyPflughoeft이 ​​접근 방식에주의하십시오. 예를 들어 안정적인 분기를 수행하는 방법에 따라 분기가 마스터 분기에 병합 된 것처럼 보일 수 있으며 결국 분기를 제거하게됩니다. 서버에서 제거하지 않기 때문에 큰 손실은 아니지만 지점에 대한 특별한 구성이 있으면 지점을 삭제할 때 손실됩니다.
John Szakmeister

1
@Cloud 완전히 사실이 아닙니다. 참조는 압축 될 수 있으므로 ( 영역 의 packed-refs파일 참조 .git) 반드시 파일 탐색기를 통해 삭제하는 간단한 문제는 아닙니다. 명령을 사용하여 둘 다 올바르게 관리되도록하는 것이 좋습니다.
John Szakmeister 19

55

git remote prunegit fetch --prune 당신이 말한대로, 원격에 존재하지 않는 지점에 심판을 삭제 : 같은 일을. 두 번째 명령은 리모트에 연결하고 정리하기 전에 현재 분기를 페치합니다.

그러나 체크 아웃 한 현지 지점을 만지지 마십시오.

git branch -d  random_branch_I_want_deleted

교체 -d-D 분기 다른 곳에서 병합되지 않은 경우

git prune 다른 것을 수행하고, 도달 할 수없는 객체, 분기 또는 태그에서 도달 할 수없는 커밋을 제거하여 더 이상 필요하지 않습니다.


1
나는 그것이 명백해 git prune보이지만 가지와 태그뿐만 아니라 다른 모든 참조도 찾습니다.

내 경우에는 왜 자두가 작동하지 않습니까? 로컬 브랜치가 아니라 원격 참조에 관심이 있기 때문에? 간결한 정보 주셔서 감사합니다.
gogogadgetinternet

@ hvd 브랜치와 태그 외에 어떤 종류의 참조가 있습니까?
CharlesB

@gogogadgetinternet 그렇습니다. (당신이 의미 랬 git remote prune)
CharlesB

4
IMO는 객체 수집 참조 정리 모두에 "prune"을 사용하는 git 명명 규칙이 혼동을 일으키는 곳입니다. 그러나 이것은 git의 많은 UI 퍼즐 중 하나 일뿐입니다. :-)
torek

14

누군가가 관심을 가질 경우. 원격으로 추적되지 않는 모든 로컬 브랜치를 제거하는 빠른 쉘 스크립트가 있습니다. 주의 사항 : 병합 여부에 관계없이 원격으로 추적되지 않는 분기를 제거합니다.

이 문제가 발생하면 알려 주시면 해결하겠습니다 (등 등).

파일을 호출하고 git-rm-ntb(무엇이든 호출) 다음을 PATH실행하십시오.

git-rm-ntb <remote1:optional> <remote2:optional> ...

clean()
{
  REMOTES="$@";
  if [ -z "$REMOTES" ]; then
    REMOTES=$(git remote);
  fi
  REMOTES=$(echo "$REMOTES" | xargs -n1 echo)
  RBRANCHES=()
  while read REMOTE; do
    CURRBRANCHES=($(git ls-remote $REMOTE | awk '{print $2}' | grep 'refs/heads/' | sed 's:refs/heads/::'))
    RBRANCHES=("${CURRBRANCHES[@]}" "${RBRANCHES[@]}")
  done < <(echo "$REMOTES" )
  [[ $RBRANCHES ]] || exit
  LBRANCHES=($(git branch | sed 's:\*::' | awk '{print $1}'))
  for i in "${LBRANCHES[@]}"; do
    skip=
    for j in "${RBRANCHES[@]}"; do
      [[ $i == $j ]] && { skip=1; echo -e "\033[32m Keeping $i \033[0m"; break; }
    done
    [[ -n $skip ]] || { echo -e "\033[31m $(git branch -D $i) \033[0m"; }
  done
}

clean $@

감사! 컬러 출력으로 멋진 터치 ;-)
BVengerov

2
병합 된 분기 만 삭제하는 것이 $ (git branch -d $ i) 더 안전하지 않습니까?
user2012677

너무 도움이 너무 감사합니다 !!!
로빈 하트 랜드


13

한가지 차이점 유의 git remote --prune하고 git fetch --prune함께 고정되는 10a6cc8를 저지 하여, 톰 밀러 ( tmiller) (자식 1.9 / 2.0, Q1 2014) :

frotz/nitfol이전 페치에서 " " 라는 원격 추적 분기가 있고 업스트림에 이제 "** frotz "** 라는 분기가 있으면 업스트림에서 fetch" frotz/nitfol"로 " " 를 제거하지 못합니다 git fetch --prune.
git은 사용자에게 " git remote prune"를 사용하여 문제를 해결 하라고 알려줍니다 .

따라서 업스트림 리포지토리에 브랜치 계층 구조 와 이름이 같은 브랜치 ( "frotz")가있는 경우 ( "frotz / xxx", 브랜치 명명 규칙 ), 리포지토리 git remote --prune에서 원격 추적 브랜치를 정리할 때 성공했습니다. 하지만git fetch --prune 실패했다.

더 이상 :

fetch --prune가져 오기 작업 전에 제거 작업을 이동하여 " "작동 방식을 변경하십시오 .
이런 식으로 사용자에게 충돌을 경고하는 대신 자동으로 수정합니다.

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