协慌网

登录 贡献 社区

检查是否需要在 Git 中拉

如何检查远程存储库是否已更改并且需要拉出?

现在,我使用以下简单脚本:

git pull --dry-run | grep -q -v 'Already up-to-date.' && changed=1

但是它很重。

有没有更好的办法?理想的解决方案是检查所有远程分支,并返回已更改分支的名称以及每个分支中新提交的数量。

答案

首先使用git remote update ,使您的远程引用保持最新。然后,您可以做几件事之一,例如:

  1. git status -uno会告诉您正在跟踪的分支是在前,在后还是在分支。如果什么也没说,则本地和远程相同。

  2. git show-branch *master将向您显示名称以'master' 结尾的所有分支的提交(例如masterorigin / master )。

如果将-vgit remote updategit remote -v update )结合使用,则可以看到更新了哪些分支,因此您实际上不需要任何其他命令。

但是,您似乎想在脚本或程序中执行此操作,并最终得到 true / false 值。如果是这样,尽管有四种可能的结果,您不能将其简化为是 / 否,但是有多种方法可以检查当前的HEAD 提交与要跟踪的分支的头之间的关系。但是,如果您准备进行pull --rebase则可以将 “本地落后” 和 “本地分歧” 视为“需要拉”,将其他两个视为“不需要拉”。

git rev-parse <ref>获得任何参考的提交 ID,因此您可以针对masterorigin / master进行比较。如果它们相等,则分支相同。如果它们不相等,那么您想知道哪个先于另一个。使用git merge-base master origin/master会告诉您两个分支的共同祖先,如果它们没有分歧,则它们将彼此相同。如果您获得三个不同的 ID,则说明分支已经分开。

为了正确执行此操作(例如在脚本中),您需要能够引用当前分支以及它正在跟踪的远程分支。 /etc/bash_completion.d的 bash 提示设置功能具有一些用于获取分支名称的有用代码。但是,您实际上可能不需要获取名称。 Git 在引用分支和提交方面有一些简洁的捷径(如git rev-parse --help )。特别是,您可以将@用于当前分支(假设您不处于分离状态),并将@{u}用于其上游分支(例如origin/master )。因此git merge-base @ @{u}将返回(哈希值)提交,当前分支及其上游分支在此处提交,并且git rev-parse @git rev-parse @{u}将为您提供哈希值两个技巧。可以在以下脚本中进行总结:

#!/bin/sh

UPSTREAM=${1:-'@{u}'}
LOCAL=$(git rev-parse @)
REMOTE=$(git rev-parse "$UPSTREAM")
BASE=$(git merge-base @ "$UPSTREAM")

if [ $LOCAL = $REMOTE ]; then
    echo "Up-to-date"
elif [ $LOCAL = $BASE ]; then
    echo "Need to pull"
elif [ $REMOTE = $BASE ]; then
    echo "Need to push"
else
    echo "Diverged"
fi

注:旧版本的 Git 不允许@自身的,所以你可能需要使用@{0}来代替。

UPSTREAM=${1:-'@{u}'}允许您选择显式地传递上游分支,以防您要检查与为当前分支配置的远程分支不同的远程分支。这通常是remotename / branchname的形式。如果未提供任何参数,则该值默认为@{u}

该脚本假定您首先进行了git fetchgit remote update ,以使跟踪分支保持最新状态。我之所以没有将其构建到脚本中,是因为它能够作为单独的操作来进行获取和比较,因此更加灵活,例如,如果您希望在不进行获取的情况下进行比较,因为您已经获取了最近的内容。

如果您有上游分支机构

git fetch <remote>
git status

如果您没有上游分支

比较两个分支:

git fetch <remote>
git log <local_branch_name>..<remote_branch_name> --oneline

例如:

git fetch origin

# See if there are any incoming changes
git log HEAD..origin/master --oneline

(我假设origin/master是您的远程跟踪分支)

如果上面的输出中列出了任何提交,则您有传入的更改 - 您需要合并。 git log没有列出任何提交,则没有任何要合并的内容。

请注意,即使您在功能分支上也没有问题,因为该分支没有跟踪遥控器,因为如果显式引用了origin/master节点,而不是隐式使用 Git 记住的上游分支。

如果这是用于脚本的,则可以使用:

git fetch
$(git rev-parse HEAD) == $(git rev-parse @{u})

(注意:此答案与先前答案的好处是,您不需要单独的命令即可获取当前分支名称。“HEAD” 和 “@ {u}”(当前分支的上游)将为您提供帮助。请参见有关更多详细信息,请参见 “git rev-parse --help”。)