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

xjreopfe  于 2022-12-10  发布在  Git
关注(0)|答案(4)|浏览(456)

我的情况是这样的...在同一个回购协议上工作的人从他的本地和远程回购协议中删除了一个分支...
大多数在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 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':的部分中
为什么?

yruzcnhs

yruzcnhs1#

我并不责怪你对此感到沮丧。最好的方法是这样看的。每个远程分支可能有三个版本:
1.远程资源库上的实际分支
(e.g.,远程存储库位于https://example.com/repo.gitrefs/heads/master
1.您本地的该分支的快照(存储在refs/remotes/...下)
(e.g.,本地存储库,refs/remotes/origin/master
1.以及可能跟踪远程分支的本地分支
(e.g.,本地存储库,refs/heads/master
让我们从git prune开始。这将删除不再被引用的 objects,而不是删除引用。在您的例子中,您有一个本地分支。这意味着有一个名为random_branch_I_want_deleted的引用,它引用一些代表该分支历史的对象。因此,根据定义,git prune不会删除random_branch_I_want_deleted。实际上,git prune是一种删除Git中累积但没有被任何东西引用的数据的方法。一般来说,它不会影响你对任何分支的查看。
git remote prune origingit fetch --prune都在refs/remotes/...下的引用上操作(我将把这些称为远程引用)。它不影响本地分支。如果您只想删除特定remote下的远程引用,则git remote版本非常有用。否则,这两个版本做的事情完全相同。因此,简而言之,git remote prunegit fetch --prune的作用是执行上面的第二个命令。例如,如果你使用git web GUI删除了一个分支,并且不想让它再出现在本地分支列表中(git branch -r),那么你应该使用这个命令。
要删除本地分支,应该使用git branch -d(如果没有合并,则使用-D)。FWIW,没有git命令可以在远程分支消失时自动删除本地跟踪分支。

ca1c2owp

ca1c2owp2#

git remote prunegit fetch --prune执行相同的操作:第二个命令连接到远程节点并在修剪之前获取它的当前分支。
但是,它不会触及您已 checkout 的本地分支,您只需使用

git branch -d  random_branch_I_want_deleted

如果分支未在其他位置合并,则将-d替换为-D
git prune做了一些不同的事情,它清除不可达的对象,那些在任何分支或标记中都不可达的提交,因此不再需要。

v2g6jxz6

v2g6jxz63#

这里有一个快速的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 $@
qeeaahzv

qeeaahzv4#

请注意,git remote --prunegit fetch --prune之间的一个区别是commit 10a6cc8Tom Miller ( tmiller )修复了(对于git 1.9/2.0,Q1 2014):
当我们有一个名为“frotz/nitfol“的远程跟踪分支来自上一次提取时,并且上游现在有一个名为“frotz"的分支fetch将无法从上游移除带有“git fetch --prune“的“frotz/nitfol“。
git会通知用户使用“git remote prune“来修复问题。
因此:当一个**upstream repo**有一个分支(“frotz”)与一个 * branch hierarchy *(“frotz/xxx”,可能是一个branch naming convention)同名时,git remote --prune是成功的(从您的存储库中清除远程跟踪分支),但是git fetch --prune失败了。
不再是了:
通过将修剪操作移到提取操作之前来更改“fetch --prune“的工作方式。
这样,它不会警告用户发生冲突,而是自动修复冲突。
另一个不同之处:
在Git 2.39(Q4 2022)中,“git prune“(man)可能会尝试遍历.git/objects/pack以删除其中的垃圾文件,并在目录丢失时大声失败,这是不必要的。
司令部已经被教导要忽略这样的失败。
...而git fetch --prune在目录丢失时仍然会大声失败
2022年11月19日,Eric Wong ( ele828 )发布。
(2022年11月28日,由Junio C Hamano -- gitster --commit 7d7ed48中合并)
第1001章:缺少目录时执行quiet ENOENT
签署人:黄家辉
可以删除$GIT_DIR/objects/pack以将inode保存在共享存储库中。
$GIT_DIR/objects$GIT_DIR/objects/pack不存在的情况下执行静默清理,但在其他情况下发出系统错误,以帮助用户诊断权限问题或资源限制。
因此,当$GIT_DIR/objects$GIT_DIR/objects/pack丢失时,git修剪不会显示“无法打开目录...”。

相关问题