Skip to content

Instantly share code, notes, and snippets.

@takumakei
Last active August 29, 2015 14:24
Show Gist options
  • Save takumakei/ad20d5c1614d36905ecd to your computer and use it in GitHub Desktop.
Save takumakei/ad20d5c1614d36905ecd to your computer and use it in GitHub Desktop.
git subtreeを実際に動かして学ぶための教材
#!/bin/bash
WORK=$PWD
main() {
trap "exit 1" SIGINT
msg "git subtreeを実際に動かして学ぶための教材。" \
"適当なところに pause を仕掛けて" \
"ディレクトリ構造やgitの状態を覗き見して" \
"git subtreeの動きを確かめられる。" \
"" \
"こんなツリーを作る" \
"" \
"├── projA (projAのワークツリー)" \
"│ ├── .git" \
"│ ├── README" \
"│ └── share" \
"│ └── Hello.thrift" \
"├── projB (projBのワークツリー)" \
"│ ├── .git" \
"│ ├── README" \
"│ └── share" \
"│ └── Hello.thrift" \
"├── share.git (shareのbareリポジトリ)" \
"└── share (share.gitのワークツリー)" \
" └── .git" \
" └── Hello.thrift"
pause
SQUASH_A=--squash # コメントアウトするとprojAでsubtreeする時にsquashしなくなる
# SQUASH_B=--squash # コメントアウトするとprojBでsubtreeする時にsquashしなくなる
# 前回の実行結果があったら綺麗に消しておく
for i in share.git share projA projB; do
[ -d "$i" ] && rm -fr "$i"
done
##################################################
msg "shareを準備する"
run git init --bare share.git
run git clone share.git share
cd $WORK/share
cat <<EOF > Hello.thrift
namespace cpp share
EOF
run git add Hello.thrift
run git commit -m 'Initial commit'
cat <<EOF > Hello.thrift
namespace cpp share
namespace java share
EOF
run git add Hello.thrift
run git commit -m '2nd commit'
git_log
run git push origin
##################################################
msg "projAを作る"
cd $WORK
run git init projA
cd $WORK/projA
cat <<EOF > README
projA
EOF
run git add README
run git commit -m 'Initial commit'
msg "projAにshareをremote登録する" \
"remoteに登録しなくてもsubtreeできるけれど" \
"毎回url入力する手間が省けるのでremoteに登録しておく"
run git remote add share ../share.git -f
msg "projAにshareをsubtree addする" \
"すなわち..." \
" --prefix=share(のディレクトリに)" \
" (リモート)share/(の)master(ブランチを)" \
" --squash(1つのコミットとして)" \
" -m ...(メッセージ付きでマージしてコミットする)" \
"という意味"
run git subtree add --prefix=share share/master $SQUASH_A -m 'shareをsubtree addする'
pause
git_log
##################################################
msg "projBを作る"
cd $WORK
run git init projB
cd $WORK/projB
cat <<EOF > README
projB
EOF
run git add README
run git commit -m 'Initial commit'
msg "projBにshareをremote登録する"
run git remote add share ../share.git -f
msg "projBにshareをsubtree addする"
run git subtree add --prefix=share share/master $SQUASH_B -m 'shareをsubtree addする'
git_log
##################################################
cd $WORK
msg "ワークツリーの構造"
if which tree > /dev/null; then
tree -I .git -I share.git
else
find . -name '*.git' -prune -or -type f -print
fi
pause
##################################################
cd $WORK/projA
msg "projAでshareを更新する(1)"
cat <<EOF > share/Hello.thrift
namespace cpp share
namespace java share
struct Hello {
1: string hello
}
EOF
run git add share/Hello.thrift
run git commit -m 'projAでshareを更新する(1)'
msg "projAでshareを更新する(2)"
cat <<EOF > share/Hello.thrift
namespace cpp share
namespace java share
struct Hello {
1: string hello
2: string world
}
EOF
run git add share/Hello.thrift
run git commit -m 'projAでshareを更新する(2)'
run git fetch share
run git subtree pull --prefix=share share master $SQUASH_A -m 'projAでpushの前にpull'
run git subtree push --prefix=share share master -m 'projAの成果をpush'
run git fetch share
git_log
##################################################
cd $WORK/projB
msg "projBにshareの更新を取り込む"
run git fetch share
run git subtree pull --prefix=share share master $SQUASH_B -m 'projBにprojAの成果を取り込む'
msg "projBでshareを更新する(1)"
cat <<EOF > share/Hello.thrift
namespace cpp share
namespace java share
struct Hello {
1: string hello;
2: string world;
}
struct World {
1: string hello;
}
EOF
run git add share/Hello.thrift
run git commit -m 'projBでshareを更新する(1)'
msg "projBでshareを更新する(2)"
cat <<EOF > share/Hello.thrift
namespace cpp share
namespace java share
struct Hello {
1: string hello;
2: string world;
}
struct World {
1: string hello;
2: string world;
}
EOF
run git add share/Hello.thrift
run git commit -m 'projBでshareを更新する(2)'
run git fetch share
run git subtree pull --prefix=share share master $SQUASH_B -m 'projBでpushの前にpull'
run git subtree push --prefix=share share master -m 'projBの成果をpush'
run git fetch share
git_log
##################################################
cd $WORK/projA
msg "projAにshareの更新を取り込む"
run git fetch share
run git subtree pull --prefix=share share master $SQUASH_A -m 'projAにprojBの成果を取り込む'
msg "コンフリクトしたので修正する"
run cat share/Hello.thrift
pause
run git checkout --theirs -- share/Hello.thrift
run git add share/Hello.thrift
run git commit -m 'projAにprojBの成果を取り込む(コンフリクトしたよ)'
git_log
##################################################
cd $WORK/projA
msg "projAでshareを更新する(3)"
cat <<EOF > share/Hello.thrift
namespace cpp share
namespace java share
struct Hello {
1: string hello;
2: string world;
3: string smile;
}
struct World {
1: string hello;
2: string world;
}
EOF
run git add share/Hello.thrift
run git commit -m 'projAでshareを更新する(3)'
msg "projAでshareを更新する(4)"
cat <<EOF > share/Hello.thrift
namespace cpp share
namespace java share
struct Hello {
1: string hello;
2: string world;
3: string smile;
}
struct World {
1: string hello;
2: string world;
3: string smile;
}
EOF
run git add share/Hello.thrift
run git commit -m 'projAでshareを更新する(4)'
run git fetch share
run git subtree pull --prefix=share share master $SQUASH_A -m 'projAでpushの前にpull'
run git subtree push --prefix=share share master -m 'projAの成果をpush'
run git fetch share
git_log
##################################################
cd $WORK/projB
msg "projBにshareの更新を取り込む"
run git fetch share
run git subtree pull --prefix=share share master $SQUASH_B -m 'projBにprojAの成果を取り込む'
msg "コンフリクトしたので修正する"
run cat share/Hello.thrift
pause
run git checkout --theirs -- share/Hello.thrift
run git add share/Hello.thrift
run git commit -m 'projBにprojAの成果を取り込む(コンフリクトしたよ)'
##################################################
cd $WORK/share
run git pull
git_log
cd $WORK/projA
run git fetch share
git_log
cd $WORK/projB
run git fetch share
git_log
}
git_log() {
run git --no-pager log --graph --format="[%h]%s %d%n" --all
}
msg() {
echo "**************************************************"
for i in "$@"; do
echo "* $i"
done
echo "**************************************************"
}
run() {
local i j
echo -n "==>"
for i in "$@"; do
j=$(printf "%q" "$i")
[ "$i" == "$j" ] && echo -n " $i" || echo -n " "'"'"$i"'"'
done
echo
"$@"
}
pause() {
if [ -t 1 ]; then
echo "... INPUT [ENTER] TO CONTINUE ..."
read
fi
}
main
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment