git 制作一个shell脚本来更新3个git repos

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17099564/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 16:23:04  来源:igfitidea点击:

Make a shell script to update 3 git repos

gitshell

提问by ado

I am working with 5 repos that I have cloned in my development environment. When I want to update a git repo, I enter the folder /home/adrian/repo1/ and do:

我正在使用我在开发环境中克隆的 5 个存储库。当我想更新 git repo 时,我进入文件夹 /home/adrian/repo1/ 并执行以下操作:

git checkout master git pull origin master

git checkout master git pull origin master

But then, every morning I have to do the same thing for the other 4 repos. This is quite troublesome.

但是,每天早上我都必须为其他 4 个 repos 做同样的事情。这相当麻烦。

Can I put this in a shell script? I mean, if I write these git commands in the shell script, and run it, will I be able to update all the repos?

我可以把它放在一个shell脚本中吗?我的意思是,如果我在 shell 脚本中编写这些 git 命令并运行它,我是否能够更新所有存储库?

I was thinking of writing something like this...

本来想写这样的。。。

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

(i'm on linux)

(我在 linux 上)

Edit: Maybe this is more challenging than what I thought. Most times when I do "git pull origin master", i get erorrs like "Your local changes to .... would be overwritten by merge." So i have to enter into the respective branch and stash the stuff..

编辑:也许这比我想象的更具挑战性。大多数时候,当我执行“git pull origin master”时,我会收到诸如“您对...的本地更改将被合并覆盖”之类的错误。所以我必须进入相应的分支并将这些东西藏起来。

Edit 2:

编辑2:

What I'm thinking of doing is, if a conflict happens, ignore it and go to the next repo

我想做的是,如果发生冲突,请忽略它并转到下一个仓库

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

but i dont know how to write the thing in parenthesis.

但我不知道如何在括号中写东西。

回答by Richard Hansen

First, I recommend against using git pull. Instead, create a safer git upalias:

首先,我建议不要使用git pull. 相反,创建一个更安全的git up别名:

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

See this answerfor an explanation of git up.

有关的解释,请参阅此答案git up

Then you can safely script it:

然后你可以安全地编写脚本:

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

回答by M. Sutterlin

As I have many git repo's checked out locally for work, i decided to write a more detailed script to update all the repo's (bash script will search for git repos up to 3 folders deep to update. It will then do a git stash, fetch, rebase, and stash pop the local changes back. Script for me runs in git bash shell on windows.

由于我在本地签出了许多 git repo 以进行工作,因此我决定编写一个更详细的脚本来更新所有 repo(bash 脚本将搜索 git repos 最多 3 个文件夹深以进行更新。然后它会执行 git stash、fetch , rebase, and stash pop the local changes back. 对我来说,脚本在 Windows 上的 git bash shell 中运行。

#!/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=""
    local original_dir=""
    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=

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!"

回答by eding42

I know I'm really late to the party on this question, but here's a little shell script I wrote for this exact purpose.

我知道我在这个问题上真的迟到了,但这是我为此确切目的编写的一个小 shell 脚本。

It probably seems very amateurish, but that's because it probably is! I mainly wrote this to help myself learn bash, but I hope it helps you (or whoever may be reading this right now).

这可能看起来很业余,但那是因为它可能是!我写这篇文章主要是为了帮助自己学习 bash,但我希望它可以帮助你(或者现在可能正在阅读这篇文章的人)。

There's a lot of unnecessary fluff on this that you can remove (like changing the color of the text, and listing the repositories with uncommitted changes) that you can remove.

您可以删除许多不必要的内容(例如更改文本的颜色,并列出具有未提交更改的存储库),您可以删除这些内容。

The link to the repo is 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"

回答by Chetabahana

I would suggest to manage the update of all the repos with a cron script.
Here is an example script for auto updatebase to their upstream.

我建议使用 cron 脚本管理所有存储库的更新。
这是自动更新基础到上游的示例脚本。

#!/bin/bash

repo_update() {
    echo -e "\nUpdating " && cd 
    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