16

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

  1. 检查远程 git 存储库是否有任何要提取的更改。
  2. 如果远程 git 存储库中有更改,请拉取这些更改。
  3. 循环浏览新的或已修改的文件。

通过我的研究,我发现了一些必要的命令来做这些事情,但我无法让它们在 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 语句。我尝试过使用其他 git 命令的 if 语句,它们也总是正确的。似乎 git 不像正常的 shell 命令那样工作,你得到 0 或 1 响应。如何获得这样的 git 命令或其他 git 命令以在 if 语句中返回正确的响应?
  2. 如何将命令输出的变量分配给数组以查看更改的文件,以便我可以使用 for 循环遍历它们?

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

编辑:抱歉,当我遍历更改的文件时应该更清楚,我需要在遍历文件之前从远程存储库中提取更改,以便在处理这些文件时获得最新的更改。

4

4 回答 4

14

对于您的第一个问题,您可以使用git diff --quiet(或git diff --exit-code,但通常当您将它用于其退出代码时,您希望它不打印输出,并且git diff --quiet暗示--exit-code)来确定是否有任何更改。如果有变化,这将为您提供 1 值,如果没有,则为 0。因此,如果您想拥有仅在发生更改时才运行的代码:

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--no-renames

于 2012-12-05T03:15:52.820 回答
10

您可以简单地使用git diff --name-only列出更改的文件的所有文件名。

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

#!/bin/bash
files=`git diff --name-only | grep -E '.php$' `
for file in $files; do
  php -l $file
done
于 2017-08-09T13:47:19.277 回答
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
于 2012-12-05T03:00:43.540 回答
1

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

# 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

这是我能找到的最简单的检查新文件、更改文件和暂存文件的方法。

于 2018-08-31T22:32:27.290 回答