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
09f8d05
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-am.sh
Blame
Blame
Latest commit
Stephan Beyer
and
Junio C Hamano
git-am: Mention --abort in usage string part of OPTIONS_SPEC
Jul 26, 2008
09f8d05
·
Jul 26, 2008
History
History
executable file
·
529 lines (480 loc) · 12.4 KB
Breadcrumbs
git
/
git-am.sh
Top
File metadata and controls
Code
Blame
executable file
·
529 lines (480 loc) · 12.4 KB
Raw
#!/bin/sh # # Copyright (c) 2005, 2006 Junio C Hamano SUBDIRECTORY_OK=Yes OPTIONS_KEEPDASHDASH= OPTIONS_SPEC="\ git am [options] [<mbox>|<Maildir>...] git am [options] (--resolved | --skip | --abort) -- d,dotest= (removed -- do not use) i,interactive run interactively b,binary pass --allow-binary-replacement to git-apply 3,3way allow fall back on 3way merging if needed s,signoff add a Signed-off-by line to the commit message u,utf8 recode into utf8 (default) k,keep pass -k flag to git-mailinfo whitespace= pass it through git-apply C= pass it through git-apply p= pass it through git-apply resolvemsg= override error message when patch failure occurs r,resolved to be used after a patch failure skip skip the current patch abort restore the original branch and abort the patching operation. rebasing (internal use for git-rebase)" . git-sh-setup prefix=$(git rev-parse --show-prefix) set_reflog_action am require_work_tree cd_to_toplevel git var GIT_COMMITTER_IDENT >/dev/null || die "You need to set your committer info first" stop_here () { echo "$1" >"$dotest/next" exit 1 } stop_here_user_resolve () { if [ -n "$resolvemsg" ]; then printf '%s\n' "$resolvemsg" stop_here $1 fi cmdline="git am" if test '' != "$interactive" then cmdline="$cmdline -i" fi if test '' != "$threeway" then cmdline="$cmdline -3" fi echo "When you have resolved this problem run \"$cmdline --resolved\"." echo "If you would prefer to skip this patch, instead run \"$cmdline --skip\"." echo "To restore the original branch and stop patching run \"$cmdline --abort\"." stop_here $1 } go_next () { rm -f "$dotest/$msgnum" "$dotest/msg" "$dotest/msg-clean" \ "$dotest/patch" "$dotest/info" echo "$next" >"$dotest/next" this=$next } cannot_fallback () { echo "$1" echo "Cannot fall back to three-way merge." exit 1 } fall_back_3way () { O_OBJECT=`cd "$GIT_OBJECT_DIRECTORY" && pwd` rm -fr "$dotest"/patch-merge-* mkdir "$dotest/patch-merge-tmp-dir" # First see if the patch records the index info that we can use. git apply --build-fake-ancestor "$dotest/patch-merge-tmp-index" \ "$dotest/patch" && GIT_INDEX_FILE="$dotest/patch-merge-tmp-index" \ git write-tree >"$dotest/patch-merge-base+" || cannot_fallback "Repository lacks necessary blobs to fall back on 3-way merge." echo Using index info to reconstruct a base tree... if GIT_INDEX_FILE="$dotest/patch-merge-tmp-index" \ git apply $binary --cached <"$dotest/patch" then mv "$dotest/patch-merge-base+" "$dotest/patch-merge-base" mv "$dotest/patch-merge-tmp-index" "$dotest/patch-merge-index" else cannot_fallback "Did you hand edit your patch? It does not apply to blobs recorded in its index." fi test -f "$dotest/patch-merge-index" && his_tree=$(GIT_INDEX_FILE="$dotest/patch-merge-index" git write-tree) && orig_tree=$(cat "$dotest/patch-merge-base") && rm -fr "$dotest"/patch-merge-* || exit 1 echo Falling back to patching base and 3-way merge... # This is not so wrong. Depending on which base we picked, # orig_tree may be wildly different from ours, but his_tree # has the same set of wildly different changes in parts the # patch did not touch, so recursive ends up canceling them, # saying that we reverted all those changes. eval GITHEAD_$his_tree='"$FIRSTLINE"' export GITHEAD_$his_tree git-merge-recursive $orig_tree -- HEAD $his_tree || { git rerere echo Failed to merge in the changes. exit 1 } unset GITHEAD_$his_tree } prec=4 dotest="$GIT_DIR/rebase-apply" sign= utf8=t keep= skip= interactive= resolved= binary= rebasing= abort= resolvemsg= resume= git_apply_opt= while test $# != 0 do case "$1" in -i|--interactive) interactive=t ;; -b|--binary) binary=t ;; -3|--3way) threeway=t ;; -s|--signoff) sign=t ;; -u|--utf8) utf8=t ;; # this is now default --no-utf8) utf8= ;; -k|--keep) keep=t ;; -r|--resolved) resolved=t ;; --skip) skip=t ;; --abort) abort=t ;; --rebasing) rebasing=t threeway=t keep=t binary=t ;; -d|--dotest) die "-d option is no longer supported. Do not use." ;; --resolvemsg) shift; resolvemsg=$1 ;; --whitespace) git_apply_opt="$git_apply_opt $1=$2"; shift ;; -C|-p) git_apply_opt="$git_apply_opt $1$2"; shift ;; --) shift; break ;; *) usage ;; esac shift done # If the dotest directory exists, but we have finished applying all the # patches in them, clear it out. if test -d "$dotest" && last=$(cat "$dotest/last") && next=$(cat "$dotest/next") && test $# != 0 && test "$next" -gt "$last" then rm -fr "$dotest" fi if test -d "$dotest" then case "$#,$skip$resolved$abort" in 0,*t*) # Explicit resume command and we do not have file, so # we are happy. : ;; 0,) # No file input but without resume parameters; catch # user error to feed us a patch from standard input # when there is already $dotest. This is somewhat # unreliable -- stdin could be /dev/null for example # and the caller did not intend to feed us a patch but # wanted to continue unattended. tty -s ;; *) false ;; esac || die "previous rebase directory $dotest still exists but mbox given." resume=yes case "$skip,$abort" in t,) git rerere clear git read-tree --reset -u HEAD HEAD orig_head=$(cat "$GIT_DIR/ORIG_HEAD") git reset HEAD git update-ref ORIG_HEAD $orig_head ;; ,t) git rerere clear git read-tree --reset -u HEAD ORIG_HEAD git reset ORIG_HEAD rm -fr "$dotest" exit ;; esac else # Make sure we are not given --skip, --resolved, nor --abort test "$skip$resolved$abort" = "" || die "Resolve operation not in progress, we are not resuming." # Start afresh. mkdir -p "$dotest" || exit if test -n "$prefix" && test $# != 0 then first=t for arg do test -n "$first" && { set x first= } case "$arg" in /*) set "$@" "$arg" ;; *) set "$@" "$prefix$arg" ;; esac done shift fi git mailsplit -d"$prec" -o"$dotest" -b -- "$@" > "$dotest/last" || { rm -fr "$dotest" exit 1 } # -b, -s, -u, -k and --whitespace flags are kept for the # resuming session after a patch failure. # -3 and -i can and must be given when resuming. echo "$binary" >"$dotest/binary" echo " $ws" >"$dotest/whitespace" echo "$sign" >"$dotest/sign" echo "$utf8" >"$dotest/utf8" echo "$keep" >"$dotest/keep" echo 1 >"$dotest/next" if test -n "$rebasing" then : >"$dotest/rebasing" else : >"$dotest/applying" git update-ref ORIG_HEAD HEAD fi fi case "$resolved" in '') files=$(git diff-index --cached --name-only HEAD --) || exit if [ "$files" ]; then echo "Dirty index: cannot apply patches (dirty: $files)" >&2 exit 1 fi esac if test "$(cat "$dotest/binary")" = t then binary=--allow-binary-replacement fi if test "$(cat "$dotest/utf8")" = t then utf8=-u else utf8=-n fi if test "$(cat "$dotest/keep")" = t then keep=-k fi ws=`cat "$dotest/whitespace"` if test "$(cat "$dotest/sign")" = t then SIGNOFF=`git-var GIT_COMMITTER_IDENT | sed -e ' s/>.*/>/ s/^/Signed-off-by: /' ` else SIGNOFF= fi last=`cat "$dotest/last"` this=`cat "$dotest/next"` if test "$skip" = t then this=`expr "$this" + 1` resume= fi if test "$this" -gt "$last" then echo Nothing to do. rm -fr "$dotest" exit fi while test "$this" -le "$last" do msgnum=`printf "%0${prec}d" $this` next=`expr "$this" + 1` test -f "$dotest/$msgnum" || { resume= go_next continue } # If we are not resuming, parse and extract the patch information # into separate files: # - info records the authorship and title # - msg is the rest of commit log message # - patch is the patch body. # # When we are resuming, these files are either already prepared # by the user, or the user can tell us to do so by --resolved flag. case "$resume" in '') git mailinfo $keep $utf8 "$dotest/msg" "$dotest/patch" \ <"$dotest/$msgnum" >"$dotest/info" || stop_here $this # skip pine's internal folder data grep '^Author: Mail System Internal Data$' \ <"$dotest"/info >/dev/null && go_next && continue test -s "$dotest/patch" || { echo "Patch is empty. Was it split wrong?" stop_here $this } if test -f "$dotest/rebasing" && commit=$(sed -e 's/^From \([0-9a-f]*\) .*/\1/' \ -e q "$dotest/$msgnum") && test "$(git cat-file -t "$commit")" = commit then git cat-file commit "$commit" | sed -e '1,/^$/d' >"$dotest/msg-clean" else SUBJECT="$(sed -n '/^Subject/ s/Subject: //p' "$dotest/info")" case "$keep_subject" in -k) SUBJECT="[PATCH] $SUBJECT" ;; esac (printf '%s\n\n' "$SUBJECT"; cat "$dotest/msg") | git stripspace > "$dotest/msg-clean" fi ;; esac GIT_AUTHOR_NAME="$(sed -n '/^Author/ s/Author: //p' "$dotest/info")" GIT_AUTHOR_EMAIL="$(sed -n '/^Email/ s/Email: //p' "$dotest/info")" GIT_AUTHOR_DATE="$(sed -n '/^Date/ s/Date: //p' "$dotest/info")" if test -z "$GIT_AUTHOR_EMAIL" then echo "Patch does not have a valid e-mail address." stop_here $this fi export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_AUTHOR_DATE case "$resume" in '') if test '' != "$SIGNOFF" then LAST_SIGNED_OFF_BY=` sed -ne '/^Signed-off-by: /p' \ "$dotest/msg-clean" | sed -ne '$p' ` ADD_SIGNOFF=` test "$LAST_SIGNED_OFF_BY" = "$SIGNOFF" || { test '' = "$LAST_SIGNED_OFF_BY" && echo echo "$SIGNOFF" }` else ADD_SIGNOFF= fi { if test -s "$dotest/msg-clean" then cat "$dotest/msg-clean" fi if test '' != "$ADD_SIGNOFF" then echo "$ADD_SIGNOFF" fi } >"$dotest/final-commit" ;; *) case "$resolved$interactive" in tt) # This is used only for interactive view option. git diff-index -p --cached HEAD -- >"$dotest/patch" ;; esac esac resume= if test "$interactive" = t then test -t 0 || die "cannot be interactive without stdin connected to a terminal." action=again while test "$action" = again do echo "Commit Body is:" echo "--------------------------" cat "$dotest/final-commit" echo "--------------------------" printf "Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all " read reply case "$reply" in [yY]*) action=yes ;; [aA]*) action=yes interactive= ;; [nN]*) action=skip ;; [eE]*) git_editor "$dotest/final-commit" action=again ;; [vV]*) action=again LESS=-S ${PAGER:-less} "$dotest/patch" ;; *) action=again ;; esac done else action=yes fi FIRSTLINE=$(sed 1q "$dotest/final-commit") if test $action = skip then go_next continue fi if test -x "$GIT_DIR"/hooks/applypatch-msg then "$GIT_DIR"/hooks/applypatch-msg "$dotest/final-commit" || stop_here $this fi printf 'Applying: %s\n' "$FIRSTLINE" case "$resolved" in '') git apply $git_apply_opt $binary --index "$dotest/patch" apply_status=$? ;; t) # Resolved means the user did all the hard work, and # we do not have to do any patch application. Just # trust what the user has in the index file and the # working tree. resolved= git diff-index --quiet --cached HEAD -- && { echo "No changes - did you forget to use 'git add'?" stop_here_user_resolve $this } unmerged=$(git ls-files -u) if test -n "$unmerged" then echo "You still have unmerged paths in your index" echo "did you forget to use 'git add'?" stop_here_user_resolve $this fi apply_status=0 git rerere ;; esac if test $apply_status = 1 && test "$threeway" = t then if (fall_back_3way) then # Applying the patch to an earlier tree and merging the # result may have produced the same tree as ours. git diff-index --quiet --cached HEAD -- && { echo No changes -- Patch already applied. go_next continue } # clear apply_status -- we have successfully merged. apply_status=0 fi fi if test $apply_status != 0 then echo Patch failed at $msgnum. stop_here_user_resolve $this fi if test -x "$GIT_DIR"/hooks/pre-applypatch then "$GIT_DIR"/hooks/pre-applypatch || stop_here $this fi tree=$(git write-tree) && parent=$(git rev-parse --verify HEAD) && commit=$(git commit-tree $tree -p $parent <"$dotest/final-commit") && git update-ref -m "$GIT_REFLOG_ACTION: $FIRSTLINE" HEAD $commit $parent || stop_here $this if test -x "$GIT_DIR"/hooks/post-applypatch then "$GIT_DIR"/hooks/post-applypatch fi go_next done git gc --auto rm -fr "$dotest"
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
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
You can’t perform that action at this time.