Merge branch 'th/difftool-diffall'
[git] / contrib / examples / git-resolve.sh
1 #!/bin/sh
2 #
3 # Copyright (c) 2005 Linus Torvalds
4 #
5 # Resolve two trees.
6 #
7
8 echo 'WARNING: This command is DEPRECATED and will be removed very soon.' >&2
9 echo 'WARNING: Please use git-merge or git-pull instead.' >&2
10 sleep 2
11
12 USAGE='<head> <remote> <merge-message>'
13 . git-sh-setup
14
15 dropheads() {
16         rm -f -- "$GIT_DIR/MERGE_HEAD" \
17                 "$GIT_DIR/LAST_MERGE" || exit 1
18 }
19
20 head=$(git rev-parse --verify "$1"^0) &&
21 merge=$(git rev-parse --verify "$2"^0) &&
22 merge_name="$2" &&
23 merge_msg="$3" || usage
24
25 #
26 # The remote name is just used for the message,
27 # but we do want it.
28 #
29 if [ -z "$head" -o -z "$merge" -o -z "$merge_msg" ]; then
30         usage
31 fi
32
33 dropheads
34 echo $head > "$GIT_DIR"/ORIG_HEAD
35 echo $merge > "$GIT_DIR"/LAST_MERGE
36
37 common=$(git merge-base $head $merge)
38 if [ -z "$common" ]; then
39         die "Unable to find common commit between" $merge $head
40 fi
41
42 case "$common" in
43 "$merge")
44         echo "Already up-to-date. Yeeah!"
45         dropheads
46         exit 0
47         ;;
48 "$head")
49         echo "Updating $(git rev-parse --short $head)..$(git rev-parse --short $merge)"
50         git read-tree -u -m $head $merge || exit 1
51         git update-ref -m "resolve $merge_name: Fast-forward" \
52                 HEAD "$merge" "$head"
53         git diff-tree -p $head $merge | git apply --stat
54         dropheads
55         exit 0
56         ;;
57 esac
58
59 # We are going to make a new commit.
60 git var GIT_COMMITTER_IDENT >/dev/null || exit
61
62 # Find an optimum merge base if there are more than one candidates.
63 LF='
64 '
65 common=$(git merge-base -a $head $merge)
66 case "$common" in
67 ?*"$LF"?*)
68         echo "Trying to find the optimum merge base."
69         G=.tmp-index$$
70         best=
71         best_cnt=-1
72         for c in $common
73         do
74                 rm -f $G
75                 GIT_INDEX_FILE=$G git read-tree -m $c $head $merge \
76                         2>/dev/null || continue
77                 # Count the paths that are unmerged.
78                 cnt=`GIT_INDEX_FILE=$G git ls-files --unmerged | wc -l`
79                 if test $best_cnt -le 0 -o $cnt -le $best_cnt
80                 then
81                         best=$c
82                         best_cnt=$cnt
83                         if test "$best_cnt" -eq 0
84                         then
85                                 # Cannot do any better than all trivial merge.
86                                 break
87                         fi
88                 fi
89         done
90         rm -f $G
91         common="$best"
92 esac
93
94 echo "Trying to merge $merge into $head using $common."
95 git update-index --refresh 2>/dev/null
96 git read-tree -u -m $common $head $merge || exit 1
97 result_tree=$(git write-tree  2> /dev/null)
98 if [ $? -ne 0 ]; then
99         echo "Simple merge failed, trying Automatic merge"
100         git-merge-index -o git-merge-one-file -a
101         if [ $? -ne 0 ]; then
102                 echo $merge > "$GIT_DIR"/MERGE_HEAD
103                 die "Automatic merge failed, fix up by hand"
104         fi
105         result_tree=$(git write-tree) || exit 1
106 fi
107 result_commit=$(echo "$merge_msg" | git commit-tree $result_tree -p $head -p $merge)
108 echo "Committed merge $result_commit"
109 git update-ref -m "resolve $merge_name: In-index merge" \
110         HEAD "$result_commit" "$head"
111 git diff-tree -p $head $result_commit | git apply --stat
112 dropheads