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
ce2c3eb
Documentation
arm
compat
contrib
git-gui
gitk-git
gitweb
mozilla-sha1
perl
ppc
t
templates
xdiff
.gitattributes
.gitignore
.mailmap
COPYING
GIT-VERSION-GEN
INSTALL
Makefile
README
RelNotes
abspath.c
alias.c
alloc.c
archive-tar.c
archive-zip.c
archive.c
archive.h
attr.c
attr.h
base85.c
blob.c
blob.h
branch.c
branch.h
builtin-add.c
builtin-annotate.c
builtin-apply.c
builtin-archive.c
builtin-blame.c
builtin-branch.c
builtin-bundle.c
builtin-cat-file.c
builtin-check-attr.c
builtin-check-ref-format.c
builtin-checkout-index.c
builtin-checkout.c
builtin-clean.c
builtin-clone.c
builtin-commit-tree.c
builtin-commit.c
builtin-config.c
builtin-count-objects.c
builtin-describe.c
builtin-diff-files.c
builtin-diff-index.c
builtin-diff-tree.c
builtin-diff.c
builtin-fast-export.c
builtin-fetch--tool.c
builtin-fetch-pack.c
builtin-fetch.c
builtin-fmt-merge-msg.c
builtin-for-each-ref.c
builtin-fsck.c
builtin-gc.c
builtin-grep.c
builtin-http-fetch.c
builtin-init-db.c
builtin-log.c
builtin-ls-files.c
builtin-ls-remote.c
builtin-ls-tree.c
builtin-mailinfo.c
builtin-mailsplit.c
builtin-merge-base.c
builtin-merge-file.c
builtin-merge-ours.c
builtin-merge-recursive.c
builtin-merge.c
builtin-mv.c
builtin-name-rev.c
builtin-pack-objects.c
builtin-pack-refs.c
builtin-prune-packed.c
builtin-prune.c
builtin-push.c
builtin-read-tree.c
builtin-reflog.c
builtin-remote.c
builtin-rerere.c
builtin-reset.c
builtin-rev-list.c
builtin-rev-parse.c
builtin-revert.c
builtin-rm.c
builtin-send-pack.c
builtin-shortlog.c
builtin-show-branch.c
builtin-show-ref.c
builtin-stripspace.c
builtin-symbolic-ref.c
builtin-tag.c
builtin-tar-tree.c
builtin-unpack-objects.c
builtin-update-index.c
builtin-update-ref.c
builtin-upload-archive.c
builtin-verify-pack.c
builtin-verify-tag.c
builtin-write-tree.c
builtin.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
combine-diff.c
command-list.txt
commit.c
commit.h
config.c
config.mak.in
configure.ac
connect.c
convert.c
copy.c
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
dump-cache-tree.c
editor.c
entry.c
environment.c
exec_cmd.c
exec_cmd.h
fast-import.c
fetch-pack.h
fixup-builtins
fsck.c
fsck.h
generate-cmdlist.sh
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-filter-branch.sh
git-instaweb.sh
git-lost-found.sh
git-merge-octopus.sh
git-merge-one-file.sh
git-merge-resolve.sh
git-mergetool.sh
git-parse-remote.sh
git-pull.sh
git-quiltimport.sh
git-rebase--interactive.sh
git-rebase.sh
git-relink.perl
git-repack.sh
git-request-pull.sh
git-send-email.perl
git-sh-setup.sh
git-stash.sh
git-submodule.sh
git-svn.perl
git-web--browse.sh
git.c
git.spec.in
graph.c
graph.h
grep.c
grep.h
hash-object.c
hash.c
hash.h
help.c
http-push.c
http-walker.c
http.c
http.h
ident.c
imap-send.c
index-pack.c
interpolate.c
interpolate.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-file.c
merge-index.c
merge-recursive.h
merge-tree.c
mktag.c
mktree.c
name-hash.c
object.c
object.h
pack-check.c
pack-redundant.c
pack-refs.c
pack-refs.h
pack-revindex.c
pack-revindex.h
pack-write.c
pack.h
pager.c
parse-options.c
parse-options.h
patch-delta.c
patch-id.c
patch-ids.c
patch-ids.h
path.c
pkt-line.c
pkt-line.h
pretty.c
progress.c
progress.h
quote.c
quote.h
reachable.c
reachable.h
read-cache.c
receive-pack.c
reflog-walk.c
reflog-walk.h
refs.c
refs.h
remote.c
remote.h
rerere.c
rerere.h
revision.c
revision.h
run-command.c
run-command.h
send-pack.h
server-info.c
setup.c
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
strbuf.c
strbuf.h
string-list.c
string-list.h
symlinks.c
tag.c
tag.h
tar.h
test-chmtime.c
test-date.c
test-delta.c
test-genrandom.c
test-match-trees.c
test-parse-options.c
test-path-utils.c
test-sha1.c
test-sha1.sh
thread-utils.c
thread-utils.h
trace.c
transport.c
transport.h
tree-diff.c
tree-walk.c
tree-walk.h
tree.c
tree.h
unpack-file.c
unpack-trees.c
unpack-trees.h
update-server-info.c
upload-pack.c
usage.c
utf8.c
utf8.h
var.c
walker.c
walker.h
wrapper.c
write_or_die.c
ws.c
wt-status.c
wt-status.h
xdiff-interface.c
xdiff-interface.h
Breadcrumbs
git
/
git-mergetool.sh
Blame
Blame
Latest commit
History
History
executable file
·
426 lines (389 loc) · 9.69 KB
Breadcrumbs
git
/
git-mergetool.sh
Top
File metadata and controls
Code
Blame
executable file
·
426 lines (389 loc) · 9.69 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] [file to merge] ...' SUBDIRECTORY_OK=Yes OPTIONS_SPEC= . git-sh-setup require_work_tree prefix=$(git rev-parse --show-prefix) # Returns true if the mode reflects a symlink is_symlink () { test "$1" = 120000 } 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 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")'" else if base_present; then echo "modified" else echo "created" fi fi } resolve_symlink_merge () { while true; do printf "Use (l)ocal or (r)emote, or (a)bort? " read ans case "$ans" in [lL]*) git checkout-index -f --stage=2 -- "$MERGED" git add -- "$MERGED" cleanup_temp_files --save-backup return ;; [rR]*) git checkout-index -f --stage=3 -- "$MERGED" git add -- "$MERGED" cleanup_temp_files --save-backup return ;; [aA]*) exit 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 case "$ans" in [mMcC]*) git add -- "$MERGED" cleanup_temp_files --save-backup return ;; [dD]*) git rm -- "$MERGED" > /dev/null cleanup_temp_files return ;; [aA]*) exit 1 ;; esac done } check_unchanged () { if test "$MERGED" -nt "$BACKUP" ; then status=0; else while true; do echo "$MERGED seems unchanged." printf "Was the merge successful? [y/n] " read answer < /dev/tty case "$answer" in y*|Y*) status=0; break ;; n*|N*) status=1; break ;; esac done 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 exit 1 fi ext="$$$(expr "$MERGED" : '.*\(\.[^/]*\)$')" BACKUP="./$MERGED.BACKUP.$ext" LOCAL="./$MERGED.LOCAL.$ext" REMOTE="./$MERGED.REMOTE.$ext" BASE="./$MERGED.BASE.$ext" mv -- "$MERGED" "$BACKUP" cp -- "$BACKUP" "$MERGED" 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;}'` base_present && git cat-file blob ":1:$prefix$MERGED" >"$BASE" 2>/dev/null local_present && git cat-file blob ":2:$prefix$MERGED" >"$LOCAL" 2>/dev/null remote_present && git cat-file blob ":3:$prefix$MERGED" >"$REMOTE" 2>/dev/null 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" printf "Hit return to start merge resolution tool (%s): " "$merge_tool" read ans case "$merge_tool" in kdiff3) if base_present ; then ("$merge_tool_path" --auto --L1 "$MERGED (Base)" --L2 "$MERGED (Local)" --L3 "$MERGED (Remote)" \ -o "$MERGED" "$BASE" "$LOCAL" "$REMOTE" > /dev/null 2>&1) else ("$merge_tool_path" --auto --L1 "$MERGED (Local)" --L2 "$MERGED (Remote)" \ -o "$MERGED" "$LOCAL" "$REMOTE" > /dev/null 2>&1) fi status=$? ;; tkdiff) if base_present ; then "$merge_tool_path" -a "$BASE" -o "$MERGED" "$LOCAL" "$REMOTE" else "$merge_tool_path" -o "$MERGED" "$LOCAL" "$REMOTE" fi status=$? ;; meld|vimdiff) touch "$BACKUP" "$merge_tool_path" "$LOCAL" "$MERGED" "$REMOTE" check_unchanged ;; gvimdiff) touch "$BACKUP" "$merge_tool_path" -f "$LOCAL" "$MERGED" "$REMOTE" check_unchanged ;; xxdiff) touch "$BACKUP" if base_present ; then "$merge_tool_path" -X --show-merged-pane \ -R 'Accel.SaveAsMerged: "Ctrl-S"' \ -R 'Accel.Search: "Ctrl+F"' \ -R 'Accel.SearchForward: "Ctrl-G"' \ --merged-file "$MERGED" "$LOCAL" "$BASE" "$REMOTE" else "$merge_tool_path" -X --show-merged-pane \ -R 'Accel.SaveAsMerged: "Ctrl-S"' \ -R 'Accel.Search: "Ctrl+F"' \ -R 'Accel.SearchForward: "Ctrl-G"' \ --merged-file "$MERGED" "$LOCAL" "$REMOTE" fi check_unchanged ;; opendiff) touch "$BACKUP" if base_present; then "$merge_tool_path" "$LOCAL" "$REMOTE" -ancestor "$BASE" -merge "$MERGED" | cat else "$merge_tool_path" "$LOCAL" "$REMOTE" -merge "$MERGED" | cat fi check_unchanged ;; ecmerge) touch "$BACKUP" if base_present; then "$merge_tool_path" "$BASE" "$LOCAL" "$REMOTE" --default --mode=merge3 --to="$MERGED" else "$merge_tool_path" "$LOCAL" "$REMOTE" --default --mode=merge2 --to="$MERGED" fi check_unchanged ;; emerge) if base_present ; then "$merge_tool_path" -f emerge-files-with-ancestor-command "$LOCAL" "$REMOTE" "$BASE" "$(basename "$MERGED")" else "$merge_tool_path" -f emerge-files-command "$LOCAL" "$REMOTE" "$(basename "$MERGED")" fi status=$? ;; *) if test -n "$merge_tool_cmd"; then if test "$merge_tool_trust_exit_code" = "false"; then touch "$BACKUP" ( eval $merge_tool_cmd ) check_unchanged else ( eval $merge_tool_cmd ) status=$? fi fi ;; esac if test "$status" -ne 0; then echo "merge of $MERGED failed" 1>&2 mv -- "$BACKUP" "$MERGED" exit 1 fi if test "$merge_keep_backup" = "true"; then mv -- "$BACKUP" "$MERGED.orig" else rm -- "$BACKUP" fi git add -- "$MERGED" cleanup_temp_files } while test $# != 0 do case "$1" in -t|--tool*) case "$#,$1" in *,*=*) merge_tool=`expr "z$1" : 'z-[^=]*=\(.*\)'` ;; 1,*) usage ;; *) merge_tool="$2" shift ;; esac ;; --) shift break ;; -*) usage ;; *) break ;; esac shift done valid_custom_tool() { merge_tool_cmd="$(git config mergetool.$1.cmd)" test -n "$merge_tool_cmd" } valid_tool() { case "$1" in kdiff3 | tkdiff | xxdiff | meld | opendiff | emerge | vimdiff | gvimdiff | ecmerge) ;; # happy *) if ! valid_custom_tool "$1"; then return 1 fi ;; esac } init_merge_tool_path() { merge_tool_path=`git config mergetool.$1.path` if test -z "$merge_tool_path" ; then case "$1" in emerge) merge_tool_path=emacs ;; *) merge_tool_path=$1 ;; esac fi } if test -z "$merge_tool"; then merge_tool=`git config merge.tool` if test -n "$merge_tool" && ! valid_tool "$merge_tool"; then echo >&2 "git config option merge.tool set to unknown tool: $merge_tool" echo >&2 "Resetting to default..." unset merge_tool fi fi if test -z "$merge_tool" ; then if test -n "$DISPLAY"; then merge_tool_candidates="kdiff3 tkdiff xxdiff meld gvimdiff" if test -n "$GNOME_DESKTOP_SESSION_ID" ; then merge_tool_candidates="meld $merge_tool_candidates" fi if test "$KDE_FULL_SESSION" = "true"; then merge_tool_candidates="kdiff3 $merge_tool_candidates" fi fi if echo "${VISUAL:-$EDITOR}" | grep 'emacs' > /dev/null 2>&1; then merge_tool_candidates="$merge_tool_candidates emerge" fi if echo "${VISUAL:-$EDITOR}" | grep 'vim' > /dev/null 2>&1; then merge_tool_candidates="$merge_tool_candidates vimdiff" fi merge_tool_candidates="$merge_tool_candidates opendiff emerge vimdiff" echo "merge tool candidates: $merge_tool_candidates" for i in $merge_tool_candidates; do init_merge_tool_path $i if type "$merge_tool_path" > /dev/null 2>&1; then merge_tool=$i break fi done if test -z "$merge_tool" ; then echo "No known merge resolution program available." exit 1 fi else if ! valid_tool "$merge_tool"; then echo >&2 "Unknown merge_tool $merge_tool" exit 1 fi init_merge_tool_path "$merge_tool" merge_keep_backup="$(git config --bool merge.keepBackup || echo true)" if test -z "$merge_tool_cmd" && ! type "$merge_tool_path" > /dev/null 2>&1; then echo "The merge tool $merge_tool is not available as '$merge_tool_path'" exit 1 fi if ! test -z "$merge_tool_cmd"; then merge_tool_trust_exit_code="$(git config --bool mergetool.$merge_tool.trustExitCode || echo false)" fi fi if test $# -eq 0 ; then files=`git ls-files -u | sed -e 's/^[^ ]* //' | sort -u` if test -z "$files" ; then echo "No files need merging" exit 0 fi echo Merging the files: "$files" git ls-files -u | sed -e 's/^[^ ]* //' | sort -u | while IFS= read i do printf "\n" merge_file "$i" < /dev/tty > /dev/tty done else while test $# -gt 0; do printf "\n" merge_file "$1" shift done fi exit 0
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
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
426
You can’t perform that action at this time.