用于检查git是否有更改然后循环更改文件的Shell脚本?

时间:2012-12-05 02:53:22

标签: git bash shell pull

我正在尝试编写一个执行以下操作的shell脚本:

  1. 检查远程git存储库是否有任何更改。
  2. 如果远程git存储库中有更改,请拉出这些更改。
  3. 循环播放新文件或已修改的文件。
  4. 通过我的研究,我找到了一些必要的命令来完成这些工作,但我无法让它们在shell脚本中一起工作。

    这是一个包含我的一些命令的脚本:

    #!/bin/sh
    
    #Check if there are any changed files
    git --git-dir="/dir/.git" fetch origin
    
    if git --git-dir="/dir/.git" log HEAD..origin/master --oneline
    then
    
    #Output the modified files from the last pull
            git --git-dir="/dir/.git" diff --name-status ORIG_HEAD..
    
    fi
    

    我无法使用此脚本中的命令:

    1. 用于检查是否有更改的if语句始终为true。我已尝试使用其他git命令的if语句,并且它们也始终为true。似乎git不像普通的shell命令那样得到0或1的响应。我怎样才能获得像这个或其他git命令的git命令来在if语句中返回正确的响应?
    2. 如何从命令中分配变量输出以查看已更改的文件到数组,以便我可以使用for?
    3. 循环它们

      如果我的脚本中的命令在这种情况下不能真正起作用,那么更好的方法是什么?

      编辑:对不起,当我循环浏览已更改的文件时,我需要更清楚,我需要在循环浏览文件之前从远程存储库中提取更改,以便在处理这些文件时,我有最新的更改。

4 个答案:

答案 0 :(得分:12)

对于您的第一个问题,您可以使用git diff --quiet(或git diff --exit-code,但通常当您将其用于退出代码时,您希望它无论如何都不打印输出,{{1} }暗示git diff --quiet)确定是否有任何变化。如果有变化,那将给你一个值,如果没有变化则给你一个0。因此,如果您希望代码仅在存在更改时运行:

--exit-code

对于第二个问题,我建议使用if ! git --git-dir="/dir/.git" diff --quiet then # do stuff... fi 循环来读取while read ...中的行:

git diff-tree

请注意,git --git-dir="/dir/.git" diff-tree ORIG_HEAD.. | \ while read srcmode dstmode srcsha dstsha status srcfile dstfile do # do something with $srcfile and $dstfile done 在开头会有一个额外的$srcmode,而:只有在重命名文件时才有值。如果您不想担心重命名,请传递$dstfile,而不是看到重命名,您只会看到添加和删除。

答案 1 :(得分:3)

你是对的,git通常不会以非零状态退出,除非出现错误。我发现检测未提交更改的最简单方法是这样的:

 let changes=0
 while read status filename; do
    let changes=1
    # do something with this filename/status
 done < <(git status --porcelain)
 if (( ! changes )); then
    echo "No changes."
 fi

通常,如果您打算尝试从代码中驱动git,则应在支持它的子命令上使用--porcelain,以使其以更加自动化的方式运行。您可能还想调查其他语言的库以与git交互而无需构建您自己的shell命令;例如,在Ruby中有grit

现在,在您的情况下,您想要检测上游更改的内容。为此,您可能希望使用git diff-tree。与上述类似的逻辑:

 git fetch   # not pull
 while read filename; do
   # do something with filename
 done < <(git diff-tree --name-only origin/master master)  # or whatever branch you're using

答案 2 :(得分:2)

您只需使用git diff --name-only列出已更改文件的所有文件名。

例如,这里有一个简单的脚本,列出所有编辑的PHP文件并测试语法。

#!/bin/bash
files=`git diff --name-only | grep -E '.php$' `
for file in $files; do
  php -l $file
done

答案 3 :(得分:0)

如果您正在编写脚本并希望确保存储库处于提交状态(例如,没有新的,已修改的或暂存的文件),请尝试以下操作:

``` bash
# Get to code.  Exit if unsaved changes in repo
if `git status | grep -q "nothing to commit"`; then
  git checkout --quiet $BRANCH || exit 1
else
  echo "ERROR: repo has unsaved changes"
  exit 1
fi
```

这是我可以找到的最简单的方法,即检查新文件,更改文件和暂存文件。