Shell script, чтобы проверить git на изменения, а затем прокрутить измененные файлы?

Я пытаюсь написать оболочку script, которая делает следующее:

  • Проверяет удаленный репозиторий git на любые изменения.
  • Если изменения в удаленном репозитории git вызывают эти изменения.
  • Прокручивает файлы, которые являются новыми или были изменены.

В ходе моих исследований я нашел некоторые необходимые команды для выполнения этих задач, но мне не удалось заставить их работать вместе в оболочке script.

Вот script с некоторыми из команд, которые у меня есть:

#!/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

То, что мне не удалось получить с командами в этом script, это:

  • Оператор if, проверяющий, есть ли изменения или не всегда, является истинным. Я пробовал, если инструкции с другими командами git, и они также всегда верны. Кажется, что git не работает, как обычные команды оболочки, где вы получаете ответ 0 или 1. Как я могу получить команду git, подобную той или иной команде git, чтобы возвращать правильные ответы в инструкции if?
  • Как я могу назначить переменные, выводимые из команды, чтобы увидеть измененные файлы в массиве, чтобы я мог их прокручивать, используя для?

Если команды в моем script не будут работать в этом случае, что лучший способ сделать это?

Изменить: извините, если я прокрутил измененные файлы, мне нужно вытащить изменения из удаленного репозитория, прежде чем прокручивать файлы, чтобы при работе с этими файлами у меня были последние изменения.

Ответ 1

Для вашего первого вопроса вы можете использовать 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, и вместо просмотра переименований вы увидите только добавление и удаление.

Ответ 2

Вы правы, 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 без создания собственных команд оболочки; например, в 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

Ответ 3

Вы можете просто использовать git diff --name-only для отображения всех файлов с именами файлов.

Например, здесь простой script для отображения всех файлов PHP, отредактированных и протестированных синтаксисом.

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