Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
检查Git中是否需要拉动_Git_Bash_Shell - Fatal编程技术网

检查Git中是否需要拉动

检查Git中是否需要拉动,git,bash,shell,Git,Bash,Shell,如何检查远程存储库是否已更改,是否需要拉取 现在我使用这个简单的脚本: git pull --dry-run | grep -q -v 'Already up-to-date.' && changed=1 但是它相当重 有更好的办法吗?理想的解决方案是检查所有远程分支,并返回已更改分支的名称以及每个分支中新提交的数量。命令 git ls-remote origin -h refs/heads/master 将在遥控器上列出当前头部——您可以将其与以前的值进行比较,或者查看您的

如何检查远程存储库是否已更改,是否需要拉取

现在我使用这个简单的脚本:

git pull --dry-run | grep -q -v 'Already up-to-date.' && changed=1
但是它相当重

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

命令

git ls-remote origin -h refs/heads/master

将在遥控器上列出当前头部——您可以将其与以前的值进行比较,或者查看您的本地回购中是否有SHA。

我认为最好的方法是:

git diff remotes/origin/HEAD
假设已注册此参照规范。如果您已经克隆了存储库,则应该这样做,否则(即,如果repo是在本地从头创建的,并推送到远程),则需要显式添加refspec。

首先使用,以使远程ref更新。然后您可以执行以下几项操作之一,例如:

  • git status-uno
    将告诉您正在跟踪的分支是在前面、后面还是已经分支。如果它什么也没说,本地和远程是一样的

  • git show branch*master
    将显示名称以“master”(例如master和origin/master)结尾的所有分支中的提交

  • 如果将
    -v
    git remote update
    git remote-v update
    )一起使用,您可以看到哪些分支得到了更新,因此实际上不需要任何进一步的命令

    但是,看起来您希望在脚本或程序中执行此操作,并以真/假值结束。如果是这样的话,有很多方法可以检查您当前的负责人提交和您正在跟踪的分支机构负责人之间的关系,尽管有四种可能的结果,您不能将其归结为是/否。但是,如果您准备做一个
    pull--rebase
    ,那么您可以将“local is behind”和“local has divered”视为“need to pull”,将另外两个视为“not need to pull”

    您可以使用
    git rev parse
    获取任何ref的提交id,因此您可以对master和origin/master执行此操作,并对它们进行比较。如果它们相等,则分支相同。如果它们不相等,你想知道哪个在前面。使用
    git merge base master origin/master
    将告诉您这两个分支的共同祖先,如果它们没有分叉,这将与其中一个相同。如果您得到三个不同的ID,则分支已分叉

    要正确执行此操作,例如在脚本中,您需要能够引用当前分支及其跟踪的远程分支。
    /etc/bash_completion.d
    中的bash提示符设置函数包含一些用于获取分支名称的有用代码。但是,您可能实际上不需要获取名称。Git有一些简洁的方法来引用分支和提交(如
    Git rev parse--help
    中所述)。特别是,您可以对当前分支使用
    @
    (假设您没有处于分离的头部状态),对其上游分支使用
    @{u}
    (例如
    原点/主节点
    )。因此,
    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获取
    git远程更新
    ,以更新跟踪分支。我没有将其构建到脚本中,因为它更灵活,可以将获取和比较作为单独的操作来执行,例如,如果您想在不获取的情况下进行比较,因为您最近已经获取了数据。

    Run
    git fetch(remote)
    要更新远程引用,它将向您显示新内容。然后,当您签出本地分支机构时,它将显示它是否位于上游分支机构之后。

    如果您有上游分支机构 (我假设
    origin/master
    是您的远程跟踪分支)

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


    请注意,即使您在功能分支上,这也会起作用——该分支没有跟踪遥控器,因为if显式地引用
    origin/master
    ,而不是隐式地使用Git记住的上游分支。

    我会按照brool建议的方式执行。下面的一行脚本获取您上一个提交版本的SHA1,并将其与远程源代码的SHA1进行比较,并且仅当它们不同时才提取更改。 基于
    git-pull
    git-fetch
    的解决方案更加轻量级

    [ `git log --pretty=%H ...refs/heads/master^` != `git ls-remote origin
    -h refs/heads/master |cut -f1` ] && git pull
    
    将列出任何远程中引用的、不在您的repo中的所有内容。要捕获对已有内容的远程引用更改(例如,重置为以前的提交),需要花费更多的时间:

    git pack-refs --all
    mine=`mktemp`
    sed '/^#/d;/^^/{G;s/.\(.*\)\n.* \(.*\)/\1 \2^{}/;};h' .git/packed-refs | sort -k2 >$mine
    for r in `git remote`; do 
        echo Checking $r ...
        git ls-remote $r | sort -k2 | diff -b - $mine | grep ^\<
    done
    
    git包引用--全部
    我的=`mktemp`
    sed'/^#/d/^^/{G;s/\(.*)\n.\(.*)/\1\2^{}/;};h'.git/包装参考|排序-k2>$mine
    对于'git remote'中的r;做
    回音检查$r。。。
    git ls remote$r | sort-k2 | diff-b-$mine | grep^\<
    完成
    
    我建议你去看剧本。我已经编写了这个脚本,用于一次性签入所有Git存储库,它显示了谁没有提交,谁没有推/拉

    下面是一个示例结果:


    我基于@jberger的评论提出了这个解决方案

    if git checkout master &&
        git fetch origin master &&
        [ `git rev-list HEAD...origin/master --count` != 0 ] &&
        git merge origin/master
    then
        echo 'Updated!'
    else
        echo 'Not updated.'
    fi
    

    下面是我的Bash脚本版本,它检查所有reposit
    [ `git log --pretty=%H ...refs/heads/master^` != `git ls-remote origin
    -h refs/heads/master |cut -f1` ] && git pull
    
    git ls-remote | cut -f1 | git cat-file --batch-check >&-
    
    git pack-refs --all
    mine=`mktemp`
    sed '/^#/d;/^^/{G;s/.\(.*\)\n.* \(.*\)/\1 \2^{}/;};h' .git/packed-refs | sort -k2 >$mine
    for r in `git remote`; do 
        echo Checking $r ...
        git ls-remote $r | sort -k2 | diff -b - $mine | grep ^\<
    done
    
    if git checkout master &&
        git fetch origin master &&
        [ `git rev-list HEAD...origin/master --count` != 0 ] &&
        git merge origin/master
    then
        echo 'Updated!'
    else
        echo 'Not updated.'
    fi
    
    git fetch
    $(git rev-parse HEAD) == $(git rev-parse @{u})
    
    #!/bin/bash
    
    git fetch -v --dry-run 2>&1 |
        grep -qE "\[up\s+to\s+date\]\s+$(
            git branch 2>/dev/null |
               sed -n '/^\*/s/^\* //p' |
                    sed -r 's:(\+|\*|\$):\\\1:g'
        )\s+" || {
            echo >&2 "Current branch need a 'git pull' before commit"
            exit 1
    }
    
    Merge branch 'foobar' of url:/path/to/git/foobar into foobar
    
    .git/hooks/pre-commit
    
    chmod +x .git/hooks/pre-commit
    
    [ $(git rev-parse HEAD) = $(git ls-remote $(git rev-parse --abbrev-ref @{u} | \
    sed 's/\// /g') | cut -f1) ] && echo up to date || echo not up to date
    
    if [ -n "$1" ]; then
        gitbin="git -C $1"
    else
        gitbin="git"
    fi
    
    # Fetches from all the remotes, although --all can be replaced with origin
    $gitbin fetch --all
    if [ $($gitbin rev-parse HEAD) != $($gitbin rev-parse @{u}) ]; then
        $gitbin rebase @{u} --preserve-merges
    fi
    
    # Operates on /abc/def/my-git-repo-dir
    git-fetch-and-rebase /abc/def/my-git-repo-dir
    
    # Operates on the Git repository which the current working directory is part of
    git-fetch-and-rebase
    
    # Check return value to see if there are incoming updates.
    if ! git diff --quiet remotes/origin/HEAD; then
     # pull or whatever you want to do
    fi
    
    - local path e.g. /d/source/project1 - Git URL e.g. https://username@bitbucket.org/username/project1.git - password if a password should not be entered on the command line in plain text, then modify the script to check if GITPASS is empty; do not replace and let Git prompt for a password
    - Find the current branch
    - Get the SHA1 of the remote on that branch
    - Get the SHA1 of the local on that branch
    - Compare them.
    
    #!/bin/bash
    
    # Shell script to check if a Git pull is required.
    
    LOCALPATH=$1
    GITURL=$2
    GITPASS=$3
    
    cd $LOCALPATH
    BRANCH="$(git rev-parse --abbrev-ref HEAD)"
    
    echo
    echo git url = $GITURL
    echo branch = $BRANCH
    
    # Bash replace - replace @ with :password@ in the GIT URL
    GITURL2="${GITURL/@/:$GITPASS@}"
    FOO="$(git ls-remote $GITURL2 -h $BRANCH 2> /dev/null)"
    if [ "$?" != "0" ]; then
      echo cannot get remote status
      exit 2
    fi
    FOO_ARRAY=($FOO)
    BAR=${FOO_ARRAY[0]}
    echo [$BAR]
    
    LOCALBAR="$(git rev-parse HEAD)"
    echo [$LOCALBAR]
    echo
    
    if [ "$BAR" == "$LOCALBAR" ]; then
      #read -t10 -n1 -r -p 'Press any key in the next ten seconds...' key
      echo No changes
      exit 0
    else
      #read -t10 -n1 -r -p 'Press any key in the next ten seconds...' key
      #echo pressed $key
      echo There are changes between local and remote repositories.
      exit 1
    fi
    
    #!/bin/bash
    dir="/path/to/root"
    lock=/tmp/update.lock
    msglog="/var/log/update.log"
    
    log()
    {
            echo "$(date) ${1:-missing}" >> $msglog
    }
    
    if [ -f $lock ]; then
            log "Already run, exiting..."
    else
            > $lock
            git -C ~/$dir remote update &> /dev/null
            checkgit=`git -C ~/$dir status`
            if [[ ! "$checkgit" =~ "Your branch is up-to-date" ]]; then
                    log "-------------- Update ---------------"
                    git -C ~/$dir pull &>> $msglog
                    log "-------------------------------------"
            fi
            rm $lock
    
    fi
    exit 0
    
    changed=0
    git remote update && git status -uno | grep -q 'Your branch is behind' && changed=1
    if [ $changed = 1 ]; then
        git pull
        echo "Updated successfully";
    else
        echo "Up-to-date"
    fi
    
    str=$(git status) 
    if [[ $str =~ .*Your\ branch\ is\ behind.*by.*commits,\ and\ can\ be\ fast-forwarded ]]; then
        echo `date "+%Y-%m-%d %H:%M:%S"` "Needs pull"
    else
        echo "Code is up to date"
    fi
    
    cd C:\<path to repo>
    git remote update                           #update remote
    $msg = git remote show origin               #capture status
    $update = $msg -like '*local out of date*'
    if($update.length -gt 0){                   #if local needs update
        Write-Host ('needs update')
        git pull
        git reset --hard origin/master
        Write-Host ('local updated')
    } else {
        Write-Host ('no update needed')
    }
    
    git rev-list HEAD...origin/master --count will give you the total number of "different" commits between the two. – Jake Berger Feb 5 '13 at 19:23
    
    #!/bin/bash
    
    BRANCH="<your branch name>"
    LAST_UPDATE=`git show --no-notes --format=format:"%H" $BRANCH | head -n 1`
    LAST_COMMIT=`git show --no-notes --format=format:"%H" origin/$BRANCH | head -n 1`
    
    git remote update
    if [ $LAST_COMMIT != $LAST_UPDATE ]; then
            echo "Updating your branch $BRANCH"
            git pull --no-edit
    else
            echo "No updates available"
    fi
    
    import os
    import logging
    import subprocess
    
    def check_for_updates(directory:str) -> None:
        """Check git repo state in respect to remote"""
        git_cmd = lambda cmd: subprocess.run(
            ["git"] + cmd,
            cwd=directory,
            stdout=subprocess.PIPE,
            check=True,
            universal_newlines=True).stdout.rstrip("\n")
    
        origin = git_cmd(["config", "--get", "remote.origin.url"])
        logging.debug("Git repo origin: %r", origin)
        for line in git_cmd(["fetch"]):
            logging.debug(line)
        local_sha = git_cmd(["rev-parse", "@"])
        remote_sha = git_cmd(["rev-parse", "@{u}"])
        base_sha = git_cmd(["merge-base", "@", "@{u}"])
        if local_sha == remote_sha:
            logging.info("Repo is up to date")
        elif local_sha == base_sha:
            logging.info("You need to pull")
        elif remote_sha == base_sha:
            logging.info("You need to push")
        else:
            logging.info("Diverged")
    
    check_for_updates(os.path.dirname(__file__))
    
    git fetch; [ $(git rev-parse HEAD) = $(git rev-parse @{u}) ] \
        && echo "Up to date" || echo "Not up to date"