我的情况是这样的…某人在同一个回购上工作,已经从他的本地和远程回购中删除了一个分支…

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

然而,在MY的情况下,分支不应该在那里,是本地的:

* 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 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'的部分中:

Why?


当前回答

Git remote prune和Git fetch——prune做同样的事情:删除对远程上不存在的分支的引用,就像你说的那样。第二个命令连接到远程并在修剪之前获取其当前分支。

但是,它不会触及您已经签出的本地分支,您可以简单地删除它们

git branch -d  random_branch_I_want_deleted

如果分支没有在其他地方合并,则将-d替换为-d

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

其他回答

请注意,git remote -prune和git fetch -prune之间的一个区别正在被修复,commit 10a6cc8,由Tom Miller (tmiller)(用于git 1.9/2.0, 2014年第一季度):

当我们有一个远程跟踪分支命名为“frotz/nitfol”从以前的获取,而上游现在有一个分支命名为“frotz”,获取将无法删除“frotz/nitfol”与“git获取-修剪”从上游。 Git会通知用户使用“Git远程修剪”来解决这个问题。

所以:当上游回购有一个分支(“frotz”)与分支层次结构(“frotz/xxx”,一个可能的分支命名约定)同名时,git remote -prune是成功的(在清理远程跟踪分支从你的回购),但git fetch -prune是失败的。

不了:

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


另一个区别:

在Git 2.39 (Q4 2022)中,“Git prune”(man)可能会尝试遍历. Git /objects/pack以删除其中的垃圾文件,当目录丢失时,会大声失败,这是不必要的。 该司令部已被教导忽略此类失败。

... 当目录丢失时,git的fetch -prune仍然会大声失败

参见Eric Wong (ele828)提交6974765(2022年11月19日)。 (由Junio C Hamano - gitster -在commit 7d7ed48,2022年11月28日合并)

删除:删除丢失的目录 署名:Eric Wong

$GIT_DIR/objects/pack可以被删除以保存共享存储库中的inode。 在$GIT_DIR/objects或$GIT_DIR/objects/pack不存在的情况下停止修剪,但在其他情况下发出系统错误,以帮助用户诊断权限问题或资源限制。

因此,当$GIT_DIR/objects或$GIT_DIR/objects/pack丢失时,没有“无法打开目录…”

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

远程存储库上的实际分支 (例如,在https://example.com/repo.git, refs/heads/master远程回购) 本地分支的快照(存储在refs/remotes/…下) (例如,本地repo, refs/remotes/origin/master) 以及可能正在跟踪远程分支的本地分支 (例如,本地回购,refs/heads/master)

Let's start with git prune. This removes objects that are no longer being referenced, it does not remove references. In your case, you have a local branch. That means there's a ref named random_branch_I_want_deleted that refers to some objects that represent the history of that branch. So, by definition, git prune will not remove random_branch_I_want_deleted. Really, git prune is a way to delete data that has accumulated in Git but is not being referenced by anything. In general, it doesn't affect your view of any branches.

git remote prune origin and git fetch --prune both operate on references under refs/remotes/... (I'll refer to these as remote references). It doesn't affect local branches. The git remote version is useful if you only want to remove remote references under a particular remote. Otherwise, the two do exactly the same thing. So, in short, git remote prune and git fetch --prune operate on number 2 above. For example, if you deleted a branch using the git web GUI and don't want it to show up in your local branch list anymore (git branch -r), then this is the command you should use.

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

Git remote prune和Git fetch——prune做同样的事情:删除对远程上不存在的分支的引用,就像你说的那样。第二个命令连接到远程并在修剪之前获取其当前分支。

但是,它不会触及您已经签出的本地分支,您可以简单地删除它们

git branch -d  random_branch_I_want_deleted

如果分支没有在其他地方合并,则将-d替换为-d

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

如果有人感兴趣的话。下面是一个快速的shell脚本,它将删除所有不能远程跟踪的本地分支。提醒一句:无论是否合并,这将消除任何未被远程跟踪的分支。

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

将它保存在PATH上一个名为git-rm-ntb的文件中,然后运行:

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 $@