如果我的本地 Git 存储库发生更改,如何签入 Bash 脚本?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5143795/
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-10 10:14:09  来源:igfitidea点击:

How can I check in a Bash script if my local Git repository has changes?

git

提问by kmindi

There are some scripts that do not work correctly if they check for changes.

如果检查更改,有些脚本将无法正常工作。

I tried it like this:

我是这样试的:

VN=$(git describe --abbrev=7 HEAD 2>/dev/null)

git update-index -q --refresh
CHANGED=$(git diff-index --name-only HEAD --)
if [ ! -z $CHANGED ];
    then VN="$VN-mod"
fi

Is there some kind of boolean check if there has been changes since the last commit, or how can I really test if there are new changes to my local repository?

是否有某种布尔检查自上次提交以来是否有更改,或者我如何真正测试本地存储库是否有新更改?

I'm doing all this for a version creation script (that I found somewhere here).

我正在为版本创建脚本(我在此处找到的某个地方)执行所有这些操作。

回答by ryanmoon

Using git status:

使用git status

cd /git/directory
if [[ `git status --porcelain` ]]; then
  # Changes
else
  # No changes
fi

回答by Cascabel

What you're doing will almost work: you should quote $CHANGEDin case it's empty, and -ztests for empty, which means no changes. What you meant was:

你所做的几乎可以工作:你应该引用$CHANGED以防它为空,并-z测试为空,这意味着没有变化。你的意思是:

if [ -n "$CHANGED" ]; then
    VN="$VN-mod"
fi

A quote from Git's GIT-VERSION-GEN:

来自 Git 的引用GIT-VERSION-GEN

git update-index -q --refresh
test -z "$(git diff-index --name-only HEAD --)" ||
VN="$VN-dirty"

It looks like you were copying that, but you just forgot that detail of quoting.

看起来您正在复制它,但您只是忘记了引用的细节。

Of course, you could also just do this:

当然,你也可以这样做:

if git diff-index --quiet HEAD --; then
    # No changes
else
    # Changes
fi

Or if you only care about the "something has changed" case:

或者,如果您只关心“某些事情发生了变化”的情况:

if ! git diff-index --quiet HEAD --; then
    VN="$VN-mod"
fi

Using --quiethas the benefit that Git can stop processing as soon as it encounters a single diff, so it may not have to check your entire work tree.

使用--quiet的好处是 Git 可以在遇到单个差异时立即停止处理,因此它可能不必检查整个工作树。

回答by Arrowmaster

Although Jefromi's answer is good, I'm posting this just for reference.

尽管 Jefromi 的回答很好,但我发布此内容仅供参考。

From the Git source code there is a shscript which includes the following.

Git 源代码中有一个sh脚本,其中包含以下内容。

require_clean_work_tree () {
    git rev-parse --verify HEAD >/dev/null || exit 1
    git update-index -q --ignore-submodules --refresh
    err=0

    if ! git diff-files --quiet --ignore-submodules
    then
        echo >&2 "Cannot : You have unstaged changes."
        err=1
    fi

    if ! git diff-index --cached --quiet --ignore-submodules HEAD --
    then
        if [ $err = 0 ]
        then
            echo >&2 "Cannot : Your index contains uncommitted changes."
        else
            echo >&2 "Additionally, your index contains uncommitted changes."
        fi
        err=1
    fi

    if [ $err = 1 ]
    then
        test -n "" && echo >&2 ""
        exit 1
    fi
}

回答by Leon Waldman

I had a similar problem, but I had to check for added files also. So I did the following:

我有一个类似的问题,但我还必须检查添加的文件。所以我做了以下事情:

cd /local/repo
RUN=0
git diff --no-ext-diff --quiet --exit-code || RUN=1
if [ $RUN = 0 ]; then
    RUN=`git ls-files --exclude-standard --others| wc -l`
fi

if [ $RUN = 0 ]; then
    exit 0
fi

回答by AndrewD

git statusis your friend

git status是你的朋友

Change to the Git directory for git statusto work:

切换到 Git 目录以git status进行工作:

cd c:/path/to/.git

Set a variable to set the work tree so you don't get 'This operation must be run in a work tree' error:

设置一个变量来设置工作树,这样您就不会收到“必须在工作树中运行此操作”错误:

WORKTREE=c:/path/to/worktree

Capture the git statusoutput in a Bash variable

捕获git statusBash 变量中的输出

Use --porcelainwhich guarantees to be in a standard format and parsable:

使用--porcelainwhich 保证采用标准格式并且可解析:

