Skip to content
Navigation Menu
Toggle navigation
Sign in
In this repository
All GitHub Enterprise
↵
Jump to
↵
No suggested jump to results
In this repository
All GitHub Enterprise
↵
Jump to
↵
In this organization
All GitHub Enterprise
↵
Jump to
↵
In this repository
All GitHub Enterprise
↵
Jump to
↵
Sign in
Reseting focus
You signed in with another tab or window.
Reload
to refresh your session.
You signed out in another tab or window.
Reload
to refresh your session.
You switched accounts on another tab or window.
Reload
to refresh your session.
Dismiss alert
{{ message }}
git-mirror
/
git
Public
Notifications
You must be signed in to change notification settings
Fork
0
Star
0
Code
Issues
0
Pull requests
0
Actions
Projects
0
Security
Insights
Additional navigation options
Code
Issues
Pull requests
Actions
Projects
Security
Insights
Files
9a8c2b6
Documentation
block-sha1
builtin
compat
contrib
ewah
git-gui
gitk-git
gitweb
mergetools
perl
po
ppc
t
templates
vcs-svn
xdiff
.gitattributes
.gitignore
.mailmap
COPYING
GIT-VERSION-GEN
INSTALL
LGPL-2.1
Makefile
README
RelNotes
abspath.c
aclocal.m4
advice.c
advice.h
alias.c
alloc.c
archive-tar.c
archive-zip.c
archive.c
archive.h
argv-array.c
argv-array.h
attr.c
attr.h
base85.c
bisect.c
bisect.h
blob.c
blob.h
branch.c
branch.h
builtin.h
bulk-checkin.c
bulk-checkin.h
bundle.c
bundle.h
cache-tree.c
cache-tree.h
cache.h
check-builtins.sh
check-racy.c
check_bindir
color.c
color.h
column.c
column.h
combine-diff.c
command-list.txt
commit-slab.h
commit.c
commit.h
config.c
config.mak.in
config.mak.uname
configure.ac
connect.c
connect.h
connected.c
connected.h
convert.c
convert.h
copy.c
credential-cache--daemon.c
credential-cache.c
credential-store.c
credential.c
credential.h
csum-file.c
csum-file.h
ctype.c
daemon.c
date.c
decorate.c
decorate.h
delta.h
diff-delta.c
diff-lib.c
diff-no-index.c
diff.c
diff.h
diffcore-break.c
diffcore-delta.c
diffcore-order.c
diffcore-pickaxe.c
diffcore-rename.c
diffcore.h
dir.c
dir.h
editor.c
entry.c
environment.c
exec_cmd.c
exec_cmd.h
fast-import.c
fetch-pack.c
fetch-pack.h
fmt-merge-msg.h
fsck.c
fsck.h
generate-cmdlist.sh
gettext.c
gettext.h
git-add--interactive.perl
git-am.sh
git-archimport.perl
git-bisect.sh
git-compat-util.h
git-cvsexportcommit.perl
git-cvsimport.perl
git-cvsserver.perl
git-difftool--helper.sh
git-difftool.perl
git-filter-branch.sh
git-instaweb.sh
git-merge-octopus.sh
git-merge-one-file.sh
git-merge-resolve.sh
git-mergetool--lib.sh
git-mergetool.sh
git-p4.py
git-parse-remote.sh
git-pull.sh
git-quiltimport.sh
git-rebase--am.sh
git-rebase--interactive.sh
git-rebase--merge.sh
git-rebase.sh
git-relink.perl
git-remote-testgit.sh
git-request-pull.sh
git-send-email.perl
git-sh-i18n.sh
git-sh-setup.sh
git-stash.sh
git-submodule.sh
git-svn.perl
git-web--browse.sh
git.c
git.rc
git.spec.in
gpg-interface.c
gpg-interface.h
graph.c
graph.h
grep.c
grep.h
hashmap.c
hashmap.h
help.c
help.h
hex.c
http-backend.c
http-fetch.c
http-push.c
http-walker.c
http.c
http.h
ident.c
imap-send.c
khash.h
kwset.c
kwset.h
levenshtein.c
levenshtein.h
line-log.c
line-log.h
line-range.c
line-range.h
list-objects.c
list-objects.h
ll-merge.c
ll-merge.h
lockfile.c
log-tree.c
log-tree.h
mailmap.c
mailmap.h
match-trees.c
merge-blobs.c
merge-blobs.h
merge-recursive.c
merge-recursive.h
merge.c
mergesort.c
mergesort.h
name-hash.c
notes-cache.c
notes-cache.h
notes-merge.c
notes-merge.h
notes-utils.c
notes-utils.h
notes.c
notes.h
object.c
object.h
pack-bitmap-write.c
pack-bitmap.c
pack-bitmap.h
pack-check.c
pack-objects.c
pack-objects.h
pack-revindex.c
pack-revindex.h
pack-write.c
pack.h
pager.c
parse-options-cb.c
parse-options.c
parse-options.h
patch-delta.c
patch-ids.c
patch-ids.h
path.c
pathspec.c
pathspec.h
pkt-line.c
pkt-line.h
preload-index.c
pretty.c
prio-queue.c
prio-queue.h
progress.c
progress.h
prompt.c
prompt.h
quote.c
quote.h
reachable.c
reachable.h
read-cache.c
reflog-walk.c
reflog-walk.h
refs.c
refs.h
remote-curl.c
remote-testsvn.c
remote.c
remote.h
replace_object.c
rerere.c
rerere.h
resolve-undo.c
resolve-undo.h
revision.c
revision.h
run-command.c
run-command.h
send-pack.c
send-pack.h
sequencer.c
sequencer.h
server-info.c
setup.c
sh-i18n--envsubst.c
sha1-array.c
sha1-array.h
sha1-lookup.c
sha1-lookup.h
sha1_file.c
sha1_name.c
shallow.c
shell.c
shortlog.h
show-index.c
sideband.c
sideband.h
sigchain.c
sigchain.h
strbuf.c
strbuf.h
streaming.c
streaming.h
string-list.c
string-list.h
submodule.c
submodule.h
symlinks.c
tag.c
tag.h
tar.h
test-chmtime.c
test-ctype.c
test-date.c
test-delta.c
test-dump-cache-tree.c
test-genrandom.c
test-hashmap.c
test-index-version.c
test-line-buffer.c
test-match-trees.c
test-mergesort.c
test-mktemp.c
test-parse-options.c
test-path-utils.c
test-prio-queue.c
test-read-cache.c
test-regex.c
test-revision-walking.c
test-run-command.c
test-scrap-cache-tree.c
test-sha1.c
test-sha1.sh
test-sigchain.c
test-string-list.c
test-subprocess.c
test-svn-fe.c
test-urlmatch-normalization.c
test-wildmatch.c
thread-utils.c
thread-utils.h
trace.c
transport-helper.c
transport.c
transport.h
tree-diff.c
tree-walk.c
tree-walk.h
tree.c
tree.h
unimplemented.sh
unix-socket.c
unix-socket.h
unpack-trees.c
unpack-trees.h
upload-pack.c
url.c
url.h
urlmatch.c
urlmatch.h
usage.c
userdiff.c
userdiff.h
utf8.c
utf8.h
varint.c
varint.h
version.c
version.h
versioncmp.c
walker.c
walker.h
wildmatch.c
wildmatch.h
wrap-for-bin.sh
wrapper.c
write_or_die.c
ws.c
wt-status.c
wt-status.h
xdiff-interface.c
xdiff-interface.h
zlib.c
Breadcrumbs
git
/
git-mergetool.sh
Blame
Blame
Latest commit
History
History
executable file
·
425 lines (383 loc) · 8.18 KB
Breadcrumbs
git
/
git-mergetool.sh
Top
File metadata and controls
Code
Blame
executable file
·
425 lines (383 loc) · 8.18 KB
Raw
#!/bin/sh # # This program resolves merge conflicts in git # # Copyright (c) 2006 Theodore Y. Ts'o # # This file is licensed under the GPL v2, or a later version # at the discretion of Junio C Hamano. # USAGE='[--tool=tool] [--tool-help] [-y|--no-prompt|--prompt] [file to merge] ...' SUBDIRECTORY_OK=Yes OPTIONS_SPEC= TOOL_MODE=merge . git-sh-setup . git-mergetool--lib require_work_tree # Returns true if the mode reflects a symlink is_symlink () { test "$1" = 120000 } is_submodule () { test "$1" = 160000 } local_present () { test -n "$local_mode" } remote_present () { test -n "$remote_mode" } base_present () { test -n "$base_mode" } cleanup_temp_files () { if test "$1" = --save-backup then rm -rf -- "$MERGED.orig" test -e "$BACKUP" && mv -- "$BACKUP" "$MERGED.orig" rm -f -- "$LOCAL" "$REMOTE" "$BASE" else rm -f -- "$LOCAL" "$REMOTE" "$BASE" "$BACKUP" fi } describe_file () { mode="$1" branch="$2" file="$3" printf " {%s}: " "$branch" if test -z "$mode" then echo "deleted" elif is_symlink "$mode" then echo "a symbolic link -> '$(cat "$file")'" elif is_submodule "$mode" then echo "submodule commit $file" elif base_present then echo "modified file" else echo "created file" fi } resolve_symlink_merge () { while true do printf "Use (l)ocal or (r)emote, or (a)bort? " read ans || return 1 case "$ans" in [lL]*) git checkout-index -f --stage=2 -- "$MERGED" git add -- "$MERGED" cleanup_temp_files --save-backup return 0 ;; [rR]*) git checkout-index -f --stage=3 -- "$MERGED" git add -- "$MERGED" cleanup_temp_files --save-backup return 0 ;; [aA]*) return 1 ;; esac done } resolve_deleted_merge () { while true do if base_present then printf "Use (m)odified or (d)eleted file, or (a)bort? " else printf "Use (c)reated or (d)eleted file, or (a)bort? " fi read ans || return 1 case "$ans" in [mMcC]*) git add -- "$MERGED" cleanup_temp_files --save-backup return 0 ;; [dD]*) git rm -- "$MERGED" > /dev/null cleanup_temp_files return 0 ;; [aA]*) return 1 ;; esac done } resolve_submodule_merge () { while true do printf "Use (l)ocal or (r)emote, or (a)bort? " read ans || return 1 case "$ans" in [lL]*) if ! local_present then if test -n "$(git ls-tree HEAD -- "$MERGED")" then # Local isn't present, but it's a subdirectory git ls-tree --full-name -r HEAD -- "$MERGED" | git update-index --index-info || exit $? else test -e "$MERGED" && mv -- "$MERGED" "$BACKUP" git update-index --force-remove "$MERGED" cleanup_temp_files --save-backup fi elif is_submodule "$local_mode" then stage_submodule "$MERGED" "$local_sha1" else git checkout-index -f --stage=2 -- "$MERGED" git add -- "$MERGED" fi return 0 ;; [rR]*) if ! remote_present then if test -n "$(git ls-tree MERGE_HEAD -- "$MERGED")" then # Remote isn't present, but it's a subdirectory git ls-tree --full-name -r MERGE_HEAD -- "$MERGED" | git update-index --index-info || exit $? else test -e "$MERGED" && mv -- "$MERGED" "$BACKUP" git update-index --force-remove "$MERGED" fi elif is_submodule "$remote_mode" then ! is_submodule "$local_mode" && test -e "$MERGED" && mv -- "$MERGED" "$BACKUP" stage_submodule "$MERGED" "$remote_sha1" else test -e "$MERGED" && mv -- "$MERGED" "$BACKUP" git checkout-index -f --stage=3 -- "$MERGED" git add -- "$MERGED" fi cleanup_temp_files --save-backup return 0 ;; [aA]*) return 1 ;; esac done } stage_submodule () { path="$1" submodule_sha1="$2" mkdir -p "$path" || die "fatal: unable to create directory for module at $path" # Find $path relative to work tree work_tree_root=$(cd_to_toplevel && pwd) work_rel_path=$(cd "$path" && GIT_WORK_TREE="${work_tree_root}" git rev-parse --show-prefix ) test -n "$work_rel_path" || die "fatal: unable to get path of module $path relative to work tree" git update-index --add --replace --cacheinfo 160000 "$submodule_sha1" "${work_rel_path%/}" || die } checkout_staged_file () { tmpfile=$(expr \ "$(git checkout-index --temp --stage="$1" "$2" 2>/dev/null)" \ : '\([^ ]*\) ') if test $? -eq 0 -a -n "$tmpfile" then mv -- "$(git rev-parse --show-cdup)$tmpfile" "$3" else >"$3" fi } merge_file () { MERGED="$1" f=$(git ls-files -u -- "$MERGED") if test -z "$f" then if test ! -f "$MERGED" then echo "$MERGED: file not found" else echo "$MERGED: file does not need merging" fi return 1 fi ext="$$$(expr "$MERGED" : '.*\(\.[^/]*\)$')" BACKUP="./$MERGED.BACKUP.$ext" LOCAL="./$MERGED.LOCAL.$ext" REMOTE="./$MERGED.REMOTE.$ext" BASE="./$MERGED.BASE.$ext" base_mode=$(git ls-files -u -- "$MERGED" | awk '{if ($3==1) print $1;}') local_mode=$(git ls-files -u -- "$MERGED" | awk '{if ($3==2) print $1;}') remote_mode=$(git ls-files -u -- "$MERGED" | awk '{if ($3==3) print $1;}') if is_submodule "$local_mode" || is_submodule "$remote_mode" then echo "Submodule merge conflict for '$MERGED':" local_sha1=$(git ls-files -u -- "$MERGED" | awk '{if ($3==2) print $2;}') remote_sha1=$(git ls-files -u -- "$MERGED" | awk '{if ($3==3) print $2;}') describe_file "$local_mode" "local" "$local_sha1" describe_file "$remote_mode" "remote" "$remote_sha1" resolve_submodule_merge return fi mv -- "$MERGED" "$BACKUP" cp -- "$BACKUP" "$MERGED" checkout_staged_file 1 "$MERGED" "$BASE" checkout_staged_file 2 "$MERGED" "$LOCAL" checkout_staged_file 3 "$MERGED" "$REMOTE" if test -z "$local_mode" -o -z "$remote_mode" then echo "Deleted merge conflict for '$MERGED':" describe_file "$local_mode" "local" "$LOCAL" describe_file "$remote_mode" "remote" "$REMOTE" resolve_deleted_merge return fi if is_symlink "$local_mode" || is_symlink "$remote_mode" then echo "Symbolic link merge conflict for '$MERGED':" describe_file "$local_mode" "local" "$LOCAL" describe_file "$remote_mode" "remote" "$REMOTE" resolve_symlink_merge return fi echo "Normal merge conflict for '$MERGED':" describe_file "$local_mode" "local" "$LOCAL" describe_file "$remote_mode" "remote" "$REMOTE" if "$prompt" = true then printf "Hit return to start merge resolution tool (%s): " "$merge_tool" read ans || return 1 fi if base_present then present=true else present=false fi if ! run_merge_tool "$merge_tool" "$present" then echo "merge of $MERGED failed" 1>&2 mv -- "$BACKUP" "$MERGED" if test "$merge_keep_temporaries" = "false" then cleanup_temp_files fi return 1 fi if test "$merge_keep_backup" = "true" then mv -- "$BACKUP" "$MERGED.orig" else rm -- "$BACKUP" fi git add -- "$MERGED" cleanup_temp_files return 0 } prompt=$(git config --bool mergetool.prompt || echo true) while test $# != 0 do case "$1" in --tool-help) show_tool_help ;; -t|--tool*) case "$#,$1" in *,*=*) merge_tool=$(expr "z$1" : 'z-[^=]*=\(.*\)') ;; 1,*) usage ;; *) merge_tool="$2" shift ;; esac ;; -y|--no-prompt) prompt=false ;; --prompt) prompt=true ;; --) shift break ;; -*) usage ;; *) break ;; esac shift done prompt_after_failed_merge () { while true do printf "Continue merging other unresolved paths (y/n) ? " read ans || return 1 case "$ans" in [yY]*) return 0 ;; [nN]*) return 1 ;; esac done } if test -z "$merge_tool" then merge_tool=$(get_merge_tool "$merge_tool") || exit fi merge_keep_backup="$(git config --bool mergetool.keepBackup || echo true)" merge_keep_temporaries="$(git config --bool mergetool.keepTemporaries || echo false)" last_status=0 rollup_status=0 files= if test $# -eq 0 then cd_to_toplevel if test -e "$GIT_DIR/MERGE_RR" then files=$(git rerere remaining) else files=$(git ls-files -u | sed -e 's/^[^ ]* //' | sort -u) fi else files=$(git ls-files -u -- "$@" | sed -e 's/^[^ ]* //' | sort -u) fi if test -z "$files" then echo "No files need merging" exit 0 fi printf "Merging:\n" printf "%s\n" "$files" IFS=' ' for i in $files do if test $last_status -ne 0 then prompt_after_failed_merge || exit 1 fi printf "\n" merge_file "$i" last_status=$? if test $last_status -ne 0 then rollup_status=1 fi done exit $rollup_status
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
You can’t perform that action at this time.