chiark / gitweb /
Merge commit 'refs/top-bases/features/vim-modelines' into features/vim-modelines
authorCarsten Hey <>
Mon, 26 Apr 2010 08:18:59 +0000 (10:18 +0200)
committerCarsten Hey <>
Mon, 26 Apr 2010 08:18:59 +0000 (10:18 +0200)
* commit 'refs/top-bases/features/vim-modelines': (31 commits)
  tg patch: treat all files as ascii
  tg mail: document config setting to prevent unintended mass mail sending
  Don't call pre-commit hook if tg is not installed
  tg-delete: Handle the case where the branch has been removed already, but the base is still left.
  tg-mail: Properly quote argument to --in-reply-to
  tg-push: Filter out plain SHA1s from being pushed.
  Make 'tg patch' work in subdirectories
  quote $LESS in case it includes spaces
  deal with single quotes in from/to headers
  bump version number to 0.8
  Fix tg export --quilt --numbered w/ > 8 patches
  tg-push: add bash completion
  help: use pager
  tg-push: handle non-tgish branches
  tg-push: prevent handing branches more than once to git-push
  tg-push: remove useless warning about missing bases for non-tgish branches
  tg-update: fix user visible typo in info msg
  tg-remote: don't add push specs but warn about existing ones.
  tg-push: new command pushing a tgish branch
  recurse_deps: if no_remotes is set don't recurse into remote deps

14 files changed:
COPYING [new file with mode: 0644]
hooks/ [new file with mode: 0644]

index eb56446..2f6d991 100644 (file)
@@ -21,6 +21,8 @@
diff --git a/COPYING b/COPYING
new file mode 100644 (file)
index 0000000..a3ddeb9
--- /dev/null
@@ -0,0 +1,405 @@
+This file has several parts:
+ - this index (just to get this list complete)
+ - Description for Signed-off-by including Developer's Certificate of Origin 1.1
+Note that TopGit (unless specified otherwise in the corresponding file) doesn't
+allow you to choose a later version of the GPL as suggested by the Free
+Software Foundation.
+                   GNU GENERAL PUBLIC LICENSE
+                      Version 2, June 1991
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+                           Preamble
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+  The precise terms and conditions for copying, distribution and
+modification follow.
+                   GNU GENERAL PUBLIC LICENSE
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+                           NO WARRANTY
+                    END OF TERMS AND CONDITIONS
+           How to Apply These Terms to Your New Programs
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+    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
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    GNU General Public License for more details.
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+Also add information on how to contact you by electronic and paper mail.
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
+Each patch added to TopGit shall have a sign-off by its author, forwarders (if
+applicable) and final commiter.
+This is what core GIT and Linux kernel require, too.
+The sign-off is a simple line at the end of the explanation for
+the patch, which certifies that you wrote it or otherwise have
+the right to pass it on as a open-source patch.  The rules are
+pretty simple: if you can certify the below:
+        Developer's Certificate of Origin 1.1
+        By making a contribution to this project, I certify that:
+        (a) The contribution was created in whole or in part by me and I
+            have the right to submit it under the open source license
+            indicated in the file; or
+        (b) The contribution is based upon previous work that, to the best
+            of my knowledge, is covered under an appropriate open source
+            license and I have the right under that license to submit that
+            work with modifications, whether created in whole or in part
+            by me, under the same open source license (unless I am
+            permitted to submit under a different license), as indicated
+            in the file; or
+        (c) The contribution was provided directly to me by some other
+            person who certified (a), (b) or (c) and I have not modified
+            it.
+       (d) I understand and agree that this project and the contribution
+           are public and that a record of the contribution (including all
+           personal information I submit with it, including my sign-off) is
+           maintained indefinitely and may be redistributed consistent with
+           this project or the open source license(s) involved.
+then you just add a line saying
+       Signed-off-by: Random J Developer <>
+This line can be automatically added by git if you run the git-commit
+command with the -s option.
+Notice that you can place your own Signed-off-by: line when
+forwarding somebody else's patch with the above rules for
+D-C-O.  Indeed you are encouraged to do so.  Do not forget to
+place an in-body "From: " line at the beginning to properly attribute
+the change to its true author (see (2) above).
+Also notice that a real name is used in the Signed-off-by: line. Please
+don't hide your real name.
diff --git a/README b/README
index d2f095d..c418ff4 100644 (file)
--- a/README
+++ b/README
@@ -244,6 +244,10 @@ tg delete
        only empty branch (base == head); use '-f' to remove
        non-empty branch.