CHANGED=$(git --work-tree=${WORKTREE} status --porcelain)

If -n (not null), we have changes.

如果 -n (非空),我们有变化。

if [ -n "${CHANGED}" ]; then
  echo 'changed';

else
  echo 'not changed';
fi

回答by robertberrington

This works nicely. It will also list the files affected:

这很好用。它还将列出受影响的文件:

if git diff-index --name-status --exit-code HEAD;
then
    echo Git working copy is clean...;
else
    echo ;
    echo ERROR: Git working copy is dirty!;
    echo Commit your changes and try again.;
fi;

回答by Sean

Here is a nice set of Bash script functions that check if there is a diff, prints it to the user and prompts the user if they would like to commit changes before deployment. It is built for a Heroku and Python application, but it needs little change for any other application.

这是一组不错的 Bash 脚本函数,用于检查是否存在差异,将其打印给用户并提示用户是否希望在部署前提交更改。它是为 Heroku 和 Python 应用程序构建的,但对于任何其他应用程序几乎不需要更改。

commit(){
    echo "Please enter a commit message..."
    read msg
    git add . --all
    git commit -am $msg
}

check_commit(){
    echo ========== CHECKING FOR CHANGES ========
    changes=$(git diff)
    if [ -n "$changes" ]; then
        echo ""
        echo "*** CHANGES FOUND ***"
        echo "$changes"
        echo ""
        echo "You have uncomitted changes."
        echo "Would you like to commit them (y/n)?"
        read n
        case $n in
            "y") commit;;
            "n") echo "Changes will not be included...";;
            *) echo "invalid option";;
        esac
    else
        echo "... No changes found"
    fi
}

deploy(){
    check_commit
    echo ========== DEPLOYING TO HEROKU ========
    git push heroku master
    heroku run python manage.py syncdb
}

You can copy from Gists on: https://gist.github.com/sshadmand/f33afe7c9071bb725105

您可以从 Gists 复制:https://gist.github.com/sshadmand/f33afe7c9071bb725105

回答by Robert A

nano checker_git.sh

paste this

粘贴这个

#!/bin/bash

echo "First arg: "

cd 

bob="Already up-to-date."
echo $bob

echo $(git pull) > s.txt
cat s.txt
if [ "$(cat s.txt)" == "$bob" ]
then
echo "up"
else
echo "not up"

fi
rm -rf st.txt


run sh checker_git.sh gitpath

sh checker_git.sh gitpath

回答by Dennis

Based on @storm_m2138 comment to @RyanMoon's answer (link) I am using the following in Powershell.

基于@storm_m2138 对@RyanMoon 的回答(链接)的评论,我在Powershell.

function hasChanges($dir="."){ $null -ne (iex "git -C $dir status --porcelain --untracked-files=no") }

gci -Directory | ?{ hasChanges $_ } | %{ Write-Host "$_ has changes" }
gci -Directory | ?{ hasChanges $_ } | %{ iex "git -C $_ add -u"; iex "git -C $_ commit -m"Somemthing" }

回答by Seamus

The OP's question is more than 9 years old now. I don't know what man git-statussaid then, but here's what it says now:

OP的问题现在已经超过9年了。我不知道当时man git-status说了什么,但现在是这样说的:

--porcelain[=<version>]  
Give the output in an easy-to-parse format for scripts. This is similar to the 
short output, but will remain stable across Git versions and regardless of user 
configuration. See below for details.  

The version parameter is used to specify the format version. This is optional and 
defaults to the original version v1 format.  

This suggests that the --porcelainargument is well-suited to testing the status of a repo for changes.

这表明该--porcelain论点非常适合测试回购状态的变化。

Wrt the OP's question, "Is there some kind of boolean check if there has been changes since the last commit, or how can I really test if there are new changes to my local repository?"

写 OP 的问题,“是否有某种布尔检查自上次提交以来是否有更改,或者我如何真正测试本地存储库是否有新更改?”

I don't think that bashhas boolean data types per se, but this may be close enough:

我不认为它本身bash具有布尔数据类型,但这可能足够接近:

[ -z "`git status --porcelain`" ] && echo "NULL-NO DIFFS" || echo "DIFFS EXIST"

This can be re-cast as a if-then-elseform for a script, or executed as-is fm the CLI while in the git repo folder. Otherwise, use the -Coption with a path spec to the repo of interest:

这可以重新转换if-then-else为脚本的形式,或者在 git repo 文件夹中按 CLI 原样执行。否则,使用-C带有路径规范的选项到感兴趣的存储库:

git -C ~/path/to/MyGitRepo status --porcelain