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
Make a shell script to update 3 git repos
提问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 up
alias:
首先,我建议不要使用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