show all unresolved files and some additional errors
[git-test-merge.git] / git-test-merge
blobbfdaee7acbf87ed1ef8dd83a0b40b0af523311d3
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
6 set -e
8 me="git-test-merge" # name of script
9 tmp=".git/$me/tmp"
10 cont=".git/$me/continue"
11 mkdir -p ".git/$me"
12 [ -f "$tmp" ] && rm "$tmp"
13 COMMIT_MESSAGE=" auto merge MERGE  - warning, this branch will be rebased, don't base your work on this branch" 
15 failmessage="!!        git-test-merge failed, log : \`$tmp'\n"
16 trap  'echo -en "$failmessage"' EXIT;
17 echo log is "$tmp"
19 conflicted(){
20   for f in "$@"; do
21     if egrep -l '^<<<<<<<|^>>>>>>>'  "$f" &> /dev/null; then
22       return 1
23     fi
24   done
25   return 0
28 fst(){ echo "$1"; }
30 submerge(){
31   while let $(( $# > 0 )); do
32     echo "* merging with $1 ";
33     git merge -m "${COMMIT_MESSAGE/MERGE/$name}" "$1" >> "$tmp" 2>&1 \
34     || { 
35     grep ' does not point to a commit' "$tmp" && { echo '        ^^^^^^^^^^^^ ';  exit 1; }
36     echo "probably merge conflicts, have they all been resolved by git-rerere ?"
37       while read -er f; do
38         echo -n "checking $f .. "
39         if conflicted "$f"; then
40           echo -e "\n >>    \`$f' contains unresolved conflicts"
41           echo "$name" > "$cont"; echo "$@" >> "$cont"
42           conflicted=1
43         else
44           echo "resolved"
45           git add "$f"
46         fi
47         [ -n "$conflicted" ] && { 
48           echo "resolve conflicts, run   $me c to continue"
49           echo " unmerged files will be git-added automatically"
50           exit 1
51         }
52       done < <( git status | sed -n 's/#\s*unmerged:\s*\(.*\)/\1/p' )
53       # commit ourselves.. and continue 
54       echo "continuing"
55       git commit -m "${COMMIT_MESSAGE/MERGE/$name}" >> "$tmp" 2>&1
56    }
57     shift; 
58   done # submerge
61 gittestmerge(){
62   case "$1" in
63     d|debug) shift
64       set -x; gittestmerge "$@";;
65     c|continue)
66       while read -er f; do
67         conflicted "$f" || { echo " \`$f' still contains conflicts, resolve them and continue, exiting"; failmessage=; exit 1; }
68         git add "$f" >> "$tmp" 2>&1
69       done < <( git status | sed -n 's/#\s*unmerged:\s*\(.*\)/\1/p' )
70       cat $cont | { read name; read x; set $x --; }
71       submerge "$@"
72     ;;
73     u|update) shift
74       git config --get rerere.enabled >>/dev/null || {
75         echo ">> git rerere is disabled, maybe you want to enable it using the following command"
76         echo "# git config rerere.enabled 1"
77       }
78       names=$1;
79       if [ "$names" == "" ]; then
80         names=$(fst "$(git config -l | sed -n "s/$me\\.\\([^=]*\\).*/\\1/p")")
81       else
82         shift
83       fi
84       for name in $names; do
85         echo -e "\nupdating merge $name"
86         set -- `git config --get "$me.$name"`
87         git checkout "$1" >> "$tmp" 2>&1 || {
88           grep 'error: you need to resolve your current index first' "$tmp" && { echo '        ^^^^^^^^^^^^ ';  exit 1; }
89         }
90         git branch -f "$name" "$1" >> "$tmp" 2>&1; shift # setting it to the first branch, could be another one
91         git checkout "$name" >> "$tmp" 2>&1
92         # try octopus first
93         echo "* merging using octopus"
94         git merge -s octopus -m "${COMMIT_MESSAGE/MERGE/$name based on $@}" "$@" >> "$tmp" 2>&1 \
95         || {
96           grep ' - not something we can merge' "$tmp" && { echo '^^^^^^^^^^^^ ';  exit 1; }
97           echo "octopus merge failed, resetting, using git merge multiple times .."
98           git reset --hard  >> "$tmp" 2>&1
99           submerge "$@"
100         }
101       done
102     ;;
103     s|set) shift
104       name="$1"; shift
105       IFS=, git config "$me.$name" "$*"
106     ;;
107     a|add) shift
108       name="$1"; shift
109       IFS=, git config "$me.$name" "`git config --get "$me.$name"` $*"
110     ;;
111     l|list)
112       git config -l | sed -n "s/$me\\.//p"
113     ;;
114     *) echo '
115       git-test-merge usage:
117       git-test-merge (s or set) name branch1 branch2 branch3
118          defines b
119       git-test-merge (a or add) name b1 b2
120          adds branches b1 b2 to merge name
121       git-test-merge (l or list) shows all defined merge sets
123       git-test-merge (u or update) list of names
124       if you omit the list of names the first entry will be updated
126       git-test-merge (c or continue) will continue merge (this name only)
128       update name will create a new branch called name by merging
129               branch1, branch2, branch3
130       If you commit to branch1 and you want the the merge
131       to be based on the last commit, run update again
133       if your first arg is (d or debug) set -x will be used.
134       ';;
135   esac
138 gittestmerge "$@"; # on failure script will exit with trap
139 failmessage=