web-dev-qa-db-ja.com

3 gitリポジトリを更新するシェルスクリプトを作成する

開発環境でクローンを作成した5つのリポジトリで作業しています。 gitリポジトリを更新する場合、フォルダー/ home/adrian/repo1 /を入力して、次の操作を行います。

git checkout master git pull Origin master

しかし、その後、毎朝、他の4つのレポについても同じことをしなければなりません。これは非常に面倒です。

これをシェルスクリプトに入れることはできますか?つまり、これらのgitコマンドをシェルスクリプトで記述して実行すると、すべてのリポジトリを更新できますか?

私はこのようなものを書くことを考えていました...

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」を実行すると、「...へのローカル変更はマージによって上書きされます」などのエラーが発生します。だから私はそれぞれのブランチに入り、ものを隠さなければなりません。

編集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 ..

しかし、私は括弧内に物を書く方法を知りません。

22
ado

最初に、I git pullの使用を推奨しません 。代わりに、より安全なgit upエイリアスを作成します。

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

git upの説明については、 この回答 を参照してください。

その後、安全にスクリプトを作成できます。

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

多くのgitレポジトリをローカルでチェックアウトしているため、すべてのレポジトリを更新するためのより詳細なスクリプトを作成することにしました(bashスクリプトは、更新するために最大3つのフォルダまでgitレポジトリを検索します。 、リベース、およびstashを実行すると、ローカルの変更が元に戻ります。

#!/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" == "git@someserver: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's 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!"
4
M. Sutterlin

私はこの質問でパーティーに本当に遅れていることを知っていますが、この正確な目的のために書いた小さなシェルスクリプトを次に示します。

おそらく非常に素人っぽいようですが、それはおそらくそうだからです!私は主に自分がbashを学ぶのを助けるためにこれを書きましたが、それがあなた(または今これを読んでいる人)に役立つことを願っています。

削除できる(テキストの色の変更、コミットされていない変更のあるリポジトリの一覧表示など)削除できる不要な綿毛がたくさんあります。

リポジトリへのリンクは here です


#!/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"
0
eding42

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's 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
0
Chetabahana