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 ;-)
56 if [ "$1" = "755" ]; then
63 # Set ways[] to the symbolic names of the particular ways
64 load_unescaped_sym_ways
()
66 if [ "$_CG_MERGING_LOCAL" ]; then
67 ways
=("original" "local" "target")
69 ways
=("merge base" "$_git_head" "$(cat "$_git/cg-merge-state
/merging-sym
")")
74 load_unescaped_sym_ways
75 ways
[0]="${ways[0]// //}"
76 ways
=("${ways[@]//\//~}")
80 case "${id0:-.}${id1:-.}${id2:-.}" in
82 # Deleted in both or deleted in one and unchanged in the other
84 "$id0.." |
"$id0.$id0" |
"$id0$id0.")
85 #echo "Removing $file"
86 if test -f "$file"; then
89 exec git-update-index
--remove -- "$file"
93 # Deleted in one and changed in the other
95 "$id0$id1." |
"$id0.$id2")
96 #echo "Removing $file"
100 num
=1; mode
="$mode1"; id
="$id1"
102 num
=2; mode
="$mode2"; id
="$id2"
104 while [ -e "$filev~${ways[0]}" ] ||
[ -e "$filev~${ways[$num]}" ]; do
107 error
"File $file removed in one branch but modified in the other!"
108 error
"The original version saved as '$filev~${ways[0]}', the modified one as '$filev~${ways[$num]}'."
109 git-update-index
--add --cacheinfo "$mode0" "$id0" "$file" &&
110 git-checkout-index
-u -f -- "$file" &&
111 mv "$file" "$filev~${ways[0]}" ||
112 error
"Cannot create '$filev~${ways[0]}'"
113 git-update-index
--add --cacheinfo "$mode" "$id" "$file" &&
114 git-checkout-index
-u -f -- "$file" &&
115 mv "$file" "$filev~${ways[$num]}" ||
116 error
"Cannot create '$filev~${ways[$num]}'"
117 git-update-index
--force-remove "$file"
122 ".$id1." |
"..$id2" )
124 git-update-index
--add --cacheinfo "$mode1$mode2" "$id1$id2" "$file" &&
125 exec git-checkout-index
-u -f -- "$file"
129 # Added same in both (check for same permissions).
133 git-update-index
--add --cacheinfo "$mode1" "$id1" "$file" &&
134 git-checkout-index
-u -f -- "$file"
136 if [ "$mode1" != "$mode2" ]; then
137 pmxmc
"$mode2"; chmod ${_pmxmc}x
"$file"
138 error
"$file: added in both branches, permissions conflict $mode1->$mode2 (defaulting to $mode2)"
145 # Added in both (different in each).
151 while [ -e "$filev~${ways[1]}" ] ||
[ -e "$filev~${ways[2]}" ]; do
154 error
"File $file added in both branches, but different in each!"
155 error
"Conflicting versions saved as '$filev~${ways[1]}' and '$filev~${ways[2]}'."
156 git-update-index
--add --cacheinfo "$mode1" "$id1" "$file" &&
157 git-checkout-index
-u -f -- "$file" &&
158 mv "$file" "$filev~${ways[1]}" ||
159 error
"Cannot create '$filev~${ways[1]}'"
160 git-update-index
--add --cacheinfo "$mode2" "$id2" "$file" &&
161 git-checkout-index
-u -f -- "$file" &&
162 mv "$file" "$filev~${ways[2]}" ||
163 error
"Cannot create '$filev~${ways[2]}'"
168 # Modified in both, but differently.
171 echo "... Auto-merging $file"
172 orig
=$
(git-unpack-file
$id0)
173 src2
=$
(git-unpack-file
$id2)
174 merged
=$
(mktemp .mergeresult-XXXXXX
)
176 load_unescaped_sym_ways
177 # We reset the index to the first branch, making
178 # git-diff-file useful
179 git-update-index
--add --cacheinfo "$mode1" "$id1" "$file"
180 git-checkout-index
-u -f -- "$file" &&
181 { diff3 -m -E -L "${ways[1]}" -L "${ways[0]}" -L "${ways[2]}" "$file" "$orig" "$src2" >"$merged"; }
183 rm -f -- "$orig" "$src2"
184 cat "$merged" >"$file"
187 if [ "$mode1" != "$mode2" ]; then
188 if [ "$mode0" = "$mode1" ]; then
193 pmxmc "$moded"; chmod ${_pmxmc}x "$file"
194 error "Permissions conflict
: $mode0->$mode1,$mode2 (defaulting to
$moded)"
198 if [ $ret -ne 0 ]; then
199 echo " CONFLICTS during merge.
" >&2
202 exec git-update-index -- "$file"
206 error "$file: Not handling
case: ${id0:-empty} -> ${id1:-empty} -> ${id2:-empty} (this would be a Cogito bug
, please report it
)"