git remote prune,git prune,git fetch --prune等有什么区别

时间:2013-11-20 20:49:56

标签: git remote-branch

我的情况就是这样......在同一个回购工作的人从他的本地&上删除了一个分支。远程回购...

大多数在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':

的部分中

为什么?

4 个答案:

答案 0 :(得分:563)

我不会因为对此感到沮丧而责怪你。最好的方法是看这个。每个远程分支可能有三个版本:

  1. 远程存储库上的实际分支
     (例如,https://example.com/repo.gitrefs/heads/master
  2. 上的远程回购
  3. 您在本地的分支快照(存储在refs/remotes/...下)
     (例如,本地回购,refs/remotes/origin/master
  4. 可能正在跟踪远程分支的本地分支
     (例如,本地回购,refs/heads/master
  5. 让我们从git prune开始吧。这将删除不再被引用的对象,它不会删除引用。在您的情况下,您有一个本地分支。这意味着有一个名为random_branch_I_want_deleted的引用,它引用了一些表示该分支历史的对象。因此,根据定义,git prune不会删除random_branch_I_want_deleted。实际上,git prune是一种删除Git中累积但未被任何内容引用的数据的方法。一般来说,它不会影响您对任何分支的看法。

    git remote prune origingit fetch --prune都对refs/remotes/...下的引用进行操作(我将这些引用称为远程引用)。它不会影响本地分支机构。如果您只想删除特定远程下的远程引用,则git remote版本非常有用。否则,两者完全一样。因此,简而言之,git remote prunegit fetch --prune对上面的数字2进行操作。例如,如果您使用git Web GUI删除了分支,并且不希望它再次显示在您的本地分支列表中(git branch -r),那么这就是您应该使用的命令。

    要删除本地分支,您应该使用git branch -d(如果未在任何地方合并,则使用-D)。 FWIW,如果远程分支消失,则没有git命令自动删除本地跟踪分支。

答案 1 :(得分:50)

git remote prunegit fetch --prune执行相同的操作:正如您所说,将refs删除到遥控器上不存在的分支。第二个命令连接到远程并在修剪之前获取其当前分支。

但是,它不会触及您已检出的本地分支,您只需使用

删除即可
git branch -d  random_branch_I_want_deleted

如果分支未在别处合并,则将-d替换为-D

git prune做了不同的事情,它清除了无法访问的对象,那些在任何分支或标记中都无法访问的提交,因此不再需要了。

答案 2 :(得分:13)

请注意,git remote --prunegit fetch --prune之间的差异由commit 10a6cc8修复Tom Miller (tmiller)(对于git 1.9 / 2.0,2014年第1季度):

  

当我们有一个名为“frotz/nitfol”的远程跟踪分支时,,而上游现在有一个名为“** frotz ”的分支**,{{1无法从上游删除带有“fetch”的“frotz/nitfol”   git会通知用户使用“git fetch --prune”来解决问题。

所以:当 upstream repo 有一个与 branch hierarchy 同名的分支(“frotz”)时(“frotz / xxx” “,可能branch naming convention),git remote prune正在成功(从您的仓库中清理远程跟踪分支),但git remote --prune失败了。

不再:

  

通过在提取操作之前移动修剪操作来更改“git fetch --prune”的工作方式   这样,它不会警告用户冲突,而是自动修复它。

答案 3 :(得分:11)

如果有人会感兴趣的话。这是一个快速shell脚本,它将删除所有未远程跟踪的本地分支。需要注意的是:无论是否合并,都将删除任何未被远程跟踪的分支。

如果你们发现任何问题请告诉我,我会解决它(等等)

将其保存在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 $@