我正在编写一个 Bash 脚本来进行一些 Git 存储库维护。一些存储库使用
'master'
作为主分支,而其他存储库则使用 'main'
。我可以使用什么 Git 命令来返回存在的第一个分支?
附注我想检查存储库的本地分支,因为总会有本地
'master'
或 'main'
分支。
git branch
和 -l
/--list
选项:
git branch -l master main # outputs 'master' or 'main', provided only one exists
Git 还用星号标记当前分支,因此您可以添加
--format
来防止这种情况:
git branch -l main master --format '%(refname:short)'
要了解某些 other Git 存储库的
HEAD
是什么,请使用 git ls-remote
:
$ git ls-remote --symref origin HEAD
ref: refs/heads/master HEAD
670b81a890388c60b7032a4f5b879f2ece8c4558 HEAD
这假设您的 Git 和远程的 Git 都没有太旧以至于不支持
--symref
(双方都必须支持)。请注意,此命令可以直接使用 URL 在任何存储库外部运行,而不是像 origin
这样的远程名称。
要找出其他 Git 存储库中存在哪些分支名称,请克隆它并检查生成的远程跟踪名称,或使用
git ls-remote
。请注意,您可以仅指定 refs/heads
将输出限制为仅分支名称,或者完全省略它以获取所有内容(所有分支和标签名称以及它们选择公开的任何其他名称)。
我可以使用什么 Git 命令来返回这些存在的第一个分支?
git branch -r
返回遥控器列表。grep origin/ma
将匹配 main
和 master
。grep -E 'origin/(main|master)'
将返回的列表分配给数组应该可以,但要警惕带有空格和 c 的名称,因为数组元素由空格分隔,整个事情可能会崩溃。
b=( $(git branch -r | grep origin/ma ) ) # all matches
git checkout "${b[0]##*/}" # first hit
如果你想更小心一点,
for n in main master; do
b="$(git branch -r -l "origin/$n")"
if [[ -n "$b" ]]; then
git checkout "${b[0]##*/}"
break # keep the first success
fi
done
嗯,“默认分支”在本地没有任何意义;仅当您的存储库是其他人的远程仓库或其他人托管的远程仓库时,它才有意义。 (另外,就“当我从这个本地分支拉取时,我默认拉取哪个分支,但如果你知道这一点,你就不会问这个了。)
git fetch
git branch -r --list 'origin/HEAD' | grep '>'
#Update local/fork default to match remote. Can also delete current local branch using -D (to clean up a finished feature branch)
gum(){
REMOTES=( $(git branch -r | grep -Eo " (origin|upstream)/(master|main)") )
RNAME=${REMOTES[-1]%%/*} # Prefix of last one in the list (prefer fetching from upstream over origin)
RBRANCH=${REMOTES[-1]##*/} # Suffix of last matching remote
LBRANCH="$(git rev-parse --abbrev-ref HEAD)" # Name of current checked out branch
if [[ "$LBRANCH" != "$RBRANCH" && "$1" != "-D" ]]; then
echo "error current branch is '$LBRANCH' not $RBRANCH and -D not specified to delete current branch"
elif [[ ! -z $(git status -s) ]]; then
echo "error pending changes on local branch"
else
# Switch to local default, delete current if requested
if [[ "$LBRANCH" != "$RBRANCH" && "$1" == "-D" ]]; then
git checkout $RBRANCH
git branch -D $LBRANCH
fi
# fetch all and prune, then update local default
git fetch --all -p && git merge $RNAME/$RBRANCH && if [[ "$RNAME" != "origin" ]]; then
git push ${REMOTES[0]%%/*} $RBRANCH # also update default branch on fork
fi
fi
}
我想检查存储库的本地分支,因为总会有本地将其视为对预期用例环境的可靠描述,因为在一般使用中它通常是不正确的,
master
或main
分支
我可以使用什么 Git 命令来返回这些存在的第一个分支?一个简洁的方法是
if git cat-file -e refs/heads/master 2>&-; then echo master
elif git cat-file -e refs/heads/main 2>&-; then echo main
fi
但对于任何更复杂的事情,你可能需要 for-each-ref,
{ git for-each-ref --format='%(refname)' refs/{heads,remotes/*}/master;
git for-each-ref --format='%(refname)' refs/{heads,remotes/*}/main;
} | sed -E 's,(.*)/,\1 ,' | sort -usk1,1
它给出了本地分支和所有跟踪的遥控器的答案,没有任何 foofaraw。例如,在我的
git
存储库中,此报告为
refs/remotes/origin master
,并且 Git 项目使两个分支名称保持一致。但正如其他人指出的那样,有些项目会保留
master
作为他们离开时所在位置的记录,并且您可能已经注意到,我没有有
master
或
main
分支。我的
make
分支跟踪
origin/next
,这是我运行部署的分支,还有其他几个用于小项目。只做本地分行做的事情
{ git for-each-ref --format='%(refname:short)' refs/heads/master;
git for-each-ref --format='%(refname:short)' refs/heads/main;
} | head -1
参见示例,它是为此而构建的。