3 # Merge two revisions of a file
4 # Copyright (c) Linus Torvalds, 2005
5 # Copyright (c) Petr Baudis, 2005, 2006
7 # This is the git per-file merge script, called with
9 # $1 - original file SHA1 (or empty)
10 # $2 - file in branch1 SHA1 (or empty)
11 # $3 - file in branch2 SHA1 (or empty)
12 # $4 - pathname in repository
13 # $5 - original file mode (or empty)
14 # $6 - file in branch1 mode (or empty)
15 # $7 - file in branch2 mode (or empty)
17 # We are designed to merge $3 _to_ $2, so we will give it
20 # FIXME: Make at least some effort to protect against checking in
23 # FIXME: What if a symlink replaces a regular file? What if symlinks conflict?
24 # What about directory-regularfile conflicts?
29 # If set, we are merging local changes, not "real" three trees.
31 .
"${COGITO_LIB}"cg-Xlib ||
exit 1
43 echo "MERGE ERROR: $@" >&2
49 echo "MERGE WARNING: $@" >&2
52 # Returns stuff in $_pmxmc
53 # PlusMinus+XModeChar ;-)
64 # Set ways[] to the symbolic names of the particular ways
65 load_unescaped_sym_ways
()
67 if [ "$_CG_MERGING_LOCAL" ]; then
68 ways
=("original" "local" "target")
70 ways
=("merge base" "$_git_head" "$(cat "$_git/cg-merge-state
/merging-sym
")")
75 load_unescaped_sym_ways
76 ways
[0]="${ways[0]// //}"
77 ways
=("${ways[@]//\//~}")
81 case "${id0:-.}${id1:-.}${id2:-.}" in
83 # Deleted in both or deleted in one and unchanged in the other
85 "$id0.." |
"$id0.$id0" |
"$id0$id0.")
86 #echo "Removing $file"
87 if test -f "$file"; then
90 exec git-update-index
--remove -- "$file"
94 # Deleted in one and changed in the other
96 "$id0$id1." |
"$id0.$id2")
97 #echo "Removing $file"
101 num
=1; mode
="$mode1"; id
="$id1"
103 num
=2; mode
="$mode2"; id
="$id2"
105 while [ -e "$filev~${ways[0]}" ] ||
[ -e "$filev~${ways[$num]}" ]; do
108 error
"File $file removed in one branch but modified in the other!"
109 error
"The original version saved as '$filev~${ways[0]}', the modified one as '$filev~${ways[$num]}'."
110 git-update-index
--add --cacheinfo "$mode0" "$id0" "$file" &&
111 git-checkout-index
-u -f -- "$file" &&
112 mv "$file" "$filev~${ways[0]}" ||
113 error
"Cannot create '$filev~${ways[0]}'"
114 git-update-index
--add --cacheinfo "$mode" "$id" "$file" &&
115 git-checkout-index
-u -f -- "$file" &&
116 mv "$file" "$filev~${ways[$num]}" ||
117 error
"Cannot create '$filev~${ways[$num]}'"
118 git-update-index
--force-remove "$file"
123 ".$id1." |
"..$id2" )
125 git-update-index
--add --cacheinfo "$mode1$mode2" "$id1$id2" "$file" &&
126 exec git-checkout-index
-u -f -- "$file"
130 # Added same in both (check for same permissions).
134 git-update-index
--add --cacheinfo "$mode1" "$id1" "$file" &&
135 git-checkout-index
-u -f -- "$file"
137 if [ "$mode1" != "$mode2" ]; then
138 pmxmc
"$mode2"; chmod ${_pmxmc}x
"$file"
139 error
"$file: added in both branches, permissions conflict $mode1->$mode2 (defaulting to $mode2)"
146 # Added in both (different in each).
152 while [ -e "$filev~${ways[1]}" ] ||
[ -e "$filev~${ways[2]}" ]; do
155 error
"File $file added in both branches, but different in each!"
156 error
"Conflicting versions saved as '$filev~${ways[1]}' and '$filev~${ways[2]}'."
157 git-update-index
--add --cacheinfo "$mode1" "$id1" "$file" &&
158 git-checkout-index
-u -f -- "$file" &&
159 mv "$file" "$filev~${ways[1]}" ||
160 error
"Cannot create '$filev~${ways[1]}'"
161 git-update-index
--add --cacheinfo "$mode2" "$id2" "$file" &&
162 git-checkout-index
-u -f -- "$file" &&
163 mv "$file" "$filev~${ways[2]}" ||
164 error
"Cannot create '$filev~${ways[2]}'"
169 # Modified in both, but differently.
172 echo "... Auto-merging $file"
173 orig
=$
(git-unpack-file
$id0)
174 src2
=$
(git-unpack-file
$id2)
175 merged
=$
(mktemp .mergeresult-XXXXXX
)
177 load_unescaped_sym_ways
178 # We reset the index to the first branch, making
179 # git-diff-file useful
180 git-update-index
--add --cacheinfo "$mode1" "$id1" "$file"
181 git-checkout-index
-u -f -- "$file" &&
182 { diff3 -m -E -L "${ways[1]}" -L "${ways[0]}" -L "${ways[2]}" "$file" "$orig" "$src2" >"$merged"; }
184 rm -f -- "$orig" "$src2"
185 cat "$merged" >"$file"
188 if [ "$mode1" != "$mode2" ]; then
189 if [ "$mode0" = "$mode1" ]; then
194 pmxmc "$moded"; chmod ${_pmxmc}x "$file"
195 error "Permissions conflict
: $mode0->$mode1,$mode2 (defaulting to
$moded)"
199 if [ $ret -ne 0 ]; then
200 echo " CONFLICTS during merge.
" >&2
203 exec git-update-index -- "$file"
207 error "$file: Not handling
case: ${id0:-empty} -> ${id1:-empty} -> ${id2:-empty} (this would be a Cogito bug
, please report it
)"