Сделать оболочку script для обновления 3 git repos

Я работаю с 5 репозиториями, которые я клонировал в своей среде разработки. Когда я хочу обновить репозиторий git, я вхожу в папку/home/adrian/repo1/и делаю:

git мастер проверки git основной источник тяги

Но потом, каждое утро я должен делать то же самое для других 4 репозиториев. Это довольно хлопотно.

Можно ли поместить это в оболочку script? Я имею в виду, если я напишу эти команды git в оболочке script и запустим его, смогу ли я обновить все репозитории?

Я подумывал написать что-то вроде этого...

cd repo1
git checkout master 
git pull origin master
cd ..
cd repo2
git checkout master 
git pull origin master
cd ..

(я на Linux)

Изменить: Может быть, это более сложно, чем я думал. В большинстве случаев, когда я делаю "git pull origin master", я получаю erorrs как "Ваши локальные изменения... будут перезаписаны слиянием". Так что я должен войти в соответствующую ветку и засунуть вещи..

Изменить 2:

То, что я собираюсь сделать, - это конфликт, проигнорируйте его и перейдите к следующему репо

cd repo1
git checkout master 
git pull origin master

(if there is conflict, ignore and go to the next line but dont stop here)

cd ..
cd repo2
git checkout master 
git pull origin master
cd ..

но я не знаю, как записать это в скобках.

Ответы

Ответ 1

Во-первых, я рекомендую не использовать git pull. Вместо этого создайте более безопасный псевдоним git up:

git config --global alias.up '!git remote update -p; git merge --ff-only @{u}'

См. этот ответ для объяснения git up.

Затем вы можете безопасно script it:

#!/bin/sh
for repo in repo1 repo2 repo3 repo4; do
    (cd "${repo}" && git checkout master && git up)
done

Ответ 2

Поскольку у меня много git repo проверено локально для работы, я решил написать более подробный script для обновления всего репо (bash script будет искать git repos до 3 папок глубокое обновление. Затем он выполнит git stash, fetch, rebase и stash, чтобы вернуть локальные изменения. script для меня работает в оболочке git bash на окнах.

#!/bin/bash
# Usage:
#   ./update_git_repos.sh [parent_directory] 
#   example usage:
#       ./update_git_repos.sh C:/GitProjects/ [MAKE SURE YOU USE / SLASHES]

updateRepo() {
    local dir="$1"
    local original_dir="$2"
    cd $dir # switch to the git repo
    repo_url=$(git config --get remote.origin.url)

    echo "****************************************************************************"
    echo "Updating Repo: $dir with url: $repo_url"
    echo "Starting update in $PWD"

    main_branch="master" 
    if [ "$repo_url" == "[email protected]:repo/repo.git" ]; then # if you have a repo where the primary branch isnt master
        $main_branch="trunk"
    fi

    # update the repo, then stash any local changes
    echo -e "\ncalling: git fetch --all && git stash"
    (git fetch --all && git stash)
    current_branch=$(git rev-parse --abbrev-ref HEAD)

    # switch to master/trunk branch and rebase it, then switch back to original branch
    if [ $current_branch != $main_branch ]; then
        echo -e "\ncalling: git checkout $main_branch && git rebase && git checkout $current_branch"
        (git checkout $main_branch && git rebase && git checkout $current_branch)
    fi

    # rebase the original branch and then stash pop back to original state
    echo -e "\ncalling: git rebase && git stash pop on branch: $current_branch"
    (git rebase && git stash pop ) 

    #switch back to the starting directory
    cd $original_dir
    echo ""
}

directory_to_update=${1}

if [ -z "$directory_to_update" ] ; then
    echo "no directory passed in, using current directory"
    directory_to_update=$PWD
fi 
echo "Updating git repo in directory: $directory_to_update"
count=0
for dir in $(find $directory_to_update -maxdepth 4 -type d -name .git | xargs -n 1 dirname); do
    updateRepo $dir $directory_to_update #& #uncomment to make it run in multiple threads, meh
    ((count+=1))
done

echo "$count local git repos have been updated!"

Ответ 3

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

Это, вероятно, кажется очень любительским, но это потому, что это, вероятно, так! В основном я написал это, чтобы помочь себе освоить bash, но я надеюсь, что это поможет вам (или тому, кто сейчас читает это).

В этом есть много ненужного мусора, который вы можете удалить (например, изменить цвет текста и перечислить репозитории с незафиксированными изменениями), который вы можете удалить.

Ссылка на репо здесь


#!/bin/bash
declare -a my_array
for f in *; do
    if [ -d "$f" ] ; then
        cd "$f"
        echo -e "\n ------------------ NEW REPOSITORY ------------------\n"
        echo "Now checking $f"
        if [ -d .git ] ; then 
            git add .
            git diff-index --quiet HEAD --
            if [ "$?" -ne 0 ] ; then
                echo "THE REPO NEEDS TO BE COMMITTED"
                my_array=( "${my_array[@]}" "${PWD##*/}" )
            fi
            git status
            git push
            git pull
        fi
        cd ..
    fi
done
RED='tput setaf 1'
reset='tput sgr0'
green='tput setaf 2'
if [ ${#my_array[@]} -ne 0 ]; then
    var=$(IFS=' '; echo "${my_array[*]}")
    var="${RED}$var${reset}"
    if [ ${#my_array[@]} -eq 1 ]; then
        var="The repository $var"
        var="$var has uncomitted changes."
    else
        var="The repositories $var"
        var="$var have uncomitted changes."
    fi
    echo "$var"

Ответ 4

Я бы предложил управлять обновлением всех репозиториев с помощью скрипта cron.
Вот пример сценария для автоматического обновления базы до их апстрима.

#!/bin/bash

repo_update() {
    echo -e "\nUpdating $1" && cd $1
    if [[ 'git rev-parse --abbrev-ref HEAD' != master ]]; then git checkout master; fi
    GIT_URL=$(git config --get remote.origin.url) && REMOTE=${GIT_URL##*:}
    REMOTE=https://api.github.com/repos/${REMOTE%.*}

    UPSTREAM=$(curl -s $REMOTE | jq -r '.parent.ssh_url')
    if [[ $UPSTREAM == null ]]; then return 1; fi
    if grep -q $UPSTREAM << EOF
    'git remote -v'
EOF
    then
        git remote set-url upstream $UPSTREAM
    else
        git remote add upstream $UPSTREAM
    fi

    git fetch --prune upstream
    if [[ 'git rev-list HEAD...upstream/master --count' == 0 ]]
    then
        echo -e "all the same, do nothing"
    else
        echo -e "update exist, let checking!"
        git pull --rebase upstream master
        git reset --hard upstream/master
        push $GIT_URL
    fi
}

# Check connection
ssh-add -l &>/dev/null
if [[ "$?" == 2 ]]; then eval 'ssh-agent' > /dev/null; fi

# Check identity
ssh-add -l &>/dev/null
if [[ "$?" == 1 ]]; then expect $HOME/.ssh/agent > /dev/null && ssh-add -l; fi

# Update repositories
find ~/.gits -maxdepth 1 -mindepth 1 -type d | while read repo; do repo_update $repo; done