+       The '-f' option is also useful to force removal of a branch's base, if
+       you used 'git branch -D B' to remove the branch B, and then certain
+       TopGit commands complain, because the base of branch B is still there.
        Currently, this command will _NOT_ remove the branch from
        the dependency list in other branches. You need to take
        care of this _manually_. This is even more complicated
@@ -304,6 +308,13 @@ tg mail
        The '-r' parameter with msgid can be used to generate in-reply-to
        and reference headers to an earlier mail.
+       Note: be careful when using this command.  It easily sends out several
+       mails.  You might want to run
+               git config sendemail.confirm always
+       to let `git send-email` ask for confirmation before sending any mail.
        TODO: 'tg mail patchfile' to mail an already exported patch
        TODO: mailing patch series
        TODO: specifying additional options and addresses on command
@@ -480,6 +491,12 @@ tg update
        TODO: tg update -a for updating all topic branches
+tg push
+       pushes a TopGit-controlled topic branch to a remote
+       repository.  By default the remote gets all dependencies
+       (both tgish and non-tgish) and bases pushed to.
 TODO: tg rename
index de8a7b5..0ee233c 100755 (executable)
@@ -370,6 +370,29 @@ _tg_patch ()
+_tg_push ()
+       local cur="${COMP_WORDS[COMP_CWORD]}"
+       __tg_complete_arg "-r" && {
+               __tgcomp "$(__tg_remotes)"
+               return
+       }
+       case "$cur" in
+       -*)
+               __tgcomp "
+                       --no-deps
+                       --dry-run
+                       --tgish-only
+                       -r
+               "
+               ;;
+       *)
+               __tgcomp "$(__tg_topics)"
+       esac
 _tg_remote ()
        local cur="${COMP_WORDS[COMP_CWORD]}"
@@ -449,6 +472,7 @@ _tg ()
        info)        _tg_info ;;
        mail)        _tg_mail ;;
        patch)       _tg_patch ;;
+       push)        _tg_push ;;
        remote)      _tg_remote ;;
        summary)     _tg_summary ;;
        update)      _tg_update ;;
index da63185..9d677e9 100644 (file)
@@ -17,9 +17,19 @@ tg_util
 ## Generally have fun
 # Don't do anything on non-topgit branch
