Skip to content

Commit 4fb32ed

Browse files
committed
Merge branch 'git-post'
2 parents 1e82256 + 18da057 commit 4fb32ed

File tree

10 files changed

+202
-1
lines changed

10 files changed

+202
-1
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@
121121
/git-pack-objects
122122
/git-pack-refs
123123
/git-patch-id
124+
/git-post
124125
/git-prune
125126
/git-prune-packed
126127
/git-pull

Documentation/git-cherry-pick.adoc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,8 @@ $ git cherry-pick -Xpatience topic^ <4>
252252

253253
SEE ALSO
254254
--------
255-
linkgit:git-revert[1]
255+
linkgit:git-revert[1],
256+
linkgit:git-post[1]
256257
257258
GIT
258259
---

Documentation/git-post.adoc

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
git-post(1)
2+
===========
3+
4+
NAME
5+
----
6+
git-post - Apply a commit on top of a branch that is not checked out
7+
8+
SYNOPSIS
9+
--------
10+
[verse]
11+
'git post' dest-branch [source-rev]
12+
13+
DESCRIPTION
14+
-----------
15+
16+
Applies the changes made by 'source-rev' (or, if not given, `HEAD`)
17+
on top of the branch 'dest-branch' and records a new commit.
18+
'dest-branch' is advanced to point to the new commit.
19+
The operation that this command performs can be regarded as
20+
the opposite of cherry-picking.
21+
22+
EXAMPLES
23+
--------
24+
25+
Assume, while working on a topic, you find and fix an unrelated bug.
26+
Now:
27+
28+
------------
29+
$ git commit <1>
30+
$ git post master <2>
31+
$ git show | git apply -R && git reset HEAD^ <3>
32+
------------
33+
34+
<1> create a commit with the fix on the current branch
35+
<2> copy the fix onto the branch where it ought to be
36+
<3> revert current topic branch to the unfixed state;
37+
can also be done with `git reset --keep HEAD^` if there are no
38+
unstaged changes in files that are modified by the fix
39+
40+
Oftentimes, switching branches triggers a rebuild of a code base.
41+
With the sequence above the branch switch can be avoided.
42+
That said, it is good practice to test the bug fix on the
43+
destination branch eventually.
44+
45+
BUGS
46+
----
47+
48+
The change can be applied on `dest-branch` only if there is
49+
no textual conflict.
50+
51+
SEE ALSO
52+
--------
53+
linkgit:git-cherry-pick[1].
54+
55+
GIT
56+
---
57+
Part of the linkgit:git[1] suite

Documentation/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ manpages = {
100100
'git-pack-objects.adoc' : 1,
101101
'git-pack-refs.adoc' : 1,
102102
'git-patch-id.adoc' : 1,
103+
'git-post.adoc' : 1,
103104
'git-prune-packed.adoc' : 1,
104105
'git-prune.adoc' : 1,
105106
'git-pull.adoc' : 1,

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -717,6 +717,7 @@ SCRIPT_SH += git-merge-octopus.sh
717717
SCRIPT_SH += git-merge-one-file.sh
718718
SCRIPT_SH += git-merge-resolve.sh
719719
SCRIPT_SH += git-mergetool.sh
720+
SCRIPT_SH += git-post.sh
720721
SCRIPT_SH += git-quiltimport.sh
721722
SCRIPT_SH += git-request-pull.sh
722723
SCRIPT_SH += git-submodule.sh

command-list.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ git-pack-objects plumbingmanipulators
150150
git-pack-redundant plumbinginterrogators
151151
git-pack-refs ancillarymanipulators
152152
git-patch-id purehelpers
153+
git-post mainporcelain
153154
git-prune ancillarymanipulators complete
154155
git-prune-packed plumbingmanipulators
155156
git-pull mainporcelain remote

git-post.sh

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
#!/bin/sh
2+
# Copyright (c) 2017 Johannes Sixt
3+
4+
SUBDIRECTORY_OK=Yes
5+
OPTIONS_SPEC="\
6+
git post dest-branch [source-rev]
7+
--
8+
"
9+
. git-sh-setup
10+
11+
while test $# != 0
12+
do
13+
case "$1" in
14+
--) shift; break;;
15+
-*) usage;;
16+
*) break;;
17+
esac
18+
shift
19+
done
20+
21+
dest=$(git rev-parse --verify --symbolic-full-name "$1") || exit
22+
if test -z "$dest"
23+
then
24+
die "$(gettext "Destination must be a branch tip")"
25+
fi
26+
27+
shift
28+
case $# in
29+
0) set -- HEAD;;
30+
1) : good;;
31+
*) usage;;
32+
esac
33+
34+
# apply change to a temporary index
35+
tmpidx=$GIT_DIR/index-post-$$
36+
git read-tree --index-output="$tmpidx" "$dest" || exit
37+
GIT_INDEX_FILE=$tmpidx
38+
export GIT_INDEX_FILE
39+
trap 'rm -f "$tmpidx"' 0 1 2 15
40+
41+
git diff-tree -p --binary -M -C "$1" | git apply --cached || exit
42+
43+
newtree=$(git write-tree) &&
44+
newrev=$(
45+
eval "$(get_author_ident_from_commit "$1")" &&
46+
export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_AUTHOR_DATE
47+
git cat-file commit "$1" | sed -e '1,/^$/d' |
48+
git commit-tree $newtree -p "$dest"
49+
) || exit
50+
51+
if git check-ref-format "$dest"
52+
then
53+
set_reflog_action post
54+
subject=$(git log --no-walk --pretty=%s "$newrev") &&
55+
git update-ref -m "$GIT_REFLOG_ACTION: $subject" "$dest" "$newrev" || exit
56+
fi
57+
if test -z "$GIT_QUIET"
58+
then
59+
git rev-list -1 --oneline "$newrev"
60+
fi

meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1912,6 +1912,7 @@ scripts_sh = [
19121912
'git-merge-resolve.sh',
19131913
'git-mergetool--lib.sh',
19141914
'git-mergetool.sh',
1915+
'git-post.sh',
19151916
'git-quiltimport.sh',
19161917
'git-request-pull.sh',
19171918
'git-sh-i18n.sh',

t/meson.build

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,7 @@ integration_tests = [
399399
't3512-cherry-pick-submodule.sh',
400400
't3513-revert-submodule.sh',
401401
't3514-cherry-pick-revert-gpg.sh',
402+
't3515-post.sh',
402403
't3600-rm.sh',
403404
't3601-rm-pathspec-file.sh',
404405
't3602-rm-sparse-checkout.sh',

t/t3515-post.sh

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
#!/bin/sh
2+
3+
test_description='test git post
4+
5+
We build this history:
6+
7+
A--B--C <-- master, HEAD
8+
/
9+
O <-- side-base, side
10+
11+
Then we post B and C on top of branch "side":
12+
13+
A--B--C <-- master, HEAD
14+
/
15+
O <-- side-base
16+
\
17+
B*--C* <-- side
18+
19+
B has a different author, which must be copied to B*.
20+
'
21+
22+
. ./test-lib.sh
23+
24+
test_expect_success setup '
25+
26+
printf "a%s\n" 1 2 3 4 >file-a &&
27+
printf "b%s\n" 5 6 7 8 >file-b &&
28+
29+
test_tick &&
30+
git add file-a file-b &&
31+
git commit -m initial &&
32+
git tag side-base &&
33+
34+
test_tick &&
35+
echo "Advance master" >>file-a &&
36+
git commit -a -m advance-master &&
37+
38+
test_tick &&
39+
echo "Unrelated fix" >>file-b &&
40+
GIT_AUTHOR_NAME="S O Else" git commit -a -m fix-for-b &&
41+
42+
test_tick &&
43+
echo "Another fix" >>file-b &&
44+
git commit -a -m another-fix-for-b
45+
'
46+
47+
test_expect_success 'post two commits on top of side' '
48+
49+
git branch -f side side-base &&
50+
test_tick &&
51+
git post side HEAD^ &&
52+
test_tick &&
53+
git post side &&
54+
55+
git log --pretty="%at %an %ae %s" HEAD~2.. >expect &&
56+
git log --pretty="%at %an %ae %s" side-base..side >actual &&
57+
58+
test_cmp expect actual &&
59+
git cat-file blob side:file-b >actual &&
60+
test_cmp file-b actual &&
61+
62+
git diff --exit-code side-base side -- file-a # no change
63+
'
64+
65+
test_expect_success 'post requiring merge resolution fails' '
66+
67+
git branch -f side side-base &&
68+
test_must_fail git post side HEAD
69+
'
70+
71+
test_expect_success 'cannot post onto arbitrary commit name' '
72+
73+
git branch -f side side-base &&
74+
test_must_fail git post side^0 HEAD^
75+
'
76+
77+
test_done

0 commit comments

Comments
 (0)