我遇到了类似的问题:
- 我想要一次同步所有本地跟踪分支
- 我希望此操作是安全的。换句话说,如果存在本地修改或分支分歧,请发出警告并不要触及历史记录(也不要篡改未提交的修改)
在寻找简单解决方案时,我最终使用了自己的解决方案(不是很简单),基于一系列 git 别名(代码添加到.gitconfig
文件中):https://gist.github.com/arnauldvm/dcec7ee043c25dce30dbae1b576f2102
⚠ 这是新代码,尚未经过严格测试。
用法:git sync
一些解释:
tracking = "!f() { git for-each-ref --format '%(refname:short):%(upstream:short)' 'refs/heads' | egrep -v ':$'; }; f"
→ 这将检索所有本地跟踪分支和相应的远程分支,使用冒号分隔。
is-clean-workdir = "!f() { git diff --stat --exit-code || { echo \"Workdir dirty\"; exit 1; }; }; f"
is-clean-index = "!f() { git diff --stat --cached --exit-code || { echo \"Index dirty\"; exit 2; }; }; f"
is-clean = "!f() { git is-clean-workdir && git is-clean-index; }; f"
→ 这将验证工作目录中是否有未决的更改。
co-merge = "!f() { local=\"$1\"; remote=\"$2\"; git checkout \"$local\"; git merge --ff-only \"$remote\"; }; f"
→ 这个命令需要传入两个参数(一个本地分支和一个远程分支),它会切换到本地分支并将其与远程分支合并。它使用--ff-only
来避免创建提交合并 ⇒ 如果本地分支与远程分支不一致,它将在标准错误流上发出“fatal: Not possible to fast-forward, aborting.” 的消息。
current-branch = rev-parse --abbrev-ref HEAD
→ 获取当前检出的分支名称。将用于在最后将工作目录恢复到其初始状态。
sync = "!f() { git is-clean || { echo Aborting sync.; exit 1; }; current=$(git current-branch); git fetch --all; git tracking | while IFS=: read local remote; do echo \"Merging $local with $remote\"; git co-merge \"$local\" \"$remote\"; done 3>&1 1>&2 2>&3 | egrep -i --color 'fatal|$' 3>&1 1>&2 2>&3; git checkout \"$current\"; }; f"
→ 这是主要部分。让我们将其分成几个部分:
git is-clean || { echo Aborting sync.; exit 1; }
→→ 如果工作目录中有未完成的任务,则终止该命令。
current=$(git current-branch)
→→ 存储当前检出分支的名称。
git fetch --all
→→ 同步所有远程分支 (--all
)。
git tracking | while IFS=: read local remote; do ...
→→ 遍历每个本地跟踪分支。
3>&1 1>&2 2>&3 | egrep -i --color 'fatal|$' 3>&1 1>&2 2>&3
→→ 强调了包含“fatal”关键字的错误。 "3>&1 1>&2 2>&3" 这个神奇的公式可以交换STDOUT和STDERR,必须能够将STDERR管道传输到egrep命令。
git checkout "$current"
→→ 将工作目录恢复到初始状态。
git branch -r
命令,您可以看到所有引用都与远程上的完全相同。git branch
命令则只显示本地仓库中的内容。 - Andrew C