-git rev-parse --verify "$(git symbolic-ref HEAD | sed 's/heads/top-bases/')" >/dev/null 2>&1 ||
-       exit 0
+if head_=$(git symbolic-ref -q HEAD); then
+       case "$head_" in
+               refs/heads/*)
+                       git rev-parse -q --verify "refs/top-bases${head_#refs/heads}" >/dev/null || exit 0;;
+               *)
+                       exit 0;;
+       esac
+       exit 0;
+# TODO: check the index, not the working copy
 [ -s "$root_dir/.topdeps" ] ||
        die ".topdeps is missing"
 [ -s "$root_dir/.topmsg" ] ||
index ab121c2..e1eea17 100644 (file)
@@ -3,7 +3,7 @@
 # (c) Petr Baudis <>  2008
 # GPLv2
-force= # Whether to delete non-empty branch
+force= # Whether to delete non-empty branch, or branch where only the base is left.
@@ -28,21 +28,22 @@ done
 [ -n "$name" ] || die "no branch name specified"
 branchrev="$(git rev-parse --verify "$name" 2>/dev/null)" ||
-       die "invalid branch name: $name"
+       if [ -n "$force" ]; then
+               info "invalid branch name: $name; assuming it has been deleted already"
+       else
+               die "invalid branch name: $name"
+       fi
 baserev="$(git rev-parse --verify "refs/top-bases/$name" 2>/dev/null)" ||
        die "not a TopGit topic branch: $name"
 ! git symbolic-ref HEAD >/dev/null || [ "$(git symbolic-ref HEAD)" != "refs/heads/$name" ] ||
        die "cannot delete your current branch"
-branch_empty "$name" || nonempty=1
-[ -z "$nonempty" ] || [ -n "$force" ] || die "branch is non-empty: $name"
+[ -z "$force" ] && { branch_empty "$name" || die "branch is non-empty: $name"; }
 ## Wipe out
 git update-ref -d "refs/top-bases/$name" "$baserev"
-git update-ref -d "refs/heads/$name" "$branchrev"
+[ -z "$branchrev" ] || git update-ref -d "refs/heads/$name" "$branchrev"
 # vim:noet
index ef5f94f..e1a6f17 100644 (file)
@@ -37,9 +37,6 @@ done
 [ -n "$name" ] || die "no branch name specified"
 branchrev="$(git rev-parse --verify "$name" 2>/dev/null)" ||
        die "invalid branch name: $name"
-baserev="$(git rev-parse --verify "refs/top-bases/$name" 2>/dev/null)" ||
-       die "not a TopGit topic branch: $name"
 ## Record new dependency
index 748ca54..a16c290 100644 (file)
@@ -185,8 +185,8 @@ quilt()
                echo "Skip empty patch $_dep";
                if "$numbered"; then
-                       number="$(printf "%04u" $(($(cat "$playground/^number" 2>/dev/null) + 1)))";
-                       bn="$number-$bn";
+                       number="$(echo $(($(cat "$playground/^number" 2>/dev/null) + 1)))";
+                       bn="$(printf "%04u-$bn" $number)";
                        echo "$number" >"$playground/^number";
@@ -216,22 +216,25 @@ linearize()
                        # already included, just skip
-                       git merge -s recursive "$_dep";
-                       retmerge="$?";
+                       retmerge=0;
+                       git merge -s recursive "$_dep" || retmerge="$?";
                        if test "x$retmerge" != "x0"; then
                                echo fix up the merge, commit and then exit;
                                #todo error handling
-                               sh -i
+                               sh -i </dev/tty;
-               git merge-recursive "$(pretty_tree "refs/top-bases/$_dep")" -- HEAD "$(pretty_tree "refs/heads/$_dep")";
-               retmerge="$?";
+               retmerge=0;
+               git merge-recursive "$(pretty_tree "refs/top-bases/$_dep")" -- HEAD "$(pretty_tree "refs/heads/$_dep")" || retmerge="$?";
                if test "x$retmerge" != "x0"; then
+                       git rerere;
                        echo "fix up the merge and update the index.  Don't commit!"
                        #todo error handling
-                       sh -i
+                       sh -i </dev/tty;
                result_tree=$(git write-tree)
index 4a68464..8167ade 100644 (file)
@@ -29,12 +29,8 @@ done
 base_rev="$(git rev-parse --short --verify "refs/top-bases/$name" 2>/dev/null)" ||
        die "not a TopGit-controlled branch"
-if ! git send-email --help >/dev/null 2>&1; then
-       die "git send-email command not available"
 if [ -n "$in_reply_to" ]; then
-       send_email_args="$send_email_args --in-reply-to=$in_reply_to"
+       send_email_args="$send_email_args --in-reply-to='$in_reply_to'"
@@ -42,7 +38,7 @@ patchfile="$(mktemp -t tg-mail.XXXXXX)"
 $tg patch "$name" >"$patchfile"
-header="$(sed -e '/^$/,$d' "$patchfile")"
+header="$(sed -e '/^$/,$d' -e "s,','\\\\'',g" "$patchfile")"
index d701c54..7bafdfe 100644 (file)
@@ -56,7 +56,8 @@ git diff --name-only $diff_opts "$base_rev" ${diff_committed_only:+"$name"} -- |
        fgrep -vx ".topdeps" |
        fgrep -vx ".topmsg" >"$git_is_stupid" || : # fgrep likes to fail randomly?
 if [ -s "$git_is_stupid" ]; then
-       cat "$git_is_stupid" | xargs git diff --patch-with-stat $diff_opts "$base_rev" ${diff_committed_only:+"$name"} --
+       cd "$root_dir"
+       cat "$git_is_stupid" | xargs git diff -a --patch-with-stat $diff_opts "$base_rev" ${diff_committed_only:+"$name"} --
        echo "No changes."
diff --git a/ b/
new file mode 100644 (file)
index 0000000..199d738
--- /dev/null
@@ -0,0 +1,80 @@
+# TopGit - A different patch queue manager
+# GPLv2
+## Parse options
+while [ -n "$1" ]; do
+       arg="$1"; shift
+       case "$arg" in
+       --no-deps)
+               recurse_deps=false;;
+       --dry-run)
+               dry_run=--dry-run;;
+       --tgish-only)
+               tgish_deps_only=true;;
+       -h|--help)
+               echo "Usage: tg push [--dry-run] [--no-deps] [--tgish-only] [-r remote] branch*"
+               exit 0;;
+       -r)
+               remote="$1"
+               shift
+               ;;
+       *)
+               branches="$branches $arg";;
+       esac
+if [ -z "$remote" ]; then
+       remote="$base_remote"
+if [ -z "$remote" ]; then
+       die "no remote location given. Either use -r remote argument or set topgit.remote"
+if [ -z "$branches" ]; then
+       branches="$(git symbolic-ref HEAD | sed 's#^refs/heads/##')"
+for name in $branches; do
+       ref_exists "$name" || die "detached HEAD? Can't push $name"
+_listfile="$(mktemp -t tg-push-listfile.XXXXXX)"
+trap "rm -f \"$_listfile\"" 0
+       # if so desired omit non tgish deps
+       $tgish_deps_only && [ -z "$_dep_is_tgish" ] && return 0
+       # filter out plain SHA1s.  These don't need to be pushed explicitly as
+       # the patches that depend on the sha1 have it already in their ancestry.
+       is_sha1 "$_dep" && return 0
+       echo "$_dep" >> "$_listfile"
+       [ -z "$_dep_is_tgish" ] ||
+               echo "top-bases/$_dep" >> "$_listfile"
+for name in $branches; do
+       # current branch
+       # re-use push_branch, which expects some pre-defined variables
+       _dep="$name"
+       _dep_is_tgish=1
+       ref_exists "top-bases/$_dep" ||
+               _dep_is_tgish=
+       push_branch "$name"
+       # deps but only if branch is tgish
+       $recurse_deps && [ -n "$_dep_is_tgish" ] &&
+               no_remotes=1 recurse_deps push_branch "$name"
+       # remove multiple occurrences of the same branch
+       sort -u "$_listfile" | xargs git push $dry_run "$remote"
index 3a40081..86dcd9a 100644 (file)
@@ -28,8 +28,13 @@ git config "remote.$name.url" >/dev/null || die "unknown remote '$name'"
 ## Configure the remote
 git config --replace-all "remote.$name.fetch" "+refs/top-bases/*:refs/remotes/$name/top-bases/*" "\\+refs/top-bases/\\*:refs/remotes/$name/top-bases/\\*"
-git config --replace-all "remote.$name.push" "+refs/top-bases/*:refs/top-bases/*" "\\+refs/top-bases/\\*:refs/top-bases/\\*"
-git config --replace-all "remote.$name.push" "+refs/heads/*:refs/heads/*" "\\+refs/heads/\\*:refs/heads/\\*"
+if git config --get-all "remote.$name.push" "\\+refs/top-bases/\\*:refs/top-bases/\\*" >/dev/null && test "xtrue" != "x$(git config --bool --get topgit.dontwarnonoldpushspecs)"; then
+       info "Probably you want to remove the push specs introduced by an old version of topgit:"
+       info '       git config --unset-all "remote.'$name'.push" "\\+refs/top-bases/\\*:refs/top-bases/\\*"'
+       info '       git config --unset-all "remote.'$name'.push" "\\+refs/heads/\\*:refs/heads/\\*"'
+       info '(or use git config --bool --add topgit.dontwarnonoldpushspecs true to get rid of this warning)'
 info "Remote $name can now follow TopGit topic branches."
 if [ -z "$populate" ]; then
index 288ec14..73280c6 100644 (file)
@@ -59,7 +59,7 @@ if [ -s "$depcheck" ]; then
                                        info "You are in a subshell. If you abort the merge,"
                                        info "use \`exit 1\` to abort the recursive update altogether."
                                        if ! sh -i </dev/tty; then
-                                               info "Ok, you aborated the merge. Now, you just need to"
+                                               info "Ok, you aborted the merge. Now, you just need to"
                                                info "switch back to some sane branch using \`git checkout\`."
                                                exit 3
diff --git a/ b/
index f0496f1..9d08d63 100644 (file)
--- a/
+++ b/
@@ -3,7 +3,7 @@
 # (c) Petr Baudis <>  2008
 # GPLv2
 ## Auxiliary functions
@@ -54,6 +54,8 @@ setup_hook()
                hook_call="exec $hook_call"
+       # Don't call hook if tg is not installed
+       hook_call="if which \"$tg\" > /dev/null; then $hook_call; fi"
        # Insert call into the hook
                echo "#!/bin/sh"
@@ -126,6 +128,13 @@ branch_annihilated()
        test "$(git rev-parse "$mb^{tree}")" = "$(git rev-parse "$_name^{tree}")";
+# is_sha1 REF
+# Whether REF is a SHA1 (compared to a symbolic name).
+       [ "$(git rev-parse "$1")" = "$1" ]
 # recurse_deps CMD NAME [BRANCHPATH...]
 # Recursively eval CMD on all dependencies of NAME.
 # CMD can refer to $_name for queried branch name,
@@ -136,6 +145,7 @@ branch_annihilated()
 # of the whole function.
 # If recurse_deps() hits missing dependencies, it will append
 # them to space-separated $missing_deps list and skip them.
+# remote dependencies are processed if no_remotes is unset.
        _cmd="$1"; shift
@@ -143,9 +153,9 @@ recurse_deps()
        _depsfile="$(mktemp -t tg-depsfile.XXXXXX)"
-       # Check also our base against remote base. Checking our head
-       # against remote head has to be done in the helper.
-       if has_remote "top-bases/$_name"; then
+       # If no_remotes is unset check also our base against remote base.
+       # Checking our head against remote head has to be done in the helper.
+       if test -z "$no_remotes" && has_remote "top-bases/$_name"; then
                echo "refs/remotes/$base_remote/top-bases/$_name" >>"$_depsfile"
@@ -226,7 +236,7 @@ needs_update()
 # branch_empty NAME
-       [ -z "$(git diff-tree "refs/top-bases/$1" "$1" | fgrep -v "     .top")" ]
+       [ -z "$(git diff-tree "refs/top-bases/$1" "$1" -- | fgrep -v "  .top")" ]
 # switch_to_base NAME [SEED]
@@ -268,7 +278,8 @@ do_help()
                echo "TopGit v$TG_VERSION - A different patch queue manager"
                echo "Usage: tg [-r REMOTE] ($cmds|help) ..."
        elif [ -r "@cmddir@"/tg-$1 ] ; then
-               @cmddir@/tg-$1 -h || :
+               setup_pager
+               @cmddir@/tg-$1 -h 2>&1 || :
                if [ -r "@sharedir@/tg-$1.txt" ] ; then
                        cat "@sharedir@/tg-$1.txt"
@@ -302,7 +313,7 @@ setup_pager()
        # now spawn pager
-       export LESS=${LESS:-FRSX}       # as in pager.c:pager_preexec()
+       export LESS="${LESS:-FRSX}"     # as in pager.c:pager_preexec()
        _pager_fifo_dir="$(mktemp -t -d tg-pager-fifo.XXXXXX)"
@@ -340,8 +351,9 @@ setup_hook "pre-commit"
 ## Dispatch
 # We were sourced from another script for our utility functions;
-# this is set by hooks.
-[ -z "$tg__include" ] || return 0
+# this is set by hooks.  Skip the rest of the file.  A simple return doesn't
+# work as expected in every shell.  See
+if [ -z "$tg__include" ]; then
 if [ "$1" = "-r" ]; then
@@ -374,4 +386,6 @@ help|--help|-h)
        . "@cmddir@"/tg-$cmd;;
 # vim:noet