1 #!/nix/var/nix/profiles/per-user/marc/profile/bin/bash
2 # needing bash because of < <( .. ) below
3 # author Marc Weber Th 17. Jul 00:58:14 CEST 2008
5 # TODO: integrate http://thread.gmane.org/gmane.comp.version-control.git/89644 somehow
8 me="git-test-merge" # name of script
10 cont=".git/$me/continue"
11 merge_hist=".git/$me/merge_hist"
14 [ -f "$tmp" ] && rm "$tmp"
15 COMMIT_MESSAGE=" auto merge MERGE - warning, this branch will be rebased, don't base your work on this branch"
17 failmessage="!! git-test-merge failed, log : \`$tmp'\n"
19 echo -en "$failmessage"
20 errors="`egrep 'You have local changes to' "$tmp"`"
23 echo " failure probably caused by"
27 trap 'trappedFailure' EXIT;
32 if egrep -l '^<<<<<<<|^>>>>>>>' "$f" &> /dev/null; then
42 # argv : branch names left to merge
44 while let $(( $# > 0 )); do
45 echo "* merging with $1 ";
46 git merge -m "${COMMIT_MESSAGE/MERGE/$name}" "$1" >> "$tmp" 2>&1 \
48 grep ' does not point to a commit' "$tmp" && { echo ' ^^^^^^^^^^^^ '; exit 1; }
49 echo "probably merge conflicts, have they all been resolved by git-rerere ?"
51 echo -n "checking $f .. "
52 if conflicted "$f"; then
56 echo -e "\n >> \`$f' contains unresolved conflicts"
57 echo "$name" > "$cont"; echo "$@" >> "$cont"
60 [ -n "$conflicted" ] && {
61 echo "resolve conflicts, run $me c to continue"
62 echo " unmerged files will be git-added automatically"
65 done < <( git status | sed -n 's/#\s*unmerged:\s*\(.*\)/\1/p' )
66 # commit ourselves.. and continue
68 git commit -m "${COMMIT_MESSAGE/MERGE/$name}" >> "$tmp" 2>&1
72 logSuccessfulMerge $name
76 echo `date` $name set to `git rev-parse --verify HEAD` >> $merge_hist
82 set -x; gittestmerge "$@";;
85 conflicted "$f" || { echo " \`$f' still contains conflicts, resolve them and continue, exiting"; failmessage=; exit 1; }
86 git add "$f" >> "$tmp" 2>&1
87 done < <( git status | sed -n 's/#\s*unmerged:\s*\(.*\)/\1/p' )
88 { read name; read x; set -- $x; } < $cont
92 git config --get rerere.enabled >>/dev/null || {
93 echo ">> git rerere is disabled, maybe you want to enable it using the following command"
94 echo "# git config rerere.enabled 1"
97 if [ "$names" == "" ]; then
98 names=$(fst $(git config -l | sed -n "s/$me\\.\\([^=]*\\).*/\\1/p"))
102 for name in $names; do
103 echo -e "\nupdating merge $name"
104 set -- `git config --get "$me.$name"`
105 git checkout "$1" >> "$tmp" 2>&1 || {
106 grep 'error: you need to resolve your current index first' "$tmp" && { echo ' ^^^^^^^^^^^^ '; exit 1; }
108 git branch -f "$name" "$1" >> "$tmp" 2>&1; shift # setting it to the first branch, could be another one
109 git checkout "$name" >> "$tmp" 2>&1
111 echo "* merging using octopus"
112 { git merge -s octopus -m "${COMMIT_MESSAGE/MERGE/$name based on $@}" "$@" >> "$tmp" 2>&1 \
113 && logSuccessfulMerge $name
115 grep ' - not something we can merge' "$tmp" && { echo '^^^^^^^^^^^^ '; exit 1; }
116 echo "octopus merge failed, resetting, using git merge multiple times .."
118 # remove all unmerged files before running git reset because I had a case where a file was left in work directory
119 # causing submerge failure
122 done < <( git status | sed -n 's/#\s*unmerged:\s*\(.*\)/\1/p' )
123 git reset --hard >> "$tmp" 2>&1
130 IFS=, git config "$me.$name" "$*"
134 IFS=, git config "$me.$name" "`git config --get "$me.$name"` $*"
137 git config -l | sed -n "s/$me\\.//p"
140 git-test-merge usage:
142 git-test-merge (s or set) name branch1 branch2 branch3
144 git-test-merge (a or add) name b1 b2
145 adds branches b1 b2 to merge name
146 git-test-merge (l or list) shows all defined merge sets
148 git-test-merge (u or update) list of names
149 if you omit the list of names the first entry will be updated
151 git-test-merge (c or continue) will continue merge (this name only)
153 update name will create a new branch called name by merging
154 branch1, branch2, branch3
155 If you commit to branch1 and you want the the merge
156 to be based on the last commit, run update again
158 if your first arg is (d or debug) set -x will be used.
163 gittestmerge "$@"; # on failure script will exit with trap