首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >是否有办法清除指向远程上不存在的分支的本地“工作树”文件夹?

是否有办法清除指向远程上不存在的分支的本地“工作树”文件夹?
EN

Stack Overflow用户
提问于 2022-10-29 09:14:56
回答 2查看 39关注 0票数 2

我非常喜欢git worktree命令。我的项目目录包含许多文件夹,这些文件夹指向我目前正在处理的分支。

代码语言:javascript
运行
复制
.../project directory                
├── bugfix             
│   ├── IBD-15         
│   ├── IBD-17         
│   ├── IBD-18         
│   ├── IBD-21         
│   ├── IBD-22         
│   └── IBD-23  
...       
├── main             
└── story              
    ├── logs           
    └── IBD-7      
                       
X directories         

经过一段时间,我通过使用CI工具的合并请求(CI自动删除远程分支)关闭了一个特性。但是特性分支在项目文件夹中保持活动状态,我需要定期查看关闭的特性列表,并手动删除指向远程上不存在的分支的文件夹:

代码语言:javascript
运行
复制
$ rm -rf bugfix/IBD-15
$ rm -rf bugfix/IBD-23
...
$ git worktree prune

那么,是否有一种方法可以使工作树文件夹用于分支,这些分支在remote上已经不存在了(当然,如果'worktree‘文件夹不包含未推送、提交或未跟踪的本地更改)?

EN

回答 2

Stack Overflow用户

发布于 2022-10-29 10:25:07

我刚刚测试了git fetch --prune之后发生的关于现有工作树的事情。

一个git branch -avv将显示:

代码语言:javascript
运行
复制
+ ee                    60f5e46 (C:/Users/vonc/git/tests/b2/ee) [origin/ee: gone] Move...

这意味着你可以做这样的事情:

代码语言:javascript
运行
复制
git branch -avv|grep ": gone"|cut -f 2 -d '('|cut -f 1 -d ')'|xargs git worktree remove

你所有过时的工作树都会消失。一条龙。

票数 1
EN

Stack Overflow用户

发布于 2022-11-01 10:38:35

我为周末编写了一个交互式bash脚本,它遍历所有的工作树文件夹,并要求用户删除该文件夹。脚本检查工作树文件夹中是否存在上游分支是否存在远程或未受惩罚的提交。您需要从任何工作树文件夹中运行脚本,它将完成它的工作。

代码语言:javascript
运行
复制
#!/usr/bin/env bash
# filename: worktree-cleanup
#
# get rid 'worktree' folders which branches doesn't exists 
# This script automatically walks through all wortree folders
# and ask for removing them
#
CUR_DIR=$(pwd)

function pushd {
  command pushd "$@" > /dev/null
}

function popd {
  command popd "$@" > /dev/null
}

function locate_git_tool {                         
  for path in ${PATH//:/ }; do                     
    [ -x "$path/git" ] && echo "$path/git" && break
  done                                             
  echo ""                                          
} # end of function locate_git_tool                

function git_fetch {
  $GIT_TOOL fetch --all
}

function contains_untracked_changes {
  local dir=$1
  pushd "$dir"
  local status="$($GIT_TOOL status --short)"
  popd
  echo "$status"
} # end of function contains_untracked_changes

function is_git_dir {
  local dir="$1"
  pushd "$dir"
  [ -d "$dir" ] && [ -d "$dir/.git" -o -e "$dir/.git" ] 
  popd
} #end of function is_git_dir

function is_dir_exist {
  [ -e "$@" -a -d "$@" ]
} # end of function is_dir_exist

function is_current_dir {
  [ "$CUR_DIR" == "$@" ]
}

function choose {
  local default="$1"
  local prompt="$2"
  local choice_yes="$3"
  local choice_no="$4"
  local answer

  read -p "$prompt" answer
  [ -z "$answer" ] && answer="$default"

  case "$answer" in
    [yY1] ) eval "$choice_yes"
      ;;
    [nN0] ) eval "$choice_no"
      ;;
    *     ) printf "%b" "Unexpected answer '$answer'!" >&2 ;;
  esac
} # end of function choose

function contains_unpushed_commits {
  pushd "$@"
  local output=$(git log @{u}.. -p)
  popd
  echo "$output"
}

function is_upstream_branch_exists {
  local path="$1"
  local branch="$2"
  pushd "$path"
  local output=$(git ls-remote --heads --quiet | grep 'branch')
  popd
  echo "$output"
}

function cleanup_worktree_folder {
  local path="$1"

  choose "y" \
    "Remove $path? (y or n)" \
    "$GIT_TOOL worktree remove --force \"$path\"" \
    ":"
}

function check_and_cleanup_forlder {
  local path="$1"
  local branch="$2"

  if [ ! -z "$(contains_untracked_changes $path)" ] ; then
    printf "%s\n%s\n" "Warning: $path contains changes" "$(contains_untracked_changes $path)"
    cleanup_worktree_folder "$path"
  elif [ -z "$(is_upstream_branch_exists $path $branch)" ] ; then
    printf "%s\n" "Warning: $path doesn't have upstream branch"
    cleanup_worktree_folder "$path"
  elif [ ! -z "$(contains_unpushed_commits $path)" ] ; then 
    printf "%s\n%s\n" "Warning: $path" "$(contains_unpushed_commits $path)"
  else 
    cleanup_worktree_folder "$path"
  fi
}

GIT_TOOL=$(locate_git_tool)
[ -x "${GIT_TOOL}" ] || { printf "%b" "Fatal: 'git' tool not found.\n" ; exit 1 ; }
[ -d "$CUR_DIR/.git" -o -e "$CUR_DIR/.git" ] || { printf "%b" "Fatal: not a git repository.\n" ; exit 1 ; }

git_fetch

IFS=$'\n'       
for line in $($GIT_TOOL worktree list) ; do
  path=$(echo $line | awk '{print $1}')
  branch=$(echo $line | awk '{print $3}')
  branch="${branch%]}"
  branch="${branch#[}"
  if ! $(is_dir_exist "$path") ; then 
    echo "$path not exists"
  elif $(is_current_dir "$path") ; then
    :
  elif ! $(is_git_dir "$path") ; then 
    printf "%b" "Warning: not a git repository. Skip.\n" 
  else 
    check_and_cleanup_forlder "$path" "$branch"
  fi
done
unset IFS

您可以找到脚本这里

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74244099

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档