Add Meta/Reintegrate
In a workflow that uses topic branches heavily, you would need to keep
updating test integration branch(es) all the time. If they are managed
like my 'next' by merging the tips of topics that have grown since the
last integration, it is not so difficult. You only need to review output
from "git branch --no-merged next" to see if there are topics that can and
needs to be merged to 'next'.
But sometimes it is easier to rebuild a test integration branch from
scratch all the time, especially if you do not publish it for others to
build on.
I've been using this script for some time to rebuild jch and pu branches
in my workflow. jch's tip is supposed to always match 'next', but it is
rebuilt from scratch on top of 'master' by merging the same topics that
are in 'next'. You can use the same script in your work.
To use it, you give a commit range base..tip to the script, and you will
see a shell script that uses a series of 'git-merge'. "base" is the more
stable branch that you rebuild your test integration branch on top (in my
case, 'master'), and "tip" is where the tip of the test integration branch
is from the last round (in my case, 'jch' or 'pu').
Then you can run the resulting script, fix conflicted merge and use
'git-commit', and then repeat until all the branches are re-integrated on
top of the base branch.
$ Meta/Reintegrate master..jch >/var/tmp/redo-jch.sh
$ cat /var/tmp/redo-jch.sh
#!/bin/sh
while read branch eh
do
case "$eh" in
"") git merge "$branch" || break ;;
?*) echo >&2 "Eh? $branch $eh"; break ;;
esac
done <<EOF
jc/blame
js/notes
ks/maint-mailinfo-folded~3
tr/previous-branch
EOF
$ git checkout jch
$ git reset --hard master
$ /var/tmp/redo-jch.sh
... if there is conflict, resolve, "git commit" here ...
$ /var/tmp/redo-jch.sh
... repeat until everything is applied.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
16 years ago
|
|
|
#!/bin/sh
|
|
|
|
|
|
|
|
accept_rerere="--rerere-autoupdate" generate=no update= diff= edit= stop_at_cut=
|
|
|
|
while case "$#,$1" in 0,*) break;; *,-*) ;; esac
|
|
|
|
do
|
|
|
|
case "$1" in
|
|
|
|
-n) accept_rerere= ;;
|
|
|
|
-e) edit=t ;;
|
|
|
|
-c) stop_at_cut=1 ;;
|
|
|
|
-c?*) stop_at_cut=${1#-c} ;;
|
|
|
|
-d) update=${2?"diff with what?"}
|
|
|
|
diff=yes
|
|
|
|
generate=yes
|
|
|
|
shift ;;
|
|
|
|
-u) update=${2?"update what?"}
|
|
|
|
generate=yes
|
|
|
|
shift ;;
|
|
|
|
*) generate=yes
|
|
|
|
break ;;
|
|
|
|
esac
|
|
|
|
shift
|
|
|
|
done
|
|
|
|
|
|
|
|
annotate_merge () {
|
|
|
|
test -f Meta/whats-cooking.txt || return 0
|
|
|
|
|
|
|
|
perl -e '
|
|
|
|
sub wildo_match {
|
|
|
|
s/^\s*//;
|
|
|
|
if (/^Will (?:\S+ ){0,2}(fast-track|keep|merge|drop|discard|cook|kick|defer|be re-?rolled)[,. ]/ ||
|
|
|
|
/^Not urgent/ || /^Not ready/ || /^Waiting for / ||
|
|
|
|
/^Can wait in / ||
|
|
|
|
/^Needs? / || /^Expecting / || /^May want to /) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
my ($branch) = $ARGV[0];
|
|
|
|
my ($in_section, $in_desc);
|
|
|
|
my @msg = ();
|
|
|
|
while (<STDIN>) {
|
|
|
|
chomp;
|
|
|
|
if (/^\* $branch /) {
|
|
|
|
$in_section = 1;
|
|
|
|
next;
|
|
|
|
}
|
|
|
|
last if (/^[-*\[]/ && $in_section);
|
|
|
|
next unless $in_section;
|
|
|
|
s/^\s+//;
|
|
|
|
if (/^$/) {
|
|
|
|
$in_desc = 1;
|
|
|
|
}
|
|
|
|
next unless ($in_section && $in_desc);
|
|
|
|
next if (/Originally merged to '\''next'\'' on ([-0-9]+)/);
|
|
|
|
next if (wildo_match($_));
|
|
|
|
push @msg, "$_\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($in_section && @msg) {
|
|
|
|
open(my $fh, "-|", qw(git cat-file commit HEAD));
|
|
|
|
my @original = (<$fh>);
|
|
|
|
close $fh;
|
|
|
|
my @final;
|
|
|
|
$in_section = 0;
|
|
|
|
for (@original) {
|
|
|
|
if (!$in_section) {
|
|
|
|
$in_section = 1 if (/^$/);
|
|
|
|
next;
|
|
|
|
}
|
|
|
|
if (/^Conflicts:$/ && $in_section == 2) {
|
|
|
|
$in_section = 3;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($in_section == 3) {
|
|
|
|
$_ = "# $_";
|
|
|
|
}
|
|
|
|
push @final, $_;
|
|
|
|
if (/^$/ && $in_section == 1) {
|
|
|
|
push @final, @msg;
|
|
|
|
push @final, "\n";
|
|
|
|
$in_section = 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
open($fh, "|-", qw(git commit --amend -F -));
|
|
|
|
print $fh @final;
|
|
|
|
close $fh;
|
|
|
|
}
|
|
|
|
' <Meta/whats-cooking.txt "$1"
|
|
|
|
}
|
|
|
|
|
|
|
|
case "$generate" in
|
|
|
|
no)
|
|
|
|
accept_rerere () {
|
|
|
|
if ! git write-tree 2>/dev/null >/dev/null
|
|
|
|
then
|
|
|
|
git rerere remaining
|
|
|
|
return 1
|
|
|
|
else
|
|
|
|
EDITOR=: git commit --no-verify
|
|
|
|
echo "Accepted previous resolution"
|
|
|
|
return 0
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
|
|
|
mark_cut () {
|
|
|
|
test -n "$stop_at_cut" && return
|
|
|
|
|
|
|
|
count_since_last_cut=$(( $count_since_last_cut + 1 ))
|
|
|
|
test -z "$prev_cut" && return
|
|
|
|
git commit --allow-empty -m "$prev_cut"
|
|
|
|
prev_cut=
|
|
|
|
}
|
|
|
|
|
|
|
|
cut_seen=0 prev_cut= count_since_last_cut=0
|
|
|
|
while read branch eh
|
|
|
|
do
|
|
|
|
case "$branch" in '###') cut_seen=$(( $cut_seen + 1 )) ;; esac
|
|
|
|
if test -n "$stop_at_cut" && test $stop_at_cut -le $cut_seen
|
|
|
|
then
|
|
|
|
continue ;# slurp the remainder and skip
|
|
|
|
fi
|
|
|
|
|
|
|
|
case "$branch" in
|
|
|
|
'###')
|
|
|
|
if test "$count_since_last_cut" = 0
|
|
|
|
then
|
|
|
|
prev_cut=
|
|
|
|
else
|
|
|
|
echo >&2 "$branch $eh"
|
|
|
|
prev_cut="$branch $eh"
|
|
|
|
count_since_last_cut=0
|
|
|
|
fi
|
|
|
|
continue ;;
|
|
|
|
'#'* | '')
|
|
|
|
continue ;;
|
|
|
|
esac
|
|
|
|
|
|
|
|
case "$eh" in
|
|
|
|
"" | "#"*)
|
|
|
|
echo >&2 "* $branch"
|
|
|
|
|
|
|
|
save=$(git rev-parse --verify HEAD) &&
|
|
|
|
tip=$(git rev-parse --verify "$branch^0") &&
|
|
|
|
mb=$(git merge-base "$tip" "$save") ||
|
|
|
|
exit
|
|
|
|
|
|
|
|
test "$mb" = "$tip" && continue
|
|
|
|
|
|
|
|
mark_cut
|
|
|
|
|
|
|
|
rebuild=$(git config "branch.$branch.rebuild" || :)
|
|
|
|
|
|
|
|
EDITOR=: git merge $rebuild $accept_rerere --edit "$branch" ||
|
|
|
|
accept_rerere ||
|
|
|
|
exit
|
|
|
|
|
|
|
|
annotate_merge "$branch" || exit
|
|
|
|
test -z "$edit" ||
|
|
|
|
git commit --amend || exit
|
|
|
|
|
|
|
|
this=$(git rev-parse --verify HEAD)
|
|
|
|
if test "$this" = "$save"
|
|
|
|
then
|
|
|
|
:
|
|
|
|
elif git show-ref -q --verify "refs/merge-fix/$branch"
|
|
|
|
then
|
|
|
|
echo >&2 "Fixing up the merge"
|
|
|
|
git cherry-pick --no-commit "refs/merge-fix/$branch" &&
|
|
|
|
EDITOR=: git commit --amend -a || exit
|
|
|
|
fi
|
|
|
|
;;
|
|
|
|
pick" "*)
|
|
|
|
echo >&2 "* $eh"
|
|
|
|
|
|
|
|
mark_cut
|
|
|
|
|
|
|
|
git cherry-pick "$branch" || exit ;;
|
|
|
|
*) echo >&2 "Eh? $branch $eh"; exit ;;
|
|
|
|
esac
|
|
|
|
done
|
|
|
|
exit
|
|
|
|
esac
|
|
|
|
|
|
|
|
if test -n "$update" && test $# = 0
|
|
|
|
then
|
|
|
|
set x $(sed -n -e '2s/^# //p' <"$update") &&
|
|
|
|
shift
|
|
|
|
fi
|
|
|
|
|
|
|
|
# Generation (or updating)
|
|
|
|
|
|
|
|
x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
|
|
|
|
x40="$x40$x40$x40$x40$x40$x40$x40$x40"
|
|
|
|
LF='
|
|
|
|
'
|
Add Meta/Reintegrate
In a workflow that uses topic branches heavily, you would need to keep
updating test integration branch(es) all the time. If they are managed
like my 'next' by merging the tips of topics that have grown since the
last integration, it is not so difficult. You only need to review output
from "git branch --no-merged next" to see if there are topics that can and
needs to be merged to 'next'.
But sometimes it is easier to rebuild a test integration branch from
scratch all the time, especially if you do not publish it for others to
build on.
I've been using this script for some time to rebuild jch and pu branches
in my workflow. jch's tip is supposed to always match 'next', but it is
rebuilt from scratch on top of 'master' by merging the same topics that
are in 'next'. You can use the same script in your work.
To use it, you give a commit range base..tip to the script, and you will
see a shell script that uses a series of 'git-merge'. "base" is the more
stable branch that you rebuild your test integration branch on top (in my
case, 'master'), and "tip" is where the tip of the test integration branch
is from the last round (in my case, 'jch' or 'pu').
Then you can run the resulting script, fix conflicted merge and use
'git-commit', and then repeat until all the branches are re-integrated on
top of the base branch.
$ Meta/Reintegrate master..jch >/var/tmp/redo-jch.sh
$ cat /var/tmp/redo-jch.sh
#!/bin/sh
while read branch eh
do
case "$eh" in
"") git merge "$branch" || break ;;
?*) echo >&2 "Eh? $branch $eh"; break ;;
esac
done <<EOF
jc/blame
js/notes
ks/maint-mailinfo-folded~3
tr/previous-branch
EOF
$ git checkout jch
$ git reset --hard master
$ /var/tmp/redo-jch.sh
... if there is conflict, resolve, "git commit" here ...
$ /var/tmp/redo-jch.sh
... repeat until everything is applied.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
16 years ago
|
|
|
|
|
|
|
show_merge () {
|
|
|
|
case "$msg" in
|
|
|
|
"Merge branch '"*"'"*)
|
|
|
|
branch=$(expr "$msg" : "Merge branch '\(.*\)'")
|
|
|
|
merge_hier=heads/
|
|
|
|
;;
|
|
|
|
"Merge remote branch '"*"'"*)
|
|
|
|
branch=$(expr "$msg" : "Merge remote branch '\(.*\)'")
|
|
|
|
merge_hier=
|
|
|
|
;;
|
|
|
|
*)
|
|
|
|
echo 2>&1 "Huh?: $msg"
|
|
|
|
return
|
|
|
|
;;
|
|
|
|
esac &&
|
|
|
|
tip=$(git rev-parse --verify "refs/$merge_hier$branch" 2>/dev/null) &&
|
|
|
|
merged=$(git name-rev --refs="refs/$merge_hier$branch" "$other" 2>/dev/null) &&
|
|
|
|
merged=$(expr "$merged" : "$x40 \(.*\)") &&
|
|
|
|
test "$merged" != undefined || {
|
|
|
|
other=$(git log -1 --pretty='format:%s' $other) &&
|
|
|
|
merged="$branch :rebased? $other"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
show_pick () {
|
|
|
|
case "$msg" in
|
|
|
|
"### "* | "###")
|
|
|
|
merged="$msg"
|
|
|
|
;;
|
|
|
|
*)
|
|
|
|
merged="$(git rev-parse --verify "$commit") pick $msg"
|
|
|
|
;;
|
|
|
|
esac
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
generate () {
|
|
|
|
PROGRAM=$1
|
|
|
|
shift
|
|
|
|
echo '#!/bin/sh'
|
|
|
|
echo "# $1"
|
|
|
|
echo 'case "$#,$1" in'
|
|
|
|
echo '1,-u|1,-d)'
|
|
|
|
echo " exec $PROGRAM" '"$1" "$0"'
|
|
|
|
echo 'esac'
|
|
|
|
echo "$PROGRAM" '"$@" <<\EOF'
|
|
|
|
git log --no-decorate --pretty=oneline --first-parent "$1" |
|
|
|
|
{
|
|
|
|
series=
|
|
|
|
while read commit msg
|
|
|
|
do
|
|
|
|
if other=$(git rev-parse -q --verify "$commit^2")
|
|
|
|
then
|
|
|
|
show_merge
|
|
|
|
else
|
|
|
|
show_pick
|
|
|
|
fi
|
|
|
|
|
|
|
|
if test -z "$series"
|
|
|
|
then
|
|
|
|
series="$merged"
|
|
|
|
else
|
|
|
|
series="$merged$LF$series"
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
echo "$series"
|
|
|
|
}
|
|
|
|
echo EOF
|
Add Meta/Reintegrate
In a workflow that uses topic branches heavily, you would need to keep
updating test integration branch(es) all the time. If they are managed
like my 'next' by merging the tips of topics that have grown since the
last integration, it is not so difficult. You only need to review output
from "git branch --no-merged next" to see if there are topics that can and
needs to be merged to 'next'.
But sometimes it is easier to rebuild a test integration branch from
scratch all the time, especially if you do not publish it for others to
build on.
I've been using this script for some time to rebuild jch and pu branches
in my workflow. jch's tip is supposed to always match 'next', but it is
rebuilt from scratch on top of 'master' by merging the same topics that
are in 'next'. You can use the same script in your work.
To use it, you give a commit range base..tip to the script, and you will
see a shell script that uses a series of 'git-merge'. "base" is the more
stable branch that you rebuild your test integration branch on top (in my
case, 'master'), and "tip" is where the tip of the test integration branch
is from the last round (in my case, 'jch' or 'pu').
Then you can run the resulting script, fix conflicted merge and use
'git-commit', and then repeat until all the branches are re-integrated on
top of the base branch.
$ Meta/Reintegrate master..jch >/var/tmp/redo-jch.sh
$ cat /var/tmp/redo-jch.sh
#!/bin/sh
while read branch eh
do
case "$eh" in
"") git merge "$branch" || break ;;
?*) echo >&2 "Eh? $branch $eh"; break ;;
esac
done <<EOF
jc/blame
js/notes
ks/maint-mailinfo-folded~3
tr/previous-branch
EOF
$ git checkout jch
$ git reset --hard master
$ /var/tmp/redo-jch.sh
... if there is conflict, resolve, "git commit" here ...
$ /var/tmp/redo-jch.sh
... repeat until everything is applied.
Signed-off-by: Junio C Hamano <gitster@pobox.com>
16 years ago
|
|
|
}
|
|
|
|
|
|
|
|
if test -z "$update"
|
|
|
|
then
|
|
|
|
generate "$0" "$@"
|
|
|
|
elif test -z "$diff"
|
|
|
|
then
|
|
|
|
generate "$0" "$@" | diff -w -u "$update" -
|
|
|
|
if test $? = 0
|
|
|
|
then
|
|
|
|
echo >&2 "No changes."
|
|
|
|
else
|
|
|
|
echo >&2 -n "Update [y/N]? "
|
|
|
|
read yesno
|
|
|
|
case "$yesno" in
|
|
|
|
[Yy]*)
|
|
|
|
generate "$0" "$@" |
|
|
|
|
sed -e 's/ :rebased?.*//' >"$update" ;;
|
|
|
|
*)
|
|
|
|
echo >&2 "No update then." ;;
|
|
|
|
esac
|
|
|
|
fi
|
|
|
|
else
|
|
|
|
generate "$0" "$@" | diff -w -u "$update" -
|
|
|
|
fi
|