Permalink
Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
executable file 419 lines (326 sloc) 19.6 KB
#!/bin/bash
promptcolor="\033[31m"
bannercolor="\033[32m"
cmdcolor="\033[36m"
commentcolor="\033[1;35m"
sepcolor="\033[37m"
infocolor="\033[1;33m"
errcolor="\033[1;31m"
nocolor="\033[0m"
dood() {
line=$*
firstword=`echo $line | awk -F " " '{print $1}'`
flag=0
for w in /bin/rm git pwd pushd popd echo touch cd cp diff mkdir cat sed; do
if [ "$firstword" == "$w" ]; then
flag=1
fi
done
if [ "$flag" -eq 1 ]; then
echo -e $sepcolor"----------------------------------------------------------------------"$nocolor
# handle comments
cmdall="$*"
cmd=${cmdall%%#*}
comment=${cmdall##*#}
if [ "$cmdall" == "$cmd" ]; then
echo -e $promptcolor"$ "$nocolor$cmdcolor"$cmd"$nocolor
else
echo -e $promptcolor"$ "$nocolor$cmdcolor"$cmd"$commentcolor"#$comment"$nocolor
fi
eval "$cmd"
# let's check the return value (note: ``diff'', ``git merge'', ``git reset HEAD'' and ``git rebase'' are excluded)
retval=$?
if [ $retval -ne 0 ]; then
echo -e $infocolor"\nCommand "$nocolor$errcolor$cmd$nocolor$infocolor"returns non-zero: "$nocolor$errcolor$retval$nocolor$infocolor"."$nocolor
#if [ "$firstword" == "diff" ] || [ "${line:0:9}" == "git merge" ]; then
if [ "$firstword" == "diff" ] || [ "${line:0:9}" == "git merge" ] || [ "${line:0:14}" == "git reset HEAD" ] || [ "${line:0:10}" == "git rebase" ]; then
#echo -e $infocolor"It doesn't matter. Let's continue.\n"$nocolor
echo
else
echo -n -e $infocolor"Press ! to quit, any other key to continue: "$nocolor
read ans
if [ "$ans" == "!" ]; then
exit 100
else
echo -e $infocolor"OK, here we go.\n"$nocolor
fi
fi
fi
else
if [ "${line:0:2}" == "##" ] || [ "${line:0:2}" == "==" ]; then
echo -e $bannercolor"$*"$nocolor
else
echo -e "Error: "$errcolor$line$nocolor
exit 100
fi
fi
}
dood "######################################################################"
dood "/bin/rm -rf remote/"
dood "/bin/rm -rf local/.git local/foo.txt local/bar.txt local/baz.txt"
dood "mkdir remote"
dood "git init --bare remote/doodle.git"
if [ ! -d local ]; then
dood "mkdir local"
fi
dood "pushd local"
dood "======================================================================"
dood "## can we undo a push?"
dood "pwd"
dood "git init # init"
dood "touch foo.txt # create foo.txt"
dood "git add foo.txt"
dood "git commit -m first-commit # first commit"
dood "git remote add origin ../remote/doodle.git"
dood "git push -u origin master # push"
dood "echo a >> foo.txt # modify foo.txt"
dood "cat foo.txt"
dood "git add foo.txt"
dood "git commit -m a # commit a"
dood "git push # push"
dood "echo b >> foo.txt # modify foo.txt"
dood "cat foo.txt"
dood "git add foo.txt"
dood "git commit -m b # commit b"
dood "git push # push"
echo doodle.git.`git log --pretty=oneline | head -n 1 | cut -c1-7`-`head -c10 /dev/urandom | sha1sum | head -c 3` > /tmp/gitdoodle.bakname
dood "cp -r ../remote/doodle.git ../remote/`cat /tmp/gitdoodle.bakname`"
dood "echo This line is supposed to be a bad line in a bad commit-and-push to be undone. >> foo.txt # modify foo.txt"
dood "cat foo.txt"
dood "git add foo.txt"
dood "git commit -m bad # commit bad"
dood "git push # push"
dood "git log --pretty=oneline"
git log --oneline -1 | cut -d' ' -f1 > /tmp/gitdoodle.bad
dood "git push -f origin HEAD^:master # undo push"
dood "git status"
dood "git log --pretty=oneline"
dood "git branch"
dood "git reset --hard HEAD^ # get back to previous commit (will lose working tree)"
dood "git status"
dood "git log --pretty=oneline"
dood "diff -r ../remote/`cat /tmp/gitdoodle.bakname` ../remote/doodle.git # difference before and after push&unpush"
dood "git checkout `cat /tmp/gitdoodle.bad` # the commit's undone, but it's not really gone"
dood "git log --oneline --graph --decorate --all"
dood "cat foo.txt # we see the bad line again"
dood "git checkout master # switch back to 'master'"
dood "git gc # even 'gc' cannot remove it"
dood "git checkout `cat /tmp/gitdoodle.bad` # still here"
dood "git log --oneline --graph --decorate --all # yes, it's still here"
dood "cat foo.txt # ah, we see the bad line again"
dood "git checkout master # switch back to 'master'"
# echo doodle.git.`git log --pretty=oneline | head -n 1 | cut -c1-7`-`head -c10 /dev/urandom | sha1sum | head -c 3` > /tmp/gitdoodle.bakname
# dood "cp -r ../remote/doodle.git ../remote/`cat /tmp/gitdoodle.bakname`"
# dood "echo This line is supposed to be a bad line in a bad commit-and-push to be undone. >> foo.txt # modify foo.txt"
# dood "cat foo.txt"
# dood "git add foo.txt"
# dood "git commit -m bad # commit bad"
# dood "git push # push"
# dood "git log --pretty=oneline"
# dood "git rebase -i HEAD~2 # delete the 2nd line in the editor"
# dood "git push origin +master # undo push"
# dood "git status"
# dood "git log --pretty=oneline"
# dood "diff -r ../remote/`cat /tmp/gitdoodle.bakname` ../remote/doodle.git # difference before and after push&unpush"
dood "echo c >> foo.txt # modify foo.txt"
dood "cat foo.txt"
dood "git add foo.txt"
dood "git commit -m c # commit c"
dood "git push # push"
dood "echo d >> foo.txt # modify foo.txt"
dood "cat foo.txt"
dood "git add foo.txt"
dood "git commit -m d # commit d"
dood "git push # push"
dood "git log --pretty=oneline"
dood "======================================================================"
dood "## branching"
dood "git checkout -b bar # swith to a new branch 'bar' (== git branch bar && git checkout bar)"
dood "touch bar.txt # create bar.txt"
dood "git add bar.txt"
dood "git commit -m e # commit e"
dood "echo a >> bar.txt # modify bar.txt"
dood "git commit -a -m f # commit f"
dood "git branch -v"
dood "git log --oneline --graph --decorate --all"
dood "git checkout master # switch to branch 'master'"
dood "git branch -v"
dood "git log --oneline --graph --decorate --all"
dood "git checkout -b baz # switch to a new branch 'baz'"
dood "touch baz.txt # create baz.txt"
dood "git add baz.txt"
dood "git commit -m g # commit g"
dood "echo a >> baz.txt # modify baz.txt"
dood "git commit -a -m h # commit h"
dood "git branch -v"
dood "git log --oneline --graph --decorate --all"
dood "git checkout master # switch to branch 'master'"
dood "git branch -v"
dood "git log --oneline --graph --decorate --all"
dood "git merge bar # merge branch 'bar'"
dood "git log --oneline --graph --decorate --all"
dood "git branch -d bar # delete branch 'bar'"
dood "git log --oneline --graph --decorate --all"
dood "git checkout baz # switch to branch 'baz'"
dood "echo b >> baz.txt # modify baz.txt"
dood "git commit -a -m i # commit i"
dood "git branch -v"
dood "git log --oneline --graph --decorate --all"
dood "git checkout master # switch to branch 'master'"
dood "git merge baz # merge baz"
dood "git log --oneline --graph --decorate --all"
dood "echo c >> baz.txt # modify baz.txt"
dood "git commit -a -m j # commit j"
dood "git checkout baz # switch to branch 'baz'"
dood "echo d >> baz.txt # modify baz.txt"
dood "git commit -a -m k # commit k"
dood "git log --oneline --graph --decorate --all"
dood "git checkout master # switch to branch 'master'"
dood "git merge baz # merge baz"
dood "git status"
dood "/bin/rm baz.txt"
dood "echo a >> baz.txt"
dood "echo b >> baz.txt"
dood "echo c >> baz.txt # solve conflicts in baz.txt"
dood "git status"
dood "git commit -a -m l # commit l"
dood "git log --oneline --graph --decorate --all"
dood "git push # push 'master'"
dood "git remote show origin # peek remote"
dood "git log --oneline --graph --decorate --all"
dood "git push origin baz # push 'baz'"
dood "git remote show origin # peek remote"
dood "git log --oneline --graph --decorate --all"
dood "git push origin :baz # delete remote 'baz'"
dood "git remote show origin # peek remote"
dood "git log --oneline --graph --decorate --all"
dood "git push origin baz # push 'baz'"
dood "git branch -d baz # delete local 'baz'"
dood "git remote show origin # peek remote"
dood "git log --oneline --graph --decorate --all"
dood "git checkout --track origin/baz # track 'origin/baz'"
dood "git log --oneline --graph --decorate --all"
dood "git checkout master # switch to branch 'master'"
dood "git branch -d baz # delete local 'baz'"
dood "git log --oneline --graph --decorate --all"
dood "git checkout -b baz origin/baz # switch to new tracking branch 'baz'"
dood "git log --oneline --graph --decorate --all"
dood "git checkout master # switch to branch 'master'"
dood "git branch -d baz # delete local 'baz'"
dood "git remote show origin # peek remote"
dood "git log --oneline --graph --decorate --all # peek local"
dood "git push origin :baz # delete remote 'baz'"
dood "git remote show origin # peek remote"
dood "git log --oneline --graph --decorate --all # peek local"
dood "======================================================================"
dood "## more about undo"
dood "git checkout `cat /tmp/gitdoodle.bad` # remember the undone push? the commit's never gone"
dood "git log --oneline --graph --decorate --all # ya it's still here"
dood "cat foo.txt # we see the bad line again"
dood "git checkout master # switch back to 'master'"
dood "cat foo.txt # the latest foo.txt"
for opt in "--hard" "--soft"; do
echo doodle.git.`git log --pretty=oneline | head -n 1 | cut -c1-7`-`head -c10 /dev/urandom | sha1sum | head -c 3` > /tmp/gitdoodle.bakname
dood "cp -r ../remote/doodle.git ../remote/`cat /tmp/gitdoodle.bakname`"
dood "echo blah >> foo.txt # modify foo.txt"
dood "cat foo.txt"
dood "git commit -a -m blah # commit blah"
dood "git log --oneline --graph --decorate --all"
git log --oneline -1 | cut -d' ' -f1 > /tmp/gitdoodle.bad
dood "git reset $opt HEAD^ # undo commit"
dood "git status"
if [ "$opt" == "--soft" ]; then
dood "git reset HEAD foo.txt # unstage foo.txt"
dood "git checkout -- foo.txt # discard changes of foo.txt"
dood "git status"
fi
dood "git log --oneline --graph --decorate --all"
dood "diff -r ../remote/`cat /tmp/gitdoodle.bakname` ../remote/doodle.git # difference before and after push&unpush"
if [ "$opt" == "--hard" ]; then
x="e"
else
x="f"
fi
dood "echo $x >> foo.txt # modify foo.txt"
dood "cat foo.txt"
dood "git commit -a -m m-$x # commit m-$x"
dood "git log --oneline --graph --decorate --all"
dood "git checkout `cat /tmp/gitdoodle.bad` # the commit's undone, but it's not really gone"
dood "git log --oneline --graph --decorate --all"
dood "cat foo.txt # we see it again"
dood "git checkout master # switch back to 'master'"
dood "git gc # even 'gc' cannot remove it"
dood "git checkout `cat /tmp/gitdoodle.bad` # still here"
dood "git log --oneline --graph --decorate --all # yes, it's still here"
dood "cat foo.txt # ah, we see it again"
dood "git checkout master # switch back to 'master'"
dood "git log --oneline --graph --decorate --all"
done
dood "##"
dood "## Summary:"
dood "## if an object is commited:"
dood "## it'll be stored in local repos -- even if the commit is undone"
dood "## if it's pushed:"
dood "## it'll appear in remote repos -- even if the push is undone"
dood "## else:"
dood "## it will not appear in remote repos (GOOD NEWS)"
dood "##"
dood "======================================================================"
dood "## rebase"
dood "git branch bar # new branch 'bar'"
dood "git log --oneline --graph --decorate --all"
dood "echo g >> foo.txt # modify foo.txt"
dood "cat foo.txt"
dood "git commit -a -m n # commit n"
dood "git checkout bar # switch to 'bar'"
dood "echo b >> bar.txt # modify bar.txt"
dood "cat bar.txt"
dood "git commit -a -m o # commit o"
dood "git log --oneline --graph --decorate --all"
dood "git rebase master # rebase (no conflict)"
dood "git log --oneline --graph --decorate --all"
dood "git checkout master # switch to 'master'"
dood "git merge bar # fast-forward"
dood "git log --oneline --graph --decorate --all"
dood "=========================="
dood "## rebasing with conflicts"
dood "echo d >> baz.txt # modify baz.txt"
dood "cat baz.txt"
dood "git commit -a -m p # commit p"
dood "git checkout bar # switch to 'bar'"
dood "echo e >> baz.txt # modify baz.txt"
dood "cat bar.txt"
dood "git commit -a -m q # commit q"
dood "git log --oneline --graph --decorate --all"
dood "git rebase master bar # rebase (with conflict)"
dood "git rebase --abort # abort rebasing"
dood "git status"
dood "git log --oneline --graph --decorate --all"
dood "git rebase master bar # rebase (with conflict)"
dood "git status"
dood "cat baz.txt"
dood "sed -e '/<<<<<<</d' -e '/>>>>>>>/d' -e '/=======/d' -i baz.txt # solve conflicts"
dood "cat baz.txt"
dood "git add baz.txt # tell git that the conflict has been resolved"
dood "git status"
dood "git rebase --continue # continue to rebase"
dood "git status"
dood "git checkout master # switch to 'master'"
dood "git merge bar # fast-forward"
dood "git branch -d bar # delete branch 'bar'"
dood "git log --oneline --graph --decorate --all"
dood "git diff HEAD^^..HEAD^"
dood "git diff HEAD^"
dood "======================================================================"
dood "## tools"
dood "git reflog -30"
dood "git show HEAD@{5}"
dood "git show HEAD~5"
dood "git log origin/master..HEAD"
dood "git push"
dood "git log origin/master..HEAD"
dood "======================================================================"
dood "git log --oneline --graph --decorate --all"
dood "======================================================================"
dood "popd"
dood "######################################################################"