bash 检查本地 git repo 是否在远程之前/之后

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17719829/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 05:56:48  来源:igfitidea点击:

Check if local git repo is ahead/behind remote

linuxgitbashshellgithub

提问by Vittorio Romeo

I'm developing a git plug-in, and I need to know when a local repo is changed(can commit changes), ahead(can push to remote) or behind(can pull from remote) using the command line.

我正在开发一个Git插件,我需要知道,当一个本地回购被改变(可提交更改),未来(可推送到远程)或后面使用命令行(可以从远程拉)。

This is what I am doing so far:

这是我目前正在做的事情:

  • Can commit?

    If git diff-index --name-only --ignore-submodules HEAD --returns something, then yes, there are changes to commit.

  • Can push?

    If git status -sbcontains the word aheadin it's output, then yes, there are commits to push.

  • Can pull?

    Nothing implemented yet.

  • 可以答应吗?

    如果git diff-index --name-only --ignore-submodules HEAD --返回某些内容,那么是的,需要提交更改。

  • 可以推吗?

    如果在它的输出中git status -sb包含前面的单词,那么是的,有提交要推送。

  • 可以拉吗?

    尚未实施。

The can commit?part seems to work properly. Can push?only works for the master branch, and this is a huge problem.

可以提交?部分似乎工作正常。可以推吗?仅适用于 master 分支,这是一个大问题。

How can I safely check if, on every branch, a git repo has changes to commit, commits to push, or needs a git pull?

如何安全地检查 git repo 在每个分支上是否有更改要提交、提交要推送或需要一个git pull?

采纳答案by Vittorio Romeo

In the end, I implemented this in my C++11 git-ws plugin.

最后,我在我的 C++11 git-ws 插件中实现了这个。

string currentBranch = run("git rev-parse --abbrev-ref HEAD"); 
bool canCommit = run("git diff-index --name-only --ignore-submodules HEAD --").empty();
bool canPush = stoi(run("git rev-list HEAD...origin/" + currentBranch + " --ignore-submodules --count")[0]) > 0;

Seems to work so far. canPullstill needs to be tested and implemented.

到目前为止似乎工作。canPull仍然需要测试和实施。

Explanation:

解释:

  • currentBranchgets the console output, which is a string of the current branch name
  • canCommitgets whether the console outputs something (difference between current changes and HEAD, ignoring submodules)
  • canPushgets the count of changes between origin/currentBranchand the local repo - if > 0, the local repo can be pushed
  • currentBranch获取控制台输出,这是当前分支名称的字符串
  • canCommit获取控制台是否输出某些内容(当前更改和 HEAD 之间的差异,忽略子模块)
  • canPush获取 origin/currentBranch和本地仓库之间变化的计数- 如果> 0,则可以推送本地仓库

回答by Trebor Rude

You can do this with a combination of git merge-baseand git rev-parse. If git merge-base <branch> <remote branch>returns the same as git rev-parse <remote branch>, then your local branch is ahead. If it returns the same as git rev-parse <branch>, then your local branch is behind. If merge-basereturns a different answer than either rev-parse, then the branches have diverged and you'll need to do a merge.

您可以组合做git merge-basegit rev-parse。如果git merge-base <branch> <remote branch>返回与 相同git rev-parse <remote branch>,则您的本地分支领先。如果它返回与 相同git rev-parse <branch>,则您的本地分支落后。如果merge-base返回的答案与任何一个都不同rev-parse,则分支已分叉,您需要进行合并。

It would be best to do a git fetchbefore checking the branches, though, otherwise your determination of whether or not you need to pull will be out of date. You'll also want to verify that each branch you check has a remote tracking branch. You can use git for-each-ref--format='%(upstream:short)' refs/heads/<branch>to do that. That command will return the remote tracking branch of <branch>or the empty string if it doesn't have one. Somewhere on SO there's a different version which will return an error if the branch doesn't haven't a remote tracking branch, which may be more useful for your purpose.

但是,最好git fetch在检查分支之前执行 a ,否则您对是否需要拉取的决定将过时。您还需要验证您检查的每个分支是否都有一个远程跟踪分支。你可以用它git for-each-ref--format='%(upstream:short)' refs/heads/<branch>来做到这一点。如果没有,该命令将返回远程跟踪分支<branch>或空字符串。在 SO 上的某个地方有一个不同的版本,如果分支没有远程跟踪分支,它将返回错误,这可能对您的目的更有用。

回答by Panch93

For future reference. As of Git v2.17.0

备查。从 Git v2.17.0 开始

git status -sb

contains the word behind. So that can be used directly to check for pulls.

包含后面的词。这样就可以直接使用它来检查拉动。

Note: Remember to run git fetchbefore running git status -sb

注意:运行git fetch前记得运行git status -sb

回答by Vittorio Romeo

Thanks to @Trebor I just threw together a simple fish function for the purpose:

感谢@Trebor,我为此目的拼凑了一个简单的鱼函数:

#! /usr/bin/fish
#
# Echos (to stdout) whether your branch is up-to-date, behind, ahead or diverged from another branch.
# Don't forget to fetch before calling.
#
# @param branch
# @param otherbranch
#
# @echo string up-to-date/behind/ahead/diverged
#
# @example
#
#   # if master is ahead of origin/master you can find out like this:
#   #
#   if test ( branch-status master origin/master ) = ahead
#
#      echo "We should push"
#
#   end
#
function branch-status

    set -l a $argv[ 1 ]
    set -l b $argv[ 2 ]

    set -l base ( git merge-base $a $b )
    set -l aref ( git rev-parse  $a    )
    set -l bref ( git rev-parse  $b    )

         if [ $aref = $bref ]; echo up-to-date

    else if [ $aref = $base ]; echo behind
    else if [ $bref = $base ]; echo ahead

    else                     ; echo diverged
    end

end