【问题标题】:Reset all branches of a local repo to be the same as remote将本地 repo 的所有分支重置为与远程相同
【发布时间】:2016-07-01 08:54:11
【问题描述】:

首先这是不同的,因为这是针对所有分支而不是一个。 (我发现的所有这些一次只指定一个分支)

我在一个有大约 20-30 个分支的 repo 上工作(我知道我知道长故事不好的做法)

无论如何,我正在使用 git bfg 清理器删除一些旧的提交,在使用它之后,您需要删除并重新克隆代码或重置每个分支。

我知道如何设置分支

git fetch origin
git reset --hard origin/master

但是有没有办法用一个命令重置每个分支,还是我必须一次执行一个分支?

我有很多本地文件被忽略,我不想处理复制和重写。 (如 IDE 文件、计算机配置文件等)

【问题讨论】:

标签: git github branch bfg-repo-cleaner


【解决方案1】:

首先这是不同的,因为这是针对所有分支而不是一个

你可以使用一个脚本来遍历你的分支,然后在每个分支上做你想做的事情:

# Loop on all the desired branches
for ref in $(git branch -a)
do
   # ... DO ANYTHING YOU NEED HERE
   # You have the $ref which stores the branch name
   # ex: remotes/origin/master
done

有没有更好更简单的解决方案?

是的,只需再次克隆项目,您将拥有与源相同的内容。
这正是您为每个分支手动执行的操作。


注意:

您可以使用此命令一次获取所有数据:

# Fetch all remotes, branches and remove deledted content
git fetch --all --prune

【讨论】:

  • 我有大量的本地文件,通过再次克隆它会被删除,这比仅仅通过 30 个分支需要更多的工作
  • 好的,你可以使用 loopp 脚本了。这将完成工作
  • git 1.9.1 告诉我“fetch --all 不接受存储库参数”;应该是git fetch origin --prune
【解决方案2】:

为什么不直接删除所有本地分支,然后每当远程分支重新签出时,您就会被同步?

 # BE CAREFUL!!!
 # THIS COMMAND WIPES OUT ALL LOCAL BRANCHES
 ​git branch | xargs git branch -D

xargs 针对标准输入的每一行运行提供的命令,在本例中,针对原始“git branch”命令的每一行执行“git branch -D”。

当前分支的“git branch -D”命令将失败,但所有其他分支都会被清除。

或者,您可以使用“xargs”运行“git branch -f”来强制将每个本地分支设置为其远程副本,但我认为上面的“git branch -D”方法是最简单的,并且就后果和潜在危害而言,也是最直接的。

【讨论】:

  • git 分支将在本地结帐分支上工作。 git branch -agit branch -r 将适用于所有分支和远程分支
  • 是的,我认为 OP 只想重置本地分支
  • 旁注:你会得到当前分支的两个错误,一个来自*(无害,只是一个抱怨),一个是因为 git 不会让你删除你所在的分支站在。您需要git reset --hard 当前分支,或者进入分离的 HEAD 状态。总的来说,这是一个很好的解决方案,只要你不介意放弃你的 reflog。
【解决方案3】:

刚刚写了一个 small tool 来做这个。

此工具的优点:

  1. 在一个存储库中支持多个遥控器。
  2. 支持本地和跟踪分支使用不同的名称。
  3. 没有容易出错的正则表达式解析/编辑。

这是脚本:

#!/bin/bash

ENOENT=2
EEXIST=17

curref=$(git symbolic-ref HEAD 2>&-)

fetch_all() {
  git fetch --all
  ret=$?
  [ "$ret" -eq 0 ] || {
    return "$ret"
  }
}

hard_reset_all() {
  ret=0

  while read -r line; do
    branch=$(echo "$line" | cut -c 8- | rev | cut -c 8- | rev)
    remote=$(git config --local --get "branch.$branch.remote")
    upstream=$(git config --local --get "branch.$branch.merge" | cut -c 12-)

    if ! git rev-parse --verify --quiet "$remote/$upstream" 1>&- 2>&-; then
      ret=$(( $ret | $ENOENT ))
      echo "Branch $branch"
      echo "  skipped: upstream is absent"
      continue
    fi

    if [ -z "$(git log --oneline -1 "$branch...$remote/$upstream")" ]; then
      continue
    fi

    echo "Branch $branch"

    echo "  $(git log --oneline -1 $branch)"
    if [ "refs/heads/$branch" = "$curref" ]; then
      git reset --hard "$remote/$upstream" 1>&- 2>&-
    else
      git update-ref "refs/heads/$branch" "$remote/$upstream" 1>&- 2>&-
    fi
    echo "  -> $(git log --oneline -1 $remote/$upstream)"
  done < <(git config --local --name-only --get-regex '^branch.*remote$')

  return "$ret"
}

fetch_all
excode=$?
[ "$excode" -eq 0 ] || {
  exit "$excode"
}

if output=$(git status --porcelain) && [ -n "$output" ]; then
  echo "Skipped: repo is not clean"
  exit $EEXIST
fi

hard_reset_all
excode=$?
[ "$excode" -eq 0 ] || {
  exit "$excode"
}

【讨论】:

    【解决方案4】:

    您可以使用以下oneliner(基于that other answer):

    git branch --format='%(refname:short)' | xargs -i sh -c "git checkout {} &amp;&amp; git reset --hard origin/{}"

    • --format='%(refname:short)'git branch 中删除了烦人的 *
    • -i 允许使用 {} 作为分支的占位符

    警告:我没有经常使用该命令,因此它可能并不完全安全,如果您想让它更安全,请参阅that answer

    【讨论】:

      【解决方案5】:

      完全删除目录,然后克隆存储库。

      rm -R repodir
      git clone https://github.com/repodir/repodir
      

      【讨论】:

        猜你喜欢
        • 2013-11-15
        • 2022-11-05
        • 2017-11-03
        • 2021-09-23
        • 2013-06-09
        • 1970-01-01
        • 2010-09-27
        • 2018-04-27
        • 1970-01-01
        相关资源
        最近更新 更多