* Re: [PATCH 2/2] Teach rebase an interactive mode
From: Junio C Hamano @ 2007-06-24 8:15 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0706240001150.4059@racer.site>
Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
> index 0c00090..2e474e8 100644
> --- a/Documentation/git-rebase.txt
> +++ b/Documentation/git-rebase.txt
> ...
> +Interactive mode
> +----------------
> +
> +Rebasing interactively means that you have a chance to edit the commits
> +which are rebased. You can not only reorder the commits, but also
> +remove them (weeding out bad or otherwise unwanted patches).
Maybe it's just my bad English comprehension skill, but I needed
to read "You can not only ... but also" twice. "You can reorder
and also remove" would mean the same thing and would be much
easier for non natives to understand.
> +
> +The list will look like this:
> +
> +-------------------------------------------
> +pick deadbee The oneline of this commit
> +pick fa1afe1 The oneline of the next commit
> +...
> +-------------------------------------------
> +
> +The oneline descriptions are purely for your pleasure; `git-rebase` will
> +not look at them but at the commit names, so do not delete or edit the
> +names.
By "commit name", do you mean deadbee? After reading the full
patch I know that is what you meant, but it was a bit unclear
during my initial pass.
> +By replacing the command "pick" with the command "edit", you can tell
> +`git-rebase` to stop after applying that commit, so that you can edit
> +the files and/or the commit message, amend the commit and continue
> +rebasing.
> +
> +If you want to fold two commits into one, just replace the command "pick"
> +with "squash" for the second commit. After squashing the commits,
> +`git-rebase` will start an editor with both commit messages, so you
> +can compose the commit message for the squashed commit.
There was a question about squashing more than two on the list,
and you explained it as "one would get the idea", but I am not
sure I got it right. Would this be what you meant?
If you want to fold two or more commits into one,
replace the command "pick" with "squash" for the second
and subsequent commit.
> diff --git a/Makefile b/Makefile
> index 0d904a9..edb421b 100644
> --- a/Makefile
> +++ b/Makefile
> ...
> +# MOTIVATION
> +#
> +# Consider this type of workflow:
> ...
> +# Sometimes the thing fixed in B.2. cannot be amended to the not-quite
> +# perfect commit it fixes, because that commit is buried deeply in a
> +# patch series.
> +#
> +# Use this script after plenty of "A"s and "B"s, by rearranging, and
> +# possibly editing and merging commits.
This part is missing from Documentation/git-rebase.txt and
should move there, and the USAGE: part of the documentation
should be removed from here; otherwise you need to maintain the
two in sync.
> +USAGE='(--continue | --abort | --skip | [--onto <branch>] <upstream> [<branch>])'
> +
> +. git-sh-setup
> +require_work_tree
> +
> +DOTEST="$GIT_DIR/.dotest-merge"
> +TODO="$DOTEST"/todo
> +DONE="$DOTEST"/done
> +STRATEGY=
> +VERBOSE=
> +
> +warn () {
> + echo "$@" >&2
> +}
I would have used "$*" instead.
> +require_clean_work_tree () {
> + # test if working tree is dirty
> + git rev-parse --verify HEAD > /dev/null &&
> + git update-index --refresh &&
> + test -z "`git diff-files --name-only`" &&
> + test -z "`git diff-index --cached --name-only HEAD`" ||
> + die "Working tree is dirty"
> +}
Heh, I think I showed
git diff-files --quiet && git diff-index --cached --quiet
to somebody else today. Let's be modern ;-).
Is today my "nitpick shell scripts day"? ;-)
> +ORIG_REFLOG_ACTION="$GIT_REFLOG_ACTION"
> +
> +comment_for_reflog () {
> + if test -z "$ORIG_REFLOG_ACTION"; then
> + GIT_REFLOG_ACTION="rebase --interactive ($1)"
> + export GIT_REFLOG_ACTION
Please use shorter prefix, "rebase -i". "git reflog" output is
easer to read that way.
> + fi
> +}
> +
> +mark_action_done () {
> + sed -n 1p < "$TODO" >> "$DONE"
> + sed -n '2,$p' < "$TODO" >> "$TODO".new
> + mv -f "$TODO".new "$TODO"
> +}
I would have written "sed -e 1q" and "sed -e 1d".
> +make_patch () {
> + parent_sha1=$(git rev-parse --verify "$1"^ 2> /dev/null)
> + git diff "$parent_sha1".."$1" > "$DOTEST"/patch
> +}
> +
> +die_with_patch () {
> + make_patch "$1"
> + die "$2"
> +}
> +
> +pick_one () {
> + case "$1" in -n) sha1=$2 ;; *) sha1=$1 ;; esac
> + parent_sha1=$(git rev-parse --verify $sha1^ 2>/dev/null)
> + current_sha1=$(git rev-parse --verify HEAD)
> + if [ $current_sha1 = $parent_sha1 ]; then
> + git reset --hard $sha1
> + sha1=$(git rev-parse --short $sha1)
> + warn Fast forward to $sha1
> + else
> + git cherry-pick $STRATEGY "$@"
> + fi
> +}
I wonder what happens when the user mistakenly breaks the commit
object name on the 'pick' command line and the above --verify
fails. A bit better error checking is needed here.
> +
> +do_next () {
> + read command sha1 rest < "$TODO"
> + case "$command" in
> + \#)
Hmph. Don't you allow a blank line also as a comment (for readability)?
> + mark_action_done
> + continue
> + ;;
Style. Indent ';;' one more level, that is:
case "$to_test" in
arm1)
action
;;
...
esac
> + squash)
> + comment_for_reflog squash
> +
> + test -s "$DONE" ||
> + die "Cannot 'squash' without a previous commit"
As '#' comment line is sent to DONE file with mark_action_done,
non empty DONE file does not necessarily mean you have a
previous commit --- am I mistaken?
> +
> + mark_action_done
> + failed=f
> + pick_one -n $sha1 || failed=t
> + MSG="$DOTEST"/message
> + echo "# This is a combination of two commits." > "$MSG"
> + echo "# The first commit's message is:" >> "$MSG"
> + git cat-file commit HEAD | sed -n '/^$/,$p' >> "$MSG"
> + echo >> "$MSG"
> + echo "# And this is the 2nd commit message:" >> "$MSG"
> + echo >> "$MSG"
> + git cat-file commit $sha1 | sed -n '/^$/,$p' >> "$MSG"
So you have one blank line after "# The first commit's message is:"
but have two blank lines after "# And this is the 2nd"?
Style. Always prefix sed scripts with "-e", like so:
git cat-file commit HEAD | sed -e '1,/^$/d'
> + git reset --soft HEAD^
> + author_script=$(get_author_ident_from_commit $sha1)
> + case $failed in
> + f)
> + # This is like --amend, but with a different message
> + eval $author_script
Missing dq, like the other patch to git-commit?
> + export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_AUTHOR_DATE
> + git commit -F "$MSG" -e
> + ;;
> + t)
> + cp "$MSG" "$GIT_DIR"/MERGE_MSG
> + warn
> + warn "Could not apply $sha1... $rest"
> + warn "After you fixed that, commit the result with"
> + warn
> + warn " $(echo $author_script | tr '\012' ' ') \\"
> + warn " git commit -F \"$GIT_DIR\"/MERGE_MSG -e"
> + die_with_patch $sha1 ""
> + esac
> + ;;
> + *)
> + warn "Unknown command: $command $sha1 $rest"
> + die_with_patch $sha1 "Please fix this in the file $TODO."
> + esac
> + test -s "$TODO" && continue
It is not clear to me from reading the POSIX that this
"continue" is allowed, although both bash and dash seem to work
as you expect. continue "shall return to the top of the
smallest enclosing for, while or until loop" and the enclosing
while loop you are continuing is actually the one in do_rest
function, which is the caller of this. If POSIX meant dynamic
scoping rules, that is fine, but lexically that 'while' does not
enclose this 'continue'.
I think this one can safely be changed to "return" and there
won't be any need for such an worry.
> +
> + HEAD=$(git rev-parse HEAD)
> + HEADNAME=$(cat "$DOTEST"/head-name)
> + git update-ref $HEADNAME $HEAD &&
> + git symbolic-ref HEAD $HEADNAME || exit
Don't we want reflog entries for these two operations?
> + rm -rf "$DOTEST" &&
> + warn "Successfully rebased and updated $HEADNAME."
> +
> + exit $?
> +}
> +
> +do_rest () {
> + while :
> + do
> + do_next
> + done
>
> + test $? = 0 -a -f "$DOTEST"/verbose &&
> + git diff --stat $(cat "$DOTEST"/head)..HEAD
I am not sure what command's exit status $? refers to at this
point. do_next is not run in a subshell, so when it exits, you
would not reach here, would you?
> + exit
> +}
One says "exit $?" the other says "exit" -- they mean the same
;-).
> +while case "$#" in 0) break ;; esac
> +do
No need to quote $#.
> + case "$1" in
> + --continue)
> + comment_for_reflog continue
> +
> + test -d "$DOTEST" || die "No interactive rebase running"
> +
> + require_clean_work_tree
> + do_rest
> + ;;
Indent ;; one more level please.
> + --abort)
> + comment_for_reflog abort
> +
> + test -d "$DOTEST" || die "No interactive rebase running"
> +
> + HEADNAME=$(cat "$DOTEST"/head-name)
> + HEAD=$(cat "$DOTEST"/head)
> + git symbolic-ref HEAD $HEADNAME &&
> + git reset --hard $HEAD &&
> + rm -rf "$DOTEST"
> + exit
> + ;;
> + --skip)
> + comment_for_reflog skip
> +
> + test -d "$DOTEST" || die "No interactive rebase running"
> +
> + git reset --hard && do_rest
> + ;;
> + -s|--strategy)
> + case "$#,$1" in
> + *,*=*)
> + STRATEGY="-s `expr "z$1" : 'z-[^=]*=\(.*\)'`" ;;
> + 1,*)
> + usage ;;
> + *)
> + STRATEGY="-s $2"
> + shift ;;
> + esac
Are we missing a shift before the above "case"?
> + ;;
> + --merge)
> + # we use merge anyway
> + ;;
> + -C*)
> + die "Interactive rebase uses merge, so $1 does not make sense"
> + ;;
> + -v)
> + VERBOSE=t
> + ;;
> + -i|--interactive)
> + # yeah, we know
> + ;;
> + ''|-h)
> + usage
> + ;;
> + *)
> + test -d "$DOTEST" &&
> + die "Interactive rebase already started"
> +
> + git var GIT_COMMITTER_IDENT >/dev/null ||
> + die "You need to set your committer info first"
> +
> + comment_for_reflog start
> +
> + ONTO=
> + case "$1" in
> + --onto)
> + ONTO=$(git rev-parse --verify "$2") ||
> + die "Does not point to a valid commit: $2"
> + shift; shift
> + ;;
> + esac
> +
> + require_clean_work_tree
> +
> + test -z "$2" || git checkout "$2" ||
> + die "Could not checkout $2"
Can you afford to detach HEAD here? Later you check with
symbolic-ref so I think not, which means "$2" must be a valid
branch name, so it should be tested like:
git show-ref --verify --quiet "refs/heads/$2"
> + HEAD=$(git rev-parse --verify HEAD) || die "No HEAD?"
> + UPSTREAM=$(git rev-parse --verify "$1") || die "Invalid base"
> +
> + test -z "$ONTO" && ONTO=$UPSTREAM
> +
> + mkdir "$DOTEST" || die "Could not create temporary $DOTEST"
> + : > "$DOTEST"/interactive || die "Could not mark as interactive"
> + git symbolic-ref HEAD > "$DOTEST"/head-name ||
> + die "Could not get HEAD"
> +
> + echo $HEAD > "$DOTEST"/head
> + echo $UPSTREAM > "$DOTEST"/upstream
> + echo $ONTO > "$DOTEST"/onto
> + test t = "$VERBOSE" && : > "$DOTEST"/verbose
> +
> + cat > "$TODO" << EOF
> +# Reorder by exchanging lines. Skip by removing lines. If you want to
> +# edit a commit, replace the "pick" command with "edit". If you want to
> +# squash the changes of a commit A into a commit B, place A directly
> +# after B, and replace the "pick" command with "squash".
> +EOF
> + git rev-list --no-merges --pretty=oneline --abbrev-commit \
> + --abbrev=7 --reverse $UPSTREAM..$HEAD | \
> + sed "s/^/pick /" >> "$TODO"
> +
> + test -s "$TODO" || die "Nothing to do"
> +
> + cp "$TODO" "$TODO".backup
> + ${VISUAL:-${EDITOR:-vi}} "$TODO" ||
> + die "Could not execute editor"
> +
> + git reset --hard $ONTO && do_rest
> + ;;
> + esac
> + shift
> +done
> diff --git a/git-rebase.sh b/git-rebase.sh
> index 2aa3a01..9e25158 100755
> --- a/git-rebase.sh
> +++ b/git-rebase.sh
> @@ -3,7 +3,7 @@
> # Copyright (c) 2005 Junio C Hamano.
> #
>
> -USAGE='[-v] [--onto <newbase>] <upstream> [<branch>]'
> +USAGE='[--interactive | -i] [-v] [--onto <newbase>] <upstream> [<branch>]'
> LONG_USAGE='git-rebase replaces <branch> with a new branch of the
> same name. When the --onto option is provided the new branch starts
> out with a HEAD equal to <newbase>, otherwise it is equal to <upstream>
> @@ -120,6 +120,16 @@ finish_rb_merge () {
> echo "All done."
> }
>
> +is_interactive () {
> + test -f "$dotest"/interactive ||
> + while case "$1" in ''|-i|--interactive) break ;; esac
> + do
> + shift
> + done && test -n "$1"
> +}
I think by case "$1" in '') you meant "we ran out", but that is
not a good pattern. Check $# at the same time, otherwise you
would stop at an empty argument that is followed by other
arguments.
This is just an idea, but I have been wondering if it would be
useful if we teach rebase (interactive or not) to handle a merge
from an unrelated (wrt the rebase that is being performed)
branch. That is, if you had this development on top of the
origin 'O':
X
\
A---M---B
/
---o---O
that you committed A, merged X and then committed B, you should
be able to rebase on top of an updated upstream 'Q':
X
\
A---M---B
/
---o---O---P---Q
by 'pick A/merge M/pick B', which would do:
X
\
A'--M'--B'
/
---o---O---P---Q
Note that A', M' and B' are different commit objects (rebase
rewrites the history) from the original picture, but X is the
same commit from the original picture.
^ permalink raw reply
* Re: git tool to keep a subversion mirror
From: Jan Hudec @ 2007-06-24 7:45 UTC (permalink / raw)
To: Sergey Yanovich; +Cc: git, normalperson
In-Reply-To: <11821061823423-git-send-email-ynvich@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 927 bytes --]
On Sun, Jun 17, 2007 at 21:49:42 +0300, Sergey Yanovich wrote:
> I am actively using git for my project. Thanks everyone envolved.
>
> However, I got tired of administering own web server and registered my
> project at sourceforge. Unlike repo.or.cz (thanks again for everyone
> envolved), they do not provide git hosting. But a project without a
> source repository is non-sence.
It is. But project on sourceforge with source repository on repo.or.cz is
perfectly ok.
Providing subversion interface to your project might make sense, but on the
other hand you probably want your potential contributors make contributions
with git and not with subversion.
As yet another alternative you might want to go to some other hosting. Maybe
http://en.wikipedia.org/wiki/Comparison_of_free_software_hosting_facilities
could be good starting point for looking for some.
--
Jan 'Bulb' Hudec <bulb@ucw.cz>
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: [PATCH 1/2] Move the pick_author code to git-sh-setup
From: Junio C Hamano @ 2007-06-24 7:09 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: git
In-Reply-To: <7v7ipt3lh6.fsf@assigned-by-dhcp.cox.net>
Junio C Hamano <gitster@pobox.com> writes:
> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
>
>> - set_author_env=`git show -s --pretty=raw --encoding="$encoding" "$use_commit" |
>> - LANG=C LC_ALL=C sed -ne "$pick_author_script"`
>> - eval "$set_author_env"
>> ...
>> + eval $(get_author_ident_from_commit "$use_commit")
>
> Are you sure about this part of the change? I suspect that you
> are losing IFS by not dq'ing the argument you give to the eval.
>
> ...
If you care about your data in your variable and do not want
word-splitting at $IFS to happen, you should always dq your
variable. A quick rule of thumb is that the only place that you
can get away by not quoting is straight assignment to another
variable, like so:
var='a b c '
another=$var ;# another="$var" is fine but unnecessary.
^ permalink raw reply
* Re: [PATCH] transplant: move a series of commits to a different parent
From: Steffen Prohaska @ 2007-06-24 7:08 UTC (permalink / raw)
To: Alex Riesen; +Cc: Git Mailing List
In-Reply-To: <81b0412b0706231404hc8b4bc4xd5bc51c733d8ea69@mail.gmail.com>
On Jun 23, 2007, at 11:04 PM, Alex Riesen wrote:
>> git-transplant.sh <onto> <from> <to>
>>
>> transplant starts with the contents of <onto> and puts on top of
>> it the contents of files if they are touched by the series of
>> commits <from>..<to>. If a commit touches a file the content of
>> this file is taken as it is in the commit. No merging is
>> performed. Original authors, commiters, and commit messages are
>> preserved.
>>
> [...]
> # detached head
> git checkout $(git rev-parse onto) && git format-patch --stdout
> --full-index from..to|git am -3
No. This one tries to apply the _changes_ between from..to. What I
need is the resulting _content_ of files modified between from..to.
The _changes_ are already wrong because they are relative to the
history. But the history was messed up by git-cvsimport, as I tried to
explaine in my first mail in this thread. So the changes derived
from the wrong history are useless.
transplant only checks if a file is modified by a commit. If it is
it takes the _content_ of the file in that commit. The changes from
the parent commit, which you can find by format-patch, do not matter.
I believe it's more like git-filter-branch, but I wasn't yet abel to
tell git-filter-branch how to do the job.
Steffen
^ permalink raw reply
* [PATCH] git-svnimport: added explicit merge graph option -G
From: Junio C Hamano @ 2007-06-24 7:06 UTC (permalink / raw)
To: git; +Cc: Stas Maximov
From: Stas Maximov <smaximov@yahoo.com>
Date: Sat, 23 Jun 2007 09:06:30 -0700
Allows explicit merge graph information to be provided. Each line
of merge graph file must contain a pair of SVN revision numbers
separated by space. The first number is child (merged to) SVN rev
number and the second is the parent (merged from) SVN rev number.
Comments can be started with '#' and continue to the end of line.
Empty and space-only lines are allowed and will be ignored.
---
* Stas, please give a "Signed-off-by" line, and get in the
habit of always CC the list.
I received a format-patch output as attachment from Stas. As
I cannot comment on the patch in that format, I am making a
verbatim forward to the list.
I'll comment on the patch separately when I am through it,
but would appreciate comments from people who were involved
in git-svnimport in the past, and still use it.
"You should use git-svn instead" people can repeat that as
usual, but at the same time it might be worth realizing that
there are people who maintain git-svnimport being better for
one-short importing.
Documentation/git-svnimport.txt | 11 +++++-
git-svnimport.perl | 71 +++++++++++++++++++++++++++++++++++++--
2 files changed, 78 insertions(+), 4 deletions(-)
mode change 100644 => 100755 Documentation/git-svnimport.txt
diff --git a/Documentation/git-svnimport.txt b/Documentation/git-svnimport.txt
old mode 100644
new mode 100755
index e97d15e..c902b64
--- a/Documentation/git-svnimport.txt
+++ b/Documentation/git-svnimport.txt
@@ -13,7 +13,8 @@ SYNOPSIS
'git-svnimport' [ -o <branch-for-HEAD> ] [ -h ] [ -v ] [ -d | -D ]
[ -C <GIT_repository> ] [ -i ] [ -u ] [-l limit_rev]
[ -b branch_subdir ] [ -T trunk_subdir ] [ -t tag_subdir ]
- [ -s start_chg ] [ -m ] [ -r ] [ -M regex ]
+ [ -s start_chg ] [ -r ]
+ [ -m ] [ -M regex ] [-G merge_graph_file ]
[ -I <ignorefile_name> ] [ -A <author_file> ]
[ -R <repack_each_revs>] [ -P <path_from_trunk> ]
<SVN_repository_URL> [ <path> ]
@@ -102,6 +103,14 @@ repository without -A.
regex. It can be used with -m to also see the default regexes.
You must escape forward slashes.
+-G <merge_graph_file>::
+ Allows explicit merge graph information to be provided. Each line
+ of merge graph file must contain a pair of SVN revision numbers
+ separated by space. The first number is child (merged to) SVN rev
+ number and the second is the parent (merged from) SVN rev number.
+ Comments can be started with '#' and continue to the end of line.
+ Empty and space-only lines are allowed and will be ignored.
+
-l <max_rev>::
Specify a maximum revision number to pull.
+
diff --git a/git-svnimport.perl b/git-svnimport.perl
index f459762..113b252 100755
--- a/git-svnimport.perl
+++ b/git-svnimport.perl
@@ -32,7 +32,7 @@ $ENV{'TZ'}="UTC";
our($opt_h,$opt_o,$opt_v,$opt_u,$opt_C,$opt_i,$opt_m,$opt_M,$opt_t,$opt_T,
$opt_b,$opt_r,$opt_I,$opt_A,$opt_s,$opt_l,$opt_d,$opt_D,$opt_S,$opt_F,
- $opt_P,$opt_R);
+ $opt_P,$opt_R,$opt_G);
sub usage() {
print STDERR <<END;
@@ -40,12 +40,13 @@ Usage: ${\basename $0} # fetch/update GIT from SVN
[-o branch-for-HEAD] [-h] [-v] [-l max_rev] [-R repack_each_revs]
[-C GIT_repository] [-t tagname] [-T trunkname] [-b branchname]
[-d|-D] [-i] [-u] [-r] [-I ignorefilename] [-s start_chg]
- [-m] [-M regex] [-A author_file] [-S] [-F] [-P project_name] [SVN_URL]
+ [-m] [-M regex] [-G merge_graph_file] [-A author_file]
+ [-S] [-F] [-P project_name] [SVN_URL]
END
exit(1);
}
-getopts("A:b:C:dDFhiI:l:mM:o:rs:t:T:SP:R:uv") or usage();
+getopts("A:b:C:dDFhiI:l:mM:G:o:rs:t:T:SP:R:uv") or usage();
usage if $opt_h;
my $tag_name = $opt_t || "tags";
@@ -80,6 +81,39 @@ if ($opt_M) {
unshift (@mergerx, qr/$opt_M/);
}
+
+# merge_graph will be used for finding all parent SVN revisions for a given SVN
+# revision. It will be implemented as a hash of hashes. First level hash will
+# be keyed with the child SVN rev and contain a hash keyed with the parent SVN
+# revisions. Values of the second level hash are not important (1 will be
+# used). The keys will be used to store the parent revs for uniqueness.
+our %merge_graph;
+
+
+# read-in the explicit merge graph specified with -G option
+if ($opt_G) {
+ open(F,"cat $opt_G | sed -e 's/#.*\$//' -e '/^\$/d' |") or
+ die("Can not open $opt_G");
+ while(<F>) {
+ chomp;
+ die "ERROR: invalid line in $opt_G: $_" unless /^\s*(\d+)\s+(\d+)\s*$/;
+ # $merge_graph{child_rev}{parent_rev} = 1;
+ $merge_graph{$1}{$2} = 1;
+ }
+ close(F);
+}
+
+
+# Given an SVN revision (string), finds all its parent SVN revisions in the
+# merge graph.
+sub merge_graph_get_parents($)
+{
+ my $child_svnrev = shift;
+ my @parents = keys(%{$merge_graph{$child_svnrev}});
+ return @parents;
+}
+
+
# Absolutize filename now, since we will have chdir'ed by the time we
# get around to opening it.
$opt_A = File::Spec->rel2abs($opt_A) if $opt_A;
@@ -356,6 +390,24 @@ if ($opt_A) {
open BRANCHES,">>", "$git_dir/svn2git";
+
+# Given an SVN revision (string), returns all corresponding GIT revisions.
+#
+# Note that it is possible that one SVN revision needs to be split into two or
+# more GIT commits (revision). For example, this will happen if SVN user
+# commits two branches at once.
+sub svnrev_to_gitrevs($)
+{
+ my $svnrev = shift;
+ my @gitrevs;
+ for my $b (keys(%branches)) {
+ push (@gitrevs, $branches{$b}{$svnrev})
+ if defined($branches{$b}{$svnrev});
+ }
+ return @gitrevs;
+}
+
+
sub node_kind($$) {
my ($svnpath, $revision) = @_;
my $pool=SVN::Pool->new;
@@ -815,6 +867,19 @@ sub commit {
}
}
}
+
+ # add parents from explicit merge graph (-G)
+ {
+ my @svnpars = merge_graph_get_parents($revision);
+ foreach my $svnp (@svnpars) {
+ my @gitpars = svnrev_to_gitrevs($svnp);
+ foreach my $gitp (@gitpars) {
+ push (@parents, $gitp);
+ #print OUT "MG: $svnp -merge-> $revision\n";
+ }
+ }
+ }
+
my %seen_parents = ();
my @unique_parents = grep { ! $seen_parents{$_} ++ } @parents;
foreach my $bparent (@unique_parents) {
--
1.5.1.3
^ permalink raw reply related
* Re: [PATCH] transplant: move a series of commits to a different parent
From: Steffen Prohaska @ 2007-06-24 6:55 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0706232151480.4059@racer.site>
On Jun 23, 2007, at 10:54 PM, Johannes Schindelin wrote:
>> git-transplant.sh <onto> <from> <to>
>>
>> transplant starts with the contents of <onto> and puts on top of
>> it the contents of files if they are touched by the series of
>> commits <from>..<to>.
>
> This reeks of rebase.
>
> IOW, I suspect that it does almost the same as
>
> git checkout <to>
> git rebase -s ours --onto <onto> <from>^
It doesn't do anything useful for me. In fact it seems as if it
did nothing.
I tried your proposal:
- rebase says 'Changes from <onto> to <onto>',
- then it rewinds to <onto>,
- next it says several time 'Already applied: ...' with increasing
patch numbers,
- then 'All done',
- The result is the same as if I executed 'git reset --hard <onto>'.
I thought about something similar before I wrote transplant.
Honestly, I didn't understand what rebase would do combined with ours.
Steffen
^ permalink raw reply
* Re: Stupid quoting...
From: Jan Hudec @ 2007-06-24 6:50 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Johannes Schindelin, David Kastrup, git
In-Reply-To: <7vd4zrw3k4.fsf@assigned-by-dhcp.pobox.com>
[-- Attachment #1: Type: text/plain, Size: 3033 bytes --]
On Tue, Jun 19, 2007 at 23:19:39 -0700, Junio C Hamano wrote:
> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
>
> >> I don't see our discourse leading anywhere: the points have been made.
> >
> > I would really, really, really like to see a solution. Alas, I cannot
> > think of one, other than _forcing_ the developers to use ASCII-only
> > filenames.
> >
> > Note that there is no convention yet in Git to state which encoding your
> > filenames are supposed to use. And in fact, we already had a fine example
> > in git.git why this is particularly difficult. MacOSX is too clever to be
> > true, in that it gladly takes filenames in one encoding, but reads those
> > filenames out in _another_ encoding. Thus, a "git add <filename>" can well
> > end up in git-status saying that a file was deleted, and another file
> > (actually the same, but in a different encoding) is untracked.
I saw bazaar folks discussing this MacOSX issue. Basically in MacOSX
filenames are *unicode* strings (just as they are in Windows, btw). Unicode,
for compatibility reasons allows expressing many characters in multiple forms
-- composed and decomposed. For example 'á' can be expressed as '\u00e1'
('\xc3\xa1' in utf-8) or as 'a\u0301' ('a\xcc\x81' in utf-8).
MaxOSX opts to, in accord with unicode standard, treat such representations
as equal and it does so by normalizing all filenames to one form. I don't
know whether it uses compatibility normalization and I believe it uses the
decomposed form (which makes the issue immediately obvious, because most
programs work in composed form).
> By the way, the pathname quoting done by "diff" does not even
> attempt to tackle that. I already explained why in the thread
> so I would not repeat myself.
>
> Having said that, the absolute minimum that needs to be quoted
> are double-quote (because it is used by quoting as agreed with
> GNU diff/patch maintainer), backslash (used to introduce C-like
> quoting), newline and horizontal tab (makes "patch" confused, as
> it would make it ambiguous where the pathname ends), so I am not
> opposed to a patch that introduces a new mode, probably on by
> default _unless_ we are generating --format=email, that does not
> quote high byte values. That would solve "My UTF-8 filenames
> are unreadable on my terminal" problem.
IMHO it should be the default even for email format. Most projects that use
non-ascii filenames probably have all members using same locale. And for
such group, it will just work. Also usually the file names, content and
commit messages will usually be in the same (though project-specific)
encoding, so if charset in content-type is set to that, people with different
locale able to represent the same characters will still see the names
correctly. For other people, the MUA will probably print some escape anyway
(it will not screw up the terminal -- it usually knows what it can safely
pass to it).
--
Jan 'Bulb' Hudec <bulb@ucw.cz>
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: [PATCH 1/2] Move the pick_author code to git-sh-setup
From: Junio C Hamano @ 2007-06-24 6:39 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0706240000340.4059@racer.site>
Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> - set_author_env=`git show -s --pretty=raw --encoding="$encoding" "$use_commit" |
> - LANG=C LC_ALL=C sed -ne "$pick_author_script"`
> - eval "$set_author_env"
> ...
> + eval $(get_author_ident_from_commit "$use_commit")
Are you sure about this part of the change? I suspect that you
are losing IFS by not dq'ing the argument you give to the eval.
#!/bin/sh
test1 () {
echo "$1=' d e'"
}
eval $(test1 A)
eval "$(test1 B)"
echo "A=$A"
echo "B=$B"
^ permalink raw reply
* Darcs
From: Bu Bacoo @ 2007-06-24 5:32 UTC (permalink / raw)
To: git
Hello guys (girls?)
What do you think about darcs?
There was a lot written/spoken about morons and stupidos around
thinking in cvs / svn, etc... (what would be the words for dudes
around vss ....).
But not a lot of darcs, even if there are tools like Darcs-Git, etc...
Are git and darcs supposed to extend each other? Or?
The patch algebra in Darcs looks to me pretty similar to Linuse's
patch-SCM used for kernel bellow 2.6.12.something?
Thanks for opinions.
Bu
^ permalink raw reply
* Re: [PATCH 2/2] Teach rebase an interactive mode
From: Brian Gernhardt @ 2007-06-24 3:39 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: git, gitster
In-Reply-To: <Pine.LNX.4.64.0706240001150.4059@racer.site>
On Jun 23, 2007, at 7:01 PM, Johannes Schindelin wrote:
>
> With "--interactive", git-rebase now lets you edit the list of patches
> to be reapplied, so that you can reorder and/or delete patches.
>
> Such a list will typically look like this:
>
> pick deadbee The oneline of this commit
> pick fa1afe1 The oneline of the next commit
> ...
>
It's not at all obvious from your commit message or the documentation
where this list comes from. At first look I thought I would have had
to type it in. It took digging into the code to be sure how it
worked. You probably want to mention in the documentation that the
list is generated from the arguments and given in a text editor.
Is there a way to say "Oops, that's the wrong list. Don't do
anything."?
Perhaps starting the list with a header like the following would make
it more user-friendly (Obviously requires s/#.*$//):
# Rebasing $from..$to onto $commit
#
# Commands:
# pick = use commit
# squash = meld commit into previous
# <<More useful information here>>
However, those are nits to take a good idea to a great one. I like
it very much.
~~ Brian
^ permalink raw reply
* Re: [PATCH]: tree-walk.h: Warning fix
From: Luiz Fernando N. Capitulino @ 2007-06-24 2:10 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7v1wg39oqc.fsf@assigned-by-dhcp.pobox.com>
Em Fri, 22 Jun 2007 23:19:55 -0700
Junio C Hamano <gitster@pobox.com> escreveu:
| "Luiz Fernando N. Capitulino" <lcapitulino@mandriva.com.br>
| writes:
|
| > diff --git a/tree-walk.h b/tree-walk.h
| > index ee747ab..625198f 100644
| > --- a/tree-walk.h
| > +++ b/tree-walk.h
| > @@ -22,7 +22,7 @@ static inline const unsigned char *tree_entry_extract(struct tree_desc *desc, co
| >
| > static inline int tree_entry_len(const char *name, const unsigned char *sha1)
| > {
| > - return (char *)sha1 - (char *)name - 1;
| > + return (const char *)sha1 - (const char *)name - 1;
| > }
| >
| > void update_tree_entry(struct tree_desc *);
|
| Grumble. Incoming "name" is already (const char*), isn't it?
| I'd cast only the sha1 side and apply.
Yes, you're right. I'll fix it and apply again.
Thanks a lot for the feedback.
^ permalink raw reply
* Re: [PATCH][RESEND] Escape some tilde characters causing spurious subscripts in documentation
From: Junio C Hamano @ 2007-06-24 1:01 UTC (permalink / raw)
To: Jason Sewall; +Cc: gitster, Johannes.Schindelin, git
In-Reply-To: <11826426733115-git-send-email-jasonsewall@gmail.com>
Jason Sewall <jasonsewall@gmail.com> writes:
> diff --git a/Documentation/git-bundle.txt b/Documentation/git-bundle.txt
> index 5051e2b..d89f350 100644
> --- a/Documentation/git-bundle.txt
> +++ b/Documentation/git-bundle.txt
> @@ -61,7 +61,7 @@ unbundle <file>::
> [git-rev-list-args...]::
> A list of arguments, acceptable to git-rev-parse and
> git-rev-list, that specify the specific objects and references
> - to transport. For example, "master~10..master" causes the
> + to transport. For example, "master\~10..master" causes the
> current master reference to be packaged along with all objects
> added since its 10th ancestor commit. There is no explicit
> limit to the number of references and objects that may be
We seem to have {tilde} defined in Documentation/asciidoc.conf.
I wonder which is better. We should pick one that gives more
reasonable format, and is less susceptible to differences
between AsciiDoc 7 and 8.
^ permalink raw reply
* Re: [PATCH][RESEND] Escape some tilde characters causing spurious subscripts in documentation
From: Johannes Schindelin @ 2007-06-24 0:55 UTC (permalink / raw)
To: Jason Sewall; +Cc: git
In-Reply-To: <31e9dd080706231722v760b5a0cnc31e24b83deafb90@mail.gmail.com>
Hi,
On Sat, 23 Jun 2007, Jason Sewall wrote:
> Anyway, 8.1.0 is apparently what's in Fedora 7 (the distro I'm using
> right now) so it might be worth hanging on to the patch.
Oh yes, definitely, if it fixes a bug that you encountered! I was just
asking out of curiousity; I did not think that the patch was not
necessary...
Ciao,
Dscho
^ permalink raw reply
* Re: [PATCH][RESEND] Escape some tilde characters causing spurious subscripts in documentation
From: Jason Sewall @ 2007-06-24 0:22 UTC (permalink / raw)
To: Johannes Schindelin, git
In-Reply-To: <Pine.LNX.4.64.0706240109540.4059@racer.site>
On 6/23/07, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
> I just checked with my copy of asciidoc, though, and there is no mangling
> going on, at least in git-bundle.html (which is the only file I checked).
> My asciidoc is version 8.2.1. What is yours?
I've got 8.1.0; perhaps that's the problem. I wasn't so surprised to
hear the asciidoc 7 and 8 don't get along, but I'm surprised to see
that 8.1 and 8.2 are so different.
Anyway, 8.1.0 is apparently what's in Fedora 7 (the distro I'm using
right now) so it might be worth hanging on to the patch.
Thanks for your help,
Jason
^ permalink raw reply
* Re: [PATCH][RESEND] Escape some tilde characters causing spurious subscripts in documentation
From: Johannes Schindelin @ 2007-06-24 0:11 UTC (permalink / raw)
To: Jason Sewall; +Cc: gitster, git
In-Reply-To: <11826426733115-git-send-email-jasonsewall@gmail.com>
Hi,
On Sat, 23 Jun 2007, Jason Sewall wrote:
> My second attempt at submitting a patch, this time with git-send-email
> rather than copy-and-paste into gmail; let me know if this is a
> reasonably presented patch. It is truly trivial, but getting those docs
> cleaned up is important!
Applies cleanly (although the commit message now consists of one single
long line).
I just checked with my copy of asciidoc, though, and there is no mangling
going on, at least in git-bundle.html (which is the only file I checked).
My asciidoc is version 8.2.1. What is yours?
Ciao,
Dscho
^ permalink raw reply
* [PATCH][RESEND] Escape some tilde characters causing spurious subscripts in documentation
From: Jason Sewall @ 2007-06-23 23:51 UTC (permalink / raw)
To: gitster, Johannes.Schindelin, git; +Cc: Jason Sewall
A few unescaped tilde characters were causing long parts of the html documentation to be formatted as footnotes. This patch fixes them; I think I found all of them, but no promises.
Signed-off-by: Jason Sewall <jasonsewall@gmail.com>
---
My second attempt at submitting a patch, this time with git-send-email rather than copy-and-paste into gmail; let me know if this is a reasonably presented patch. It is truly trivial, but getting those docs cleaned up is important!
Documentation/git-bundle.txt | 8 ++++----
Documentation/git-daemon.txt | 2 +-
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/Documentation/git-bundle.txt b/Documentation/git-bundle.txt
index 5051e2b..d89f350 100644
--- a/Documentation/git-bundle.txt
+++ b/Documentation/git-bundle.txt
@@ -61,7 +61,7 @@ unbundle <file>::
[git-rev-list-args...]::
A list of arguments, acceptable to git-rev-parse and
git-rev-list, that specify the specific objects and references
- to transport. For example, "master~10..master" causes the
+ to transport. For example, "master\~10..master" causes the
current master reference to be packaged along with all objects
added since its 10th ancestor commit. There is no explicit
limit to the number of references and objects that may be
@@ -80,12 +80,12 @@ SPECIFYING REFERENCES
git-bundle will only package references that are shown by
git-show-ref: this includes heads, tags, and remote heads. References
-such as master~1 cannot be packaged, but are perfectly suitable for
+such as master\~1 cannot be packaged, but are perfectly suitable for
defining the basis. More than one reference may be packaged, and more
than one basis can be specified. The objects packaged are those not
contained in the union of the given bases. Each basis can be
-specified explicitly (e.g., ^master~10), or implicitly (e.g.,
-master~10..master, master --since=10.days.ago).
+specified explicitly (e.g., ^master\~10), or implicitly (e.g.,
+master\~10..master, master --since=10.days.ago).
It is very important that the basis used be held by the destination.
It is okay to err on the side of conservatism, causing the bundle file
diff --git a/Documentation/git-daemon.txt b/Documentation/git-daemon.txt
index 4b30b18..3f9cec5 100644
--- a/Documentation/git-daemon.txt
+++ b/Documentation/git-daemon.txt
@@ -98,7 +98,7 @@ OPTIONS
--verbose, thus by default only error conditions will be logged.
--user-path, --user-path=path::
- Allow ~user notation to be used in requests. When
+ Allow \~user notation to be used in requests. When
specified with no parameter, requests to
git://host/~alice/foo is taken as a request to access
'foo' repository in the home directory of user `alice`.
--
1.5.2.1.280.g38570
^ permalink raw reply related
* Re: [PATCH 2/2] Teach rebase an interactive mode
From: Johannes Schindelin @ 2007-06-23 23:36 UTC (permalink / raw)
To: Alex Riesen; +Cc: git, gitster
In-Reply-To: <81b0412b0706231633yd0f19e8xbb0b7004fd7f75ef@mail.gmail.com>
Hi,
On Sun, 24 Jun 2007, Alex Riesen wrote:
> On 6/24/07, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
>
> > +If you want to fold two commits into one, just replace the command "pick"
> > +with "squash" for the second commit. After squashing the commits,
>
> Can I fold 3 commits into one? 4 and 5?
Yes, but the wording got too complicated. So I guessed that those who need
to squash more than 2 commits into one would get the idea.
Ciao,
Dscho
^ permalink raw reply
* Re: [PATCH 2/2] Teach rebase an interactive mode
From: Alex Riesen @ 2007-06-23 23:33 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: git, gitster
In-Reply-To: <Pine.LNX.4.64.0706240001150.4059@racer.site>
On 6/24/07, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
> +If you want to fold two commits into one, just replace the command "pick"
> +with "squash" for the second commit. After squashing the commits,
Can I fold 3 commits into one? 4 and 5?
^ permalink raw reply
* Re: [PATCH/RFH] pp_header(): work around possible memory corruption
From: Johannes Schindelin @ 2007-06-23 23:32 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vps3w4g9x.fsf@assigned-by-dhcp.pobox.com>
Hi,
On Fri, 15 Jun 2007, Junio C Hamano wrote:
> At least the older humongous pretty_print_commit() got separated into
> manageable chunks, and I was happy. I was just too lazy when
> refactoring the code and stopped there.
Understandable.
> The right fix is to propagate the "realloc as needed" callchain into
> add_user_info(), instead of having "this should be enough" there.
> These two you touched are the only two callsite of that static function.
I had a go at this, but unfortunately I do not understand enough of what
is going on there. For example, add_rfc2047() sometimes quotes some text.
I have no idea what a conservative estimate of the growth is, so I cannot
continue there.
Sorry,
Dscho
^ permalink raw reply
* [PATCH 2/2] Teach rebase an interactive mode
From: Johannes Schindelin @ 2007-06-23 23:01 UTC (permalink / raw)
To: git, gitster
With "--interactive", git-rebase now lets you edit the list of patches
to be reapplied, so that you can reorder and/or delete patches.
Such a list will typically look like this:
pick deadbee The oneline of this commit
pick fa1afe1 The oneline of the next commit
...
By replacing the command "pick" with the command "edit", you can amend
that patch and/or its commit message, and by replacing it with "squash"
you can tell rebase to fold that patch into the patch before that.
It is derived from the script sent to the list in
<Pine.LNX.4.63.0702252156190.22628@wbgn013.biozentrum.uni-wuerzburg.de>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
Documentation/git-rebase.txt | 51 ++++++-
Makefile | 2 +-
git-rebase--interactive.sh | 336 +++++++++++++++++++++++++++++++++++++++++
git-rebase.sh | 12 ++-
t/t3404-rebase-interactive.sh | 163 ++++++++++++++++++++
5 files changed, 559 insertions(+), 5 deletions(-)
create mode 100755 git-rebase--interactive.sh
create mode 100755 t/t3404-rebase-interactive.sh
diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index 0c00090..2e474e8 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -8,7 +8,8 @@ git-rebase - Forward-port local commits to the updated upstream head
SYNOPSIS
--------
[verse]
-'git-rebase' [-v] [--merge] [-C<n>] [--onto <newbase>] <upstream> [<branch>]
+'git-rebase' [-i | --interactive] [-v | --verbose] [--merge] [-C<n>]
+ [--onto <newbase>] <upstream> [<branch>]
'git-rebase' --continue | --skip | --abort
DESCRIPTION
@@ -208,6 +209,10 @@ OPTIONS
context exist they all must match. By default no context is
ever ignored.
+-i, \--interactive::
+ Make a list of the commits which are about to be rebased. Let the
+ user edit that list before rebasing.
+
include::merge-strategies.txt[]
NOTES
@@ -226,9 +231,49 @@ pre-rebase hook script for an example.
You must be in the top directory of your project to start (or continue)
a rebase. Upon completion, <branch> will be the current branch.
-Author
+Interactive mode
+----------------
+
+Rebasing interactively means that you have a chance to edit the commits
+which are rebased. You can not only reorder the commits, but also
+remove them (weeding out bad or otherwise unwanted patches).
+
+The list will look like this:
+
+-------------------------------------------
+pick deadbee The oneline of this commit
+pick fa1afe1 The oneline of the next commit
+...
+-------------------------------------------
+
+The oneline descriptions are purely for your pleasure; `git-rebase` will
+not look at them but at the commit names, so do not delete or edit the
+names.
+
+By replacing the command "pick" with the command "edit", you can tell
+`git-rebase` to stop after applying that commit, so that you can edit
+the files and/or the commit message, amend the commit and continue
+rebasing.
+
+If you want to fold two commits into one, just replace the command "pick"
+with "squash" for the second commit. After squashing the commits,
+`git-rebase` will start an editor with both commit messages, so you
+can compose the commit message for the squashed commit.
+
+A common use case for the interactive mode is when you want to reorder
+the last 5 commits, such that what was HEAD~4 becomes the new HEAD. To
+achieve that, you would call `git-rebase` like this:
+
+----------------------
+$ git rebase -i HEAD~5
+----------------------
+
+And move the first patch to the end of the list.
+
+Authors
------
-Written by Junio C Hamano <junkio@cox.net>
+Written by Junio C Hamano <junkio@cox.net> and
+Johannes E. Schindelin <johannes.schindelin@gmx.de>
Documentation
--------------
diff --git a/Makefile b/Makefile
index 0d904a9..edb421b 100644
--- a/Makefile
+++ b/Makefile
@@ -204,7 +204,7 @@ SCRIPT_SH = \
git-fetch.sh \
git-ls-remote.sh \
git-merge-one-file.sh git-mergetool.sh git-parse-remote.sh \
- git-pull.sh git-rebase.sh \
+ git-pull.sh git-rebase.sh git-rebase--interactive.sh \
git-repack.sh git-request-pull.sh git-reset.sh \
git-sh-setup.sh \
git-tag.sh git-verify-tag.sh \
diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
new file mode 100755
index 0000000..6a960b4
--- /dev/null
+++ b/git-rebase--interactive.sh
@@ -0,0 +1,336 @@
+#!/bin/sh
+#
+# Copyright (c) 2006 Johannes E. Schindelin
+
+# SHORT DESCRIPTION
+#
+# This script makes it easy to fix up commits in the middle of a series,
+# and rearrange commits.
+#
+# The original idea comes from Eric W. Biederman, in
+# http://article.gmane.org/gmane.comp.version-control.git/22407
+#
+# MOTIVATION
+#
+# Consider this type of workflow:
+#
+# 1. have a wonderful idea
+# 2. hack on the code
+# 3. prepare a series for submission
+# 4. submit
+#
+# where the point (2) consists of several instances of
+#
+# A.1. finish something worthy of a commit
+# A.2. commit
+#
+# and/or
+#
+# B.1. realize that something does not work
+# B.2. fix that
+# B.3. commit it
+#
+# Sometimes the thing fixed in B.2. cannot be amended to the not-quite
+# perfect commit it fixes, because that commit is buried deeply in a
+# patch series.
+#
+# Use this script after plenty of "A"s and "B"s, by rearranging, and
+# possibly editing and merging commits.
+#
+# USAGE:
+#
+# Start it with the last commit you want to retain as-is:
+#
+# git rebase -i <after-this-commit>
+#
+# An editor will be fired up with all the commits in your current branch
+# (ignoring merge commits), which come after the given commit. You can
+# reorder the commits in this list to your heart's content, and you can
+# even remove them. The list looks more or less like this:
+#
+# pick deadbee The oneline of this commit
+# pick fa1afe1 The oneline of the next commit
+# ...
+#
+# By replacing the command "pick" with "edit" you can tell
+# this script to stop the loop so you can fix up the commit by editing
+# files and/or the commit message.
+#
+# When replacing the command "pick" with "squash", the script will squash
+# this commit's changes into the commit which comes right before it, munge
+# the commit messages of both, and open the commit message editor. If the
+# commits had different authors, it will attribute the squashed commit to
+# the author of the last commit.
+#
+# In both cases, or when a "pick" does not succeed (because of merge
+# errors), the loop will stop to let you fix things, and you can continue
+# the loop with `git rebase --continue`.
+
+USAGE='(--continue | --abort | --skip | [--onto <branch>] <upstream> [<branch>])'
+
+. git-sh-setup
+require_work_tree
+
+DOTEST="$GIT_DIR/.dotest-merge"
+TODO="$DOTEST"/todo
+DONE="$DOTEST"/done
+STRATEGY=
+VERBOSE=
+
+warn () {
+ echo "$@" >&2
+}
+
+require_clean_work_tree () {
+ # test if working tree is dirty
+ git rev-parse --verify HEAD > /dev/null &&
+ git update-index --refresh &&
+ test -z "`git diff-files --name-only`" &&
+ test -z "`git diff-index --cached --name-only HEAD`" ||
+ die "Working tree is dirty"
+}
+
+ORIG_REFLOG_ACTION="$GIT_REFLOG_ACTION"
+
+comment_for_reflog () {
+ if test -z "$ORIG_REFLOG_ACTION"; then
+ GIT_REFLOG_ACTION="rebase --interactive ($1)"
+ export GIT_REFLOG_ACTION
+ fi
+}
+
+mark_action_done () {
+ sed -n 1p < "$TODO" >> "$DONE"
+ sed -n '2,$p' < "$TODO" >> "$TODO".new
+ mv -f "$TODO".new "$TODO"
+}
+
+make_patch () {
+ parent_sha1=$(git rev-parse --verify "$1"^ 2> /dev/null)
+ git diff "$parent_sha1".."$1" > "$DOTEST"/patch
+}
+
+die_with_patch () {
+ make_patch "$1"
+ die "$2"
+}
+
+pick_one () {
+ case "$1" in -n) sha1=$2 ;; *) sha1=$1 ;; esac
+ parent_sha1=$(git rev-parse --verify $sha1^ 2>/dev/null)
+ current_sha1=$(git rev-parse --verify HEAD)
+ if [ $current_sha1 = $parent_sha1 ]; then
+ git reset --hard $sha1
+ sha1=$(git rev-parse --short $sha1)
+ warn Fast forward to $sha1
+ else
+ git cherry-pick $STRATEGY "$@"
+ fi
+}
+
+do_next () {
+ read command sha1 rest < "$TODO"
+ case "$command" in
+ \#)
+ mark_action_done
+ continue
+ ;;
+ pick)
+ comment_for_reflog pick
+
+ mark_action_done
+ pick_one $sha1 ||
+ die_with_patch $sha1 "Could not apply $sha1... $rest"
+ ;;
+ edit)
+ comment_for_reflog edit
+
+ mark_action_done
+ pick_one $sha1 ||
+ die_with_patch $sha1 "Could not apply $sha1... $rest"
+ make_patch $sha1
+ warn
+ warn "You can amend the commit now, with"
+ warn
+ warn " git commit --amend"
+ warn
+ exit 0
+ ;;
+ squash)
+ comment_for_reflog squash
+
+ test -s "$DONE" ||
+ die "Cannot 'squash' without a previous commit"
+
+ mark_action_done
+ failed=f
+ pick_one -n $sha1 || failed=t
+ MSG="$DOTEST"/message
+ echo "# This is a combination of two commits." > "$MSG"
+ echo "# The first commit's message is:" >> "$MSG"
+ git cat-file commit HEAD | sed -n '/^$/,$p' >> "$MSG"
+ echo >> "$MSG"
+ echo "# And this is the 2nd commit message:" >> "$MSG"
+ echo >> "$MSG"
+ git cat-file commit $sha1 | sed -n '/^$/,$p' >> "$MSG"
+ git reset --soft HEAD^
+ author_script=$(get_author_ident_from_commit $sha1)
+ case $failed in
+ f)
+ # This is like --amend, but with a different message
+ eval $author_script
+ export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_AUTHOR_DATE
+ git commit -F "$MSG" -e
+ ;;
+ t)
+ cp "$MSG" "$GIT_DIR"/MERGE_MSG
+ warn
+ warn "Could not apply $sha1... $rest"
+ warn "After you fixed that, commit the result with"
+ warn
+ warn " $(echo $author_script | tr '\012' ' ') \\"
+ warn " git commit -F \"$GIT_DIR\"/MERGE_MSG -e"
+ die_with_patch $sha1 ""
+ esac
+ ;;
+ *)
+ warn "Unknown command: $command $sha1 $rest"
+ die_with_patch $sha1 "Please fix this in the file $TODO."
+ esac
+ test -s "$TODO" && continue
+
+ HEAD=$(git rev-parse HEAD)
+ HEADNAME=$(cat "$DOTEST"/head-name)
+ git update-ref $HEADNAME $HEAD &&
+ git symbolic-ref HEAD $HEADNAME || exit
+ rm -rf "$DOTEST" &&
+ warn "Successfully rebased and updated $HEADNAME."
+
+ exit $?
+}
+
+do_rest () {
+ while :
+ do
+ do_next
+ done
+ test $? = 0 -a -f "$DOTEST"/verbose &&
+ git diff --stat $(cat "$DOTEST"/head)..HEAD
+ exit
+}
+
+while case "$#" in 0) break ;; esac
+do
+ case "$1" in
+ --continue)
+ comment_for_reflog continue
+
+ test -d "$DOTEST" || die "No interactive rebase running"
+
+ require_clean_work_tree
+ do_rest
+ ;;
+ --abort)
+ comment_for_reflog abort
+
+ test -d "$DOTEST" || die "No interactive rebase running"
+
+ HEADNAME=$(cat "$DOTEST"/head-name)
+ HEAD=$(cat "$DOTEST"/head)
+ git symbolic-ref HEAD $HEADNAME &&
+ git reset --hard $HEAD &&
+ rm -rf "$DOTEST"
+ exit
+ ;;
+ --skip)
+ comment_for_reflog skip
+
+ test -d "$DOTEST" || die "No interactive rebase running"
+
+ git reset --hard && do_rest
+ ;;
+ -s|--strategy)
+ case "$#,$1" in
+ *,*=*)
+ STRATEGY="-s `expr "z$1" : 'z-[^=]*=\(.*\)'`" ;;
+ 1,*)
+ usage ;;
+ *)
+ STRATEGY="-s $2"
+ shift ;;
+ esac
+ ;;
+ --merge)
+ # we use merge anyway
+ ;;
+ -C*)
+ die "Interactive rebase uses merge, so $1 does not make sense"
+ ;;
+ -v)
+ VERBOSE=t
+ ;;
+ -i|--interactive)
+ # yeah, we know
+ ;;
+ ''|-h)
+ usage
+ ;;
+ *)
+ test -d "$DOTEST" &&
+ die "Interactive rebase already started"
+
+ git var GIT_COMMITTER_IDENT >/dev/null ||
+ die "You need to set your committer info first"
+
+ comment_for_reflog start
+
+ ONTO=
+ case "$1" in
+ --onto)
+ ONTO=$(git rev-parse --verify "$2") ||
+ die "Does not point to a valid commit: $2"
+ shift; shift
+ ;;
+ esac
+
+ require_clean_work_tree
+
+ test -z "$2" || git checkout "$2" ||
+ die "Could not checkout $2"
+
+ HEAD=$(git rev-parse --verify HEAD) || die "No HEAD?"
+ UPSTREAM=$(git rev-parse --verify "$1") || die "Invalid base"
+
+ test -z "$ONTO" && ONTO=$UPSTREAM
+
+ mkdir "$DOTEST" || die "Could not create temporary $DOTEST"
+ : > "$DOTEST"/interactive || die "Could not mark as interactive"
+ git symbolic-ref HEAD > "$DOTEST"/head-name ||
+ die "Could not get HEAD"
+
+ echo $HEAD > "$DOTEST"/head
+ echo $UPSTREAM > "$DOTEST"/upstream
+ echo $ONTO > "$DOTEST"/onto
+ test t = "$VERBOSE" && : > "$DOTEST"/verbose
+
+ cat > "$TODO" << EOF
+# Reorder by exchanging lines. Skip by removing lines. If you want to
+# edit a commit, replace the "pick" command with "edit". If you want to
+# squash the changes of a commit A into a commit B, place A directly
+# after B, and replace the "pick" command with "squash".
+EOF
+ git rev-list --no-merges --pretty=oneline --abbrev-commit \
+ --abbrev=7 --reverse $UPSTREAM..$HEAD | \
+ sed "s/^/pick /" >> "$TODO"
+
+ test -s "$TODO" || die "Nothing to do"
+
+ cp "$TODO" "$TODO".backup
+ ${VISUAL:-${EDITOR:-vi}} "$TODO" ||
+ die "Could not execute editor"
+
+ git reset --hard $ONTO && do_rest
+ ;;
+ esac
+ shift
+done
diff --git a/git-rebase.sh b/git-rebase.sh
index 2aa3a01..9e25158 100755
--- a/git-rebase.sh
+++ b/git-rebase.sh
@@ -3,7 +3,7 @@
# Copyright (c) 2005 Junio C Hamano.
#
-USAGE='[-v] [--onto <newbase>] <upstream> [<branch>]'
+USAGE='[--interactive | -i] [-v] [--onto <newbase>] <upstream> [<branch>]'
LONG_USAGE='git-rebase replaces <branch> with a new branch of the
same name. When the --onto option is provided the new branch starts
out with a HEAD equal to <newbase>, otherwise it is equal to <upstream>
@@ -120,6 +120,16 @@ finish_rb_merge () {
echo "All done."
}
+is_interactive () {
+ test -f "$dotest"/interactive ||
+ while case "$1" in ''|-i|--interactive) break ;; esac
+ do
+ shift
+ done && test -n "$1"
+}
+
+is_interactive "$@" && exec git-rebase--interactive "$@"
+
while case "$#" in 0) break ;; esac
do
case "$1" in
diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
new file mode 100755
index 0000000..48aa8ea
--- /dev/null
+++ b/t/t3404-rebase-interactive.sh
@@ -0,0 +1,163 @@
+#!/bin/sh
+#
+# Copyright (c) 2007 Johannes E. Schindelin
+#
+
+test_description='git rebase interactive
+
+This test runs git rebase "interactively", by faking an edit, and verifies
+that the result still makes sense.
+'
+. ./test-lib.sh
+
+# set up two branches like this:
+#
+# A - B - C - D - E
+# \
+# F - G - H
+# \
+# I
+#
+# where B, D and G touch the same file.
+
+test_expect_success 'setup' '
+ : > file1 &&
+ git add file1 &&
+ test_tick &&
+ git commit -m A &&
+ git tag A &&
+ echo 1 > file1 &&
+ test_tick &&
+ git commit -m B file1 &&
+ : > file2 &&
+ git add file2 &&
+ test_tick &&
+ git commit -m C &&
+ echo 2 > file1 &&
+ test_tick &&
+ git commit -m D file1 &&
+ : > file3 &&
+ git add file3 &&
+ test_tick &&
+ git commit -m E &&
+ git checkout -b branch1 A &&
+ : > file4 &&
+ git add file4 &&
+ test_tick &&
+ git commit -m F &&
+ git tag F &&
+ echo 3 > file1 &&
+ test_tick &&
+ git commit -m G file1 &&
+ : > file5 &&
+ git add file5 &&
+ test_tick &&
+ git commit -m H &&
+ git checkout -b branch2 F &&
+ : > file6 &&
+ git add file6 &&
+ test_tick &&
+ git commit -m I &&
+ git tag I
+'
+
+cat > fake-editor.sh << EOF
+#!/bin/sh
+test "\$1" = .git/COMMIT_EDITMSG && exit
+test -z "\$FAKE_LINES" && exit
+grep -v "^#" < "\$1" > "\$1".tmp
+rm "\$1"
+cat "\$1".tmp
+action=pick
+for line in \$FAKE_LINES; do
+ case \$line in
+ squash)
+ action="\$line";;
+ *)
+ echo sed -n "\${line}s/^pick/\$action/p"
+ sed -n "\${line}p" < "\$1".tmp
+ sed -n "\${line}s/^pick/\$action/p" < "\$1".tmp >> "\$1"
+ action=pick;;
+ esac
+done
+EOF
+
+chmod a+x fake-editor.sh
+VISUAL="$(pwd)/fake-editor.sh"
+export VISUAL
+
+test_expect_success 'no changes are a nop' '
+ git rebase -i F &&
+ test $(git rev-parse I) = $(git rev-parse HEAD)
+'
+
+test_expect_success 'rebase on top of a non-conflicting commit' '
+ git checkout branch1 &&
+ git tag original-branch1 &&
+ git rebase -i branch2 &&
+ test file6 = $(git diff --name-only original-branch1) &&
+ test $(git rev-parse I) = $(git rev-parse HEAD~2)
+'
+
+test_expect_success 'exchange two commits' '
+ FAKE_LINES="2 1" git rebase -i HEAD~2 &&
+ test H = $(git cat-file commit HEAD^ | tail -n 1) &&
+ test G = $(git cat-file commit HEAD | tail -n 1)
+'
+
+cat > expect << EOF
+diff --git a/file1 b/file1
+index e69de29..00750ed 100644
+--- a/file1
++++ b/file1
+@@ -0,0 +1 @@
++3
+EOF
+
+cat > expect2 << EOF
+<<<<<<< HEAD:file1
+2
+=======
+3
+>>>>>>> b7ca976... G:file1
+EOF
+
+test_expect_success 'stop on conflicting pick' '
+ git tag new-branch1 &&
+ ! git rebase -i master &&
+ diff -u expect .git/.dotest-merge/patch &&
+ diff -u expect2 file1 &&
+ test 4 = $(grep -v "^#" < .git/.dotest-merge/done | wc -l) &&
+ test 0 = $(grep -v "^#" < .git/.dotest-merge/todo | wc -l)
+'
+
+test_expect_success 'abort' '
+ git rebase --abort &&
+ test $(git rev-parse new-branch1) = $(git rev-parse HEAD) &&
+ ! test -d .git/.dotest-merge
+'
+
+test_expect_success 'retain authorship' '
+ echo A > file7 &&
+ git add file7 &&
+ GIT_AUTHOR_NAME="Twerp Snog" git commit -m "different author" &&
+ git tag twerp &&
+ git rebase -i --onto master HEAD^ &&
+ git show HEAD | grep "^Author: Twerp Snog"
+'
+
+test_expect_success 'squash' '
+ git reset --hard twerp &&
+ echo B > file7 &&
+ GIT_AUTHOR_NAME="Nitfol" git commit -m "nitfol" file7 &&
+ echo "******************************" &&
+ FAKE_LINES="1 squash 2" git rebase -i --onto master HEAD~2 &&
+ test B = $(cat file7) &&
+ test $(git rev-parse HEAD^) = $(git rev-parse master)
+'
+
+test_expect_success 'retain authorship when squashing' '
+ git show HEAD | grep "^Author: Nitfol"
+'
+
+test_done
--
1.5.2.2.279.g74fb3
^ permalink raw reply related
* [PATCH 1/2] Move the pick_author code to git-sh-setup
From: Johannes Schindelin @ 2007-06-23 23:01 UTC (permalink / raw)
To: git, gitster
At the moment, only git-commit uses that code, to pick the author name,
email and date from a given commit.
This code will be reused in git rebase --interactive.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
git-commit.sh | 30 ++----------------------------
git-sh-setup.sh | 27 +++++++++++++++++++++++++++
2 files changed, 29 insertions(+), 28 deletions(-)
diff --git a/git-commit.sh b/git-commit.sh
index 5547a02..4bef375 100755
--- a/git-commit.sh
+++ b/git-commit.sh
@@ -483,34 +483,8 @@ fi >>"$GIT_DIR"/COMMIT_EDITMSG
# Author
if test '' != "$use_commit"
then
- pick_author_script='
- /^author /{
- s/'\''/'\''\\'\'\''/g
- h
- s/^author \([^<]*\) <[^>]*> .*$/\1/
- s/'\''/'\''\'\'\''/g
- s/.*/GIT_AUTHOR_NAME='\''&'\''/p
-
- g
- s/^author [^<]* <\([^>]*\)> .*$/\1/
- s/'\''/'\''\'\'\''/g
- s/.*/GIT_AUTHOR_EMAIL='\''&'\''/p
-
- g
- s/^author [^<]* <[^>]*> \(.*\)$/\1/
- s/'\''/'\''\'\'\''/g
- s/.*/GIT_AUTHOR_DATE='\''&'\''/p
-
- q
- }
- '
- encoding=$(git config i18n.commitencoding || echo UTF-8)
- set_author_env=`git show -s --pretty=raw --encoding="$encoding" "$use_commit" |
- LANG=C LC_ALL=C sed -ne "$pick_author_script"`
- eval "$set_author_env"
- export GIT_AUTHOR_NAME
- export GIT_AUTHOR_EMAIL
- export GIT_AUTHOR_DATE
+ eval $(get_author_ident_from_commit "$use_commit")
+ export GIT_AUTHOR_NAME GIT_AUTHOR_EMAIL GIT_AUTHOR_DATE
fi
if test '' != "$force_author"
then
diff --git a/git-sh-setup.sh b/git-sh-setup.sh
index f24c7f2..d861db3 100755
--- a/git-sh-setup.sh
+++ b/git-sh-setup.sh
@@ -53,6 +53,33 @@ require_work_tree () {
die "fatal: $0 cannot be used without a working tree."
}
+get_author_ident_from_commit () {
+ pick_author_script='
+ /^author /{
+ s/'\''/'\''\\'\'\''/g
+ h
+ s/^author \([^<]*\) <[^>]*> .*$/\1/
+ s/'\''/'\''\'\'\''/g
+ s/.*/GIT_AUTHOR_NAME='\''&'\''/p
+
+ g
+ s/^author [^<]* <\([^>]*\)> .*$/\1/
+ s/'\''/'\''\'\'\''/g
+ s/.*/GIT_AUTHOR_EMAIL='\''&'\''/p
+
+ g
+ s/^author [^<]* <[^>]*> \(.*\)$/\1/
+ s/'\''/'\''\'\'\''/g
+ s/.*/GIT_AUTHOR_DATE='\''&'\''/p
+
+ q
+ }
+ '
+ encoding=$(git config i18n.commitencoding || echo UTF-8)
+ git show -s --pretty=raw --encoding="$encoding" "$1" |
+ LANG=C LC_ALL=C sed -ne "$pick_author_script"
+}
+
if [ -z "$LONG_USAGE" ]
then
LONG_USAGE="Usage: $0 $USAGE"
--
1.5.2.2.279.g74fb3
^ permalink raw reply related
* Re: [PATCH] Escape some tilde characters causing spurious subscripts in documentation
From: Johannes Schindelin @ 2007-06-23 22:36 UTC (permalink / raw)
To: Jason Sewall; +Cc: Junio C Hamano, git
In-Reply-To: <31e9dd080706231519p25520183vb0f102a4585e17f4@mail.gmail.com>
Hi,
On Sat, 23 Jun 2007, Jason Sewall wrote:
> This is my first attempt at actually submitting a patch to the git list;
> let me know if this is a reasonably presented patch. It is truly
> trivial, but getting those docs cleaned up is important!
You followed SubmittingPatches really well. Commit message, diffstat and
the comment between message and diffstat.
Thanks.
> @@ -80,12 +80,12 @@ SPECIFYING REFERENCES
>
> git-bundle will only package references that are shown by
> git-show-ref: this includes heads, tags, and remote heads. References
> -such as master~1 cannot be packaged, but are perfectly suitable for
> +such as master\~1 cannot be packaged, but are perfectly suitable for
But you have some whitespace damage, unfortunately. The space at the
beginning of the lines is missing.
Judging from your email address, I suspect you copied&pasted the patch
into the web interface, and somehow this mangled the white space.
Can you send it somehow via SMTP?
Ciao,
Dscho
^ permalink raw reply
* [PATCH] Escape some tilde characters causing spurious subscripts in documentation
From: Jason Sewall @ 2007-06-23 22:19 UTC (permalink / raw)
To: Junio C Hamano, git
A few unescaped tilde characters were causing long parts of the html
documentation to be formatted as footnotes. This patch fixes them; I
think I found all of them, but no promises.
Signed-off-by: Jason Sewall <jasonsewall@gmail.com>
---
This is my first attempt at actually submitting a patch to the git
list; let me know if this is a reasonably presented patch. It is truly
trivial, but getting those docs cleaned up is important!
Documentation/git-bundle.txt | 8 ++++----
Documentation/git-daemon.txt | 2 +-
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/Documentation/git-bundle.txt b/Documentation/git-bundle.txt
index 5051e2b..d89f350 100644
--- a/Documentation/git-bundle.txt
+++ b/Documentation/git-bundle.txt
@@ -61,7 +61,7 @@ unbundle <file>::
[git-rev-list-args...]::
A list of arguments, acceptable to git-rev-parse and
git-rev-list, that specify the specific objects and references
- to transport. For example, "master~10..master" causes the
+ to transport. For example, "master\~10..master" causes the
current master reference to be packaged along with all objects
added since its 10th ancestor commit. There is no explicit
limit to the number of references and objects that may be
@@ -80,12 +80,12 @@ SPECIFYING REFERENCES
git-bundle will only package references that are shown by
git-show-ref: this includes heads, tags, and remote heads. References
-such as master~1 cannot be packaged, but are perfectly suitable for
+such as master\~1 cannot be packaged, but are perfectly suitable for
defining the basis. More than one reference may be packaged, and more
than one basis can be specified. The objects packaged are those not
contained in the union of the given bases. Each basis can be
-specified explicitly (e.g., ^master~10), or implicitly (e.g.,
-master~10..master, master --since=10.days.ago).
+specified explicitly (e.g., ^master\~10), or implicitly (e.g.,
+master\~10..master, master --since=10.days.ago).
It is very important that the basis used be held by the destination.
It is okay to err on the side of conservatism, causing the bundle file
diff --git a/Documentation/git-daemon.txt b/Documentation/git-daemon.txt
index 4b30b18..3f9cec5 100644
--- a/Documentation/git-daemon.txt
+++ b/Documentation/git-daemon.txt
@@ -98,7 +98,7 @@ OPTIONS
--verbose, thus by default only error conditions will be logged.
--user-path, --user-path=path::
- Allow ~user notation to be used in requests. When
+ Allow \~user notation to be used in requests. When
specified with no parameter, requests to
git://host/~alice/foo is taken as a request to access
'foo' repository in the home directory of user `alice`.
--
1.5.2.1.280.g38570
^ permalink raw reply related
* Re: [PATCH] transplant: move a series of commits to a different parent
From: Alex Riesen @ 2007-06-23 21:04 UTC (permalink / raw)
To: Steffen Prohaska; +Cc: git
In-Reply-To: <11826268772950-git-send-email-prohaska@zib.de>
On 6/23/07, Steffen Prohaska <prohaska@zib.de> wrote:
> git-transplant.sh <onto> <from> <to>
>
> transplant starts with the contents of <onto> and puts on top of
> it the contents of files if they are touched by the series of
> commits <from>..<to>. If a commit touches a file the content of
> this file is taken as it is in the commit. No merging is
> performed. Original authors, commiters, and commit messages are
> preserved.
>
> Warning: this is just a quick hack to solve _my_ problem.
> - No error checking is performed.
> - Removal of files is not handled.
> - Whitespace in filename is not handled.
> - The index is left in dirty state.
> - No branch is created for the result.
> - The script is not integrated with git's shell utilities.
# detached head
git checkout $(git rev-parse onto) && git format-patch --stdout
--full-index from..to|git am -3
^ permalink raw reply
* Re: [PATCH] transplant: move a series of commits to a different parent
From: Johannes Schindelin @ 2007-06-23 20:54 UTC (permalink / raw)
To: Steffen Prohaska; +Cc: git
In-Reply-To: <11826268772950-git-send-email-prohaska@zib.de>
Hi,
On Sat, 23 Jun 2007, Steffen Prohaska wrote:
> git-transplant.sh <onto> <from> <to>
>
> transplant starts with the contents of <onto> and puts on top of
> it the contents of files if they are touched by the series of
> commits <from>..<to>.
This reeks of rebase.
IOW, I suspect that it does almost the same as
git checkout <to>
git rebase -s ours --onto <onto> <from>^
Ciao,
Dscho
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox