chiark / gitweb /
dgit clone: No longer create an "origin" remote
[dgit.git] / dgit
diff --git a/dgit b/dgit
index dd052fe106d95d2fd159f739b2ea14274988f67f..cde85468cfcad54ec99661f9d0ec0d02c2572c4e 100755 (executable)
--- a/dgit
+++ b/dgit
@@ -2,8 +2,9 @@
 # dgit
 # Integration between git and Debian-style archives
 #
 # dgit
 # Integration between git and Debian-style archives
 #
-# Copyright (C)2013-2018 Ian Jackson
-# Copyright (C)2017-2018 Sean Whitton
+# Copyright (C)2013-2019 Ian Jackson
+# Copyright (C)2017-2019 Sean Whitton
+# Copyright (C)2019      Matthew Vernon / Genome Research Limited
 #
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
 #
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -53,7 +54,7 @@ use Debian::Dgit;
 our $our_version = 'UNRELEASED'; ###substituted###
 our $absurdity = undef; ###substituted###
 
 our $our_version = 'UNRELEASED'; ###substituted###
 our $absurdity = undef; ###substituted###
 
-our @rpushprotovsn_support = qw(4 3 2); # 4 is new tag format
+our @rpushprotovsn_support = qw(6 5 4); # Reverse order!
 our $protovsn;
 
 our $cmd;
 our $protovsn;
 
 our $cmd;
@@ -79,16 +80,19 @@ our $changes_since_version;
 our $rmchanges;
 our $overwrite_version; # undef: not specified; '': check changelog
 our $quilt_mode;
 our $rmchanges;
 our $overwrite_version; # undef: not specified; '': check changelog
 our $quilt_mode;
-our $quilt_modes_re = 'linear|smash|auto|nofix|nocheck|gbp|dpm|unapplied';
+our $quilt_upstream_commitish;
+our $quilt_upstream_commitish_used;
+our $quilt_upstream_commitish_message;
+our $quilt_options_re = 'gbp|dpm|baredebian(?:\+tarball|\+git)?';
+our $quilt_modes_re = "linear|smash|auto|nofix|nocheck|unapplied|$quilt_options_re";
+our $splitview_mode;
+our $splitview_modes_re = qr{auto|always|never};
 our $dodep14tag;
 our %internal_object_save;
 our $we_are_responder;
 our $we_are_initiator;
 our $initiator_tempdir;
 our $patches_applied_dirtily = 00;
 our $dodep14tag;
 our %internal_object_save;
 our $we_are_responder;
 our $we_are_initiator;
 our $initiator_tempdir;
 our $patches_applied_dirtily = 00;
-our $tagformat_want;
-our $tagformat;
-our $tagformatfn;
 our $chase_dsc_distro=1;
 
 our %forceopts = map { $_=>0 }
 our $chase_dsc_distro=1;
 
 our %forceopts = map { $_=>0 }
@@ -101,7 +105,6 @@ our %forceopts = map { $_=>0 }
 
 our %format_ok = map { $_=>1 } ("1.0","3.0 (native)","3.0 (quilt)");
 
 
 our %format_ok = map { $_=>1 } ("1.0","3.0 (native)","3.0 (quilt)");
 
-our $suite_re = '[-+.0-9a-z]+';
 our $cleanmode_re = qr{(?: dpkg-source (?: -d )? (?: ,no-check | ,all-check )?
                      | (?: git | git-ff ) (?: ,always )?
                          | check (?: ,ignores )?
 our $cleanmode_re = qr{(?: dpkg-source (?: -d )? (?: ,no-check | ,all-check )?
                      | (?: git | git-ff ) (?: ,always )?
                          | check (?: ,ignores )?
@@ -114,7 +117,6 @@ our $rewritemap = 'dgit-rewrite/map';
 
 our @dpkg_source_ignores = qw(-i(?:^|/)\.git(?:/|$) -I.git);
 
 
 our @dpkg_source_ignores = qw(-i(?:^|/)\.git(?:/|$) -I.git);
 
-our (@git) = qw(git);
 our (@dget) = qw(dget);
 our (@curl) = (qw(curl --proto-redir), '-all,http,https', qw(-L));
 our (@dput) = qw(dput);
 our (@dget) = qw(dget);
 our (@curl) = (qw(curl --proto-redir), '-all,http,https', qw(-L));
 our (@dput) = qw(dput);
@@ -176,11 +178,11 @@ autoflush STDOUT 1;
 
 our $supplementary_message = '';
 our $made_split_brain = 0;
 
 our $supplementary_message = '';
 our $made_split_brain = 0;
-our $do_split_brain = 0;
+our $do_split_brain;
 
 # Interactions between quilt mode and split brain
 # (currently, split brain only implemented iff
 
 # Interactions between quilt mode and split brain
 # (currently, split brain only implemented iff
-#  madformat_wantfixup && quiltmode_splitbrain)
+#  madformat_wantfixup && quiltmode_splitting)
 #
 #   source format        sane           `3.0 (quilt)'
 #                                       madformat_wantfixup()
 #
 #   source format        sane           `3.0 (quilt)'
 #                                       madformat_wantfixup()
@@ -192,7 +194,7 @@ our $do_split_brain = 0;
 #
 #   no split          no q cache        no q cache          forbidden,
 #     brain           PM on master      q fixup on master   prevented
 #
 #   no split          no q cache        no q cache          forbidden,
 #     brain           PM on master      q fixup on master   prevented
-#   !$do_split_brain                    PM on master
+#   !do_split_brain()                    PM on master
 #
 #   split brain       no q cache        q fixup cached, to dgit view
 #                     PM in dgit view   PM in dgit view
 #
 #   split brain       no q cache        q fixup cached, to dgit view
 #                     PM in dgit view   PM in dgit view
@@ -217,11 +219,6 @@ if (!defined $absurdity) {
     $absurdity =~ s{/[^/]+$}{/absurd} or die;
 }
 
     $absurdity =~ s{/[^/]+$}{/absurd} or die;
 }
 
-sub debiantag ($$) {
-    my ($v,$distro) = @_;
-    return $tagformatfn->($v, $distro);
-}
-
 sub madformat ($) { $_[0] eq '3.0 (quilt)' }
 
 sub lbranch () { return "$branchprefix/$csuite"; }
 sub madformat ($) { $_[0] eq '3.0 (quilt)' }
 
 sub lbranch () { return "$branchprefix/$csuite"; }
@@ -299,9 +296,15 @@ sub deliberately_not_fast_forward () {
     }
 }
 
     }
 }
 
-sub quiltmode_splitbrain () {
-    $quilt_mode =~ m/gbp|dpm|unapplied/;
+sub quiltmode_splitting () {
+    $quilt_mode =~ m/gbp|dpm|unapplied|baredebian/;
 }
 }
+sub format_quiltmode_splitting ($) {
+    my ($format) = @_;
+    return madformat_wantfixup($format) && quiltmode_splitting();
+}
+
+sub do_split_brain () { !!($do_split_brain // confess) }
 
 sub opts_opt_multi_cmd {
     my $extra = shift;
 
 sub opts_opt_multi_cmd {
     my $extra = shift;
@@ -448,7 +451,7 @@ sub branch_is_gdr ($) {
 #  > progress NBYTES
 #  [NBYTES message]
 #
 #  > progress NBYTES
 #  [NBYTES message]
 #
-#  > supplementary-message NBYTES          # $protovsn >= 3
+#  > supplementary-message NBYTES
 #  [NBYTES message]
 #
 # main sequence:
 #  [NBYTES message]
 #
 # main sequence:
@@ -468,7 +471,8 @@ sub branch_is_gdr ($) {
 #
 #  > param head DGIT-VIEW-HEAD
 #  > param csuite SUITE
 #
 #  > param head DGIT-VIEW-HEAD
 #  > param csuite SUITE
-#  > param tagformat old|new
+#  > param tagformat new              # $protovsn == 4
+#  > param splitbrain 0|1             # $protovsn >= 6
 #  > param maint-view MAINT-VIEW-HEAD
 #
 #  > param buildinfo-filename P_V_X.buildinfo   # zero or more times
 #  > param maint-view MAINT-VIEW-HEAD
 #
 #  > param buildinfo-filename P_V_X.buildinfo   # zero or more times
@@ -733,7 +737,6 @@ our %defcfg = ('dgit.default.distro' => 'debian',
               'dgit.default.archive-query' => 'madison:',
               'dgit.default.sshpsql-dbname' => 'service=projectb',
               'dgit.default.aptget-components' => 'main',
               'dgit.default.archive-query' => 'madison:',
               'dgit.default.sshpsql-dbname' => 'service=projectb',
               'dgit.default.aptget-components' => 'main',
-              'dgit.default.dgit-tag-format' => 'new,old,maint',
               'dgit.default.source-only-uploads' => 'ok',
               'dgit.dsc-url-proto-ok.http'    => 'true',
               'dgit.dsc-url-proto-ok.https'   => 'true',
               'dgit.default.source-only-uploads' => 'ok',
               'dgit.dsc-url-proto-ok.http'    => 'true',
               'dgit.dsc-url-proto-ok.https'   => 'true',
@@ -780,6 +783,12 @@ our %defcfg = ('dgit.default.distro' => 'debian',
  'dgit-distro.debian-backports.mirror' => 'http://backports.debian.org/debian-backports/',
               'dgit-distro.ubuntu.git-check' => 'false',
  'dgit-distro.ubuntu.mirror' => 'http://archive.ubuntu.com/ubuntu',
  'dgit-distro.debian-backports.mirror' => 'http://backports.debian.org/debian-backports/',
               'dgit-distro.ubuntu.git-check' => 'false',
  'dgit-distro.ubuntu.mirror' => 'http://archive.ubuntu.com/ubuntu',
+              'dgit-distro.ubuntucloud.git-check' => 'false',
+ 'dgit-distro.ubuntucloud.nominal-distro' => 'ubuntu',
+ 'dgit-distro.ubuntucloud.archive-query' => 'aptget:',
+ 'dgit-distro.ubuntucloud.mirror' => 'http://ubuntu-cloud.archive.canonical.com/ubuntu',
+ 'dgit-distro.ubuntucloud.aptget-suite-map' => 's#^([^-]+):([^:]+)$#${1}-updates/$2#; s#^(.+)-(.+):(.+)#$1-$2/$3#;',
+ 'dgit-distro.ubuntucloud.aptget-suite-rmap' => 's#/(.+)$#-$1#',
               'dgit-distro.test-dummy.ssh' => "$td/ssh",
               'dgit-distro.test-dummy.username' => "alice",
               'dgit-distro.test-dummy.git-check' => "ssh-cmd",
               'dgit-distro.test-dummy.ssh' => "$td/ssh",
               'dgit-distro.test-dummy.username' => "alice",
               'dgit-distro.test-dummy.git-check' => "ssh-cmd",
@@ -974,12 +983,33 @@ sub notpushing () {
     parseopts_late_defaults();
 }
 
     parseopts_late_defaults();
 }
 
+sub determine_whether_split_brain ($) {
+    my ($format) = @_;
+    {
+       local $access_forpush;
+       default_from_access_cfg(\$splitview_mode, 'split-view', 'auto',
+                               $splitview_modes_re);
+       $do_split_brain = 1 if $splitview_mode eq 'always';
+    }
+
+    printdebug "format $format, quilt mode $quilt_mode\n";
+
+    if (format_quiltmode_splitting $format) {
+       $splitview_mode ne 'never' or
+           fail f_ "dgit: quilt mode \`%s' (for format \`%s')".
+                   " implies split view, but split-view set to \`%s'",
+                   $quilt_mode, $format, $splitview_mode;
+       $do_split_brain = 1;
+    }
+    $do_split_brain //= 0;
+}
+
 sub supplementary_message ($) {
     my ($msg) = @_;
     if (!$we_are_responder) {
        $supplementary_message = $msg;
        return;
 sub supplementary_message ($) {
     my ($msg) = @_;
     if (!$we_are_responder) {
        $supplementary_message = $msg;
        return;
-    } elsif ($protovsn >= 3) {
+    } else {
        responder_send_command "supplementary-message ".length($msg)
            or confess "$!";
        print PO $msg or confess "$!";
        responder_send_command "supplementary-message ".length($msg)
            or confess "$!";
        print PO $msg or confess "$!";
@@ -1411,11 +1441,11 @@ sub canonicalise_suite_aptget {
        my $val = $release->{$name};
        if (defined $val) {
            printdebug "release file $name: $val\n";
        my $val = $release->{$name};
        if (defined $val) {
            printdebug "release file $name: $val\n";
+           cfg_apply_map(\$val, 'suite rmap',
+                         access_cfg('aptget-suite-rmap', 'RETURN-UNDEF'));
            $val =~ m/^$suite_re$/o or fail f_
                "Release file (%s) specifies intolerable %s",
                $aptget_releasefile, $name;
            $val =~ m/^$suite_re$/o or fail f_
                "Release file (%s) specifies intolerable %s",
                $aptget_releasefile, $name;
-           cfg_apply_map(\$val, 'suite rmap',
-                         access_cfg('aptget-suite-rmap', 'RETURN-UNDEF'));
            return $val
        }
     }
            return $val
        }
     }
@@ -1681,58 +1711,6 @@ sub archive_query_dummycat ($$) {
 sub file_in_archive_dummycat () { return undef; }
 sub package_not_wholly_new_dummycat () { return undef; }
 
 sub file_in_archive_dummycat () { return undef; }
 sub package_not_wholly_new_dummycat () { return undef; }
 
-#---------- tag format handling ----------
-# (untranslated, because everything should be new tag format by now)
-
-sub access_cfg_tagformats () {
-    split /\,/, access_cfg('dgit-tag-format');
-}
-
-sub access_cfg_tagformats_can_splitbrain () {
-    my %y = map { $_ => 1 } access_cfg_tagformats;
-    foreach my $needtf (qw(new maint)) {
-       next if $y{$needtf};
-       return 0;
-    }
-    return 1;
-}
-
-sub need_tagformat ($$) {
-    my ($fmt, $why) = @_;
-    fail "need to use tag format $fmt ($why) but also need".
-       " to use tag format $tagformat_want->[0] ($tagformat_want->[1])".
-       " - no way to proceed"
-       if $tagformat_want && $tagformat_want->[0] ne $fmt;
-    $tagformat_want = [$fmt, $why, $tagformat_want->[2] // 0];
-}
-
-sub select_tagformat () {
-    # sets $tagformatfn
-    return if $tagformatfn && !$tagformat_want;
-    die 'bug' if $tagformatfn && $tagformat_want;
-    # ... $tagformat_want assigned after previous select_tagformat
-
-    my (@supported) = grep { $_ =~ m/^(?:old|new)$/ } access_cfg_tagformats();
-    printdebug "select_tagformat supported @supported\n";
-
-    $tagformat_want //= [ $supported[0], "distro access configuration", 0 ];
-    printdebug "select_tagformat specified @$tagformat_want\n";
-
-    my ($fmt,$why,$override) = @$tagformat_want;
-
-    fail "target distro supports tag formats @supported".
-       " but have to use $fmt ($why)"
-       unless $override
-           or grep { $_ eq $fmt } @supported;
-
-    $tagformat_want = undef;
-    $tagformat = $fmt;
-    $tagformatfn = ${*::}{"debiantag_$fmt"};
-
-    fail "trying to use unknown tag format \`$fmt' ($why) !"
-       unless $tagformatfn;
-}
-
 #---------- archive query entrypoints and rest of program ----------
 
 sub canonicalise_suite () {
 #---------- archive query entrypoints and rest of program ----------
 
 sub canonicalise_suite () {
@@ -1856,7 +1834,7 @@ sub prep_ud () {
 }
 
 sub mktree_in_ud_here () {
 }
 
 sub mktree_in_ud_here () {
-    playtree_setup $gitcfgs{local};
+    playtree_setup();
 }
 
 sub git_write_tree () {
 }
 
 sub git_write_tree () {
@@ -2147,11 +2125,6 @@ END
     }
 }
 
     }
 }
 
-sub make_commit ($) {
-    my ($file) = @_;
-    return cmdoutput @git, qw(hash-object -w -t commit), $file;
-}
-
 sub clogp_authline ($) {
     my ($clogp) = @_;
     my $author = getfield $clogp, 'Maintainer';
 sub clogp_authline ($) {
     my ($clogp) = @_;
     my $author = getfield $clogp, 'Maintainer';
@@ -2305,62 +2278,9 @@ sub dotdot_bpd_transfer_origs ($$$) {
     closedir DD;
 }
 
     closedir DD;
 }
 
-sub generate_commits_from_dsc () {
-    # See big comment in fetch_from_archive, below.
-    # See also README.dsc-import.
-    prep_ud();
-    changedir $playground;
-
-    my $bpd_abs = bpd_abs();
-    my $upstreamv = upstreamversion $dsc->{version};
-    my @dfi = dsc_files_info();
-
-    dotdot_bpd_transfer_origs $bpd_abs, $upstreamv,
-       sub { grep { $_->{Filename} eq $_[0] } @dfi };
-
-    foreach my $fi (@dfi) {
-       my $f = $fi->{Filename};
-       die "$f ?" if $f =~ m#/|^\.|\.dsc$|\.tmp$#;
-       my $upper_f = "$bpd_abs/$f";
-
-       printdebug "considering reusing $f: ";
-
-       if (link_ltarget "$upper_f,fetch", $f) {
-           printdebug "linked (using ...,fetch).\n";
-       } elsif ((printdebug "($!) "),
-                $! != ENOENT) {
-           fail f_ "accessing %s: %s", "$buildproductsdir/$f,fetch", $!;
-       } elsif (link_ltarget $upper_f, $f) {
-           printdebug "linked.\n";
-       } elsif ((printdebug "($!) "),
-                $! != ENOENT) {
-           fail f_ "accessing %s: %s", "$buildproductsdir/$f", $!;
-       } else {
-           printdebug "absent.\n";
-       }
-
-       my $refetched;
-       complete_file_from_dsc('.', $fi, \$refetched)
-           or next;
-
-       printdebug "considering saving $f: ";
-
-       if (rename_link_xf 1, $f, $upper_f) {
-           printdebug "linked.\n";
-       } elsif ((printdebug "($@) "),
-                $! != EEXIST) {
-           fail f_ "saving %s: %s", "$buildproductsdir/$f", $@;
-       } elsif (!$refetched) {
-           printdebug "no need.\n";
-       } elsif (rename_link_xf 1, $f, "$upper_f,fetch") {
-           printdebug "linked (using ...,fetch).\n";
-       } elsif ((printdebug "($@) "),
-                $! != EEXIST) {
-           fail f_ "saving %s: %s", "$buildproductsdir/$f,fetch", $@;
-       } else {
-           printdebug "cannot.\n";
-       }
-    }
+sub import_tarball_tartrees ($$) {
+    my ($upstreamv, $dfi) = @_;
+    # cwd should be the playground
 
     # We unpack and record the orig tarballs first, so that we only
     # need disk space for one private copy of the unpacked source.
 
     # We unpack and record the orig tarballs first, so that we only
     # need disk space for one private copy of the unpacked source.
@@ -2370,14 +2290,13 @@ sub generate_commits_from_dsc () {
     my @tartrees;
     my $orig_f_base = srcfn $upstreamv, '';
 
     my @tartrees;
     my $orig_f_base = srcfn $upstreamv, '';
 
-    foreach my $fi (@dfi) {
+    foreach my $fi (@$dfi) {
        # We actually import, and record as a commit, every tarball
        # (unless there is only one file, in which case there seems
        # little point.
 
        my $f = $fi->{Filename};
        printdebug "import considering $f ";
        # We actually import, and record as a commit, every tarball
        # (unless there is only one file, in which case there seems
        # little point.
 
        my $f = $fi->{Filename};
        printdebug "import considering $f ";
-       (printdebug "only one dfi\n"), next if @dfi == 1;
        (printdebug "not tar\n"), next unless $f =~ m/\.tar(\.\w+)?$/;
        (printdebug "signature\n"), next if $f =~ m/$orig_f_sig_re$/o;
        my $compr_ext = $1;
        (printdebug "not tar\n"), next unless $f =~ m/\.tar(\.\w+)?$/;
        (printdebug "signature\n"), next if $f =~ m/$orig_f_sig_re$/o;
        my $compr_ext = $1;
@@ -2389,6 +2308,7 @@ sub generate_commits_from_dsc () {
                          $compr_ext, $orig_f_part
                         ), "\n";
 
                          $compr_ext, $orig_f_part
                         ), "\n";
 
+       my $path = $fi->{Path} // $f;
        my $input = new IO::File $f, '<' or die "$f $!";
        my $compr_pid;
        my @compr_cmd;
        my $input = new IO::File $f, '<' or die "$f $!";
        my $compr_pid;
        my @compr_cmd;
@@ -2454,6 +2374,7 @@ sub generate_commits_from_dsc () {
             Sort => (!$orig_f_part         ? 2 :
                     $orig_f_part =~ m/-/g ? 1 :
                                             0),
             Sort => (!$orig_f_part         ? 2 :
                     $orig_f_part =~ m/-/g ? 1 :
                                             0),
+            OrigPart => $orig_f_part, # 'orig', 'orig-XXX', or undef 
             F => $f,
             Tree => $tree,
         };
             F => $f,
             Tree => $tree,
         };
@@ -2467,36 +2388,15 @@ sub generate_commits_from_dsc () {
        $a->{F}    cmp $b->{F}
     } @tartrees;
 
        $a->{F}    cmp $b->{F}
     } @tartrees;
 
-    my $any_orig = grep { $_->{Orig} } @tartrees;
-
-    my $dscfn = "$package.dsc";
-
-    my $treeimporthow = 'package';
-
-    open D, ">", $dscfn or die "$dscfn: $!";
-    print D $dscdata or die "$dscfn: $!";
-    close D or die "$dscfn: $!";
-    my @cmd = qw(dpkg-source);
-    push @cmd, '--no-check' if $dsc_checked;
-    if (madformat $dsc->{format}) {
-       push @cmd, '--skip-patches';
-       $treeimporthow = 'unpatched';
-    }
-    push @cmd, qw(-x --), $dscfn;
-    runcmd @cmd;
+    @tartrees;
+}
 
 
-    my ($tree,$dir) = mktree_in_ud_from_only_subdir(__ "source package");
-    if (madformat $dsc->{format}) { 
-       check_for_vendor_patches();
-    }
+sub import_tarball_commits ($$) {
+    my ($tartrees, $upstreamv) = @_;
+    # cwd should be a playtree which has a relevant debian/changelog
+    # fills in $tt->{Commit} for each one
 
 
-    my $dappliedtree;
-    if (madformat $dsc->{format}) {
-       my @pcmd = qw(dpkg-source --before-build .);
-       runcmd shell_cmd 'exec >/dev/null', @pcmd;
-       rmtree '.pc';
-       $dappliedtree = git_add_write_tree();
-    }
+    my $any_orig = grep { $_->{Orig} } @$tartrees;
 
     my @clogcmd = qw(dpkg-parsechangelog --format rfc822 --all);
     my $clogp;
 
     my @clogcmd = qw(dpkg-parsechangelog --format rfc822 --all);
     my $clogp;
@@ -2550,20 +2450,22 @@ sub generate_commits_from_dsc () {
     $changes =~ s/^\n//; # Changes: \n
     my $cversion = getfield $clogp, 'Version';
 
     $changes =~ s/^\n//; # Changes: \n
     my $cversion = getfield $clogp, 'Version';
 
-    if (@tartrees) {
+    my $r1authline;
+    if (@$tartrees) {
        $r1clogp //= $clogp; # maybe there's only one entry;
        $r1clogp //= $clogp; # maybe there's only one entry;
-       my $r1authline = clogp_authline $r1clogp;
+        $r1authline = clogp_authline $r1clogp;
        # Strictly, r1authline might now be wrong if it's going to be
        # unused because !$any_orig.  Whatever.
 
        printdebug "import tartrees authline   $authline\n";
        printdebug "import tartrees r1authline $r1authline\n";
 
        # Strictly, r1authline might now be wrong if it's going to be
        # unused because !$any_orig.  Whatever.
 
        printdebug "import tartrees authline   $authline\n";
        printdebug "import tartrees r1authline $r1authline\n";
 
-       foreach my $tt (@tartrees) {
+       foreach my $tt (@$tartrees) {
            printdebug "import tartree $tt->{F} $tt->{Tree}\n";
 
            printdebug "import tartree $tt->{F} $tt->{Tree}\n";
 
-           my $mbody = f_ "Import %s", $tt->{F};
-           $tt->{Commit} = make_commit_text($tt->{Orig} ? <<END_O : <<END_T);
+           # untranslated so that different people's imports are identical
+           my $mbody = sprintf "Import %s", $tt->{F};
+           $tt->{Commit} = hash_commit_text($tt->{Orig} ? <<END_O : <<END_T);
 tree $tt->{Tree}
 author $r1authline
 committer $r1authline
 tree $tt->{Tree}
 author $r1authline
 committer $r1authline
@@ -2583,6 +2485,104 @@ END_T
        }
     }
 
        }
     }
 
+    return ($authline, $r1authline, $clogp, $changes);
+}
+
+sub generate_commits_from_dsc () {
+    # See big comment in fetch_from_archive, below.
+    # See also README.dsc-import.
+    prep_ud();
+    changedir $playground;
+
+    my $bpd_abs = bpd_abs();
+    my $upstreamv = upstreamversion $dsc->{version};
+    my @dfi = dsc_files_info();
+
+    dotdot_bpd_transfer_origs $bpd_abs, $upstreamv,
+       sub { grep { $_->{Filename} eq $_[0] } @dfi };
+
+    foreach my $fi (@dfi) {
+       my $f = $fi->{Filename};
+       die "$f ?" if $f =~ m#/|^\.|\.dsc$|\.tmp$#;
+       my $upper_f = "$bpd_abs/$f";
+
+       printdebug "considering reusing $f: ";
+
+       if (link_ltarget "$upper_f,fetch", $f) {
+           printdebug "linked (using ...,fetch).\n";
+       } elsif ((printdebug "($!) "),
+                $! != ENOENT) {
+           fail f_ "accessing %s: %s", "$buildproductsdir/$f,fetch", $!;
+       } elsif (link_ltarget $upper_f, $f) {
+           printdebug "linked.\n";
+       } elsif ((printdebug "($!) "),
+                $! != ENOENT) {
+           fail f_ "accessing %s: %s", "$buildproductsdir/$f", $!;
+       } else {
+           printdebug "absent.\n";
+       }
+
+       my $refetched;
+       complete_file_from_dsc('.', $fi, \$refetched)
+           or next;
+
+       printdebug "considering saving $f: ";
+
+       if (rename_link_xf 1, $f, $upper_f) {
+           printdebug "linked.\n";
+       } elsif ((printdebug "($@) "),
+                $! != EEXIST) {
+           fail f_ "saving %s: %s", "$buildproductsdir/$f", $@;
+       } elsif (!$refetched) {
+           printdebug "no need.\n";
+       } elsif (rename_link_xf 1, $f, "$upper_f,fetch") {
+           printdebug "linked (using ...,fetch).\n";
+       } elsif ((printdebug "($@) "),
+                $! != EEXIST) {
+           fail f_ "saving %s: %s", "$buildproductsdir/$f,fetch", $@;
+       } else {
+           printdebug "cannot.\n";
+       }
+    }
+
+    my @tartrees;
+    @tartrees = import_tarball_tartrees($upstreamv, \@dfi)
+       unless @dfi == 1; # only one file in .dsc
+
+    my $dscfn = "$package.dsc";
+
+    my $treeimporthow = 'package';
+
+    open D, ">", $dscfn or die "$dscfn: $!";
+    print D $dscdata or die "$dscfn: $!";
+    close D or die "$dscfn: $!";
+    my @cmd = qw(dpkg-source);
+    push @cmd, '--no-check' if $dsc_checked;
+    if (madformat $dsc->{format}) {
+       push @cmd, '--skip-patches';
+       $treeimporthow = 'unpatched';
+    }
+    push @cmd, qw(-x --), $dscfn;
+    runcmd @cmd;
+
+    my ($tree,$dir) = mktree_in_ud_from_only_subdir(__ "source package");
+    if (madformat $dsc->{format}) { 
+       check_for_vendor_patches();
+    }
+
+    my $dappliedtree;
+    if (madformat $dsc->{format}) {
+       my @pcmd = qw(dpkg-source --before-build .);
+       runcmd shell_cmd 'exec >/dev/null', @pcmd;
+       rmtree '.pc';
+       $dappliedtree = git_add_write_tree();
+    }
+
+    my ($authline, $r1authline, $clogp, $changes) =
+       import_tarball_commits(\@tartrees, $upstreamv);
+
+    my $cversion = getfield $clogp, 'Version';
+
     printdebug "import main commit\n";
 
     open C, ">../commit.tmp" or confess "$!";
     printdebug "import main commit\n";
 
     open C, ">../commit.tmp" or confess "$!";
@@ -2602,14 +2602,14 @@ $changes
 END
 
     close C or confess "$!";
 END
 
     close C or confess "$!";
-    my $rawimport_hash = make_commit qw(../commit.tmp);
+    my $rawimport_hash = hash_commit qw(../commit.tmp);
 
     if (madformat $dsc->{format}) {
        printdebug "import apply patches...\n";
 
        # regularise the state of the working tree so that
        # the checkout of $rawimport_hash works nicely.
 
     if (madformat $dsc->{format}) {
        printdebug "import apply patches...\n";
 
        # regularise the state of the working tree so that
        # the checkout of $rawimport_hash works nicely.
-       my $dappliedcommit = make_commit_text(<<END);
+       my $dappliedcommit = hash_commit_text(<<END);
 tree $dappliedtree
 author $authline
 committer $authline
 tree $dappliedtree
 author $authline
 committer $authline
@@ -2702,7 +2702,10 @@ END
        if ($vcmp < 0) {
            @output = ($rawimport_mergeinput, $lastpush_mergeinput,
                { ReverseParents => 1,
        if ($vcmp < 0) {
            @output = ($rawimport_mergeinput, $lastpush_mergeinput,
                { ReverseParents => 1,
-                 Message => (f_ <<END, $package, $cversion, $csuite) });
+                 # untranslated so that different people's pseudomerges
+                 # are not needlessly different (although they will
+                 # still differ if the series of pulls is different)
+                 Message => (sprintf <<END, $package, $cversion, $csuite) });
 Record %s (%s) in archive suite %s
 END
        } elsif ($vcmp > 0) {
 Record %s (%s) in archive suite %s
 END
        } elsif ($vcmp > 0) {
@@ -2983,11 +2986,7 @@ sub git_fetch_us () {
     # deliberately-not-ff, in which case we must fetch everything.
 
     my @specs = deliberately_not_fast_forward ? qw(tags/*) :
     # deliberately-not-ff, in which case we must fetch everything.
 
     my @specs = deliberately_not_fast_forward ? qw(tags/*) :
-       map { "tags/$_" }
-       (quiltmode_splitbrain
-        ? (map { $_->('*',access_nomdistro) }
-           \&debiantag_new, \&debiantag_maintview)
-        : debiantags('*',access_nomdistro));
+       map { "tags/$_" } debiantags('*',access_nomdistro);
     push @specs, server_branch($csuite);
     push @specs, $rewritemap;
     push @specs, qw(heads/*) if deliberately_not_fast_forward;
     push @specs, server_branch($csuite);
     push @specs, $rewritemap;
     push @specs, qw(heads/*) if deliberately_not_fast_forward;
@@ -3463,7 +3462,7 @@ END
        }
 
        close MC or confess "$!";
        }
 
        close MC or confess "$!";
-       $hash = make_commit $mcf;
+       $hash = hash_commit $mcf;
     } else {
        $hash = $mergeinputs[0]{Commit};
     }
     } else {
        $hash = $mergeinputs[0]{Commit};
     }
@@ -3824,7 +3823,7 @@ sub fork_for_multisuite ($) {
        $commit .=
            "author $authline\n".
            "committer $authline\n\n";
        $commit .=
            "author $authline\n".
            "committer $authline\n\n";
-       $output = make_commit_text $commit.$msg;
+       $output = hash_commit_text $commit.$msg;
        printdebug "multisuite merge generated $output\n";
     }
 
        printdebug "multisuite merge generated $output\n";
     }
 
@@ -3883,14 +3882,9 @@ sub clone ($) {
     record_maindir();
     setup_new_tree();
     clone_set_head();
     record_maindir();
     setup_new_tree();
     clone_set_head();
-    my $giturl = access_giturl(1);
-    if (defined $giturl) {
-       runcmd @git, qw(remote add), 'origin', $giturl;
-    }
     if ($hasgit) {
        progress __ "fetching existing git history";
        git_fetch_us();
     if ($hasgit) {
        progress __ "fetching existing git history";
        git_fetch_us();
-       runcmd_ordryrun_local @git, qw(fetch origin);
     } else {
        progress __ "starting new git history";
     }
     } else {
        progress __ "starting new git history";
     }
@@ -4151,7 +4145,7 @@ END
     return $i_arch_v;
 }
 
     return $i_arch_v;
 }
 
-sub pseudomerge_make_commit ($$$$ $$) {
+sub pseudomerge_hash_commit ($$$$ $$) {
     my ($clogp, $dgitview, $archive_hash, $i_arch_v,
        $msg_cmd, $msg_msg) = @_;
     progress f_ "Declaring that HEAD includes all changes in %s...",
     my ($clogp, $dgitview, $archive_hash, $i_arch_v,
        $msg_cmd, $msg_msg) = @_;
     progress f_ "Declaring that HEAD includes all changes in %s...",
@@ -4183,7 +4177,7 @@ $msg_msg
 END
     close MC or confess "$!";
 
 END
     close MC or confess "$!";
 
-    return make_commit($pmf);
+    return hash_commit($pmf);
 }
 
 sub splitbrain_pseudomerge ($$$$) {
 }
 
 sub splitbrain_pseudomerge ($$$$) {
@@ -4241,7 +4235,7 @@ ENDT
     }
 
     my $arch_v = $i_arch_v->[0];
     }
 
     my $arch_v = $i_arch_v->[0];
-    my $r = pseudomerge_make_commit
+    my $r = pseudomerge_hash_commit
        $clogp, $dgitview, $archive_hash, $i_arch_v,
        "dgit --quilt=$quilt_mode",
        (defined $overwrite_version
        $clogp, $dgitview, $archive_hash, $i_arch_v,
        "dgit --quilt=$quilt_mode",
        (defined $overwrite_version
@@ -4265,7 +4259,7 @@ sub plain_overwrite_pseudomerge ($$$) {
 
     my $m = f_ "Declare fast forward from %s", $i_arch_v->[0];
 
 
     my $m = f_ "Declare fast forward from %s", $i_arch_v->[0];
 
-    my $r = pseudomerge_make_commit
+    my $r = pseudomerge_hash_commit
        $clogp, $head, $archive_hash, $i_arch_v,
        "dgit", $m;
 
        $clogp, $head, $archive_hash, $i_arch_v,
        "dgit", $m;
 
@@ -4290,7 +4284,7 @@ sub push_parse_changelog ($) {
 
     if (!$we_are_initiator) {
        # rpush initiator can't do this because it doesn't have $isuite yet
 
     if (!$we_are_initiator) {
        # rpush initiator can't do this because it doesn't have $isuite yet
-       my $tag = debiantag($cversion, access_nomdistro);
+       my $tag = debiantag_new($cversion, access_nomdistro);
        runcmd @git, qw(check-ref-format), $tag;
     }
 
        runcmd @git, qw(check-ref-format), $tag;
     }
 
@@ -4314,7 +4308,7 @@ sub push_tagwants ($$$$) {
     my ($cversion, $dgithead, $maintviewhead, $tfbase) = @_;
     my @tagwants;
     push @tagwants, {
     my ($cversion, $dgithead, $maintviewhead, $tfbase) = @_;
     my @tagwants;
     push @tagwants, {
-        TagFn => \&debiantag,
+        TagFn => \&debiantag_new,
        Objid => $dgithead,
         TfSuffix => '',
         View => 'dgit',
        Objid => $dgithead,
         TfSuffix => '',
         View => 'dgit',
@@ -4326,14 +4320,7 @@ sub push_tagwants ($$$$) {
            TfSuffix => '-maintview',
             View => 'maint',
         };
            TfSuffix => '-maintview',
             View => 'maint',
         };
-    } elsif ($dodep14tag eq 'no' ? 0
-            : $dodep14tag eq 'want' ? access_cfg_tagformats_can_splitbrain
-            : $dodep14tag eq 'always'
-            ? (access_cfg_tagformats_can_splitbrain or fail <<END)
---dep14tag-always (or equivalent in config) means server must support
- both "new" and "maint" tag formats, but config says it doesn't.
-END
-           : die "$dodep14tag ?") {
+    } elsif ($dodep14tag ne 'no') {
        push @tagwants, {
            TagFn => \&debiantag_maintview,
            Objid => $dgithead,
        push @tagwants, {
            TagFn => \&debiantag_maintview,
            Objid => $dgithead,
@@ -4372,11 +4359,11 @@ sub push_mktags ($$ $$ $) {
 
     my $cversion = getfield $clogp, 'Version';
     my $clogsuite = getfield $clogp, 'Distribution';
 
     my $cversion = getfield $clogp, 'Version';
     my $clogsuite = getfield $clogp, 'Distribution';
+    my $format = getfield $dsc, 'Format';
 
     # We make the git tag by hand because (a) that makes it easier
     # to control the "tagger" (b) we can do remote signing
     my $authline = clogp_authline $clogp;
 
     # We make the git tag by hand because (a) that makes it easier
     # to control the "tagger" (b) we can do remote signing
     my $authline = clogp_authline $clogp;
-    my $delibs = join(" ", "",@deliberatelies);
 
     my $mktag = sub {
        my ($tw) = @_;
 
     my $mktag = sub {
        my ($tw) = @_;
@@ -4392,22 +4379,33 @@ tag $tag
 tagger $authline
 
 END
 tagger $authline
 
 END
+
+       my @dtxinfo = @deliberatelies;
+       unshift @dtxinfo, "--quilt=$quilt_mode" if madformat($format);
+       unshift @dtxinfo, do_split_brain() ? "split" : "no-split"
+           # rpush protocol 5 and earlier don't tell us
+           unless $we_are_initiator && $protovsn < 6;
+       my $dtxinfo = join(" ", "",@dtxinfo);
+       my $tag_metadata = <<END;
+[dgit distro=$declaredistro$dtxinfo]
+END
+       foreach my $ref (sort keys %previously) {
+           $tag_metadata .= <<END or confess "$!";
+[dgit previously:$ref=$previously{$ref}]
+END
+       }
+
        if ($tw->{View} eq 'dgit') {
        if ($tw->{View} eq 'dgit') {
-           print TO f_ <<ENDT, $package, $cversion, $clogsuite, $csuite
+           print TO sprintf <<ENDT, $package, $cversion, $clogsuite, $csuite
 %s release %s for %s (%s) [dgit]
 ENDT
                or confess "$!";
 %s release %s for %s (%s) [dgit]
 ENDT
                or confess "$!";
-           print TO <<END or confess "$!";
-[dgit distro=$declaredistro$delibs]
-END
-           foreach my $ref (sort keys %previously) {
-               print TO <<END or confess "$!";
-[dgit previously:$ref=$previously{$ref}]
-END
-           }
        } elsif ($tw->{View} eq 'maint') {
        } elsif ($tw->{View} eq 'maint') {
-           print TO f_ <<END, $package, $cversion, $clogsuite, $csuite,
+           print TO sprintf <<END, $package, $cversion, $clogsuite, $csuite;
 %s release %s for %s (%s)
 %s release %s for %s (%s)
+
+END
+           print TO f_ <<END,
 (maintainer view tag generated by dgit --quilt=%s)
 END
                $quilt_mode
 (maintainer view tag generated by dgit --quilt=%s)
 END
                $quilt_mode
@@ -4415,6 +4413,7 @@ END
        } else {
            confess Dumper($tw)."?";
        }
        } else {
            confess Dumper($tw)."?";
        }
+       print TO "\n", $tag_metadata;
 
        close TO or confess "$!";
 
 
        close TO or confess "$!";
 
@@ -4477,14 +4476,10 @@ Push failed, while preparing your push.
 You can retry the push, after fixing the problem, if you like.
 END
 
 You can retry the push, after fixing the problem, if you like.
 END
 
-    need_tagformat 'new', "quilt mode $quilt_mode"
-        if quiltmode_splitbrain;
-
     prep_ud();
 
     access_giturl(); # check that success is vaguely likely
     rpush_handle_protovsn_bothends() if $we_are_initiator;
     prep_ud();
 
     access_giturl(); # check that success is vaguely likely
     rpush_handle_protovsn_bothends() if $we_are_initiator;
-    select_tagformat();
 
     my $clogpfn = dgit_privdir()."/changelog.822.tmp";
     runcmd shell_cmd "exec >$clogpfn", qw(dpkg-parsechangelog);
 
     my $clogpfn = dgit_privdir()."/changelog.822.tmp";
     runcmd shell_cmd "exec >$clogpfn", qw(dpkg-parsechangelog);
@@ -4509,7 +4504,7 @@ END
     my $actualhead = git_rev_parse('HEAD');
 
     if (branch_is_gdr_unstitched_ff($symref, $actualhead, $archive_hash)) {
     my $actualhead = git_rev_parse('HEAD');
 
     if (branch_is_gdr_unstitched_ff($symref, $actualhead, $archive_hash)) {
-       if (quiltmode_splitbrain()) {
+       if (quiltmode_splitting()) {
            my ($ffq_prev, $gdrlast) = branch_gdr_info($symref, $actualhead);
            fail f_ <<END, $ffq_prev, $quilt_mode;
 Branch is managed by git-debrebase (%s
            my ($ffq_prev, $gdrlast) = branch_gdr_info($symref, $actualhead);
            fail f_ <<END, $ffq_prev, $quilt_mode;
 Branch is managed by git-debrebase (%s
@@ -4529,7 +4524,7 @@ END
 
     if (madformat_wantfixup($format)) {
        # user might have not used dgit build, so maybe do this now:
 
     if (madformat_wantfixup($format)) {
        # user might have not used dgit build, so maybe do this now:
-       if ($do_split_brain) {
+       if (do_split_brain()) {
            changedir $playground;
            my $cachekey;
            ($dgithead, $cachekey) =
            changedir $playground;
            my $cachekey;
            ($dgithead, $cachekey) =
@@ -4539,13 +4534,13 @@ END
  perhaps HEAD changed since dgit build[-source] ?",
                               $quilt_mode;
        }
  perhaps HEAD changed since dgit build[-source] ?",
                               $quilt_mode;
        }
-       if (!$do_split_brain) {
+       if (!do_split_brain()) {
            # In split brain mode, do not attempt to incorporate dirty
            # stuff from the user's working tree.  That would be mad.
            commit_quilty_patch();
        }
     }
            # In split brain mode, do not attempt to incorporate dirty
            # stuff from the user's working tree.  That would be mad.
            commit_quilty_patch();
        }
     }
-    if ($do_split_brain) {
+    if (do_split_brain()) {
        $made_split_brain = 1;
        $dgithead = splitbrain_pseudomerge($clogp,
                                           $actualhead, $dgithead,
        $made_split_brain = 1;
        $dgithead = splitbrain_pseudomerge($clogp,
                                           $actualhead, $dgithead,
@@ -4580,7 +4575,7 @@ END
        }
     }
 
        }
     }
 
-    confess unless !!$made_split_brain == !!$do_split_brain;
+    confess unless !!$made_split_brain == do_split_brain();
 
     changedir $playground;
     progress f_ "checking that %s corresponds to HEAD", $dscfn;
 
     changedir $playground;
     progress f_ "checking that %s corresponds to HEAD", $dscfn;
@@ -4696,10 +4691,9 @@ ENDT
     responder_send_command("param head $dgithead");
     responder_send_command("param csuite $csuite");
     responder_send_command("param isuite $isuite");
     responder_send_command("param head $dgithead");
     responder_send_command("param csuite $csuite");
     responder_send_command("param isuite $isuite");
-    responder_send_command("param tagformat $tagformat");
+    responder_send_command("param tagformat new"); # needed in $protovsn==4
+    responder_send_command("param splitbrain $do_split_brain");
     if (defined $maintviewhead) {
     if (defined $maintviewhead) {
-       confess "internal error (protovsn=$protovsn)"
-           if defined $protovsn and $protovsn < 4;
        responder_send_command("param maint-view $maintviewhead");
     }
 
        responder_send_command("param maint-view $maintviewhead");
     }
 
@@ -4902,10 +4896,11 @@ sub cmd_fetch {
 sub cmd_pull {
     parseopts();
     fetchpullargs();
 sub cmd_pull {
     parseopts();
     fetchpullargs();
-    if (quiltmode_splitbrain()) {
+    determine_whether_split_brain get_source_format();
+    if (do_split_brain()) {
        my ($format, $fopts) = get_source_format();
        madformat($format) and fail f_ <<END, $quilt_mode
        my ($format, $fopts) = get_source_format();
        madformat($format) and fail f_ <<END, $quilt_mode
-dgit pull not yet supported in split view mode (--quilt=%s)
+dgit pull not yet supported in split view mode (including with view-splitting quilt modes)
 END
     }
     pull();
 END
     }
     pull();
@@ -5069,10 +5064,6 @@ sub cmd_remote_push_responder { cmd_remote_push_build_host(); }
 #     a good error message)
 
 sub rpush_handle_protovsn_bothends () {
 #     a good error message)
 
 sub rpush_handle_protovsn_bothends () {
-    if ($protovsn < 4) {
-       need_tagformat 'old', "rpush negotiated protocol $protovsn";
-    }
-    select_tagformat();
 }
 
 our $i_tmp;
 }
 
 our $i_tmp;
@@ -5140,7 +5131,6 @@ sub cmd_rpush {
     changedir $i_tmp;
     ($protovsn) = initiator_expect { m/^dgit-remote-push-ready (\S+)/ };
     die "$protovsn ?" unless grep { $_ eq $protovsn } @rpushprotovsn_support;
     changedir $i_tmp;
     ($protovsn) = initiator_expect { m/^dgit-remote-push-ready (\S+)/ };
     die "$protovsn ?" unless grep { $_ eq $protovsn } @rpushprotovsn_support;
-    $supplementary_message = '' unless $protovsn >= 3;
 
     for (;;) {
        my ($icmd,$iargs) = initiator_expect {
 
     for (;;) {
        my ($icmd,$iargs) = initiator_expect {
@@ -5201,6 +5191,7 @@ sub i_resp_previously ($) {
 }
 
 our %i_wanted;
 }
 
 our %i_wanted;
+our ($i_clogp, $i_version, $i_dscfn, $i_changesfn, @i_buildinfos);
 
 sub i_resp_want ($) {
     my ($keyword) = @_;
 
 sub i_resp_want ($) {
     my ($keyword) = @_;
@@ -5210,13 +5201,18 @@ sub i_resp_want ($) {
     $isuite = $i_param{'isuite'} // $i_param{'csuite'};
     die unless $isuite =~ m/^$suite_re$/;
 
     $isuite = $i_param{'isuite'} // $i_param{'csuite'};
     die unless $isuite =~ m/^$suite_re$/;
 
-    pushing();
-    rpush_handle_protovsn_bothends();
-
-    fail f_ "rpush negotiated protocol version %s".
-       " which does not support quilt mode %s",
-       $protovsn, $quilt_mode
-       if quiltmode_splitbrain && $protovsn < 4;
+    if (!defined $dsc) {
+       pushing();
+       rpush_handle_protovsn_bothends();
+       push_parse_dsc $i_dscfn, 'remote dsc', $i_version;
+       if ($protovsn >= 6) {
+           determine_whether_split_brain getfield $dsc, 'Format';
+           $do_split_brain eq ($i_param{'splitbrain'} // '<unsent>')
+               or badproto \*RO,
+ "split brain mismatch, $do_split_brain != $i_param{'split_brain'}";
+           printdebug "rpush split brain $do_split_brain\n";
+       }
+    }
 
     my @localpaths = i_method "i_want", $keyword;
     printdebug "[[  $keyword @localpaths\n";
 
     my @localpaths = i_method "i_want", $keyword;
     printdebug "[[  $keyword @localpaths\n";
@@ -5226,8 +5222,6 @@ sub i_resp_want ($) {
     print RI "files-end\n" or confess "$!";
 }
 
     print RI "files-end\n" or confess "$!";
 }
 
-our ($i_clogp, $i_version, $i_dscfn, $i_changesfn, @i_buildinfos);
-
 sub i_localname_parsed_changelog {
     return "remote-changelog.822";
 }
 sub i_localname_parsed_changelog {
     return "remote-changelog.822";
 }
@@ -5287,16 +5281,15 @@ sub i_want_signed_tag {
     my $maintview = $i_param{'maint-view'};
     die if defined $maintview && $maintview =~ m/[^0-9a-f]/;
 
     my $maintview = $i_param{'maint-view'};
     die if defined $maintview && $maintview =~ m/[^0-9a-f]/;
 
-    select_tagformat();
-    if ($protovsn >= 4) {
+    if ($protovsn == 4) {
        my $p = $i_param{'tagformat'} // '<undef>';
        my $p = $i_param{'tagformat'} // '<undef>';
-       $p eq $tagformat
-           or badproto \*RO, "tag format mismatch: $p vs. $tagformat";
+       $p eq 'new'
+           or badproto \*RO, "tag format mismatch: $p vs. new";
     }
 
     die unless $i_param{'csuite'} =~ m/^$suite_re$/;
     $csuite = $&;
     }
 
     die unless $i_param{'csuite'} =~ m/^$suite_re$/;
     $csuite = $&;
-    push_parse_dsc $i_dscfn, 'remote dsc', $i_version;
+    defined $dsc or badproto \*RO, "dsc (before parsed-changelog)";
 
     my @tagwants = push_tagwants $i_version, $head, $maintview, "tag";
 
 
     my @tagwants = push_tagwants $i_version, $head, $maintview, "tag";
 
@@ -5419,11 +5412,11 @@ sub quiltify_tree_sentinelfiles ($) {
     return $r;
 }
 
     return $r;
 }
 
-sub quiltify_splitbrain ($$$$$$$) {
+sub quiltify_splitting ($$$$$$$) {
     my ($clogp, $unapplied, $headref, $oldtiptree, $diffbits,
        $editedignores, $cachekey) = @_;
     my $gitignore_special = 1;
     my ($clogp, $unapplied, $headref, $oldtiptree, $diffbits,
        $editedignores, $cachekey) = @_;
     my $gitignore_special = 1;
-    if ($quilt_mode !~ m/gbp|dpm/) {
+    if ($quilt_mode !~ m/gbp|dpm|baredebian/) {
        # treat .gitignore just like any other upstream file
        $diffbits = { %$diffbits };
        $_ = !!$_ foreach values %$diffbits;
        # treat .gitignore just like any other upstream file
        $diffbits = { %$diffbits };
        $_ = !!$_ foreach values %$diffbits;
@@ -5438,7 +5431,7 @@ sub quiltify_splitbrain ($$$$$$$) {
     local $ENV{GIT_AUTHOR_EMAIL} = $authline[1];
     local $ENV{GIT_AUTHOR_DATE} =  $authline[2];
 
     local $ENV{GIT_AUTHOR_EMAIL} = $authline[1];
     local $ENV{GIT_AUTHOR_DATE} =  $authline[2];
 
-    confess unless $do_split_brain;
+    confess unless do_split_brain();
 
     my $fulldiffhint = sub {
        my ($x,$y) = @_;
 
     my $fulldiffhint = sub {
        my ($x,$y) = @_;
@@ -5448,14 +5441,14 @@ sub quiltify_splitbrain ($$$$$$$) {
                  $cmd;
     };
 
                  $cmd;
     };
 
-    if ($quilt_mode =~ m/gbp|unapplied/ &&
+    if ($quilt_mode =~ m/gbp|unapplied|baredebian/ &&
        ($diffbits->{O2H} & 01)) {
        my $msg = f_
  "--quilt=%s specified, implying patches-unapplied git tree\n".
  " but git tree differs from orig in upstream files.",
                      $quilt_mode;
        $msg .= $fulldiffhint->($unapplied, 'HEAD');
        ($diffbits->{O2H} & 01)) {
        my $msg = f_
  "--quilt=%s specified, implying patches-unapplied git tree\n".
  " but git tree differs from orig in upstream files.",
                      $quilt_mode;
        $msg .= $fulldiffhint->($unapplied, 'HEAD');
-       if (!stat_exists "debian/patches") {
+       if (!stat_exists "debian/patches" and $quilt_mode !~ m/baredebian/) {
            $msg .= __
  "\n ... debian/patches is missing; perhaps this is a patch queue branch?";
        }  
            $msg .= __
  "\n ... debian/patches is missing; perhaps this is a patch queue branch?";
        }  
@@ -5468,7 +5461,23 @@ sub quiltify_splitbrain ($$$$$$$) {
  but git tree differs from result of applying debian/patches to upstream
 END
     }
  but git tree differs from result of applying debian/patches to upstream
 END
     }
-    if ($quilt_mode =~ m/gbp|unapplied/ &&
+    if ($quilt_mode =~ m/baredebian/) {
+       # We need to construct a merge which has upstream files from
+       # upstream and debian/ files from HEAD.
+
+       read_tree_upstream $quilt_upstream_commitish, 1, $headref;
+       my $version = getfield $clogp, 'Version';
+       my $upsversion = upstreamversion $version;
+       my $merge = make_commit
+           [ $headref, $quilt_upstream_commitish ],
+ [ +(f_ <<ENDT, $upsversion), $quilt_upstream_commitish_message, <<ENDU ];
+Combine debian/ with upstream source for %s
+ENDT
+[dgit ($our_version) baredebian-merge $version $quilt_upstream_commitish_used]
+ENDU
+       runcmd @git, qw(reset -q --hard), $merge;
+    }
+    if ($quilt_mode =~ m/gbp|unapplied|baredebian/ &&
        ($diffbits->{O2A} & 01)) { # some patches
        progress __ "dgit view: creating patches-applied version using gbp pq";
        runcmd shell_cmd 'exec >/dev/null', gbp_pq, qw(import);
        ($diffbits->{O2A} & 01)) { # some patches
        progress __ "dgit view: creating patches-applied version using gbp pq";
        runcmd shell_cmd 'exec >/dev/null', gbp_pq, qw(import);
@@ -5525,16 +5534,6 @@ END
 [dgit ($our_version) update-gitignore-quilt-fixup]
 ENDU
     }
 [dgit ($our_version) update-gitignore-quilt-fixup]
 ENDU
     }
-
-    my $dgitview = git_rev_parse 'HEAD';
-
-    changedir $maindir;
-    reflog_cache_insert "refs/$splitbraincache", $cachekey, $dgitview;
-
-    changedir "$playground/work";
-
-    my $saved = maybe_split_brain_save $headref, $dgitview, __ "converted";
-    progress f_ "dgit view: created (%s)", $saved;
 }
 
 sub quiltify ($$$$) {
 }
 
 sub quiltify ($$$$) {
@@ -5834,7 +5833,7 @@ sub build_maybe_quilt_fixup () {
 
     my $splitbrain_cachekey;
 
 
     my $splitbrain_cachekey;
 
-    if ($do_split_brain) {
+    if (do_split_brain()) {
        my $cachehit;
        ($cachehit, $splitbrain_cachekey) =
            quilt_check_splitbrain_cache($headref, $upstreamversion);
        my $cachehit;
        ($cachehit, $splitbrain_cachekey) =
            quilt_check_splitbrain_cache($headref, $upstreamversion);
@@ -5845,7 +5844,7 @@ sub build_maybe_quilt_fixup () {
     }
 
     unpack_playtree_need_cd_work($headref);
     }
 
     unpack_playtree_need_cd_work($headref);
-    if ($do_split_brain) {
+    if (do_split_brain()) {
        runcmd @git, qw(checkout -q -b dgit-view);
        # so long as work is not deleted, its current branch will
        # remain dgit-view, rather than master, so subsequent calls to
        runcmd @git, qw(checkout -q -b dgit-view);
        # so long as work is not deleted, its current branch will
        # remain dgit-view, rather than master, so subsequent calls to
@@ -5860,13 +5859,26 @@ sub build_maybe_quilt_fixup () {
        fail f_
  "quilt mode %s does not make sense (or is not supported) with single-debian-patch",
            $quilt_mode
        fail f_
  "quilt mode %s does not make sense (or is not supported) with single-debian-patch",
            $quilt_mode
-           if quiltmode_splitbrain();
+           if quiltmode_splitting();
        quilt_fixup_singlepatch($clogp, $headref, $upstreamversion);
     } else {
        quilt_fixup_multipatch($clogp, $headref, $upstreamversion,
                              $splitbrain_cachekey);
     }
 
        quilt_fixup_singlepatch($clogp, $headref, $upstreamversion);
     } else {
        quilt_fixup_multipatch($clogp, $headref, $upstreamversion,
                              $splitbrain_cachekey);
     }
 
+    if (do_split_brain()) {
+       my $dgitview = git_rev_parse 'HEAD';
+
+       changedir $maindir;
+       reflog_cache_insert "refs/$splitbraincache",
+           $splitbrain_cachekey, $dgitview;
+
+       changedir "$playground/work";
+
+       my $saved = maybe_split_brain_save $headref, $dgitview, __ "converted";
+       progress f_ "dgit view: created (%s)", $saved;
+    }
+
     changedir $maindir;
     runcmd_ordryrun_local
         @git, qw(pull --ff-only -q), "$playground/work", qw(master);
     changedir $maindir;
     runcmd_ordryrun_local
         @git, qw(pull --ff-only -q), "$playground/work", qw(master);
@@ -5874,13 +5886,6 @@ sub build_maybe_quilt_fixup () {
 
 sub build_check_quilt_splitbrain () {
     build_maybe_quilt_fixup();
 
 sub build_check_quilt_splitbrain () {
     build_maybe_quilt_fixup();
-
-    if ($do_split_brain) {
-       fail <<END unless access_cfg_tagformats_can_splitbrain;
-quilt mode $quilt_mode requires split view so server needs to support
- both "new" and "maint" tag formats, but config says it doesn't.
-END
-    }
 }
 
 sub unpack_playtree_need_cd_work ($) {
 }
 
 sub unpack_playtree_need_cd_work ($) {
@@ -6053,6 +6058,7 @@ sub quilt_check_splitbrain_cache ($$) {
     push @cachekey, $upstreamversion;
     push @cachekey, $quilt_mode;
     push @cachekey, $headref;
     push @cachekey, $upstreamversion;
     push @cachekey, $quilt_mode;
     push @cachekey, $headref;
+    push @cachekey, $quilt_upstream_commitish // '-';
 
     push @cachekey, hashfile('fake.dsc');
 
 
     push @cachekey, hashfile('fake.dsc');
 
@@ -6089,6 +6095,30 @@ sub quilt_check_splitbrain_cache ($$) {
     return (undef, $splitbrain_cachekey);
 }
 
     return (undef, $splitbrain_cachekey);
 }
 
+sub baredebian_origtarballs_scan ($$$) {
+    my ($fakedfi, $upstreamversion, $dir) = @_;
+    if (!opendir OD, $dir) {
+       return if $! == ENOENT;
+       fail "opendir $dir (origs): $!";
+    }
+
+    while ($!=0, defined(my $leaf = readdir OD)) {
+       {
+           local ($debuglevel) = $debuglevel-1;
+           printdebug "BDOS $dir $leaf ?\n";
+       }
+       next unless is_orig_file_of_vsn $leaf, $upstreamversion;
+       next if grep { $_->{Filename} eq $leaf } @$fakedfi;
+       push @$fakedfi, {
+            Filename => $leaf,
+            Path => "$dir/$leaf",
+                       };
+    }
+
+    die "$dir; $!" if $!;
+    closedir OD;
+}
+
 sub quilt_fixup_multipatch ($$$) {
     my ($clogp, $headref, $upstreamversion, $splitbrain_cachekey) = @_;
 
 sub quilt_fixup_multipatch ($$$) {
     my ($clogp, $headref, $upstreamversion, $splitbrain_cachekey) = @_;
 
@@ -6236,15 +6266,97 @@ END
     # We calculate some guesswork now about what kind of tree this might
     # be.  This is mostly for error reporting.
 
     # We calculate some guesswork now about what kind of tree this might
     # be.  This is mostly for error reporting.
 
+    my $tentries = cmdoutput @git, qw(ls-tree --name-only -z), $headref;
+    my $onlydebian = $tentries eq "debian\0";
+
+    my $uheadref = $headref;
+    my $uhead_whatshort = 'HEAD';
+
+    if ($quilt_mode =~ m/baredebian\+tarball/) {
+       # We need to make a tarball import.  Yuk.
+       # We want to do this here so that we have a $uheadref value
+
+       my @fakedfi;
+       baredebian_origtarballs_scan \@fakedfi, $upstreamversion, bpd_abs();
+       baredebian_origtarballs_scan \@fakedfi, $upstreamversion,
+           "$maindir/.." unless $buildproductsdir eq '..';
+       changedir '..';
+
+       my @tartrees = import_tarball_tartrees $upstreamversion, \@fakedfi;
+
+       fail __ "baredebian quilt fixup: could not find any origs"
+           unless @tartrees;
+
+       changedir 'work';
+       my ($authline, $r1authline, $clogp,) =
+           import_tarball_commits \@tartrees, $upstreamversion;
+
+       if (@tartrees == 1) {
+           $uheadref = $tartrees[0]{Commit};
+           # TRANSLATORS: this translation must fit in the ASCII art
+           # quilt differences display.  The untranslated display
+           # says %9.9s, so with that display it must be at most 9
+           # characters.
+           $uhead_whatshort = __ 'tarball';
+       } else {
+           # on .dsc import we do not make a separate commit, but
+           # here we need to do so
+           rm_subdir_cached '.';
+           my $parents;
+           foreach my $ti (@tartrees) {
+               my $c = $ti->{Commit};
+               if ($ti->{OrigPart} eq 'orig') {
+                   runcmd qw(git read-tree), $c;
+               } elsif ($ti->{OrigPart} =~ m/orig-/) {
+                   read_tree_subdir $', $c;
+               } else {
+                   confess "$ti->OrigPart} ?"
+               }
+               $parents .= "parent $c\n";
+           }
+           my $tree = git_write_tree();
+           my $mbody = f_ 'Combine orig tarballs for %s %s',
+               $package, $upstreamversion;
+           $uheadref = hash_commit_text <<END;
+tree $tree
+${parents}author $r1authline
+committer $r1authline
+
+$mbody
+
+[dgit import tarballs combine $package $upstreamversion]
+END
+           # TRANSLATORS: this translation must fit in the ASCII art
+           # quilt differences display.  The untranslated display
+           # says %9.9s, so with that display it must be at most 9
+           # characters.  This fragmentt is referring to multiple
+           # orig tarballs in a source package.
+           $uhead_whatshort = __ 'tarballs';
+
+           runcmd @git, qw(reset -q);
+       }
+       $quilt_upstream_commitish = $uheadref;
+       $quilt_upstream_commitish_used = '*orig*';
+       $quilt_upstream_commitish_message = '';
+    }
+    if ($quilt_mode =~ m/baredebian$/) {
+       $uheadref = $quilt_upstream_commitish;
+       # TRANSLATORS: this translation must fit in the ASCII art
+       # quilt differences display.  The untranslated display
+       # says %9.9s, so with that display it must be at most 9
+       # characters.
+       $uhead_whatshort = __ 'upstream';
+    }
+
     my %editedignores;
     my @unrepres;
     my $diffbits = {
         # H = user's HEAD
         # O = orig, without patches applied
         # A = "applied", ie orig with H's debian/patches applied
     my %editedignores;
     my @unrepres;
     my $diffbits = {
         # H = user's HEAD
         # O = orig, without patches applied
         # A = "applied", ie orig with H's debian/patches applied
-        O2H => quiltify_trees_differ($unapplied,$headref,   1,
+        O2H => quiltify_trees_differ($unapplied,$uheadref,   1,
                                     \%editedignores, \@unrepres),
                                     \%editedignores, \@unrepres),
-        H2A => quiltify_trees_differ($headref,  $oldtiptree,1),
+        H2A => quiltify_trees_differ($uheadref, $oldtiptree,1),
         O2A => quiltify_trees_differ($unapplied,$oldtiptree,1),
     };
 
         O2A => quiltify_trees_differ($unapplied,$oldtiptree,1),
     };
 
@@ -6259,13 +6371,23 @@ END
     progress f_
 "%s: base trees orig=%.20s o+d/p=%.20s",
               $us, $unapplied, $oldtiptree;
     progress f_
 "%s: base trees orig=%.20s o+d/p=%.20s",
               $us, $unapplied, $oldtiptree;
+    # TRANSLATORS: Try to keep this ascii-art layout right.  The 0s in
+    # %9.00009s will be ignored and are there to make the format the
+    # same length (9 characters) as the output it generates.  If you
+    # change the value 9, your translations of "upstream" and
+    # 'tarball' must fit into the new length, and you should change
+    # the number of 0s.  Do not reduce it below 4 as HEAD has to fit
+    # too.
     progress f_
 "%s: quilt differences: src:  %s orig %s     gitignores:  %s orig %s\n".
     progress f_
 "%s: quilt differences: src:  %s orig %s     gitignores:  %s orig %s\n".
-"%s: quilt differences:      HEAD %s o+d/p               HEAD %s o+d/p",
+"%s: quilt differences: %9.00009s %s o+d/p          %9.00009s %s o+d/p",
   $us,                      $dl[0], $dl[1],              $dl[3], $dl[4],
   $us,                      $dl[0], $dl[1],              $dl[3], $dl[4],
-  $us,                          $dl[2],                     $dl[5];
+  $us,        $uhead_whatshort, $dl[2],   $uhead_whatshort, $dl[5];
 
 
-    if (@unrepres) {
+    if (@unrepres && $quilt_mode !~ m/baredebian/) {
+       # With baredebian, even if the upstream commitish has this
+       # problem, we don't want to print this message, as nothing
+       # is going to try to make a patch out of it anyway.
        print STDERR f_ "dgit:  cannot represent change: %s: %s\n",
                        $_->[1], $_->[0]
            foreach @unrepres;
        print STDERR f_ "dgit:  cannot represent change: %s: %s\n",
                        $_->[1], $_->[0]
            foreach @unrepres;
@@ -6275,7 +6397,11 @@ END
     }
 
     my @failsuggestion;
     }
 
     my @failsuggestion;
-    if (!($diffbits->{O2H} & $diffbits->{O2A})) {
+    if ($onlydebian) {
+       push @failsuggestion, [ 'onlydebian', __
+ "This has only a debian/ directory; you probably want --quilt=bare debian." ]
+           unless $quilt_mode =~ m/baredebian/;
+    } elsif (!($diffbits->{O2H} & $diffbits->{O2A})) {
         push @failsuggestion, [ 'unapplied', __
  "This might be a patches-unapplied branch." ];
     } elsif (!($diffbits->{H2A} & $diffbits->{O2A})) {
         push @failsuggestion, [ 'unapplied', __
  "This might be a patches-unapplied branch." ];
     } elsif (!($diffbits->{H2A} & $diffbits->{O2A})) {
@@ -6290,18 +6416,20 @@ END
        if stat_exists '.gitattributes';
 
     push @failsuggestion, [ 'origs', __
        if stat_exists '.gitattributes';
 
     push @failsuggestion, [ 'origs', __
- "Maybe orig tarball(s) are not identical to git representation?" ];
-
-    if (quiltmode_splitbrain()) {
-       quiltify_splitbrain($clogp, $unapplied, $headref, $oldtiptree,
-                            $diffbits, \%editedignores,
-                           $splitbrain_cachekey);
+ "Maybe orig tarball(s) are not identical to git representation?" ]
+       unless $onlydebian && $quilt_mode !~ m/baredebian/;
+              # ^ in that case, we didn't really look properly
+
+    if (quiltmode_splitting()) {
+       quiltify_splitting($clogp, $unapplied, $headref, $oldtiptree,
+                          $diffbits, \%editedignores,
+                          $splitbrain_cachekey);
        return;
     }
 
     progress f_ "starting quiltify (multiple patches, %s mode)", $quilt_mode;
     quiltify($clogp,$headref,$oldtiptree,\@failsuggestion);
        return;
     }
 
     progress f_ "starting quiltify (multiple patches, %s mode)", $quilt_mode;
     quiltify($clogp,$headref,$oldtiptree,\@failsuggestion);
-    runcmd @git, qw(checkout -q master);
+    runcmd @git, qw(checkout -q), (qw(master dgit-view)[do_split_brain()]);
 
     if (!open P, '>>', ".pc/applied-patches") {
        $!==&ENOENT or confess "$!";
 
     if (!open P, '>>', ".pc/applied-patches") {
        $!==&ENOENT or confess "$!";
@@ -6336,7 +6464,7 @@ sub quilt_fixup_editor () {
 }
 
 sub maybe_apply_patches_dirtily () {
 }
 
 sub maybe_apply_patches_dirtily () {
-    return unless $quilt_mode =~ m/gbp|unapplied/;
+    return unless $quilt_mode =~ m/gbp|unapplied|baredebian/;
     print STDERR __ <<END or confess "$!";
 
 dgit: Building, or cleaning with rules target, in patches-unapplied tree.
     print STDERR __ <<END or confess "$!";
 
 dgit: Building, or cleaning with rules target, in patches-unapplied tree.
@@ -6408,6 +6536,18 @@ sub clean_tree_check () {
 sub clean_tree () {
     # We always clean the tree ourselves, rather than leave it to the
     # builder (dpkg-source, or soemthing which calls dpkg-source).
 sub clean_tree () {
     # We always clean the tree ourselves, rather than leave it to the
     # builder (dpkg-source, or soemthing which calls dpkg-source).
+    if ($quilt_mode =~ m/baredebian/ and $cleanmode =~ m/git/) {
+       fail f_ <<END, $quilt_mode, $cleanmode;
+quilt mode %s (generally needs untracked upstream files)
+contradicts clean mode %s (which would delete them)
+END
+       # This is not 100% true: dgit build-source and push-source
+       # (for example) could operate just fine with no upstream
+       # source in the working tree.  But it doesn't seem likely that
+       # the user wants dgit to proactively delete such things.
+       # -wn, for example, would produce identical output without
+       # deleting anything from the working tree.
+    }
     if ($cleanmode =~ m{^dpkg-source}) {
        my @cmd = @dpkgbuildpackage;
        push @cmd, qw(-d) if $cleanmode =~ m{^dpkg-source-d};
     if ($cleanmode =~ m{^dpkg-source}) {
        my @cmd = @dpkgbuildpackage;
        push @cmd, qw(-d) if $cleanmode =~ m{^dpkg-source-d};
@@ -6442,23 +6582,37 @@ sub WANTSRC_BUILDER () { 02; } # caller should run dpkg-buildpackage
 sub build_or_push_prep_early () {
     our $build_or_push_prep_early_done //= 0;
     return if $build_or_push_prep_early_done++;
 sub build_or_push_prep_early () {
     our $build_or_push_prep_early_done //= 0;
     return if $build_or_push_prep_early_done++;
-    badusage f_ "-p is not allowed with dgit %s", $subcommand
-       if defined $package;
     my $clogp = parsechangelog();
     $isuite = getfield $clogp, 'Distribution';
     my $clogp = parsechangelog();
     $isuite = getfield $clogp, 'Distribution';
-    $package = getfield $clogp, 'Source';
+    my $gotpackage = getfield $clogp, 'Source';
     $version = getfield $clogp, 'Version';
     $version = getfield $clogp, 'Version';
+    $package //= $gotpackage;
+    if ($package ne $gotpackage) {
+       fail f_ "-p specified package %s, but changelog says %s",
+           $package, $gotpackage;
+    }
     $dscfn = dscfn($version);
 }
 
 sub build_or_push_prep_modes () {
     $dscfn = dscfn($version);
 }
 
 sub build_or_push_prep_modes () {
-    my ($format,) = get_source_format();
-    printdebug "format $format, quilt mode $quilt_mode\n";
-    if (madformat_wantfixup($format) && quiltmode_splitbrain()) {
-       $do_split_brain = 1;
+    my ($format) = get_source_format();
+    determine_whether_split_brain($format);
+
+    fail __ "dgit: --include-dirty is not supported with split view".
+            " (including with view-splitting quilt modes)"
+       if do_split_brain() && $includedirty;
+
+    if (madformat_wantfixup $format and $quilt_mode =~ m/baredebian$/) {
+       ($quilt_upstream_commitish, $quilt_upstream_commitish_used,
+        $quilt_upstream_commitish_message)
+           = resolve_upstream_version
+           $quilt_upstream_commitish, upstreamversion $version;
+       progress f_ "dgit: --quilt=%s, %s", $quilt_mode,
+           $quilt_upstream_commitish_message;
+    } elsif (defined $quilt_upstream_commitish) {
+       fail __
+ "dgit: --upstream-commitish only makes sense with --quilt=baredebian"
     }
     }
-    fail __ "dgit: --include-dirty is not supported in split view quilt mode"
-       if $do_split_brain && $includedirty;
 }
 
 sub build_prep_early () {
 }
 
 sub build_prep_early () {
@@ -6786,7 +6940,7 @@ sub build_source {
        unlink "$buildproductsdir/$sourcechanges" or $!==ENOENT
            or fail f_ "remove %s: %s", $sourcechanges, $!;
     }
        unlink "$buildproductsdir/$sourcechanges" or $!==ENOENT
            or fail f_ "remove %s: %s", $sourcechanges, $!;
     }
-#    confess unless !!$made_split_brain == !!$do_split_brain;
+#    confess unless !!$made_split_brain == do_split_brain();
 
     my @cmd = (@dpkgsource, qw(-b --));
     my $leafdir;
 
     my @cmd = (@dpkgsource, qw(-b --));
     my $leafdir;
@@ -7158,7 +7312,7 @@ END
            my $version = getfield $dsc, 'Version';
            my $clogp = commit_getclogp $newhash;
            my $authline = clogp_authline $clogp;
            my $version = getfield $dsc, 'Version';
            my $clogp = commit_getclogp $newhash;
            my $authline = clogp_authline $clogp;
-           $newhash = make_commit_text <<ENDU
+           $newhash = hash_commit_text <<ENDU
 tree $tree
 parent $newhash
 parent $oldhash
 tree $tree
 parent $newhash
 parent $oldhash
@@ -7390,7 +7544,7 @@ sub parseopts () {
                push @ropts, $_;
                my $cmd = shift @$om;
                @$om = ($cmd, grep { $_ ne $2 } @$om);
                push @ropts, $_;
                my $cmd = shift @$om;
                @$om = ($cmd, grep { $_ ne $2 } @$om);
-           } elsif (m/^--(gbp|dpm)$/s) {
+           } elsif (m/^--($quilt_options_re)$/s) {
                push @ropts, "--quilt=$1";
                $quilt_mode = $1;
            } elsif (m/^--(?:ignore|include)-dirty$/s) {
                push @ropts, "--quilt=$1";
                $quilt_mode = $1;
            } elsif (m/^--(?:ignore|include)-dirty$/s) {
@@ -7408,16 +7562,25 @@ sub parseopts () {
            } elsif (m/^--overwrite$/s) {
                push @ropts, $_;
                $overwrite_version = '';
            } elsif (m/^--overwrite$/s) {
                push @ropts, $_;
                $overwrite_version = '';
+           } elsif (m/^--split-(?:view|brain)$/s) {
+               push @ropts, $_;
+               $splitview_mode = 'always';
+           } elsif (m/^--split-(?:view|brain)=($splitview_modes_re)$/s) {
+               push @ropts, $_;
+               $splitview_mode = $1;
            } elsif (m/^--overwrite=(.+)$/s) {
                push @ropts, $_;
                $overwrite_version = $1;
            } elsif (m/^--delayed=(\d+)$/s) {
                push @ropts, $_;
                push @dput, $_;
            } elsif (m/^--overwrite=(.+)$/s) {
                push @ropts, $_;
                $overwrite_version = $1;
            } elsif (m/^--delayed=(\d+)$/s) {
                push @ropts, $_;
                push @dput, $_;
-           } elsif (my ($k,$v) =
-                    m/^--save-(dgit-view)=(.+)$/s ||
+           } elsif (m/^--upstream-commitish=(.+)$/s) {
+               push @ropts, $_;
+               $quilt_upstream_commitish = $1;
+           } elsif (m/^--save-(dgit-view)=(.+)$/s ||
                     m/^--(dgit-view)-save=(.+)$/s
                     ) {
                     m/^--(dgit-view)-save=(.+)$/s
                     ) {
+               my ($k,$v) = ($1,$2);
                push @ropts, $_;
                $v =~ s#^(?!refs/)#refs/heads/#;
                $internal_object_save{$k} = $v;
                push @ropts, $_;
                $v =~ s#^(?!refs/)#refs/heads/#;
                $internal_object_save{$k} = $v;
@@ -7436,11 +7599,6 @@ sub parseopts () {
                    f_ "%s: warning: ignoring unknown force option %s\n",
                       $us, $_;
                $_='';
                    f_ "%s: warning: ignoring unknown force option %s\n",
                       $us, $_;
                $_='';
-           } elsif (m/^--dgit-tag-format=(old|new)$/s) {
-               # undocumented, for testing
-               push @ropts, $_;
-               $tagformat_want = [ $1, 'command line', 1 ];
-               # 1 menas overrides distro configuration
            } elsif (m/^--config-lookup-explode=(.+)$/s) {
                # undocumented, for testing
                push @ropts, $_;
            } elsif (m/^--config-lookup-explode=(.+)$/s) {
                # undocumented, for testing
                push @ropts, $_;
@@ -7586,6 +7744,7 @@ sub parseopts_late_defaults () {
            or badcfg f_ "unknown quilt-mode \`%s'", $quilt_mode;
        $quilt_mode = $1;
     }
            or badcfg f_ "unknown quilt-mode \`%s'", $quilt_mode;
        $quilt_mode = $1;
     }
+    $quilt_mode =~ s/^(baredebian)\+git$/$1/;
 
     foreach my $moc (@modeopt_cfgs) {
        local $access_forpush;
 
     foreach my $moc (@modeopt_cfgs) {
        local $access_forpush;