Merge branch 'mm/rebase-continue-freebsd-WB' into maint

* mm/rebase-continue-freebsd-WB:
  rebase: fix run_specific_rebase's use of "return" on FreeBSD
diff --git a/.gitignore b/.gitignore
index 6669bf0..6b1fd1b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -23,6 +23,7 @@
 /git-cat-file
 /git-check-attr
 /git-check-ignore
+/git-check-mailmap
 /git-check-ref-format
 /git-checkout
 /git-checkout-index
@@ -125,6 +126,7 @@
 /git-remote-ftps
 /git-remote-fd
 /git-remote-ext
+/git-remote-testgit
 /git-remote-testpy
 /git-remote-testsvn
 /git-repack
@@ -190,6 +192,8 @@
 /test-mktemp
 /test-parse-options
 /test-path-utils
+/test-prio-queue
+/test-read-cache
 /test-regex
 /test-revision-walking
 /test-run-command
@@ -228,6 +232,7 @@
 /cscope*
 *.obj
 *.lib
+*.res
 *.sln
 *.suo
 *.ncb
diff --git a/.mailmap b/.mailmap
index 48d7acf..1c1f5ec 100644
--- a/.mailmap
+++ b/.mailmap
@@ -5,98 +5,242 @@
 # same person appearing not to be so.
 #
 
+<nico@fluxnic.net> <nico@cam.org>
+Alejandro R. Sedeño <asedeno@MIT.EDU> <asedeno@mit.edu>
 Alex Bennée <kernel-hacker@bennee.com>
+Alex Riesen <raa.lkml@gmail.com> <fork0@t-online.de>
+Alex Riesen <raa.lkml@gmail.com> <raa@limbo.localdomain>
+Alex Riesen <raa.lkml@gmail.com> <raa@steel.home>
+Alex Vandiver <alex@chmrr.net> <alexmv@MIT.EDU>
 Alexander Gavrilov <angavrilov@gmail.com>
+Alexey Shumkin <alex.crezoff@gmail.com> <zapped@mail.ru>
+Alexey Shumkin <alex.crezoff@gmail.com> <Alex.Crezoff@gmail.com>
+Anders Kaseorg <andersk@MIT.EDU> <andersk@ksplice.com>
+Anders Kaseorg <andersk@MIT.EDU> <andersk@mit.edu>
 Aneesh Kumar K.V <aneesh.kumar@gmail.com>
-Brian M. Carlson <sandals@crustytoothpaste.ath.cx>
+Amos Waterland <apw@debian.org> <apw@rossby.metr.ou.edu>
+Amos Waterland <apw@debian.org> <apw@us.ibm.com>
+Ben Walton <bdwalton@gmail.com> <bwalton@artsci.utoronto.ca>
+Benoit Sigoure <tsunanet@gmail.com> <tsuna@lrde.epita.fr>
+Bernt Hansen <bernt@norang.ca> <bernt@alumni.uwaterloo.ca>
+Brandon Casey <drafnel@gmail.com> <casey@nrlssc.navy.mil>
+brian m. carlson <sandals@crustytoothpaste.ath.cx> Brian M. Carlson <sandals@crustytoothpaste.ath.cx>
+brian m. carlson <sandals@crustytoothpaste.ath.cx> <sandals@crustytoothpaste.net>
+Bryan Larsen <bryan@larsen.st> <bryan.larsen@gmail.com>
+Bryan Larsen <bryan@larsen.st> <bryanlarsen@yahoo.com>
 Cheng Renquan <crquan@gmail.com>
 Chris Shoemaker <c.shoemaker@cox.net>
+Chris Wright <chrisw@sous-sol.org> <chrisw@osdl.org>
+Cord Seele <cowose@gmail.com> <cowose@googlemail.com>
+Christian Stimming <stimming@tuhh.de> <chs@ckiste.goetheallee>
+Csaba Henk <csaba@gluster.com> <csaba@lowlife.hu>
 Dan Johnson <computerdruid@gmail.com>
-Dana L. How <danahow@gmail.com>
-Dana L. How <how@deathvalley.cswitch.com>
+Dana L. How <danahow@gmail.com> <how@deathvalley.cswitch.com>
+Dana L. How <danahow@gmail.com> Dana How
 Daniel Barkalow <barkalow@iabervon.org>
+Daniel Trstenjak <daniel.trstenjak@gmail.com> <daniel.trstenjak@online.de>
+Daniel Trstenjak <daniel.trstenjak@gmail.com> <trsten@science-computing.de>
+David Brown <git@davidb.org> <davidb@quicinc.com>
 David D. Kilzer <ddkilzer@kilzer.net>
 David Kågedal <davidk@lysator.liu.se>
+David Reiss <dreiss@facebook.com> <dreiss@dreiss-vmware.(none)>
 David S. Miller <davem@davemloft.net>
 Deskin Miller <deskinm@umich.edu>
 Dirk Süsserott <newsletter@dirk.my1.cc>
+Eric Blake <eblake@redhat.com> <ebb9@byu.net>
+Eric Hanchrow <eric.hanchrow@gmail.com> <offby1@blarg.net>
 Eric S. Raymond <esr@thyrsus.com>
 Erik Faye-Lund <kusmabite@gmail.com> <kusmabite@googlemail.com>
-Fredrik Kuivinen <freku045@student.liu.se>
+Eyvind Bernhardsen <eyvind.bernhardsen@gmail.com> <eyvind-git@orakel.ntnu.no>
+Florian Achleitner <florian.achleitner.2.6.31@gmail.com> <florian.achleitner2.6.31@gmail.com>
+Franck Bui-Huu <vagabon.xyz@gmail.com> <fbuihuu@gmail.com>
+Frank Lichtenheld <frank@lichtenheld.de> <djpig@debian.org>
+Frank Lichtenheld <frank@lichtenheld.de> <flichtenheld@astaro.com>
+Fredrik Kuivinen <frekui@gmail.com> <freku045@student.liu.se>
 Frédéric Heitzmann <frederic.heitzmann@gmail.com>
-H. Peter Anvin <hpa@bonde.sc.orionmulti.com>
-H. Peter Anvin <hpa@tazenda.sc.orionmulti.com>
-H. Peter Anvin <hpa@trantor.hos.anvin.org>
+Garry Dolley <gdolley@ucla.edu> <gdolley@arpnetworks.com>
+Greg Price <price@mit.edu> <price@MIT.EDU>
+Greg Price <price@mit.edu> <price@ksplice.com>
+Heiko Voigt <hvoigt@hvoigt.net> <git-list@hvoigt.net>
+H. Merijn Brand <h.m.brand@xs4all.nl> H.Merijn Brand <h.m.brand@xs4all.nl>
+H. Peter Anvin <hpa@zytor.com> <hpa@bonde.sc.orionmulti.com>
+H. Peter Anvin <hpa@zytor.com> <hpa@smyrno.hos.anvin.org>
+H. Peter Anvin <hpa@zytor.com> <hpa@tazenda.sc.orionmulti.com>
+H. Peter Anvin <hpa@zytor.com> <hpa@trantor.hos.anvin.org>
+Han-Wen Nienhuys <hanwen@google.com> Han-Wen Nienhuys <hanwen@xs4all.nl>
 Horst H. von Brand <vonbrand@inf.utfsm.cl>
-İsmail Dönmez <ismail@pardus.org.tr>
+J. Bruce Fields <bfields@citi.umich.edu> <bfields@fieldses.org>
+J. Bruce Fields <bfields@citi.umich.edu> <bfields@pig.linuxdev.us.dell.com>
+J. Bruce Fields <bfields@citi.umich.edu> <bfields@puzzle.fieldses.org>
 Jakub Narębski <jnareb@gmail.com>
-Jay Soffian <jaysoffian+git@gmail.com>
+James Y Knight <jknight@itasoftware.com> <foom@fuhm.net>
+# The 2 following authors are probably the same person,
+# but both emails bounce.
+Jason McMullan <jason.mcmullan@timesys.com>
+Jason McMullan <mcmullan@netapp.com>
+Jason Riedy <ejr@eecs.berkeley.edu> <ejr@EECS.Berkeley.EDU>
+Jason Riedy <ejr@eecs.berkeley.edu> <ejr@cs.berkeley.edu>
+Jay Soffian <jaysoffian@gmail.com> <jaysoffian+git@gmail.com>
 Jeff King <peff@peff.net> <peff@github.com>
+Jeff Muizelaar <jmuizelaar@mozilla.com> <jeff@infidigm.net>
+Jens Axboe <axboe@kernel.dk> <axboe@suse.de>
+Jens Axboe <axboe@kernel.dk> <jens.axboe@oracle.com>
+Jim Meyering <jim@meyering.net> <meyering@redhat.com>
 Joachim Berdal Haga <cjhaga@fys.uio.no>
-Johannes Sixt <j6t@kdbg.org> <johannes.sixt@telecom.at>
-Johannes Sixt <j6t@kdbg.org> <j.sixt@viscovery.net>
+Johannes Schindelin <Johannes.Schindelin@gmx.de> <johannes.schindelin@gmx.de>
 Johannes Sixt <j6t@kdbg.org> <J.Sixt@eudaptics.com>
-Jon Loeliger <jdl@freescale.com>
-Jon Seymour <jon@blackcubes.dyndns.org>
-Jonathan Nieder <jrnieder@uchicago.edu>
+Johannes Sixt <j6t@kdbg.org> <j.sixt@viscovery.net>
+Johannes Sixt <j6t@kdbg.org> <johannes.sixt@telecom.at>
+John 'Warthog9' Hawley <warthog9@kernel.org> <warthog9@eaglescrag.net>
+Jon Loeliger <jdl@jdl.com> <jdl@freescale.com>
+Jon Loeliger <jdl@jdl.com> <jdl@freescale.org>
+Jon Seymour <jon.seymour@gmail.com> <jon@blackcubes.dyndns.org>
+Jonathan Nieder <jrnieder@gmail.com> <jrnieder@uchicago.edu>
+Jonathan del Strother <jon.delStrother@bestbefore.tv> <maillist@steelskies.com>
+Josh Triplett <josh@joshtriplett.org> <josh@freedesktop.org>
+Josh Triplett <josh@joshtriplett.org> <josht@us.ibm.com>
+Julian Phillips <julian@quantumfyre.co.uk> <jp3@quantumfyre.co.uk>
 Junio C Hamano <gitster@pobox.com> <gitster@pobox.com>
-Junio C Hamano <gitster@pobox.com> <junio@pobox.com>
-Junio C Hamano <gitster@pobox.com> <junio@twinsun.com>
-Junio C Hamano <gitster@pobox.com> <junkio@twinsun.com>
 Junio C Hamano <gitster@pobox.com> <junio@hera.kernel.org>
 Junio C Hamano <gitster@pobox.com> <junio@kernel.org>
+Junio C Hamano <gitster@pobox.com> <junio@pobox.com>
+Junio C Hamano <gitster@pobox.com> <junio@twinsun.com>
 Junio C Hamano <gitster@pobox.com> <junkio@cox.net>
-Karl Hasselström <kha@treskal.com>
-Kevin Leung <kevinlsk@gmail.com>
+Junio C Hamano <gitster@pobox.com> <junkio@twinsun.com>
+Karl Wiberg <kha@treskal.com> Karl  Hasselström
+Karl Wiberg <kha@treskal.com> <kha@yoghurt.hemma.treskal.com>
+Karsten Blees <blees@dcon.de> <karsten.blees@dcon.de>
+Karsten Blees <blees@dcon.de> <karsten.blees@gmail.com>
+Kay Sievers <kay.sievers@vrfy.org> <kay.sievers@suse.de>
+Kay Sievers <kay.sievers@vrfy.org> <kay@mam.(none)>
+Keith Cascio <keith@CS.UCLA.EDU> <keith@cs.ucla.edu>
 Kent Engstrom <kent@lysator.liu.se>
+Kevin Leung <kevinlsk@gmail.com>
+Kirill Smelkov <kirr@navytux.spb.ru> <kirr@landau.phys.spbu.ru>
+Kirill Smelkov <kirr@navytux.spb.ru> <kirr@mns.spb.ru>
+Knut Franke <Knut.Franke@gmx.de> <k.franke@science-computing.de>
 Lars Doelle <lars.doelle@on-line ! de>
 Lars Doelle <lars.doelle@on-line.de>
+Lars Noschinski <lars@public.noschinski.de> <lars.noschinski@rwth-aachen.de>
 Li Hong <leehong@pku.edu.cn>
-Linus Torvalds <torvalds@linux-foundation.org> <torvalds@woody.linux-foundation.org>
-Linus Torvalds <torvalds@linux-foundation.org> <torvalds@osdl.org>
-Linus Torvalds <torvalds@linux-foundation.org> <torvalds@g5.osdl.org>
 Linus Torvalds <torvalds@linux-foundation.org> <torvalds@evo.osdl.org>
-Linus Torvalds <torvalds@linux-foundation.org> <torvalds@ppc970.osdl.org>
+Linus Torvalds <torvalds@linux-foundation.org> <torvalds@g5.osdl.org>
+Linus Torvalds <torvalds@linux-foundation.org> <torvalds@osdl.org>
 Linus Torvalds <torvalds@linux-foundation.org> <torvalds@ppc970.osdl.org.(none)>
-Lukas Sandström <lukass@etek.chalmers.se>
+Linus Torvalds <torvalds@linux-foundation.org> <torvalds@ppc970.osdl.org>
+Linus Torvalds <torvalds@linux-foundation.org> <torvalds@woody.linux-foundation.org>
+Lukas Sandström <luksan@gmail.com> <lukass@etek.chalmers.se>
+Marc Khouzam <marc.khouzam@ericsson.com> <marc.khouzam@gmail.com>
 Marc-André Lureau <marcandre.lureau@gmail.com>
+Marco Costalba <mcostalba@gmail.com> <mcostalba@yahoo.it>
+Mark Levedahl <mdl123@verizon.net> <mlevedahl@gmail.com>
 Mark Rada <marada@uwaterloo.ca>
 Martin Langhoff <martin@laptop.org> <martin@catalyst.net.nz>
 Martin von Zweigbergk <martinvonz@gmail.com> <martin.von.zweigbergk@gmail.com>
+Matt Draisey <matt@draisey.ca> <mattdraisey@sympatico.ca>
+Matt Kraai <kraai@ftbfs.org> <matt.kraai@amo.abbott.com>
+Matt McCutchen <matt@mattmccutchen.net> <hashproduct@gmail.com>
+Matthias Kestenholz <matthias@spinlock.ch> <mk@spinlock.ch>
+Matthias Urlichs <matthias@urlichs.de> <smurf@kiste.(none)>
+Matthias Urlichs <matthias@urlichs.de> <smurf@smurf.noris.de>
 Michael Coleman <tutufan@gmail.com>
 Michael J Gruber <git@drmicha.warpmail.net> <michaeljgruber+gmane@fastmail.fm>
+Michael S. Tsirkin <mst@kernel.org> <mst@redhat.com>
+Michael S. Tsirkin <mst@kernel.org> <mst@mellanox.co.il>
+Michael S. Tsirkin <mst@kernel.org> <mst@dev.mellanox.co.il>
 Michael W. Olson <mwolson@gnu.org>
+Michael Witten <mfwitten@gmail.com> <mfwitten@MIT.EDU>
+Michael Witten <mfwitten@gmail.com> <mfwitten@mit.edu>
+Michal Rokos <michal.rokos@nextsoft.cz> <rokos@nextsoft.cz>
 Michele Ballabio <barra_cuda@katamail.com>
-Nanako Shiraishi <nanako3@bluebottle.com>
+Miklos Vajna <vmiklos@frugalware.org> <vmiklos@suse.cz>
+Namhyung Kim <namhyung@gmail.com> <namhyung.kim@lge.com>
+Namhyung Kim <namhyung@gmail.com> <namhyung@kernel.org>
+Nanako Shiraishi <nanako3@lavabit.com> <nanako3@bluebottle.com>
 Nanako Shiraishi <nanako3@lavabit.com>
+Nelson Elhage <nelhage@mit.edu> <nelhage@MIT.EDU>
+Nelson Elhage <nelhage@mit.edu> <nelhage@ksplice.com>
 Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
-<nico@fluxnic.net> <nico@cam.org>
-Peter Krefting <peter@softwolves.pp.se> <peter@svarten.intern.softwolves.pp.se>
+Nick Stokoe <nick@noodlefactory.co.uk> Nick Woolley <nick@noodlefactory.co.uk>
+Nick Stokoe <nick@noodlefactory.co.uk> Nick Woolley <nickwoolley@yahoo.co.uk>
+Nicolas Morey-Chaisemartin <devel-git@morey-chaisemartin.com> <nicolas.morey@free.fr>
+Nicolas Morey-Chaisemartin <devel-git@morey-chaisemartin.com> <nmorey@kalray.eu>
+Nicolas Sebrecht <nicolas.s.dev@gmx.fr> <ni.s@laposte.net>
+Paolo Bonzini <bonzini@gnu.org> <paolo.bonzini@lu.unisi.ch>
+Pascal Obry <pascal@obry.net> <pascal.obry@gmail.com>
+Pascal Obry <pascal@obry.net> <pascal.obry@wanadoo.fr>
+Pat Notz <patnotz@gmail.com> <pknotz@sandia.gov>
+Paul Mackerras <paulus@samba.org> <paulus@dorrigo.(none)>
+Paul Mackerras <paulus@samba.org> <paulus@pogo.(none)>
+Peter Baumann <waste.manager@gmx.de> <Peter.B.Baumann@stud.informatik.uni-erlangen.de>
+Peter Baumann <waste.manager@gmx.de> <siprbaum@stud.informatik.uni-erlangen.de>
 Peter Krefting <peter@softwolves.pp.se> <peter@softwolves.pp.se>
+Peter Krefting <peter@softwolves.pp.se> <peter@svarten.intern.softwolves.pp.se>
 Petr Baudis <pasky@ucw.cz> <pasky@suse.cz>
+Petr Baudis <pasky@ucw.cz> <xpasky@machine>
+Phil Hord <hordp@cisco.com> <phil.hord@gmail.com>
+Philip Jägenstedt <philip@foolip.org> <philip.jagenstedt@gmail.com>
+Philipp A. Hartmann <pah@qo.cx> <ph@sorgh.de>
 Philippe Bruhat <book@cpan.org>
 Ralf Thielow <ralf.thielow@gmail.com> <ralf.thielow@googlemail.com>
 Ramsay Allan Jones <ramsay@ramsay1.demon.co.uk>
-René Scharfe <rene.scharfe@lsrfire.ath.cx>
+René Scharfe <l.s.r@web.de> <rene.scharfe@lsrfire.ath.cx>
 Robert Fitzsimons <robfitz@273k.net>
+Robert Shearman <robertshearman@gmail.com> <rob@codeweavers.com>
 Robert Zeh <robert.a.zeh@gmail.com>
-Sam Vilain <sam@vilain.net>
-Santi Béjar <sbejar@gmail.com>
+Robin Rosenberg <robin.rosenberg@dewire.com> <robin.rosenberg.lists@dewire.com>
+Rutger Nijlunsing <rutger.nijlunsing@gmail.com> <rutger@nospam.com>
+Rutger Nijlunsing <rutger.nijlunsing@gmail.com> <git@tux.tmfweb.nl>
+Ryan Anderson <ryan@michonline.com> <rda@google.com>
+Salikh Zakirov <salikh.zakirov@gmail.com> <Salikh.Zakirov@Intel.com>
+Sam Vilain <sam@vilain.net> <sam.vilain@catalyst.net.nz>
+Sam Vilain <sam@vilain.net> sam@vilain.net
+Santi Béjar <santi@agolina.net> <sbejar@gmail.com>
 Sean Estabrooks <seanlkml@sympatico.ca>
+Sebastian Schuberth <sschuberth@gmail.com> <sschuberth@visageimaging.com>
+Seth Falcon <seth@userprimary.net> <sfalcon@fhcrc.org>
 Shawn O. Pearce <spearce@spearce.org>
-Steven Grimm <koreth@midwinter.com>
+Simon Hausmann <hausmann@kde.org> <simon@lst.de>
+Simon Hausmann <hausmann@kde.org> <shausman@trolltech.com>
+Stefan Naewe <stefan.naewe@gmail.com> <stefan.naewe@atlas-elektronik.com>
+Stefan Naewe <stefan.naewe@gmail.com> <stefan.naewe@googlemail.com>
+Stefan Sperling <stsp@elego.de> <stsp@stsp.name>
+Štěpán Němec <stepnem@gmail.com> <stepan.nemec@gmail.com>
+Stephen Boyd <bebarino@gmail.com> <sboyd@codeaurora.org>
+Steven Drake <sdrake@xnet.co.nz> <sdrake@ihug.co.nz>
+Steven Grimm <koreth@midwinter.com> <sgrimm@sgrimm-mbp.local>
+Steven Grimm <koreth@midwinter.com> koreth@midwinter.com
+Steven Walter <stevenrwalter@gmail.com> <swalter@lexmark.com>
+Steven Walter <stevenrwalter@gmail.com> <swalter@lpdev.prtdev.lexmark.com>
+Sven Verdoolaege <skimo@kotnet.org> <Sven.Verdoolaege@cs.kuleuven.ac.be>
+Sven Verdoolaege <skimo@kotnet.org> <skimo@liacs.nl>
 Tay Ray Chuan <rctay89@gmail.com>
+Ted Percival <ted@midg3t.net> <ted.percival@quest.com>
 Theodore Ts'o <tytso@mit.edu>
+Thomas Ackermann <th.acker@arcor.de> <th.acker66@arcor.de>
 Thomas Rast <trast@inf.ethz.ch> <trast@student.ethz.ch>
+Timo Hirvonen <tihirvon@gmail.com> <tihirvon@ee.oulu.fi>
+Toby Allsopp <Toby.Allsopp@navman.co.nz> <toby.allsopp@navman.co.nz>
+Tom Grennan <tmgrennan@gmail.com> <tgrennan@redback.com>
+Tommi Virtanen <tv@debian.org> <tv@eagain.net>
+Tommi Virtanen <tv@debian.org> <tv@inoi.fi>
+Tommy Thorn <tommy-git@thorn.ws> <tt1729@yahoo.com>
 Tony Luck <tony.luck@intel.com>
-Uwe Kleine-König <Uwe_Zeisberger@digi.com>
-Uwe Kleine-König <Uwe.Kleine-Koenig@digi.com>
-Uwe Kleine-König <ukleinek@informatik.uni-freiburg.de>
-Uwe Kleine-König <uzeisberger@io.fsforth.de>
-Uwe Kleine-König <zeisberg@informatik.uni-freiburg.de>
-Ville Skyttä <scop@xemacs.org>
+Tor Arne Vestbø <torarnv@gmail.com> <tavestbo@trolltech.com>
+Trent Piepho <tpiepho@gmail.com> <tpiepho@freescale.com>
+Trent Piepho <tpiepho@gmail.com> <xyzzy@speakeasy.org>
+Uwe Kleine-König <u.kleine-koenig@pengutronix.de> <Uwe.Kleine-Koenig@digi.com>
+Uwe Kleine-König <u.kleine-koenig@pengutronix.de> <ukleinek@informatik.uni-freiburg.de>
+Uwe Kleine-König <u.kleine-koenig@pengutronix.de> <uzeisberger@io.fsforth.de>
+Uwe Kleine-König <u.kleine-koenig@pengutronix.de> <zeisberg@informatik.uni-freiburg.de>
+Ville Skyttä <ville.skytta@iki.fi> <scop@xemacs.org>
 Vitaly "_Vi" Shukela <public_vi@tut.by>
+W. Trevor King <wking@tremily.us> <wking@drexel.edu>
 William Pursell <bill.pursell@gmail.com>
+YONETANI Tomokazu <y0n3t4n1@gmail.com> <qhwt+git@les.ath.cx>
+YONETANI Tomokazu <y0n3t4n1@gmail.com> <y0netan1@dragonflybsd.org>
 YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
+# the two anonymous contributors are different persons:
 anonymous <linux@horizon.com>
 anonymous <linux@horizon.net>
+İsmail Dönmez <ismail@pardus.org.tr>
diff --git a/Documentation/CodingGuidelines b/Documentation/CodingGuidelines
index 7e4d571..559d5f9 100644
--- a/Documentation/CodingGuidelines
+++ b/Documentation/CodingGuidelines
@@ -237,8 +237,10 @@
 
 Writing Documentation:
 
- Most (if not all) of the documentation pages are written in AsciiDoc
- and processed into HTML output and manpages.
+ Most (if not all) of the documentation pages are written in the
+ AsciiDoc format in *.txt files (e.g. Documentation/git.txt), and
+ processed into HTML and manpages (e.g. git.html and git.1 in the
+ same directory).
 
  Every user-visible change should be reflected in the documentation.
  The same general rule as for code applies -- imitate the existing
diff --git a/Documentation/Makefile b/Documentation/Makefile
index 62dbd9a..0cfdc36 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -31,11 +31,11 @@
 MAN7_TXT += gitworkflows.txt
 
 MAN_TXT = $(MAN1_TXT) $(MAN5_TXT) $(MAN7_TXT)
-MAN_XML=$(patsubst %.txt,%.xml,$(MAN_TXT))
-MAN_HTML=$(patsubst %.txt,%.html,$(MAN_TXT))
+MAN_XML = $(patsubst %.txt,%.xml,$(MAN_TXT))
+MAN_HTML = $(patsubst %.txt,%.html,$(MAN_TXT))
 
 OBSOLETE_HTML = git-remote-helpers.html
-DOC_HTML=$(MAN_HTML) $(OBSOLETE_HTML)
+DOC_HTML = $(MAN_HTML) $(OBSOLETE_HTML)
 
 ARTICLES = howto-index
 ARTICLES += everyday
@@ -74,35 +74,35 @@
 
 DOC_HTML += $(patsubst %,%.html,$(ARTICLES) $(SP_ARTICLES))
 
-DOC_MAN1=$(patsubst %.txt,%.1,$(MAN1_TXT))
-DOC_MAN5=$(patsubst %.txt,%.5,$(MAN5_TXT))
-DOC_MAN7=$(patsubst %.txt,%.7,$(MAN7_TXT))
+DOC_MAN1 = $(patsubst %.txt,%.1,$(MAN1_TXT))
+DOC_MAN5 = $(patsubst %.txt,%.5,$(MAN5_TXT))
+DOC_MAN7 = $(patsubst %.txt,%.7,$(MAN7_TXT))
 
-prefix?=$(HOME)
-bindir?=$(prefix)/bin
-htmldir?=$(prefix)/share/doc/git-doc
-pdfdir?=$(prefix)/share/doc/git-doc
-mandir?=$(prefix)/share/man
-man1dir=$(mandir)/man1
-man5dir=$(mandir)/man5
-man7dir=$(mandir)/man7
-# DESTDIR=
+prefix ?= $(HOME)
+bindir ?= $(prefix)/bin
+htmldir ?= $(prefix)/share/doc/git-doc
+infodir ?= $(prefix)/share/info
+pdfdir ?= $(prefix)/share/doc/git-doc
+mandir ?= $(prefix)/share/man
+man1dir = $(mandir)/man1
+man5dir = $(mandir)/man5
+man7dir = $(mandir)/man7
+# DESTDIR =
 
 ASCIIDOC = asciidoc
 ASCIIDOC_EXTRA =
 MANPAGE_XSL = manpage-normal.xsl
 XMLTO = xmlto
 XMLTO_EXTRA =
-INSTALL?=install
+INSTALL ?= install
 RM ?= rm -f
 MAN_REPO = ../../git-manpages
 HTML_REPO = ../../git-htmldocs
 
-infodir?=$(prefix)/share/info
-MAKEINFO=makeinfo
-INSTALL_INFO=install-info
-DOCBOOK2X_TEXI=docbook2x-texi
-DBLATEX=dblatex
+MAKEINFO = makeinfo
+INSTALL_INFO = install-info
+DOCBOOK2X_TEXI = docbook2x-texi
+DBLATEX = dblatex
 ifndef PERL_PATH
 	PERL_PATH = /usr/bin/perl
 endif
diff --git a/Documentation/RelNotes/1.7.10.1.txt b/Documentation/RelNotes/1.7.10.1.txt
index 806a965..be68524 100644
--- a/Documentation/RelNotes/1.7.10.1.txt
+++ b/Documentation/RelNotes/1.7.10.1.txt
@@ -14,7 +14,7 @@
    not exclude them and tried to apply funny patches only to fail.
 
  * "git blame" started missing quite a few changes from the origin
-   since we stopped using the diff minimalization by default in v1.7.2
+   since we stopped using the diff minimization by default in v1.7.2
    era.
 
  * When PATH contains an unreadable directory, alias expansion code
diff --git a/Documentation/RelNotes/1.7.5.4.txt b/Documentation/RelNotes/1.7.5.4.txt
index cf3f455..7796df3 100644
--- a/Documentation/RelNotes/1.7.5.4.txt
+++ b/Documentation/RelNotes/1.7.5.4.txt
@@ -5,7 +5,7 @@
 --------------------
 
  * The single-key mode of "git add -p" was easily fooled into thinking
-   that it was told to add everthing ('a') when up-arrow was pressed by
+   that it was told to add everything ('a') when up-arrow was pressed by
    mistake.
 
  * Setting a git command that uses custom configuration via "-c var=val"
diff --git a/Documentation/RelNotes/1.7.8.2.txt b/Documentation/RelNotes/1.7.8.2.txt
index e74f4ef..b9c66aa 100644
--- a/Documentation/RelNotes/1.7.8.2.txt
+++ b/Documentation/RelNotes/1.7.8.2.txt
@@ -12,11 +12,11 @@
  * The configuration file parser used for sizes (e.g. bigFileThreshold)
    did not correctly interpret 'g' suffix.
 
- * The replacement implemention for snprintf used on platforms with
+ * The replacement implementation for snprintf used on platforms with
    native snprintf that is broken did not use va_copy correctly.
 
  * LF-to-CRLF streaming filter replaced all LF with CRLF, which might
-   be techinically correct but not friendly to people who are trying
+   be technically correct but not friendly to people who are trying
    to recover from earlier mistakes of using CRLF in the repository
    data in the first place. It now refrains from doing so for LF that
    follows a CR.
diff --git a/Documentation/RelNotes/1.7.8.txt b/Documentation/RelNotes/1.7.8.txt
index b4d90bb..2493113 100644
--- a/Documentation/RelNotes/1.7.8.txt
+++ b/Documentation/RelNotes/1.7.8.txt
@@ -9,7 +9,7 @@
  * Updates to bash completion scripts.
 
  * The build procedure has been taught to take advantage of computed
-   dependency automatically when the complier supports it.
+   dependency automatically when the compiler supports it.
 
  * The date parser now accepts timezone designators that lack minutes
    part and also has a colon between "hh:mm".
@@ -31,7 +31,7 @@
  * Variants of "git cherry-pick" and "git revert" that take multiple
    commits learned to "--continue" and "--abort".
 
- * "git daemon" gives more human readble error messages to clients
+ * "git daemon" gives more human readable error messages to clients
    using ERR packets when appropriate.
 
  * Errors at the network layer is logged by "git daemon".
diff --git a/Documentation/RelNotes/1.8.2.1.txt b/Documentation/RelNotes/1.8.2.1.txt
index 1354ad0..769a6fc 100644
--- a/Documentation/RelNotes/1.8.2.1.txt
+++ b/Documentation/RelNotes/1.8.2.1.txt
@@ -49,7 +49,7 @@
    common prefix and suffix between the two filenames overlapped.
 
  * "git submodule update", when recursed into sub-submodules, did not
-   acccumulate the prefix paths.
+   accumulate the prefix paths.
 
  * "git am $maildir/" applied messages in an unexpected order; sort
    filenames read from the maildir/ in a way that is more likely to
diff --git a/Documentation/RelNotes/1.8.2.2.txt b/Documentation/RelNotes/1.8.2.2.txt
index dab4831..708df1a 100644
--- a/Documentation/RelNotes/1.8.2.2.txt
+++ b/Documentation/RelNotes/1.8.2.2.txt
@@ -58,4 +58,4 @@
    conflicts have been applied.
 
  * "git bundle" did not like a bundle created using a commit without
-   any message as its one of the prerequistes.
+   any message as its one of the prerequisites.
diff --git a/Documentation/RelNotes/1.8.2.3.txt b/Documentation/RelNotes/1.8.2.3.txt
new file mode 100644
index 0000000..6139482
--- /dev/null
+++ b/Documentation/RelNotes/1.8.2.3.txt
@@ -0,0 +1,19 @@
+Git v1.8.2.3 Release Notes
+==========================
+
+Fixes since v1.8.2.2
+--------------------
+
+ * "rev-list --stdin" and friends kept bogus pointers into the input
+   buffer around as human readable object names.  This was not a
+   huge problem but was exposed by a new change that uses these
+   names in error output.
+
+ * When "git difftool" drove "kdiff3", it mistakenly passed --auto
+   option that was meant while resolving merge conflicts.
+
+ * "git remote add" command did not diagnose extra command line
+   arguments as an error and silently ignored them.
+
+Also contains a handful of trivial code clean-ups, documentation
+updates, updates to the test suite, etc.
diff --git a/Documentation/RelNotes/1.8.3.1.txt b/Documentation/RelNotes/1.8.3.1.txt
new file mode 100644
index 0000000..fc3ea18
--- /dev/null
+++ b/Documentation/RelNotes/1.8.3.1.txt
@@ -0,0 +1,14 @@
+Git v1.8.3.1 Release Notes
+========================
+
+Fixes since v1.8.3
+------------------
+
+ * When $HOME is misconfigured to point at an unreadable directory, we
+   used to complain and die. The check has been loosened.
+
+ * Handling of negative exclude pattern for directories "!dir" was
+   broken in the update to v1.8.3.
+
+Also contains a handful of trivial code clean-ups, documentation
+updates, updates to the test suite, etc.
diff --git a/Documentation/RelNotes/1.8.3.2.txt b/Documentation/RelNotes/1.8.3.2.txt
new file mode 100644
index 0000000..26ae142
--- /dev/null
+++ b/Documentation/RelNotes/1.8.3.2.txt
@@ -0,0 +1,59 @@
+Git v1.8.3.2 Release Notes
+==========================
+
+Fixes since v1.8.3.1
+--------------------
+
+ * Cloning with "git clone --depth N" while fetch.fsckobjects (or
+   transfer.fsckobjects) is set to true did not tell the cut-off
+   points of the shallow history to the process that validates the
+   objects and the history received, causing the validation to fail.
+
+ * "git checkout foo" DWIMs the intended "upstream" and turns it into
+   "git checkout -t -b foo remotes/origin/foo". This codepath has been
+   updated to correctly take existing remote definitions into account.
+
+ * "git fetch" into a shallow repository from a repository that does
+   not know about the shallow boundary commits (e.g. a different fork
+   from the repository the current shallow repository was cloned from)
+   did not work correctly.
+
+ * "git subtree" (in contrib/) had one codepath with loose error
+   checks to lose data at the remote side.
+
+ * "git log --ancestry-path A...B" did not work as expected, as it did
+   not pay attention to the fact that the merge base between A and B
+   was the bottom of the range being specified.
+
+ * "git diff -c -p" was not showing a deleted line from a hunk when
+   another hunk immediately begins where the earlier one ends.
+
+ * "git merge @{-1}~22" was rewritten to "git merge frotz@{1}~22"
+   incorrectly when your previous branch was "frotz" (it should be
+   rewritten to "git merge frotz~22" instead).
+
+ * "git commit --allow-empty-message -m ''" should not start an
+   editor.
+
+ * "git push --[no-]verify" was not documented.
+
+ * An entry for "file://" scheme in the enumeration of URL types Git
+   can take in the HTML documentation was made into a clickable link
+   by mistake.
+
+ * zsh prompt script that borrowed from bash prompt script did not
+   work due to slight differences in array variable notation between
+   these two shells.
+
+ * The bash prompt code (in contrib/) displayed the name of the branch
+   being rebased when "rebase -i/-m/-p" modes are in use, but not the
+   plain vanilla "rebase".
+
+ * "git push $there HEAD:branch" did not resolve HEAD early enough, so
+   it was easy to flip it around while push is still going on and push
+   out a branch that the user did not originally intended when the
+   command was started.
+
+ * "difftool --dir-diff" did not copy back changes made by the
+   end-user in the diff tool backend to the working tree in some
+   cases.
diff --git a/Documentation/RelNotes/1.8.3.3.txt b/Documentation/RelNotes/1.8.3.3.txt
new file mode 100644
index 0000000..9ba4f4d
--- /dev/null
+++ b/Documentation/RelNotes/1.8.3.3.txt
@@ -0,0 +1,47 @@
+Git v1.8.3.3 Release Notes
+==========================
+
+Fixes since v1.8.3.2
+--------------------
+
+ * "git apply" parsed patches that add new files, generated by programs
+   other than Git, incorrectly.  This is an old breakage in v1.7.11.
+
+ * Older cURL wanted piece of memory we call it with to be stable, but
+   we updated the auth material after handing it to a call.
+
+ * "git pull" into nothing trashed "local changes" that were in the
+   index.
+
+ * Many "git submodule" operations did not work on a submodule at a
+   path whose name is not in ASCII.
+
+ * "cherry-pick" had a small leak in its error codepath.
+
+ * Logic used by git-send-email to suppress cc mishandled names like
+   "A U. Thor" <author@example.xz>, where the human readable part
+   needs to be quoted (the user input may not have the double quotes
+   around the name, and comparison was done between quoted and
+   unquoted strings).  It also mishandled names that need RFC2047
+   quoting.
+
+ * "gitweb" forgot to clear a global variable $search_regexp upon each
+   request, mistakenly carrying over the previous search to a new one
+   when used as a persistent CGI.
+
+ * The wildmatch engine did not honor WM_CASEFOLD option correctly.
+
+ * "git log -c --follow $path" segfaulted upon hitting the commit that
+   renamed the $path being followed.
+
+ * When a reflog notation is used for implicit "current branch",
+   e.g. "git log @{u}", we did not say which branch and worse said
+   "branch ''" in the error messages.
+
+ * Mac OS X does not like to write(2) more than INT_MAX number of
+   bytes; work it around by chopping write(2) into smaller pieces.
+
+ * Newer MacOS X encourages the programs to compile and link with
+   their CommonCrypto, not with OpenSSL.
+
+Also contains various minor documentation updates.
diff --git a/Documentation/RelNotes/1.8.3.4.txt b/Documentation/RelNotes/1.8.3.4.txt
new file mode 100644
index 0000000..56f106e
--- /dev/null
+++ b/Documentation/RelNotes/1.8.3.4.txt
@@ -0,0 +1,20 @@
+Git v1.8.3.4 Release Notes
+==========================
+
+This update is mostly to propagate documentation fixes and test
+updates from the master front back to the maintenance track.
+
+Fixes since v1.8.3.3
+--------------------
+
+ * The bisect log listed incorrect commits when bisection ends with
+   only skipped ones.
+
+ * The test coverage framework was left broken for some time.
+
+ * The test suite for HTTP transport did not run with Apache 2.4.
+
+ * "git diff" used to fail when core.safecrlf is set and the working
+   tree contents had mixed CRLF/LF line endings. Committing such a
+   content must be prohibited, but "git diff" should help the user to
+   locate and fix such problems without failing.
diff --git a/Documentation/RelNotes/1.8.3.txt b/Documentation/RelNotes/1.8.3.txt
index b0cd887..ead568e 100644
--- a/Documentation/RelNotes/1.8.3.txt
+++ b/Documentation/RelNotes/1.8.3.txt
@@ -41,11 +41,20 @@
 
 Foreign interface
 
- * remote-hg and remote-bzr helpers (in contrib/) have been updated.
+ * remote-hg and remote-bzr helpers (in contrib/ since v1.8.2) have
+   been updated; especially, the latter has been done in an
+   accelerated schedule (read: we may not have merged to this release
+   if we were following the usual "cook sufficiently in next before
+   unleashing it to the world" workflow) in order to help Emacs folks,
+   whose primary SCM seems to be stagnating.
 
 
 UI, Workflows & Features
 
+ * A handful of updates applied to gitk, including an addition of
+   "revert" action, showing dates in tags in a nicer way, making
+   colors configurable, and support for -G'pickaxe' search.
+
  * The prompt string generator (in contrib/completion/) learned to
    show how many changes there are in total and how many have been
    replayed during a "git rebase" session.
@@ -105,9 +114,10 @@
    of erroneous inputs was suboptimal and has been improved.
 
  * When the interactive access to git-shell is not enabled, it issues
-   a message meant to help the system administrator to enable it.
-   An explicit way to help the end users who connect to the service by
-   issuing custom messages to refuse such an access has been added.
+   a message meant to help the system administrator to enable it.  An
+   explicit way has been added to issue custom messages to refuse an
+   access over the network to help the end users who connect to the
+   service expecting an interactive shell.
 
  * In addition to the case where the user edits the log message with
    the "e)dit" option of "am -i", replace the "Applying: this patch"
@@ -117,8 +127,8 @@
  * "git status" suggests users to look into using --untracked=no option
    when it takes too long.
 
- * "git status" shows a bit more information during a
-   rebase/bisect session.
+ * "git status" shows a bit more information during a rebase/bisect
+   session.
 
  * "git fetch" learned to fetch a commit at the tip of an unadvertised
    ref by specifying a raw object name from the command line when the
@@ -235,7 +245,6 @@
 
  * Various subcommands of "git remote" simply ignored extraneous
    command line arguments instead of diagnosing them as errors.
-   (merge b17dd3f tr/remote-tighten-commandline-parsing later to maint).
 
  * When receive-pack detects an error in the pack header it received in
    order to decide which of unpack-objects or index-pack to run, it
@@ -258,7 +267,6 @@
    buffer around as human readable object names.  This was not a huge
    problem but was exposed by a new change that uses these names in
    error output.
-   (merge 70d26c6 tr/copy-revisions-from-stdin later to maint).
 
  * Smart-capable HTTP servers were not restricted via the
    GIT_NAMESPACE mechanism when talking with commit-walking clients,
@@ -303,11 +311,9 @@
 
  * Fix a 1.8.1.x regression that stopped matching "dir" (without a
    trailing slash) to a directory "dir".
-   (merge efa5f82 jc/directory-attrs-regression-fix later to maint-1.8.1).
 
  * "git apply --whitespace=fix" was not prepared to see a line getting
    longer after fixing whitespaces (e.g. tab-in-indent aka Python).
-   (merge 329b26e jc/apply-ws-fix-tab-in-indent later to maint-1.8.1).
 
  * The prompt string generator (in contrib/completion/) did not notice
    when we are in a middle of a "git revert" session.
diff --git a/Documentation/RelNotes/1.8.4.1.txt b/Documentation/RelNotes/1.8.4.1.txt
new file mode 100644
index 0000000..806545a
--- /dev/null
+++ b/Documentation/RelNotes/1.8.4.1.txt
@@ -0,0 +1,50 @@
+Git v1.8.4.1 Release Notes
+========================
+
+Fixes since v1.8.4
+------------------
+
+ * Some people still use rather old versions of bash, which cannot
+   grok some constructs like 'printf -v varname' the prompt and
+   completion code started to use recently.  The completion and
+   prompt scripts have been adjusted to work better with these old
+   versions of bash.
+
+ * "git rebase -i" had a minor bug (the same could be in other
+   programs, as the root cause is pretty generic) where the code
+   feeds a random, data dependeant string to 'echo' and expects it
+   to come out literally.
+
+ * "submodule.<name>.path" variable mistakenly set to the empty
+   "true" caused the configuration parser to segfault.
+
+ * Output from "git log --full-diff -- <pathspec>" looked strange,
+   because comparison was done with the previous ancestor that
+   touched the specified <pathspec>, causing the patches for paths
+   outside the pathspec to show more than the single commit has
+   changed.
+
+ * The auto-tag-following code in "git fetch" tries to reuse the
+   same transport twice when the serving end does not cooperate and
+   does not give tags that point to commits that are asked for as
+   part of the primary transfer.  Unfortunately, Git-aware transport
+   helper interface is not designed to be used more than once, hence
+   this did not work over smart-http transfer.  Fixed.
+
+ * Send a large request to read(2)/write(2) as a smaller but still
+   reasonably large chunks, which would improve the latency when the
+   operation needs to be killed and incidentally works around broken
+   64-bit systems that cannot take a 2GB write or read in one go.
+
+ * A ".mailmap" file that ends with an incomplete line, when read
+   from a blob, was not handled properly.
+
+ * The recent "short-cut clone connectivity check" topic broke a
+   shallow repository when a fetch operation tries to auto-follow
+   tags.
+
+ * On platforms with fgetc() and friends defined as macros,
+   the configuration parser did not compile.
+
+Also contains a handful of trivial code clean-ups, documentation
+updates, updates to the test suite, etc.
diff --git a/Documentation/RelNotes/1.8.4.txt b/Documentation/RelNotes/1.8.4.txt
new file mode 100644
index 0000000..02f681b
--- /dev/null
+++ b/Documentation/RelNotes/1.8.4.txt
@@ -0,0 +1,486 @@
+Git v1.8.4 Release Notes
+========================
+
+Backward compatibility notes (for Git 2.0)
+------------------------------------------
+
+When "git push [$there]" does not say what to push, we have used the
+traditional "matching" semantics so far (all your branches were sent
+to the remote as long as there already are branches of the same name
+over there).  In Git 2.0, the default will change to the "simple"
+semantics that pushes:
+
+ - only the current branch to the branch with the same name, and only
+   when the current branch is set to integrate with that remote
+   branch, if you are pushing to the same remote as you fetch from; or
+
+ - only the current branch to the branch with the same name, if you
+   are pushing to a remote that is not where you usually fetch from.
+
+Use the user preference configuration variable "push.default" to
+change this.  If you are an old-timer who is used to the "matching"
+semantics, you can set the variable to "matching" to keep the
+traditional behaviour.  If you want to live in the future early, you
+can set it to "simple" today without waiting for Git 2.0.
+
+When "git add -u" (and "git add -A") is run inside a subdirectory and
+does not specify which paths to add on the command line, it
+will operate on the entire tree in Git 2.0 for consistency
+with "git commit -a" and other commands.  There will be no
+mechanism to make plain "git add -u" behave like "git add -u .".
+Current users of "git add -u" (without a pathspec) should start
+training their fingers to explicitly say "git add -u ."
+before Git 2.0 comes.  A warning is issued when these commands are
+run without a pathspec and when you have local changes outside the
+current directory, because the behaviour in Git 2.0 will be different
+from today's version in such a situation.
+
+In Git 2.0, "git add <path>" will behave as "git add -A <path>", so
+that "git add dir/" will notice paths you removed from the directory
+and record the removal.  Versions before Git 2.0, including this
+release, will keep ignoring removals, but the users who rely on this
+behaviour are encouraged to start using "git add --ignore-removal <path>"
+now before 2.0 is released.
+
+
+Updates since v1.8.3
+--------------------
+
+Foreign interfaces, subsystems and ports.
+
+ * Cygwin port has been updated for more recent Cygwin 1.7.
+
+ * "git rebase -i" now honors --strategy and -X options.
+
+ * Git-gui has been updated to its 0.18.0 version.
+
+ * MediaWiki remote helper (in contrib/) has been updated to use the
+   credential helper interface from Git.pm.
+
+ * Update build for Cygwin 1.[57].  Torsten Bögershausen reports that
+   this is fine with Cygwin 1.7 ($gmane/225824) so let's try moving it
+   ahead.
+
+ * The credential helper to talk to keychain on OS X (in contrib/) has
+   been updated to kick in not just when talking http/https but also
+   imap(s) and smtp.
+
+ * Remote transport helper has been updated to report errors and
+   maintain ref hierarchy used to keep track of its own state better.
+
+ * With "export" remote-helper protocol, (1) a push that tries to
+   update a remote ref whose name is different from the pushing side
+   does not work yet, and (2) the helper may not know how to do
+   --dry-run; these problematic cases are disabled for now.
+
+ * git-remote-hg/bzr (in contrib/) updates.
+
+ * git-remote-mw (in contrib/) hints users to check the certificate,
+   when https:// connection failed.
+
+ * git-remote-mw (in contrib/) adds a command to allow previewing the
+   contents locally before pushing it out, when working with a
+   MediaWiki remote.
+
+
+UI, Workflows & Features
+
+ * Sample "post-receive-email" hook script got an enhanced replacement
+   "multimail" (in contrib/).
+
+ * Also in contrib/ is a new "contacts" script that runs "git blame"
+   to find out the people who may be interested in a set of changes.
+
+ * "git clean" command learned an interactive mode.
+
+ * The "--head" option to "git show-ref" was only to add "HEAD" to the
+   list of candidate refs to be filtered by the usual rules
+   (e.g. "--heads" that only show refs under refs/heads).  The meaning
+   of the option has been changed to always show "HEAD" regardless of
+   what filtering will be applied to any other ref.
+
+   This is a backward incompatible change and might cause breakages to
+   people's existing scripts.
+
+ * "git show -s" was less discoverable than it should have been.  It
+   now has a natural synonym "git show --no-patch".
+
+ * "git check-mailmap" is a new command that lets you map usernames
+   and e-mail addresses through the mailmap mechanism, just like many
+   built-in commands do.
+
+ * "git name-rev" learned to name an annotated tag object back to its
+   tagname; "git name-rev $(git rev-parse v1.0.0)" gives "tags/v1.0.0",
+   for example.
+
+ * "git cat-file --batch-check=<format>" is added, primarily to allow
+   on-disk footprint of objects in packfiles (often they are a lot
+   smaller than their true size, when expressed as deltas) to be
+   reported.
+
+ * "git rebase [-i]" used to leave just "rebase" as its reflog messages
+   for some operations. They have been reworded to be more informative.
+
+ * In addition to the choice from "rebase, merge, or checkout-detach",
+   "submodule update" can allow a custom command to be used in to
+   update the working tree of submodules via the "submodule.*.update"
+   configuration variable.
+
+ * "git submodule update" can optionally clone the submodule
+   repositories shallowly.
+
+ * "git format-patch" learned "--from[=whom]" option, which sets the
+   "From: " header to the specified person (or the person who runs the
+   command, if "=whom" part is missing) and move the original author
+   information to an in-body From: header as necessary.
+
+ * The configuration variable "merge.ff" was cleary a tri-state to
+   choose one from "favor fast-forward when possible", "always create
+   a merge even when the history could fast-forward" and "do not
+   create any merge, only update when the history fast-forwards", but
+   the command line parser did not implement the usual convention of
+   "last one wins, and command line overrides the configuration"
+   correctly.
+
+ * "gitweb" learned to optionally place extra links that point at the
+   levels higher than the Gitweb pages themselves in the breadcrumbs,
+   so that it can be used as part of a larger installation.
+
+ * "git log --format=" now honors i18n.logoutputencoding configuration
+   variable.
+
+ * The "push.default=simple" mode of "git push" has been updated to
+   behave like "current" without requiring a remote tracking
+   information, when you push to a remote that is different from where
+   you fetch from (i.e. a triangular workflow).
+
+ * Having multiple "fixup!" on a line in the rebase instruction sheet
+   did not work very well with "git rebase -i --autosquash".
+
+ * "git log" learned the "--author-date-order" option, with which the
+   output is topologically sorted and commits in parallel histories
+   are shown intermixed together based on the author timestamp.
+
+ * Various subcommands of "git submodule" refused to run from anywhere
+   other than the top of the working tree of the superproject, but
+   they have been taught to let you run from a subdirectory.
+
+ * "git diff" learned a mode that ignores hunks whose change consists
+   only of additions and removals of blank lines, which is the same as
+   "diff -B" (ignore blank lines) of GNU diff.
+
+ * "git rm" gives a single message followed by list of paths to report
+   multiple paths that cannot be removed.
+
+ * "git rebase" can be told with ":/look for this string" syntax commits
+   to replay the changes onto and where the work to be replayed begins.
+
+ * Many tutorials teach users to set "color.ui" to "auto" as the first
+   thing after you set "user.name/email" to introduce yourselves to
+   Git.  Now the variable defaults to "auto".
+
+ * On Cygwin, "cygstart" is now recognised as a possible way to start
+   a web browser (used in "help -w" and "instaweb" among others).
+
+ * "git status" learned status.branch and status.short configuration
+   variables to use --branch and --short options by default (override
+   with --no-branch and --no-short options from the command line).
+
+ * "git cmd <name>", when <name> happens to be a 40-hex string,
+   directly uses the 40-hex string as an object name, even if a ref
+   "refs/<some hierarchy>/<name>" exists.  This disambiguation order
+   is unlikely to change, but we should warn about the ambiguity just
+   like we warn when more than one refs/ hierarchies share the same
+   name.
+
+ * "git rebase" learned "--[no-]autostash" option to save local
+   changes instead of refusing to run (to which people's normal
+   response was to stash them and re-run).  This introduced a corner
+   case breakage to "git am --abort" but it has been fixed.
+
+ * "check-ignore" (new feature since 1.8.2) has been updated to work
+   more like "check-attr" over bidi-pipes.
+
+ * "git describe" learned "--first-parent" option to limit its closest
+   tagged commit search to the first-parent chain.
+
+ * "git merge foo" that might have meant "git merge origin/foo" is
+   diagnosed with a more informative error message.
+
+ * "git log -L<line>,<range>:<filename>" has been added.  This may
+   still have leaks and rough edges, though.
+
+ * We used the approxidate() parser for "--expire=<timestamp>" options
+   of various commands, but it is better to treat --expire=all and
+   --expire=now a bit more specially than using the current timestamp.
+   "git gc" and "git reflog" have been updated with a new parsing
+   function for expiry dates.
+
+ * Updates to completion (both bash and zsh) helpers.
+
+ * The behaviour of the "--chain-reply-to" option of "git send-email"
+   have changed at 1.7.0, and we added a warning/advice message to
+   help users adjust to the new behaviour back then, but we kept it
+   around for too long.  The message has finally been removed.
+
+ * "git fetch origin master" unlike "git fetch origin" or "git fetch"
+   did not update "refs/remotes/origin/master"; this was an early
+   design decision to keep the update of remote tracking branches
+   predictable, but in practice it turns out that people find it more
+   convenient to opportunistically update them whenever we have a
+   chance, and we have been updating them when we run "git push" which
+   already breaks the original "predictability" anyway.
+
+ * The configuration variable core.checkstat was advertised in the
+   documentation but the code expected core.statinfo instead.
+   For now, we accept both core.checkstat and core.statinfo, but the
+   latter will be removed in the longer term.
+
+
+Performance, Internal Implementation, etc.
+
+ * On Cygwin, we used to use our own lstat(2) emulation that is
+   allegedly faster than the platform one in codepaths where some of
+   the information it returns did not matter, but it started to bite
+   us in a few codepaths where the trick it uses to cheat does show
+   breakages. This emulation has been removed and we use the native
+   lstat(2) emulation supplied by Cygwin now.
+
+ * The function attributes extensions are used to catch mistakes in
+   use of our own variadic functions that use NULL sentinel at the end
+   (i.e. like execl(3)) and format strings (i.e. like printf(3)).
+
+ * The code to allow configuration data to be read from in-tree blob
+   objects is in.  This may help working in a bare repository and
+   submodule updates.
+
+ * Fetching between repositories with many refs employed O(n^2)
+   algorithm to match up the common objects, which has been corrected.
+
+ * The original way to specify remote repository using .git/branches/
+   used to have a nifty feature.  The code to support the feature was
+   still in a function but the caller was changed not to call it 5
+   years ago, breaking that feature and leaving the supporting code
+   unreachable.  The dead code has been removed.
+
+ * "git pack-refs" that races with new ref creation or deletion have
+   been susceptible to lossage of refs under right conditions, which
+   has been tightened up.
+
+ * We read loose and packed references in two steps, but after
+   deciding to read a loose ref but before actually opening it to read
+   it, another process racing with us can unlink it, which would cause
+   us to barf.  The codepath has been updated to retry when such a
+   race is detected, instead of outright failing.
+
+ * Uses of the platform fnmatch(3) function (many places in the code,
+   matching pathspec, .gitignore and .gitattributes to name a few)
+   have been replaced with wildmatch, allowing "foo/**/bar" that would
+   match foo/bar, foo/a/bar, foo/a/b/bar, etc.
+
+ * Memory ownership and lifetime rules for what for-each-ref feeds to
+   its callbacks have been clarified (in short, "you do not own it, so
+   make a copy if you want to keep it").
+
+ * The revision traversal logic to improve culling of irrelevant
+   parents while traversing a mergy history has been updated.
+
+ * Some leaks in unpack-trees (used in merge, cherry-pick and other
+   codepaths) have been plugged.
+
+ * The codepath to read from marks files in fast-import/export did not
+   have to accept anything but 40-hex representation of the object
+   name.  Further, fast-export did not need full in-core object
+   representation to have parsed wen reading from them.  These
+   codepaths have been optimized by taking advantage of these access
+   patterns.
+
+ * Object lookup logic, when the object hashtable starts to become
+   crowded, has been optimized.
+
+ * When TEST_OUTPUT_DIRECTORY setting is used, it was handled somewhat
+   inconsistently between the test framework and t/Makefile, and logic
+   to summarize the results looked at a wrong place.
+
+ * "git clone" uses a lighter-weight implementation when making sure
+   that the history behind refs are complete.
+
+ * Many warnings from sparse source checker in compat/ area has been
+   squelched.
+
+ * The code to reading and updating packed-refs file has been updated,
+   correcting corner case bugs.
+
+
+Also contains various documentation updates and code clean-ups.
+
+
+Fixes since v1.8.3
+------------------
+
+Unless otherwise noted, all the fixes since v1.8.3 in the maintenance
+track are contained in this release (see release notes to them for
+details).
+
+ * Newer Net::SMTP::SSL module does not want the user programs to use
+   the default behaviour to let server certificate go without
+   verification, so by default enable the verification with a
+   mechanism to turn it off if needed.
+   (merge 35035bb rr/send-email-ssl-verify later to maint).
+
+ * When "git" is spawned in such a way that any of the low 3 file
+   descriptors is closed, our first open() may yield file descriptor 2,
+   and writing error message to it would screw things up in a big way.
+   (merge a11c396 tr/protect-low-3-fds later to maint).
+
+ * The mailmap mechanism unnecessarily downcased the e-mail addresses
+   in the output, and also ignored the human name when it is a single
+   character name.
+   (merge bd23794 jc/mailmap-case-insensitivity later to maint).
+
+ * In two places we did not check return value (expected to be a file
+   descriptor) correctly.
+   (merge a77f106 tr/fd-gotcha-fixes later to maint).
+
+ * Logic to auto-detect character encodings in the commit log message
+   did not reject overlong and invalid UTF-8 characters.
+   (merge 81050ac bc/commit-invalid-utf8 later to maint).
+
+ * Pass port number as a separate argument when "send-email" initializes
+   Net::SMTP, instead of as a part of the hostname, i.e. host:port.
+   This allows GSSAPI codepath to match with the hostname given.
+   (merge 1a741bf bc/send-email-use-port-as-separate-param later to maint).
+
+ * "git diff" refused to even show difference when core.safecrlf is
+   set to true (i.e. error out) and there are offending lines in the
+   working tree files.
+   (merge 5430bb2 jc/maint-diff-core-safecrlf later to maint).
+
+ * A test that should have failed but didn't revealed a bug that needs
+   to be corrected.
+   (merge 94d75d1 jc/t1512-fix later to maint).
+
+ * An overlong path to a .git directory may have overflown the
+   temporary path buffer used to create a name for lockfiles.
+   (merge 2fbd4f9 mh/maint-lockfile-overflow later to maint).
+
+ * Invocations of "git checkout" used internally by "git rebase" were
+   counted as "checkout", and affected later "git checkout -" to the
+   the user to an unexpected place.
+   (merge 3bed291 rr/rebase-checkout-reflog later to maint).
+
+ * The configuration variable column.ui was poorly documented.
+   (merge 5e62cc1 rr/column-doc later to maint).
+
+ * "git name-rev --refs=tags/v*" were forbidden, which was a bit
+   inconvenient (you had to give a pattern to match refs fully, like
+   --refs=refs/tags/v*).
+   (merge 98c5c4a nk/name-rev-abbreviated-refs later to maint).
+
+ * "git apply" parsed patches that add new files, generated by
+   programs other than Git, incorrectly.  This is an old breakage in
+   v1.7.11 and will need to be merged down to the maintenance tracks.
+
+ * Older cURL wanted piece of memory we call it with to be stable, but
+   we updated the auth material after handing it to a call.
+
+ * "git pull" into nothing trashed "local changes" that were in the
+   index, and this avoids it.
+
+ * Many "git submodule" operations do not work on a submodule at a
+   path whose name is not in ASCII.
+
+ * "cherry-pick" had a small leak in an error codepath.
+
+ * Logic used by git-send-email to suppress cc mishandled names like
+   "A U. Thor" <author@example.xz>, where the human readable part
+   needs to be quoted (the user input may not have the double quotes
+   around the name, and comparison was done between quoted and
+   unquoted strings).  It also mishandled names that need RFC2047
+   quoting.
+
+ * Call to discard_cache/discard_index (used when we use different
+   contents of the index in-core, in many operations like commit,
+   apply, and merge) used to leak memory that held the array of index
+   entries, which has been plugged.
+   (merge a0fc4db rs/discard-index-discard-array later to maint).
+
+ * "gitweb" forgot to clear a global variable $search_regexp upon each
+   request, mistakenly carrying over the previous search to a new one
+   when used as a persistent CGI.
+
+ * The wildmatch engine did not honor WM_CASEFOLD option correctly.
+
+ * "git log -c --follow $path" segfaulted upon hitting the commit that
+   renamed the $path being followed.
+
+ * When a reflog notation is used for implicit "current branch", we
+   did not say which branch and worse said "branch ''".
+
+ * "difftool --dir-diff" did not copy back changes made by the
+   end-user in the diff tool backend to the working tree in some
+   cases.
+
+ * "git push $there HEAD:branch" did not resolve HEAD early enough, so
+   it was easy to flip it around while push is still going on and push
+   out a branch that the user did not originally intended when the
+   command was started.
+
+ * The bash prompt code (in contrib/) displayed the name of the branch
+   being rebased when "rebase -i/-m/-p" modes are in use, but not the
+   plain vanilla "rebase".
+
+ * Handling of negative exclude pattern for directories "!dir" was
+   broken in the update to v1.8.3.
+
+ * zsh prompt script that borrowed from bash prompt script did not
+   work due to slight differences in array variable notation between
+   these two shells.
+
+ * An entry for "file://" scheme in the enumeration of URL types Git
+   can take in the HTML documentation was made into a clickable link
+   by mistake.
+
+ * "git push --[no-]verify" was not documented.
+
+ * Stop installing the git-remote-testpy script that is only used for
+   testing.
+
+ * "git commit --allow-empty-message -m ''" should not start an
+   editor.
+
+ * "git merge @{-1}~22" was rewritten to "git merge frotz@{1}~22"
+   incorrectly when your previous branch was "frotz" (it should be
+   rewritten to "git merge frotz~22" instead).
+
+ * "git diff -c -p" was not showing a deleted line from a hunk when
+   another hunk immediately begins where the earlier one ends.
+
+ * "git log --ancestry-path A...B" did not work as expected, as it did
+   not pay attention to the fact that the merge base between A and B
+   was the bottom of the range being specified.
+
+ * Mac OS X does not like to write(2) more than INT_MAX number of
+   bytes; work it around by chopping write(2) into smaller pieces.
+
+ * Newer MacOS X encourages the programs to compile and link with
+   their CommonCrypto, not with OpenSSL.
+
+ * "git clone foo/bar:baz" cannot be a request to clone from a remote
+   over git-over-ssh specified in the scp style.  This case is now
+   detected and clones from a local repository at "foo/bar:baz".
+
+ * When $HOME is misconfigured to point at an unreadable directory, we
+   used to complain and die. Loosen the check.
+
+ * "git subtree" (in contrib/) had one codepath with loose error
+   checks to lose data at the remote side.
+
+ * "git fetch" into a shallow repository from a repository that does
+   not know about the shallow boundary commits (e.g. a different fork
+   from the repository the current shallow repository was cloned from)
+   did not work correctly.
+
+ * "git checkout foo" DWIMs the intended "upstream" and turns it into
+   "git checkout -t -b foo remotes/origin/foo". This codepath has been
+   updated to correctly take existing remote definitions into account.
diff --git a/Documentation/blame-options.txt b/Documentation/blame-options.txt
index b0d31df..4e55b15 100644
--- a/Documentation/blame-options.txt
+++ b/Documentation/blame-options.txt
@@ -10,27 +10,14 @@
 	Include additional statistics at the end of blame output.
 
 -L <start>,<end>::
-	Annotate only the given line range.  <start> and <end> can take
-	one of these forms:
+-L :<regex>::
+	Annotate only the given line range.  <start> and <end> are optional.
+	``-L <start>'' or ``-L <start>,'' spans from <start> to end of file.
+	``-L ,<end>'' spans from start of file to <end>.
++
+<start> and <end> can take one of these forms:
 
-	- number
-+
-If <start> or <end> is a number, it specifies an
-absolute line number (lines count from 1).
-+
-
-- /regex/
-+
-This form will use the first line matching the given
-POSIX regex.  If <end> is a regex, it will search
-starting at the line given by <start>.
-+
-
-- +offset or -offset
-+
-This is only valid for <end> and will specify a number
-of lines before or after the line given by <start>.
-+
+include::line-range-format.txt[]
 
 -l::
 	Show long rev (Default: off).
diff --git a/Documentation/config.txt b/Documentation/config.txt
index 6e53fc5..ec57a15 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -199,6 +199,9 @@
 	amWorkDir::
 		Advice that shows the location of the patch file when
 		linkgit:git-am[1] fails to apply it.
+	rmHints::
+		In case of failure in the output of linkgit:git-rm[1],
+		show directions on how to proceed from the current state.
 --
 
 core.fileMode::
@@ -210,17 +213,6 @@
 will probe and set core.fileMode false if appropriate when the
 repository is created.
 
-core.ignoreCygwinFSTricks::
-	This option is only used by Cygwin implementation of Git. If false,
-	the Cygwin stat() and lstat() functions are used. This may be useful
-	if your repository consists of a few separate directories joined in
-	one hierarchy using Cygwin mount. If true, Git uses native Win32 API
-	whenever it is possible and falls back to Cygwin functions only to
-	handle symbol links. The native mode is more than twice faster than
-	normal Cygwin l/stat() functions. True by default, unless core.filemode
-	is true, in which case ignoreCygwinFSTricks is ignored as Cygwin's
-	POSIX emulation is required to support core.filemode.
-
 core.ignorecase::
 	If true, this option enables various workarounds to enable
 	Git to work better on filesystems that are not case sensitive,
@@ -876,16 +868,17 @@
 
 color.interactive::
 	When set to `always`, always use colors for interactive prompts
-	and displays (such as those used by "git-add --interactive").
-	When false (or `never`), never.  When set to `true` or `auto`, use
-	colors only when the output is to the terminal. Defaults to false.
+	and displays (such as those used by "git-add --interactive" and
+	"git-clean --interactive"). When false (or `never`), never.
+	When set to `true` or `auto`, use colors only when the output is
+	to the terminal. Defaults to false.
 
 color.interactive.<slot>::
-	Use customized color for 'git add --interactive'
-	output. `<slot>` may be `prompt`, `header`, `help` or `error`, for
-	four distinct types of normal output from interactive
-	commands.  The values of these variables may be specified as
-	in color.branch.<slot>.
+	Use customized color for 'git add --interactive' and 'git clean
+	--interactive' output. `<slot>` may be `prompt`, `header`, `help`
+	or `error`, for four distinct types of normal output from
+	interactive commands.  The values of these variables may be
+	specified as in color.branch.<slot>.
 
 color.pager::
 	A boolean to enable/disable colored output when the pager is in
@@ -919,17 +912,21 @@
 	as `color.diff` and `color.grep` that control the use of color
 	per command family. Its scope will expand as more commands learn
 	configuration to set a default for the `--color` option.  Set it
-	to `always` if you want all output not intended for machine
-	consumption to use color, to `true` or `auto` if you want such
-	output to use color when written to the terminal, or to `false` or
-	`never` if you prefer Git commands not to use color unless enabled
-	explicitly with some other configuration or the `--color` option.
+	to `false` or `never` if you prefer Git commands not to use
+	color unless enabled explicitly with some other configuration
+	or the `--color` option. Set it to `always` if you want all
+	output not intended for machine consumption to use color, to
+	`true` or `auto` (this is the default since Git 1.8.4) if you
+	want such output to use color when written to the terminal.
 
 column.ui::
 	Specify whether supported commands should output in columns.
 	This variable consists of a list of tokens separated by spaces
 	or commas:
 +
+These options control when the feature should be enabled
+(defaults to 'never'):
++
 --
 `always`;;
 	always show in columns
@@ -937,24 +934,39 @@
 	never show in columns
 `auto`;;
 	show in columns if the output is to the terminal
+--
++
+These options control layout (defaults to 'column').  Setting any
+of these implies 'always' if none of 'always', 'never', or 'auto' are
+specified.
++
+--
 `column`;;
-	fill columns before rows (default)
+	fill columns before rows
 `row`;;
 	fill rows before columns
 `plain`;;
 	show in one column
+--
++
+Finally, these options can be combined with a layout option (defaults
+to 'nodense'):
++
+--
 `dense`;;
 	make unequal size columns to utilize more space
 `nodense`;;
 	make equal size columns
 --
-+
-This option defaults to 'never'.
 
 column.branch::
 	Specify whether to output branch listing in `git branch` in columns.
 	See `column.ui` for details.
 
+column.clean::
+	Specify the layout when list items in `git clean -i`, which always
+	shows files and directories in columns. See `column.ui` for details.
+
 column.status::
 	Specify whether to output untracked files in `git status` in columns.
 	See `column.ui` for details.
@@ -1826,39 +1838,59 @@
 	The default merge strategy to use when pulling a single branch.
 
 push.default::
-	Defines the action `git push` should take if no refspec is given
-	on the command line, no refspec is configured in the remote, and
-	no refspec is implied by any of the options given on the command
-	line. Possible values are:
+	Defines the action `git push` should take if no refspec is
+	explicitly given.  Different values are well-suited for
+	specific workflows; for instance, in a purely central workflow
+	(i.e. the fetch source is equal to the push destination),
+	`upstream` is probably what you want.  Possible values are:
 +
 --
-* `nothing` - do not push anything.
-* `matching` - push all branches having the same name in both ends.
-  This is for those who prepare all the branches into a publishable
-  shape and then push them out with a single command.  It is not
-  appropriate for pushing into a repository shared by multiple users,
-  since locally stalled branches will attempt a non-fast forward push
-  if other users updated the branch.
-  +
-  This is currently the default, but Git 2.0 will change the default
-  to `simple`.
-* `upstream` - push the current branch to its upstream branch
-  (`tracking` is a deprecated synonym for this).
-  With this, `git push` will update the same remote ref as the one which
-  is merged by `git pull`, making `push` and `pull` symmetrical.
-  See "branch.<name>.merge" for how to configure the upstream branch.
-* `simple` - like `upstream`, but refuses to push if the upstream
-  branch's name is different from the local one. This is the safest
-  option and is well-suited for beginners. It will become the default
-  in Git 2.0.
-* `current` - push the current branch to a branch of the same name.
---
+
+* `nothing` - do not push anything (error out) unless a refspec is
+  explicitly given. This is primarily meant for people who want to
+  avoid mistakes by always being explicit.
+
+* `current` - push the current branch to update a branch with the same
+  name on the receiving end.  Works in both central and non-central
+  workflows.
+
+* `upstream` - push the current branch back to the branch whose
+  changes are usually integrated into the current branch (which is
+  called `@{upstream}`).  This mode only makes sense if you are
+  pushing to the same repository you would normally pull from
+  (i.e. central workflow).
+
+* `simple` - in centralized workflow, work like `upstream` with an
+  added safety to refuse to push if the upstream branch's name is
+  different from the local one.
 +
-The `simple`, `current` and `upstream` modes are for those who want to
-push out a single branch after finishing work, even when the other
-branches are not yet ready to be pushed out. If you are working with
-other people to push into the same shared repository, you would want
-to use one of these.
+When pushing to a remote that is different from the remote you normally
+pull from, work as `current`.  This is the safest option and is suited
+for beginners.
++
+This mode will become the default in Git 2.0.
+
+* `matching` - push all branches having the same name on both ends.
+  This makes the repository you are pushing to remember the set of
+  branches that will be pushed out (e.g. if you always push 'maint'
+  and 'master' there and no other branches, the repository you push
+  to will have these two branches, and your local 'maint' and
+  'master' will be pushed there).
++
+To use this mode effectively, you have to make sure _all_ the
+branches you would push out are ready to be pushed out before
+running 'git push', as the whole point of this mode is to allow you
+to push all of the branches in one go.  If you usually finish work
+on only one branch and push out the result, while other branches are
+unfinished, this mode is not for you.  Also this mode is not
+suitable for pushing into a shared central repository, as other
+people may add new branches there, or update the tip of existing
+branches outside your control.
++
+This is currently the default, but Git 2.0 will change the default
+to `simple`.
+
+--
 
 rebase.stat::
 	Whether to show a diffstat of what changed upstream since the last
@@ -1867,6 +1899,14 @@
 rebase.autosquash::
 	If set to true enable '--autosquash' option by default.
 
+rebase.autostash::
+	When set to true, automatically create a temporary stash
+	before the operation begins, and apply it after the operation
+	ends.  This means that you can run rebase on a dirty worktree.
+	However, use with care: the final stash application after a
+	successful rebase might result in non-trivial conflicts.
+	Defaults to false.
+
 receive.autogc::
 	By default, git-receive-pack will run "git-gc --auto" after
 	receiving data from git-push and updating refs.  You can stop
@@ -2022,6 +2062,10 @@
 sendemail.smtpssl::
 	Deprecated alias for 'sendemail.smtpencryption = ssl'.
 
+sendemail.smtpsslcertpath::
+	Path to ca-certificates (either a directory or a single file).
+	Set it to an empty string to disable certificate verification.
+
 sendemail.<identity>.*::
 	Identity-specific versions of the 'sendemail.*' parameters
 	found below, taking precedence over those when the this
@@ -2066,6 +2110,14 @@
 	relative to the repository root (this was the default for Git
 	prior to v1.5.4).
 
+status.short::
+	Set to true to enable --short by default in linkgit:git-status[1].
+	The option --no-short takes precedence over this variable.
+
+status.branch::
+	Set to true to enable --branch by default in linkgit:git-status[1].
+	The option --no-branch takes precedence over this variable.
+
 status.showUntrackedFiles::
 	By default, linkgit:git-status[1] and linkgit:git-commit[1] show
 	files which are not currently tracked by Git. Directories which
diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt
index 104579d..bbed2cd 100644
--- a/Documentation/diff-options.txt
+++ b/Documentation/diff-options.txt
@@ -26,6 +26,11 @@
 	{git-diff? This is the default.}
 endif::git-format-patch[]
 
+-s::
+--no-patch::
+	Suppress diff output. Useful for commands like `git show` that
+	show the patch by default, or to cancel the effect of `--patch`.
+
 -U<n>::
 --unified=<n>::
 	Generate diffs with <n> lines of context instead of
@@ -333,7 +338,7 @@
 	a fraction, with a decimal point before it.  I.e., `-M5` becomes
 	0.5, and is thus the same as `-M50%`.  Similarly, `-M05` is
 	the same as `-M5%`.  To limit detection to exact renames, use
-	`-M100%`.
+	`-M100%`.  The default similarity index is 50%.
 
 -C[<n>]::
 --find-copies[=<n>]::
@@ -383,14 +388,36 @@
 	that matches other criteria, nothing is selected.
 
 -S<string>::
-	Look for differences that introduce or remove an instance of
-	<string>. Note that this is different than the string simply
-	appearing in diff output; see the 'pickaxe' entry in
-	linkgit:gitdiffcore[7] for more details.
+	Look for differences that change the number of occurrences of
+	the specified string (i.e. addition/deletion) in a file.
+	Intended for the scripter's use.
++
+It is useful when you're looking for an exact block of code (like a
+struct), and want to know the history of that block since it first
+came into being: use the feature iteratively to feed the interesting
+block in the preimage back into `-S`, and keep going until you get the
+very first version of the block.
 
 -G<regex>::
-	Look for differences whose added or removed line matches
-	the given <regex>.
+	Look for differences whose patch text contains added/removed
+	lines that match <regex>.
++
+To illustrate the difference between `-S<regex> --pickaxe-regex` and
+`-G<regex>`, consider a commit with the following diff in the same
+file:
++
+----
++    return !regexec(regexp, two->ptr, 1, &regmatch, 0);
+...
+-    hit = !regexec(regexp, mf2.ptr, 1, &regmatch, 0);
+----
++
+While `git log -G"regexec\(regexp"` will show this commit, `git log
+-S"regexec\(regexp" --pickaxe-regex` will not (because the number of
+occurrences of that string did not change).
++
+See the 'pickaxe' entry in linkgit:gitdiffcore[7] for more
+information.
 
 --pickaxe-all::
 	When `-S` or `-G` finds a change, show all the changes in that
@@ -398,8 +425,8 @@
 	in <string>.
 
 --pickaxe-regex::
-	Make the <string> not a plain string but an extended POSIX
-	regex to match.
+	Treat the <string> given to `-S` as an extended POSIX regular
+	expression to match.
 endif::git-format-patch[]
 
 -O<orderfile>::
@@ -439,6 +466,9 @@
 	differences even if one line has whitespace where the other
 	line has none.
 
+--ignore-blank-lines::
+	Ignore changes whose lines are all blank.
+
 --inter-hunk-context=<lines>::
 	Show the context between diff hunks, up to the specified number
 	of lines, thereby fusing hunks that are close to each other.
@@ -480,7 +510,7 @@
 
 --ignore-submodules[=<when>]::
 	Ignore changes to submodules in the diff generation. <when> can be
-	either "none", "untracked", "dirty" or "all", which is the default
+	either "none", "untracked", "dirty" or "all", which is the default.
 	Using "none" will consider the submodule modified when it either contains
 	untracked or modified files or its HEAD differs from the commit recorded
 	in the superproject and can be used to override any settings of the
diff --git a/Documentation/fetch-options.txt b/Documentation/fetch-options.txt
index 9cb6496..ba1fe49 100644
--- a/Documentation/fetch-options.txt
+++ b/Documentation/fetch-options.txt
@@ -61,7 +61,7 @@
 ifndef::git-pull[]
 -t::
 --tags::
-	This is a short-hand for giving "refs/tags/*:refs/tags/*"
+	This is a short-hand for giving `refs/tags/*:refs/tags/*`
 	refspec from the command line, to ask all tags to be fetched
 	and stored locally.  Because this acts as an explicit
 	refspec, the default refspecs (configured with the
diff --git a/Documentation/git-am.txt b/Documentation/git-am.txt
index 19d57a8..54d8461 100644
--- a/Documentation/git-am.txt
+++ b/Documentation/git-am.txt
@@ -9,12 +9,12 @@
 SYNOPSIS
 --------
 [verse]
-'git am' [--signoff] [--keep] [--keep-cr | --no-keep-cr] [--utf8 | --no-utf8]
+'git am' [--signoff] [--keep] [--[no-]keep-cr] [--[no-]utf8]
 	 [--3way] [--interactive] [--committer-date-is-author-date]
 	 [--ignore-date] [--ignore-space-change | --ignore-whitespace]
 	 [--whitespace=<option>] [-C<n>] [-p<n>] [--directory=<dir>]
 	 [--exclude=<path>] [--include=<path>] [--reject] [-q | --quiet]
-	 [--scissors | --no-scissors]
+	 [--[no-]scissors]
 	 [(<mbox> | <Maildir>)...]
 'git am' (--continue | --skip | --abort)
 
@@ -43,8 +43,7 @@
 --keep-non-patch::
 	Pass `-b` flag to 'git mailinfo' (see linkgit:git-mailinfo[1]).
 
---keep-cr::
---no-keep-cr::
+--[no-]keep-cr::
 	With `--keep-cr`, call 'git mailsplit' (see linkgit:git-mailsplit[1])
 	with the same option, to prevent it from stripping CR at the end of
 	lines. `am.keepcr` configuration variable can be used to specify the
@@ -133,7 +132,7 @@
 --resolvemsg=<msg>::
 	When a patch failure occurs, <msg> will be printed
 	to the screen before exiting.  This overrides the
-	standard message informing you to use `--resolved`
+	standard message informing you to use `--continue`
 	or `--skip` to handle the failure.  This is solely
 	for internal use between 'git rebase' and 'git am'.
 
@@ -177,7 +176,7 @@
 
 . hand resolve the conflict in the working directory, and update
   the index file to bring it into a state that the patch should
-  have produced.  Then run the command with the '--resolved' option.
+  have produced.  Then run the command with the '--continue' option.
 
 The command refuses to process new mailboxes until the current
 operation is finished, so if you decide to start over from scratch,
diff --git a/Documentation/git-archive.txt b/Documentation/git-archive.txt
index 250e522..b97aaab 100644
--- a/Documentation/git-archive.txt
+++ b/Documentation/git-archive.txt
@@ -10,7 +10,7 @@
 --------
 [verse]
 'git archive' [--format=<fmt>] [--list] [--prefix=<prefix>/] [<extra>]
-	      [-o | --output=<file>] [--worktree-attributes]
+	      [-o <file> | --output=<file>] [--worktree-attributes]
 	      [--remote=<repo> [--exec=<git-upload-archive>]] <tree-ish>
 	      [<path>...]
 
diff --git a/Documentation/git-bisect-lk2009.txt b/Documentation/git-bisect-lk2009.txt
index 0eed3e3..afeb86c 100644
--- a/Documentation/git-bisect-lk2009.txt
+++ b/Documentation/git-bisect-lk2009.txt
@@ -1320,7 +1320,7 @@
 ;-)
 _____________
 
-Acknowledgements
+Acknowledgments
 ----------------
 
 Many thanks to Junio Hamano for his help in reviewing this paper, for
diff --git a/Documentation/git-blame.txt b/Documentation/git-blame.txt
index 9a05c2b..6cea7f1 100644
--- a/Documentation/git-blame.txt
+++ b/Documentation/git-blame.txt
@@ -8,9 +8,9 @@
 SYNOPSIS
 --------
 [verse]
-'git blame' [-c] [-b] [-l] [--root] [-t] [-f] [-n] [-s] [-e] [-p] [-w] [--incremental] [-L n,m]
-	    [-S <revs-file>] [-M] [-C] [-C] [-C] [--since=<date>] [--abbrev=<n>]
-	    [<rev> | --contents <file> | --reverse <rev>] [--] <file>
+'git blame' [-c] [-b] [-l] [--root] [-t] [-f] [-n] [-s] [-e] [-p] [-w] [--incremental]
+	    [-L n,m | -L :fn] [-S <revs-file>] [-M] [-C] [-C] [-C] [--since=<date>]
+	    [--abbrev=<n>] [<rev> | --contents <file> | --reverse <rev>] [--] <file>
 
 DESCRIPTION
 -----------
diff --git a/Documentation/git-cat-file.txt b/Documentation/git-cat-file.txt
index 30d585a..10fbc6a 100644
--- a/Documentation/git-cat-file.txt
+++ b/Documentation/git-cat-file.txt
@@ -58,12 +58,16 @@
 	to apply the filter to the content recorded in the index at <path>.
 
 --batch::
-	Print the SHA-1, type, size, and contents of each object provided on
-	stdin. May not be combined with any other options or arguments.
+--batch=<format>::
+	Print object information and contents for each object provided
+	on stdin.  May not be combined with any other options or arguments.
+	See the section `BATCH OUTPUT` below for details.
 
 --batch-check::
-	Print the SHA-1, type, and size of each object provided on stdin. May not
-	be combined with any other options or arguments.
+--batch-check=<format>::
+	Print object information for each object provided on stdin.  May
+	not be combined with any other options or arguments.  See the
+	section `BATCH OUTPUT` below for details.
 
 OUTPUT
 ------
@@ -78,28 +82,75 @@
 If <type> is specified, the raw (though uncompressed) contents of the <object>
 will be returned.
 
-If '--batch' is specified, output of the following form is printed for each
-object specified on stdin:
+BATCH OUTPUT
+------------
+
+If `--batch` or `--batch-check` is given, `cat-file` will read objects
+from stdin, one per line, and print information about them.
+
+Each line is considered as a whole object name, and is parsed as if
+given to linkgit:git-rev-parse[1].
+
+You can specify the information shown for each object by using a custom
+`<format>`. The `<format>` is copied literally to stdout for each
+object, with placeholders of the form `%(atom)` expanded, followed by a
+newline. The available atoms are:
+
+`objectname`::
+	The 40-hex object name of the object.
+
+`objecttype`::
+	The type of of the object (the same as `cat-file -t` reports).
+
+`objectsize`::
+	The size, in bytes, of the object (the same as `cat-file -s`
+	reports).
+
+`objectsize:disk`::
+	The size, in bytes, that the object takes up on disk. See the
+	note about on-disk sizes in the `CAVEATS` section below.
+
+If no format is specified, the default format is `%(objectname)
+%(objecttype) %(objectsize)`.
+
+If `--batch` is specified, the object information is followed by the
+object contents (consisting of `%(objectsize)` bytes), followed by a
+newline.
+
+For example, `--batch` without a custom format would produce:
 
 ------------
 <sha1> SP <type> SP <size> LF
 <contents> LF
 ------------
 
-If '--batch-check' is specified, output of the following form is printed for
-each object specified on stdin:
+Whereas `--batch-check='%(objectname) %(objecttype)'` would produce:
 
 ------------
-<sha1> SP <type> SP <size> LF
+<sha1> SP <type> LF
 ------------
 
-For both '--batch' and '--batch-check', output of the following form is printed
-for each object specified on stdin that does not exist in the repository:
+If a name is specified on stdin that cannot be resolved to an object in
+the repository, then `cat-file` will ignore any custom format and print:
 
 ------------
 <object> SP missing LF
 ------------
 
+
+CAVEATS
+-------
+
+Note that the sizes of objects on disk are reported accurately, but care
+should be taken in drawing conclusions about which refs or objects are
+responsible for disk usage. The size of a packed non-delta object may be
+much larger than the size of objects which delta against it, but the
+choice of which object is the base and which is the delta is arbitrary
+and is subject to change during a repack. Note also that multiple copies
+of an object may be present in the object database; in this case, it is
+undefined which copy's size will be reported.
+
+
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-check-attr.txt b/Documentation/git-check-attr.txt
index 5abdbaa..a7be80d 100644
--- a/Documentation/git-check-attr.txt
+++ b/Documentation/git-check-attr.txt
@@ -56,6 +56,11 @@
 'set';;		when the attribute is defined as true.
 <value>;;	when a value has been assigned to the attribute.
 
+Buffering happens as documented under the `GIT_FLUSH` option in
+linkgit:git[1].  The caller is responsible for avoiding deadlocks
+caused by overfilling an input buffer or reading from an empty output
+buffer.
+
 EXAMPLES
 --------
 
diff --git a/Documentation/git-check-ignore.txt b/Documentation/git-check-ignore.txt
index 854e4d0..d2df487 100644
--- a/Documentation/git-check-ignore.txt
+++ b/Documentation/git-check-ignore.txt
@@ -39,6 +39,12 @@
 	below).  If `--stdin` is also given, input paths are separated
 	with a NUL character instead of a linefeed character.
 
+-n, --non-matching::
+	Show given paths which don't match any pattern.	 This only
+	makes sense when `--verbose` is enabled, otherwise it would
+	not be possible to distinguish between paths which match a
+	pattern and those which don't.
+
 OUTPUT
 ------
 
@@ -65,6 +71,20 @@
 
 <source> <NULL> <linenum> <NULL> <pattern> <NULL> <pathname> <NULL>
 
+If `-n` or `--non-matching` are specified, non-matching pathnames will
+also be output, in which case all fields in each output record except
+for <pathname> will be empty.  This can be useful when running
+non-interactively, so that files can be incrementally streamed to
+STDIN of a long-running check-ignore process, and for each of these
+files, STDOUT will indicate whether that file matched a pattern or
+not.  (Without this option, it would be impossible to tell whether the
+absence of output for a given file meant that it didn't match any
+pattern, or that the output hadn't been generated yet.)
+
+Buffering happens as documented under the `GIT_FLUSH` option in
+linkgit:git[1].  The caller is responsible for avoiding deadlocks
+caused by overfilling an input buffer or reading from an empty output
+buffer.
 
 EXIT STATUS
 -----------
@@ -82,7 +102,7 @@
 --------
 linkgit:gitignore[5]
 linkgit:gitconfig[5]
-linkgit:git-ls-files[5]
+linkgit:git-ls-files[1]
 
 GIT
 ---
diff --git a/Documentation/git-check-mailmap.txt b/Documentation/git-check-mailmap.txt
new file mode 100644
index 0000000..39028ee
--- /dev/null
+++ b/Documentation/git-check-mailmap.txt
@@ -0,0 +1,47 @@
+git-check-mailmap(1)
+====================
+
+NAME
+----
+git-check-mailmap - Show canonical names and email addresses of contacts
+
+
+SYNOPSIS
+--------
+[verse]
+'git check-mailmap' [options] <contact>...
+
+
+DESCRIPTION
+-----------
+
+For each ``Name $$<user@host>$$'' or ``$$<user@host>$$'' from the command-line
+or standard input (when using `--stdin`), look up the person's canonical name
+and email address (see "Mapping Authors" below). If found, print them;
+otherwise print the input as-is.
+
+
+OPTIONS
+-------
+--stdin::
+	Read contacts, one per line, from the standard input after exhausting
+	contacts provided on the command-line.
+
+
+OUTPUT
+------
+
+For each contact, a single line is output, terminated by a newline.  If the
+name is provided or known to the 'mailmap', ``Name $$<user@host>$$'' is
+printed; otherwise only ``$$<user@host>$$'' is printed.
+
+
+MAPPING AUTHORS
+---------------
+
+include::mailmap.txt[]
+
+
+GIT
+---
+Part of the linkgit:git[1] suite
diff --git a/Documentation/git-check-ref-format.txt b/Documentation/git-check-ref-format.txt
index ec1739a..a49be1b 100644
--- a/Documentation/git-check-ref-format.txt
+++ b/Documentation/git-check-ref-format.txt
@@ -83,8 +83,7 @@
 
 OPTIONS
 -------
---allow-onelevel::
---no-allow-onelevel::
+--[no-]allow-onelevel::
 	Controls whether one-level refnames are accepted (i.e.,
 	refnames that do not contain multiple `/`-separated
 	components).  The default is `--no-allow-onelevel`.
diff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt
index 23a9413..ca118ac 100644
--- a/Documentation/git-checkout.txt
+++ b/Documentation/git-checkout.txt
@@ -131,9 +131,9 @@
 	"--track" in linkgit:git-branch[1] for details.
 +
 If no '-b' option is given, the name of the new branch will be
-derived from the remote-tracking branch.  If "remotes/" or "refs/remotes/"
-is prefixed it is stripped away, and then the part up to the
-next slash (which would be the nickname of the remote) is removed.
+derived from the remote-tracking branch, by looking at the local part of
+the refspec configured for the corresponding remote, and then stripping
+the initial part up to the "*".
 This would tell us to use "hack" as the local branch when branching
 off of "origin/hack" (or "remotes/origin/hack", or even
 "refs/remotes/origin/hack").  If the given name has no slash, or the above
diff --git a/Documentation/git-clean.txt b/Documentation/git-clean.txt
index bdc3ab8..8997922 100644
--- a/Documentation/git-clean.txt
+++ b/Documentation/git-clean.txt
@@ -8,7 +8,7 @@
 SYNOPSIS
 --------
 [verse]
-'git clean' [-d] [-f] [-n] [-q] [-e <pattern>] [-x | -X] [--] <path>...
+'git clean' [-d] [-f] [-i] [-n] [-q] [-e <pattern>] [-x | -X] [--] <path>...
 
 DESCRIPTION
 -----------
@@ -34,7 +34,13 @@
 -f::
 --force::
 	If the Git configuration variable clean.requireForce is not set
-	to false, 'git clean' will refuse to run unless given -f or -n.
+	to false, 'git clean' will refuse to run unless given -f, -n or
+	-i.
+
+-i::
+--interactive::
+	Show what would be done and clean files interactively. See
+	``Interactive mode'' for details.
 
 -n::
 --dry-run::
@@ -63,6 +69,67 @@
 	Remove only files ignored by Git.  This may be useful to rebuild
 	everything from scratch, but keep manually created files.
 
+Interactive mode
+----------------
+When the command enters the interactive mode, it shows the
+files and directories to be cleaned, and goes into its
+interactive command loop.
+
+The command loop shows the list of subcommands available, and
+gives a prompt "What now> ".  In general, when the prompt ends
+with a single '>', you can pick only one of the choices given
+and type return, like this:
+
+------------
+    *** Commands ***
+	1: clean                2: filter by pattern    3: select by numbers
+	4: ask each             5: quit                 6: help
+    What now> 1
+------------
+
+You also could say `c` or `clean` above as long as the choice is unique.
+
+The main command loop has 6 subcommands.
+
+clean::
+
+   Start cleaning files and directories, and then quit.
+
+filter by pattern::
+
+   This shows the files and directories to be deleted and issues an
+   "Input ignore patterns>>" prompt. You can input space-seperated
+   patterns to exclude files and directories from deletion.
+   E.g. "*.c *.h" will excludes files end with ".c" and ".h" from
+   deletion. When you are satisfied with the filtered result, press
+   ENTER (empty) back to the main menu.
+
+select by numbers::
+
+   This shows the files and directories to be deleted and issues an
+   "Select items to delete>>" prompt. When the prompt ends with double
+   '>>' like this, you can make more than one selection, concatenated
+   with whitespace or comma.  Also you can say ranges.  E.g. "2-5 7,9"
+   to choose 2,3,4,5,7,9 from the list.  If the second number in a
+   range is omitted, all remaining items are selected.  E.g. "7-" to
+   choose 7,8,9 from the list.  You can say '*' to choose everything.
+   Also when you are satisfied with the filtered result, press ENTER
+   (empty) back to the main menu.
+
+ask each::
+
+  This will start to clean, and you must confirm one by one in order
+  to delete items. Please note that this action is not as efficient
+  as the above two actions.
+
+quit::
+
+  This lets you quit without do cleaning.
+
+help::
+
+  Show brief usage of interactive git-clean.
+
 SEE ALSO
 --------
 linkgit:gitignore[5]
diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt
index 5c16e31..450f158 100644
--- a/Documentation/git-clone.txt
+++ b/Documentation/git-clone.txt
@@ -14,7 +14,7 @@
 	  [-o <name>] [-b <name>] [-u <upload-pack>] [--reference <repository>]
 	  [--separate-git-dir <git dir>]
 	  [--depth <depth>] [--[no-]single-branch]
-	  [--recursive|--recurse-submodules] [--] <repository>
+	  [--recursive | --recurse-submodules] [--] <repository>
 	  [<directory>]
 
 DESCRIPTION
@@ -188,7 +188,7 @@
 	with a long history, and would want to send in fixes
 	as patches.
 
---single-branch::
+--[no-]single-branch::
 	Clone only the history leading to the tip of a single branch,
 	either specified by the `--branch` option or the primary
 	branch remote's `HEAD` points at. When creating a shallow
@@ -239,8 +239,8 @@
 * Clone from upstream:
 +
 ------------
-$ git clone git://git.kernel.org/pub/scm/.../linux-2.6 my2.6
-$ cd my2.6
+$ git clone git://git.kernel.org/pub/scm/.../linux.git my-linux
+$ cd my-linux
 $ make
 ------------
 
@@ -257,10 +257,10 @@
 * Clone from upstream while borrowing from an existing local directory:
 +
 ------------
-$ git clone --reference my2.6 \
-	git://git.kernel.org/pub/scm/.../linux-2.7 \
-	my2.7
-$ cd my2.7
+$ git clone --reference /git/linux.git \
+	git://git.kernel.org/pub/scm/.../linux.git \
+	my-linux
+$ cd my-linux
 ------------
 
 
@@ -271,13 +271,6 @@
 ------------
 
 
-* Create a repository on the kernel.org machine that borrows from Linus:
-+
-------------
-$ git clone --bare -l -s /pub/scm/.../torvalds/linux-2.6.git \
-    /pub/scm/.../me/subsys-2.6.git
-------------
-
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt
index 8172938..1a7616c 100644
--- a/Documentation/git-commit.txt
+++ b/Documentation/git-commit.txt
@@ -12,7 +12,7 @@
 	   [--dry-run] [(-c | -C | --fixup | --squash) <commit>]
 	   [-F <file> | -m <msg>] [--reset-author] [--allow-empty]
 	   [--allow-empty-message] [--no-verify] [-e] [--author=<author>]
-	   [--date=<date>] [--cleanup=<mode>] [--status | --no-status]
+	   [--date=<date>] [--cleanup=<mode>] [--[no-]status]
 	   [-i | -o] [-S[<keyid>]] [--] [<file>...]
 
 DESCRIPTION
diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt
index 9ae2508..2dbe486 100644
--- a/Documentation/git-config.txt
+++ b/Documentation/git-config.txt
@@ -82,7 +82,7 @@
 --get::
 	Get the value for a given key (optionally filtered by a regex
 	matching the value). Returns error code 1 if the key was not
-	found and error code 2 if multiple key values were found.
+	found and the last value if multiple key values were found.
 
 --get-all::
 	Like get, but does not fail if the number of values for the key
@@ -96,28 +96,46 @@
 	names are not.
 
 --global::
-	For writing options: write to global ~/.gitconfig file rather than
-	the repository .git/config, write to $XDG_CONFIG_HOME/git/config file
-	if this file exists and the ~/.gitconfig file doesn't.
+	For writing options: write to global `~/.gitconfig` file
+	rather than the repository `.git/config`, write to
+	`$XDG_CONFIG_HOME/git/config` file if this file exists and the
+	`~/.gitconfig` file doesn't.
 +
-For reading options: read only from global ~/.gitconfig and from
-$XDG_CONFIG_HOME/git/config rather than from all available files.
+For reading options: read only from global `~/.gitconfig` and from
+`$XDG_CONFIG_HOME/git/config` rather than from all available files.
 +
 See also <<FILES>>.
 
 --system::
-	For writing options: write to system-wide $(prefix)/etc/gitconfig
-	rather than the repository .git/config.
+	For writing options: write to system-wide
+	`$(prefix)/etc/gitconfig` rather than the repository
+	`.git/config`.
 +
-For reading options: read only from system-wide $(prefix)/etc/gitconfig
+For reading options: read only from system-wide `$(prefix)/etc/gitconfig`
 rather than from all available files.
 +
 See also <<FILES>>.
 
+--local::
+	For writing options: write to the repository `.git/config` file.
+	This is	the default behavior.
++
+For reading options: read only from the repository `.git/config` rather than
+from all available files.
++
+See also <<FILES>>.
+
 -f config-file::
 --file config-file::
 	Use the given config file instead of the one specified by GIT_CONFIG.
 
+--blob blob::
+	Similar to '--file' but use the given blob instead of a file. E.g.
+	you can use 'master:.gitmodules' to read values from the file
+	'.gitmodules' in the master branch. See "SPECIFYING REVISIONS"
+	section in linkgit:gitrevisions[7] for a more complete list of
+	ways to spell blob names.
+
 --remove-section::
 	Remove the given section from the configuration file.
 
@@ -186,8 +204,7 @@
 	Opens an editor to modify the specified config file; either
 	'--system', '--global', or repository (default).
 
---includes::
---no-includes::
+--[no-]includes::
 	Respect `include.*` directives in config files when looking up
 	values. Defaults to on.
 
@@ -198,23 +215,23 @@
 If not set explicitly with '--file', there are four files where
 'git config' will search for configuration options:
 
-$GIT_DIR/config::
-	Repository specific configuration file.
+$(prefix)/etc/gitconfig::
+	System-wide configuration file.
+
+$XDG_CONFIG_HOME/git/config::
+	Second user-specific configuration file. If $XDG_CONFIG_HOME is not set
+	or empty, `$HOME/.config/git/config` will be used. Any single-valued
+	variable set in this file will be overwritten by whatever is in
+	`~/.gitconfig`.  It is a good idea not to create this file if
+	you sometimes use older versions of Git, as support for this
+	file was added fairly recently.
 
 ~/.gitconfig::
 	User-specific configuration file. Also called "global"
 	configuration file.
 
-$XDG_CONFIG_HOME/git/config::
-	Second user-specific configuration file. If $XDG_CONFIG_HOME is not set
-	or empty, $HOME/.config/git/config will be used. Any single-valued
-	variable set in this file will be overwritten by whatever is in
-	~/.gitconfig.  It is a good idea not to create this file if
-	you sometimes use older versions of Git, as support for this
-	file was added fairly recently.
-
-$(prefix)/etc/gitconfig::
-	System-wide configuration file.
+$GIT_DIR/config::
+	Repository specific configuration file.
 
 If no further options are given, all reading options will read all of these
 files that are available. If the global or the system-wide configuration
@@ -222,6 +239,10 @@
 file is not available or readable, 'git config' will exit with a non-zero
 error code. However, in neither case will an error message be issued.
 
+The files are read in the order given above, with last value found taking
+precedence over values read earlier.  When multiple values are taken then all
+values of a key from all files will be used.
+
 All writing options will per default write to the repository specific
 configuration file. Note that this also affects options like '--replace-all'
 and '--unset'. *'git config' will only ever change one file at a time*.
diff --git a/Documentation/git-daemon.txt b/Documentation/git-daemon.txt
index bfb106c..223f731 100644
--- a/Documentation/git-daemon.txt
+++ b/Documentation/git-daemon.txt
@@ -16,8 +16,10 @@
 	     [--reuseaddr] [--detach] [--pid-file=<file>]
 	     [--enable=<service>] [--disable=<service>]
 	     [--allow-override=<service>] [--forbid-override=<service>]
-	     [--access-hook=<path>]
-	     [--inetd | [--listen=<host_or_ipaddr>] [--port=<n>] [--user=<user> [--group=<group>]]
+	     [--access-hook=<path>] [--[no-]informative-errors]
+	     [--inetd |
+	      [--listen=<host_or_ipaddr>] [--port=<n>]
+	      [--user=<user> [--group=<group>]]]
 	     [<directory>...]
 
 DESCRIPTION
@@ -169,8 +171,7 @@
 	repository configuration.  By default, all the services
 	are overridable.
 
---informative-errors::
---no-informative-errors::
+--[no-]informative-errors::
 	When informative errors are turned on, git-daemon will report
 	more verbose errors to the client, differentiating conditions
 	like "no such repository" from "repository not exported". This
diff --git a/Documentation/git-describe.txt b/Documentation/git-describe.txt
index 28e5ec0..9439cd6 100644
--- a/Documentation/git-describe.txt
+++ b/Documentation/git-describe.txt
@@ -88,6 +88,11 @@
 --always::
 	Show uniquely abbreviated commit object as fallback.
 
+--first-parent::
+	Follow only the first parent commit upon seeing a merge commit.
+	This is useful when you wish to not match tags on branches merged
+	in the history of the target commit.
+
 EXAMPLES
 --------
 
@@ -149,7 +154,9 @@
 If an exact match was not found, 'git describe' will walk back
 through the commit history to locate an ancestor commit which
 has been tagged.  The ancestor's tag will be output along with an
-abbreviation of the input committish's SHA-1.
+abbreviation of the input committish's SHA-1. If '--first-parent' was
+specified then the walk will only consider the first parent of each
+commit.
 
 If multiple tags were found during the walk then the tag which
 has the fewest commits different from the input committish will be
diff --git a/Documentation/git-diff-index.txt b/Documentation/git-diff-index.txt
index c0b7c58..a86cf62 100644
--- a/Documentation/git-diff-index.txt
+++ b/Documentation/git-diff-index.txt
@@ -3,7 +3,7 @@
 
 NAME
 ----
-git-diff-index - Compares content and mode of blobs between the index and repository
+git-diff-index - Compare a tree to the working tree or index
 
 
 SYNOPSIS
@@ -13,11 +13,11 @@
 
 DESCRIPTION
 -----------
-Compares the content and mode of the blobs found via a tree
-object with the content of the current index and, optionally
-ignoring the stat state of the file on disk.  When paths are
-specified, compares only those named paths.  Otherwise all
-entries in the index are compared.
+Compares the content and mode of the blobs found in a tree object
+with the corresponding tracked files in the working tree, or with the
+corresponding paths in the index.  When <path> arguments are present,
+compares only paths matching those patterns.  Otherwise all tracked
+files are compared.
 
 OPTIONS
 -------
diff --git a/Documentation/git-diff.txt b/Documentation/git-diff.txt
index a7b4620..78d6d50 100644
--- a/Documentation/git-diff.txt
+++ b/Documentation/git-diff.txt
@@ -18,8 +18,8 @@
 DESCRIPTION
 -----------
 Show changes between the working tree and the index or a tree, changes
-between the index and a tree, changes between two trees, or changes
-between two files on disk.
+between the index and a tree, changes between two trees, changes between
+two blob objects, or changes between two files on disk.
 
 'git diff' [--options] [--] [<path>...]::
 
@@ -56,11 +56,6 @@
 	This is to view the changes between two arbitrary
 	<commit>.
 
-'git diff' [options] <blob> <blob>::
-
-	This form is to view the differences between the raw
-	contents of two blob objects.
-
 'git diff' [--options] <commit>..<commit> [--] [<path>...]::
 
 	This is synonymous to the previous form.  If <commit> on
@@ -87,6 +82,11 @@
 "<commit>\...<commit>") do not mean a range as defined in the
 "SPECIFYING RANGES" section in linkgit:gitrevisions[7].
 
+'git diff' [options] <blob> <blob>::
+
+	This form is to view the differences between the raw
+	contents of two blob objects.
+
 OPTIONS
 -------
 :git-diff: 1
diff --git a/Documentation/git-difftool.txt b/Documentation/git-difftool.txt
index 8361e6e..11887e6 100644
--- a/Documentation/git-difftool.txt
+++ b/Documentation/git-difftool.txt
@@ -69,8 +69,7 @@
 --tool-help::
 	Print a list of diff tools that may be used with `--tool`.
 
---symlinks::
---no-symlinks::
+--[no-]symlinks::
 	'git difftool''s default behavior is create symlinks to the
 	working tree when run in `--dir-diff` mode and the right-hand
 	side of the comparison yields the same content as the file in
diff --git a/Documentation/git-fast-export.txt b/Documentation/git-fast-export.txt
index 03fc8c3..85f1f30 100644
--- a/Documentation/git-fast-export.txt
+++ b/Documentation/git-fast-export.txt
@@ -106,11 +106,11 @@
 	different from the commit's first parent).
 
 [<git-rev-list-args>...]::
-       A list of arguments, acceptable to 'git rev-parse' and
-       'git rev-list', that specifies the specific objects and references
-       to export.  For example, `master~10..master` causes the
-       current master reference to be exported along with all objects
-       added since its 10th ancestor commit.
+	A list of arguments, acceptable to 'git rev-parse' and
+	'git rev-list', that specifies the specific objects and references
+	to export.  For example, `master~10..master` causes the
+	current master reference to be exported along with all objects
+	added since its 10th ancestor commit.
 
 EXAMPLES
 --------
@@ -141,7 +141,7 @@
 -----------
 
 Since 'git fast-import' cannot tag trees, you will not be
-able to export the linux-2.6.git repository completely, as it contains
+able to export the linux.git repository completely, as it contains
 a tag referencing a tree instead of a commit.
 
 GIT
diff --git a/Documentation/git-fetch-pack.txt b/Documentation/git-fetch-pack.txt
index b81e90d..1e71754 100644
--- a/Documentation/git-fetch-pack.txt
+++ b/Documentation/git-fetch-pack.txt
@@ -10,9 +10,9 @@
 --------
 [verse]
 'git fetch-pack' [--all] [--quiet|-q] [--keep|-k] [--thin] [--include-tag]
-				[--upload-pack=<git-upload-pack>]
-				[--depth=<n>] [--no-progress]
-				[-v] [<host>:]<directory> [<refs>...]
+	[--upload-pack=<git-upload-pack>]
+	[--depth=<n>] [--no-progress]
+	[-v] [<host>:]<directory> [<refs>...]
 
 DESCRIPTION
 -----------
diff --git a/Documentation/git-fmt-merge-msg.txt b/Documentation/git-fmt-merge-msg.txt
index 3a0f55e..bb1232a 100644
--- a/Documentation/git-fmt-merge-msg.txt
+++ b/Documentation/git-fmt-merge-msg.txt
@@ -35,8 +35,7 @@
 	Do not list one-line descriptions from the actual commits being
 	merged.
 
---summary::
---no-summary::
+--[no-]summary::
 	Synonyms to --log and --no-log; these are deprecated and will be
 	removed in the future.
 
diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt
index 3911877..e394276 100644
--- a/Documentation/git-format-patch.txt
+++ b/Documentation/git-format-patch.txt
@@ -187,6 +187,21 @@
 	The negated form `--no-cc` discards all `Cc:` headers added so
 	far (from config or command line).
 
+--from::
+--from=<ident>::
+	Use `ident` in the `From:` header of each commit email. If the
+	author ident of the commit is not textually identical to the
+	provided `ident`, place a `From:` header in the body of the
+	message with the original author. If no `ident` is given, use
+	the committer ident.
++
+Note that this option is only useful if you are actually sending the
+emails and want to identify yourself as the sender, but retain the
+original author (and `git am` will correctly pick up the in-body
+header). Note also that `git send-email` already handles this
+transformation for you, and this option should not be used if you are
+feeding the result to `git send-email`.
+
 --add-header=<header>::
 	Add an arbitrary header to the email headers.  This is in addition
 	to any configured headers, and may be used multiple times.
diff --git a/Documentation/git-fsck.txt b/Documentation/git-fsck.txt
index e5878bd..25c431d 100644
--- a/Documentation/git-fsck.txt
+++ b/Documentation/git-fsck.txt
@@ -30,8 +30,7 @@
 	Print out objects that exist but that aren't reachable from any
 	of the reference nodes.
 
---dangling::
---no-dangling::
+--[no-]dangling::
 	Print objects that exist but that are never 'directly' used (default).
 	`--no-dangling` can be used to omit this information from the output.
 
@@ -78,8 +77,7 @@
 	a blob, the contents are written into the file, rather than
 	its object name.
 
---progress::
---no-progress::
+--[no-]progress::
 	Progress status is reported on the standard error stream by
 	default when it is attached to a terminal, unless
 	--no-progress or --verbose is specified. --progress forces
diff --git a/Documentation/git-gc.txt b/Documentation/git-gc.txt
index b370b02..2402ed6 100644
--- a/Documentation/git-gc.txt
+++ b/Documentation/git-gc.txt
@@ -62,8 +62,9 @@
 
 --prune=<date>::
 	Prune loose objects older than date (default is 2 weeks ago,
-	overridable by the config variable `gc.pruneExpire`).  This
-	option is on by default.
+	overridable by the config variable `gc.pruneExpire`).
+	--prune=all prunes loose objects regardless of their age.
+	--prune is on by default.
 
 --no-prune::
 	Do not prune any loose objects.
diff --git a/Documentation/git-grep.txt b/Documentation/git-grep.txt
index 50d46e1..8497aa4 100644
--- a/Documentation/git-grep.txt
+++ b/Documentation/git-grep.txt
@@ -25,7 +25,7 @@
 	   [-W | --function-context]
 	   [-f <file>] [-e] <pattern>
 	   [--and|--or|--not|(|)|-e <pattern>...]
-	   [ [--exclude-standard] [--cached | --no-index | --untracked] | <tree>...]
+	   [ [--[no-]exclude-standard] [--cached | --no-index | --untracked] | <tree>...]
 	   [--] [<pathspec>...]
 
 DESCRIPTION
diff --git a/Documentation/git-index-pack.txt b/Documentation/git-index-pack.txt
index bde8eec..7a4e055 100644
--- a/Documentation/git-index-pack.txt
+++ b/Documentation/git-index-pack.txt
@@ -74,6 +74,9 @@
 --strict::
 	Die, if the pack contains broken objects or links.
 
+--check-self-contained-and-connected::
+	Die if the pack contains broken links. For internal use only.
+
 --threads=<n>::
 	Specifies the number of threads to spawn when resolving
 	deltas. This requires that index-pack be compiled with
diff --git a/Documentation/git-log.txt b/Documentation/git-log.txt
index a976534..ac2694d 100644
--- a/Documentation/git-log.txt
+++ b/Documentation/git-log.txt
@@ -62,6 +62,19 @@
 	Note that only message is considered, if also a diff is shown
 	its size is not included.
 
+-L <start>,<end>:<file>, -L :<regex>:<file>::
+
+	Trace the evolution of the line range given by "<start>,<end>"
+	(or the funcname regex <regex>) within the <file>.  You may
+	not give any pathspec limiters.  This is currently limited to
+	a walk starting from a single revision, i.e., you may only
+	give zero or one positive revision arguments.
+	You can specify this option more than once.
++
+<start> and <end> can take one of these forms:
+
+include::line-range-format.txt[]
+
 <revision range>::
 	Show only commits in the specified revision range.  When no
 	<revision range> is specified, it defaults to `HEAD` (i.e. the
@@ -84,7 +97,7 @@
 
 include::pretty-formats.txt[]
 
-Common diff options
+COMMON DIFF OPTIONS
 -------------------
 
 :git-log: 1
@@ -92,7 +105,7 @@
 
 include::diff-generate-patch.txt[]
 
-Examples
+EXAMPLES
 --------
 `git log --no-merges`::
 
@@ -115,9 +128,9 @@
 	in the "release" branch, along with the list of paths
 	each commit modifies.
 
-`git log --follow builtin-rev-list.c`::
+`git log --follow builtin/rev-list.c`::
 
-	Shows the commits that changed builtin-rev-list.c, including
+	Shows the commits that changed builtin/rev-list.c, including
 	those commits that occurred before the file was given its
 	present name.
 
@@ -140,15 +153,20 @@
 	This makes sense only when following a strict policy of merging all
 	topic branches when staying on a single integration branch.
 
+`git log -L '/int main/',/^}/:main.c`::
+
+	Shows how the function `main()` in the file 'main.c' evolved
+	over time.
+
 `git log -3`::
 	Limits the number of commits to show to 3.
 
-Discussion
+DISCUSSION
 ----------
 
 include::i18n.txt[]
 
-Configuration
+CONFIGURATION
 -------------
 
 See linkgit:git-config[1] for core variables and linkgit:git-diff[1]
diff --git a/Documentation/git-ls-remote.txt b/Documentation/git-ls-remote.txt
index 774de5e..2e22915 100644
--- a/Documentation/git-ls-remote.txt
+++ b/Documentation/git-ls-remote.txt
@@ -48,9 +48,9 @@
 	exit without talking to the remote.
 
 <repository>::
-	Location of the repository.  The shorthand defined in
-	$GIT_DIR/branches/ can be used. Use "." (dot) to list references in
-	the local repository.
+	The "remote" repository to query.  This parameter can be
+	either a URL or the name of a remote (see the GIT URLS and
+	REMOTES sections of linkgit:git-fetch[1]).
 
 <refs>...::
 	When unspecified, all references, after filtering done
@@ -70,9 +70,8 @@
 	$ git ls-remote http://www.kernel.org/pub/scm/git/git.git master pu rc
 	5fe978a5381f1fbad26a80e682ddd2a401966740	refs/heads/master
 	c781a84b5204fb294c9ccc79f8b3baceeb32c061	refs/heads/pu
-	b1d096f2926c4e37c9c0b6a7bf2119bedaa277cb	refs/heads/rc
-	$ echo http://www.kernel.org/pub/scm/git/git.git >.git/branches/public
-	$ git ls-remote --tags public v\*
+	$ git remote add korg http://www.kernel.org/pub/scm/git/git.git
+	$ git ls-remote --tags korg v\*
 	d6602ec5194c87b0fc87103ca4d67251c76f233a	refs/tags/v0.99
 	f25a265a342aed6041ab0cc484224d9ca54b6f41	refs/tags/v0.99.1
 	c5db5456ae3b0873fc659c19fafdde22313cc441	refs/tags/v0.99.2
diff --git a/Documentation/git-mailinfo.txt b/Documentation/git-mailinfo.txt
index 97e7a8e..164a3c6 100644
--- a/Documentation/git-mailinfo.txt
+++ b/Documentation/git-mailinfo.txt
@@ -9,7 +9,7 @@
 SYNOPSIS
 --------
 [verse]
-'git mailinfo' [-k|-b] [-u | --encoding=<encoding> | -n] [--scissors] <msg> <patch>
+'git mailinfo' [-k|-b] [-u | --encoding=<encoding> | -n] [--[no-]scissors] <msg> <patch>
 
 
 DESCRIPTION
diff --git a/Documentation/git-merge.txt b/Documentation/git-merge.txt
index 42391f2..a74c371 100644
--- a/Documentation/git-merge.txt
+++ b/Documentation/git-merge.txt
@@ -56,8 +56,8 @@
 was started), 'git merge --abort' will in some cases be unable to
 reconstruct the original (pre-merge) changes. Therefore:
 
-*Warning*: Running 'git merge' with uncommitted changes is
-discouraged: while possible, it leaves you in a state that is hard to
+*Warning*: Running 'git merge' with non-trivial uncommitted changes is
+discouraged: while possible, it may leave you in a state that is hard to
 back out of in the case of a conflict.
 
 
@@ -76,8 +76,7 @@
 used to give a good default for automated 'git merge'
 invocations.
 
---rerere-autoupdate::
---no-rerere-autoupdate::
+--[no-]rerere-autoupdate::
 	Allow the rerere mechanism to update the index with the
 	result of auto-conflict resolution if possible.
 
@@ -187,11 +186,11 @@
 to `git merge`, or pass `--ff-only` when you do not have any work on
 your own. e.g.
 
----
+----
 git fetch origin
 git merge v1.2.3^0
 git merge --ff-only v1.2.3
----
+----
 
 
 HOW CONFLICTS ARE PRESENTED
diff --git a/Documentation/git-mergetool.txt b/Documentation/git-mergetool.txt
index 6b563c5..07137f2 100644
--- a/Documentation/git-mergetool.txt
+++ b/Documentation/git-mergetool.txt
@@ -8,7 +8,7 @@
 SYNOPSIS
 --------
 [verse]
-'git mergetool' [--tool=<tool>] [-y|--no-prompt|--prompt] [<file>...]
+'git mergetool' [--tool=<tool>] [-y | --[no-]prompt] [<file>...]
 
 DESCRIPTION
 -----------
diff --git a/Documentation/git-name-rev.txt b/Documentation/git-name-rev.txt
index ad1d146..15b00e0 100644
--- a/Documentation/git-name-rev.txt
+++ b/Documentation/git-name-rev.txt
@@ -25,14 +25,17 @@
 	Do not use branch names, but only tags to name the commits
 
 --refs=<pattern>::
-	Only use refs whose names match a given shell pattern.
+	Only use refs whose names match a given shell pattern.  The pattern
+	can be one of branch name, tag name or fully qualified ref name.
 
 --all::
 	List all commits reachable from all refs
 
 --stdin::
-	Read from stdin, append "(<rev_name>)" to all sha1's of nameable
-	commits, and pass to stdout
+	Transform stdin by substituting all the 40-character SHA-1
+	hexes (say $hex) with "$hex ($rev_name)".  When used with
+	--name-only, substitute with "$rev_name", omitting $hex
+	altogether.  Intended for the scripter's use.
 
 --name-only::
 	Instead of printing both the SHA-1 and the name, print only
diff --git a/Documentation/git-p4.txt b/Documentation/git-p4.txt
index c579fbc..8cba16d 100644
--- a/Documentation/git-p4.txt
+++ b/Documentation/git-p4.txt
@@ -176,13 +176,16 @@
 These options can be used in the initial 'clone' as well as in
 subsequent 'sync' operations.
 
---branch <branch>::
-	Import changes into given branch.  If the branch starts with
-	'refs/', it will be used as is.  Otherwise if it does not start
-	with 'p4/', that prefix is added.  The branch is assumed to
-	name a remote tracking, but this can be modified using
-	'--import-local', or by giving a full ref name.  The default
-	branch is 'master'.
+--branch <ref>::
+	Import changes into <ref> instead of refs/remotes/p4/master.
+	If <ref> starts with refs/, it is used as is.  Otherwise, if
+	it does not start with p4/, that prefix is added.
++
+By default a <ref> not starting with refs/ is treated as the
+name of a remote-tracking branch (under refs/remotes/).  This
+behavior can be modified using the --import-local option.
++
+The default <ref> is "master".
 +
 This example imports a new remote "p4/proj2" into an existing
 Git repository:
diff --git a/Documentation/git-pack-refs.txt b/Documentation/git-pack-refs.txt
index f131677..154081f 100644
--- a/Documentation/git-pack-refs.txt
+++ b/Documentation/git-pack-refs.txt
@@ -33,8 +33,8 @@
 `$GIT_DIR/refs` directory hierarchy.
 
 A recommended practice to deal with a repository with too many
-refs is to pack its refs with `--all --prune` once, and
-occasionally run `git pack-refs --prune`.  Tags are by
+refs is to pack its refs with `--all` once, and
+occasionally run `git pack-refs`.  Tags are by
 definition stationary and are not expected to change.  Branch
 heads will be packed with the initial `pack-refs --all`, but
 only the currently active branch heads will become unpacked,
diff --git a/Documentation/git-prune.txt b/Documentation/git-prune.txt
index 80d01b0..bf82410 100644
--- a/Documentation/git-prune.txt
+++ b/Documentation/git-prune.txt
@@ -59,7 +59,7 @@
 `.git/objects/info/alternates`:
 
 ------------
-$ git prune $(cd ../another && $(git rev-parse --all))
+$ git prune $(cd ../another && git rev-parse --all)
 ------------
 
 Notes
diff --git a/Documentation/git-pull.txt b/Documentation/git-pull.txt
index 24ab07a..6ef8d59 100644
--- a/Documentation/git-pull.txt
+++ b/Documentation/git-pull.txt
@@ -3,7 +3,7 @@
 
 NAME
 ----
-git-pull - Fetch from and merge with another repository or a local branch
+git-pull - Fetch from and integrate with another repository or a local branch
 
 
 SYNOPSIS
diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt
index eb2883c..f7dfe48 100644
--- a/Documentation/git-push.txt
+++ b/Documentation/git-push.txt
@@ -11,7 +11,7 @@
 [verse]
 'git push' [--all | --mirror | --tags] [--follow-tags] [-n | --dry-run] [--receive-pack=<git-receive-pack>]
 	   [--repo=<repository>] [-f | --force] [--prune] [-v | --verbose] [-u | --set-upstream]
-	   [<repository> [<refspec>...]]
+	   [--no-verify] [<repository> [<refspec>...]]
 
 DESCRIPTION
 -----------
@@ -136,6 +136,15 @@
 	not an ancestor of the local ref used to overwrite it.
 	This flag disables the check.  This can cause the
 	remote repository to lose commits; use it with care.
+	Note that `--force` applies to all the refs that are pushed,
+	hence using it with `push.default` set to `matching` or with
+	multiple push destinations configured with `remote.*.push`
+	may overwrite refs other than the current branch (including
+	local refs that are strictly behind their remote counterpart).
+	To force a push to only one branch, use a `+` in front of the
+	refspec to push	(e.g `git push origin +master` to force a push
+	to the `master`	branch). See the `<refspec>...` section above
+	for details.
 
 --repo=<repository>::
 	This option is only relevant if no <repository> argument is
@@ -162,8 +171,7 @@
 	linkgit:git-pull[1] and other commands. For more information,
 	see 'branch.<name>.merge' in linkgit:git-config[1].
 
---thin::
---no-thin::
+--[no-]thin::
 	These options are passed to linkgit:git-send-pack[1]. A thin transfer
 	significantly reduces the amount of sent data when the sender and
 	receiver share many of the same objects in common. The default is
@@ -196,6 +204,11 @@
 	be pushed. If on-demand was not able to push all necessary
 	revisions it will also be aborted and exit with non-zero status.
 
+--[no-]verify::
+	Toggle the pre-push hook (see linkgit:githooks[5]).  The
+	default is \--verify, giving the hook a chance to prevent the
+	push.  With \--no-verify, the hook is bypassed completely.
+
 
 include::urls-remotes.txt[]
 
diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index aca8405..6b2e1c8 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -208,6 +208,9 @@
 rebase.autosquash::
 	If set to true enable '--autosquash' option by default.
 
+rebase.autostash::
+	If set to true enable '--autostash' option by default.
+
 OPTIONS
 -------
 --onto <newbase>::
@@ -386,7 +389,9 @@
 	the same ..., automatically modify the todo list of rebase -i
 	so that the commit marked for squashing comes right after the
 	commit to be modified, and change the action of the moved
-	commit from `pick` to `squash` (or `fixup`).
+	commit from `pick` to `squash` (or `fixup`).  Ignores subsequent
+	"fixup! " or "squash! " after the first, in case you referred to an
+	earlier fixup/squash with `git commit --fixup/--squash`.
 +
 This option is only valid when the '--interactive' option is used.
 +
@@ -394,6 +399,13 @@
 configuration variable `rebase.autosquash`, this option can be
 used to override and disable this setting.
 
+--[no-]autostash::
+	Automatically create a temporary stash before the operation
+	begins, and apply it after the operation ends.  This means
+	that you can run rebase on a dirty worktree.  However, use
+	with care: the final stash application after a successful
+	rebase might result in non-trivial conflicts.
+
 --no-ff::
 	With --interactive, cherry-pick all rebased commits instead of
 	fast-forwarding over the unchanged ones.  This ensures that the
diff --git a/Documentation/git-reflog.txt b/Documentation/git-reflog.txt
index fb8697e..70791b9 100644
--- a/Documentation/git-reflog.txt
+++ b/Documentation/git-reflog.txt
@@ -67,14 +67,19 @@
 --expire=<time>::
 	Entries older than this time are pruned.  Without the
 	option it is taken from configuration `gc.reflogExpire`,
-	which in turn defaults to 90 days.
+	which in turn defaults to 90 days.  --expire=all prunes
+	entries regardless of their age; --expire=never turns off
+	pruning of reachable entries (but see --expire-unreachable).
 
 --expire-unreachable=<time>::
 	Entries older than this time and not reachable from
 	the current tip of the branch are pruned.  Without the
 	option it is taken from configuration
 	`gc.reflogExpireUnreachable`, which in turn defaults to
-	30 days.
+	30 days.  --expire-unreachable=all prunes unreachable
+	entries regardless of their age; --expire-unreachable=never
+	turns off early pruning of unreachable entries (but see
+	--expire).
 
 --all::
 	Instead of listing <refs> explicitly, prune all refs.
diff --git a/Documentation/git-remote.txt b/Documentation/git-remote.txt
index 7a6f354..9c3e3bf 100644
--- a/Documentation/git-remote.txt
+++ b/Documentation/git-remote.txt
@@ -10,7 +10,7 @@
 --------
 [verse]
 'git remote' [-v | --verbose]
-'git remote add' [-t <branch>] [-m <master>] [-f] [--tags|--no-tags] [--mirror=<fetch|push>] <name> <url>
+'git remote add' [-t <branch>] [-m <master>] [-f] [--[no-]tags] [--mirror=<fetch|push>] <name> <url>
 'git remote rename' <old> <new>
 'git remote remove' <name>
 'git remote set-head' <name> (-a | -d | <branch>)
@@ -187,18 +187,25 @@
 $ git remote
 origin
 $ git branch -r
-origin/master
-$ git remote add linux-nfs git://linux-nfs.org/pub/linux/nfs-2.6.git
+  origin/HEAD -> origin/master
+  origin/master
+$ git remote add staging git://git.kernel.org/.../gregkh/staging.git
 $ git remote
-linux-nfs
 origin
-$ git fetch
-* refs/remotes/linux-nfs/master: storing branch 'master' ...
-  commit: bf81b46
+staging
+$ git fetch staging
+...
+From git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging
+ * [new branch]      master     -> staging/master
+ * [new branch]      staging-linus -> staging/staging-linus
+ * [new branch]      staging-next -> staging/staging-next
 $ git branch -r
-origin/master
-linux-nfs/master
-$ git checkout -b nfs linux-nfs/master
+  origin/HEAD -> origin/master
+  origin/master
+  staging/master
+  staging/staging-linus
+  staging/staging-next
+$ git checkout -b staging staging/master
 ...
 ------------
 
diff --git a/Documentation/git-reset.txt b/Documentation/git-reset.txt
index a404b47..f445cb3 100644
--- a/Documentation/git-reset.txt
+++ b/Documentation/git-reset.txt
@@ -9,7 +9,7 @@
 --------
 [verse]
 'git reset' [-q] [<tree-ish>] [--] <paths>...
-'git reset' (--patch | -p) [<tree-sh>] [--] [<paths>...]
+'git reset' (--patch | -p) [<tree-ish>] [--] [<paths>...]
 'git reset' [--soft | --mixed | --hard | --merge | --keep] [-q] [<commit>]
 
 DESCRIPTION
diff --git a/Documentation/git-rev-list.txt b/Documentation/git-rev-list.txt
index 65ac27e..045b37b 100644
--- a/Documentation/git-rev-list.txt
+++ b/Documentation/git-rev-list.txt
@@ -40,7 +40,7 @@
 	     [ \--right-only ]
 	     [ \--cherry-mark ]
 	     [ \--cherry-pick ]
-	     [ \--encoding[=<encoding>] ]
+	     [ \--encoding=<encoding> ]
 	     [ \--(author|committer|grep)=<pattern> ]
 	     [ \--regexp-ignore-case | -i ]
 	     [ \--extended-regexp | -E ]
diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt
index 947d62f..2b126c0 100644
--- a/Documentation/git-rev-parse.txt
+++ b/Documentation/git-rev-parse.txt
@@ -59,6 +59,22 @@
 	If there is no parameter given by the user, use `<arg>`
 	instead.
 
+--prefix <arg>::
+	Behave as if 'git rev-parse' was invoked from the `<arg>`
+	subdirectory of the working tree.  Any relative filenames are
+	resolved as if they are prefixed by `<arg>` and will be printed
+	in that form.
++
+This can be used to convert arguments to a command run in a subdirectory
+so that they can still be used after moving to the top-level of the
+repository.  For example:
++
+----
+prefix=$(git rev-parse --show-prefix)
+cd "$(git rev-parse --show-toplevel)"
+eval "set -- $(git rev-parse --sq --prefix "$prefix" "$@")"
+----
+
 --verify::
 	Verify that exactly one parameter is provided, and that it
 	can be turned into a raw 20-byte SHA-1 that can be used to
@@ -67,7 +83,7 @@
 +
 If you want to make sure that the output actually names an object in
 your object database and/or can be used as a specific type of object
-you require, you can add "^{type}" peeling operator to the parmeter.
+you require, you can add "^{type}" peeling operator to the parameter.
 For example, `git rev-parse "$VAR^{commit}"` will make sure `$VAR`
 names an existing object that is a commit-ish (i.e. a commit, or an
 annotated tag that points at a commit).  To make sure that `$VAR`
diff --git a/Documentation/git-revert.txt b/Documentation/git-revert.txt
index 70152e8..f79c9d8 100644
--- a/Documentation/git-revert.txt
+++ b/Documentation/git-revert.txt
@@ -8,7 +8,7 @@
 SYNOPSIS
 --------
 [verse]
-'git revert' [--edit | --no-edit] [-n] [-m parent-number] [-s] <commit>...
+'git revert' [--[no-]edit] [-n] [-m parent-number] [-s] <commit>...
 'git revert' --continue
 'git revert' --quit
 'git revert' --abort
diff --git a/Documentation/git-send-email.txt b/Documentation/git-send-email.txt
index 40a9a9a..f0e57a5 100644
--- a/Documentation/git-send-email.txt
+++ b/Documentation/git-send-email.txt
@@ -198,6 +198,12 @@
 --smtp-ssl::
 	Legacy alias for '--smtp-encryption ssl'.
 
+--smtp-ssl-cert-path::
+	Path to ca-certificates (either a directory or a single file).
+	Set it to an empty string to disable certificate verification.
+	Defaults to the value set to the 'sendemail.smtpsslcertpath'
+	configuration variable, if set, or `/etc/ssl/certs` otherwise.
+
 --smtp-user=<user>::
 	Username for SMTP-AUTH. Default is the value of 'sendemail.smtpuser';
 	if a username is not specified (with '--smtp-user' or 'sendemail.smtpuser'),
diff --git a/Documentation/git-show-ref.txt b/Documentation/git-show-ref.txt
index de4d352..b0a309b 100644
--- a/Documentation/git-show-ref.txt
+++ b/Documentation/git-show-ref.txt
@@ -21,6 +21,8 @@
 dereferenced into object IDs. Additionally, it can be used to test whether a
 particular ref exists.
 
+By default, shows the tags, heads, and remote refs.
+
 The --exclude-existing form is a filter that does the inverse, it shows the
 refs from stdin that don't exist in the local repository.
 
@@ -32,14 +34,14 @@
 
 --head::
 
-	Show the HEAD reference.
+	Show the HEAD reference, even if it would normally be filtered out.
 
 --tags::
 --heads::
 
-	Limit to only "refs/heads" and "refs/tags", respectively.  These
-	options are not mutually exclusive; when given both, references stored
-	in "refs/heads" and "refs/tags" are displayed.
+	Limit to "refs/heads" and "refs/tags", respectively.  These options
+	are not mutually exclusive; when given both, references stored in
+	"refs/heads" and "refs/tags" are displayed.
 
 -d::
 --dereference::
diff --git a/Documentation/git-show.txt b/Documentation/git-show.txt
index ae4edcc..4e617e6 100644
--- a/Documentation/git-show.txt
+++ b/Documentation/git-show.txt
@@ -45,6 +45,15 @@
 include::pretty-formats.txt[]
 
 
+COMMON DIFF OPTIONS
+-------------------
+
+:git-log: 1
+include::diff-options.txt[]
+
+include::diff-generate-patch.txt[]
+
+
 EXAMPLES
 --------
 
diff --git a/Documentation/git-stash.txt b/Documentation/git-stash.txt
index 711ffe1..db7e803 100644
--- a/Documentation/git-stash.txt
+++ b/Documentation/git-stash.txt
@@ -13,10 +13,11 @@
 'git stash' drop [-q|--quiet] [<stash>]
 'git stash' ( pop | apply ) [--index] [-q|--quiet] [<stash>]
 'git stash' branch <branchname> [<stash>]
-'git stash' [save [--patch] [-k|--[no-]keep-index] [-q|--quiet]
+'git stash' [save [-p|--patch] [-k|--[no-]keep-index] [-q|--quiet]
 	     [-u|--include-untracked] [-a|--all] [<message>]]
 'git stash' clear
-'git stash' create
+'git stash' create [<message>]
+'git stash' store [-m|--message <message>] [-q|--quiet] <commit>
 
 DESCRIPTION
 -----------
@@ -151,7 +152,15 @@
 
 	Create a stash (which is a regular commit object) and return its
 	object name, without storing it anywhere in the ref namespace.
+	This is intended to be useful for scripts.  It is probably not
+	the command you want to use; see "save" above.
 
+store::
+
+	Store a given stash created via 'git stash create' (which is a
+	dangling merge commit) in the stash ref, updating the stash
+	reflog.  This is intended to be useful for scripts.  It is
+	probably not the command you want to use; see "save" above.
 
 DISCUSSION
 ----------
diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
index 74d5bdc..bfef8a0 100644
--- a/Documentation/git-submodule.txt
+++ b/Documentation/git-submodule.txt
@@ -10,12 +10,12 @@
 --------
 [verse]
 'git submodule' [--quiet] add [-b <branch>] [-f|--force] [--name <name>]
-	      [--reference <repository>] [--] <repository> [<path>]
+	      [--reference <repository>] [--depth <depth>] [--] <repository> [<path>]
 'git submodule' [--quiet] status [--cached] [--recursive] [--] [<path>...]
 'git submodule' [--quiet] init [--] [<path>...]
 'git submodule' [--quiet] deinit [-f|--force] [--] <path>...
 'git submodule' [--quiet] update [--init] [--remote] [-N|--no-fetch]
-	      [-f|--force] [--rebase] [--reference <repository>]
+	      [-f|--force] [--rebase] [--reference <repository>] [--depth <depth>]
 	      [--merge] [--recursive] [--] [<path>...]
 'git submodule' [--quiet] summary [--cached|--files] [(-n|--summary-limit) <n>]
 	      [commit] [--] [<path>...]
@@ -77,6 +77,8 @@
 to exist in the superproject. If <path> is not given, the
 "humanish" part of the source repository is used ("repo" for
 "/path/to/repo.git" and "foo" for "host.xz:foo/.git").
+The <path> is also used as the submodule's logical name in its
+configuration entries unless `--name` is used to specify a logical name.
 +
 <repository> is the URL of the new submodule's origin repository.
 This may be either an absolute URL, or (if it begins with ./
@@ -124,8 +126,10 @@
 too (and can also report changes to a submodule's work tree).
 
 init::
-	Initialize the submodules, i.e. register each submodule name
-	and url found in .gitmodules into .git/config.
+	Initialize the submodules recorded in the index (which were
+	added and committed elsewhere) by copying submodule
+	names and urls from .gitmodules to .git/config.
+	Optional <path> arguments limit which submodules will be initialized.
 	It will also copy the value of `submodule.$name.update` into
 	.git/config.
 	The key used in .git/config is `submodule.$name.url`.
@@ -155,7 +159,9 @@
 	This will make the submodules HEAD be detached unless `--rebase` or
 	`--merge` is specified or the key `submodule.$name.update` is set to
 	`rebase`, `merge` or `none`. `none` can be overridden by specifying
-	`--checkout`.
+	`--checkout`. Setting the key `submodule.$name.update` to `!command`
+	will cause `command` to be run. `command` can be any arbitrary shell
+	command that takes a single argument, namely the sha1 to update to.
 +
 If the submodule is not yet initialized, and you just want to use the
 setting as stored in .gitmodules, you can automatically initialize the
@@ -258,7 +264,7 @@
 --remote::
 	This option is only valid for the update command.  Instead of using
 	the superproject's recorded SHA-1 to update the submodule, use the
-	status of the submodule's remote tracking branch.  The remote used
+	status of the submodule's remote-tracking branch.  The remote used
 	is branch's remote (`branch.<name>.remote`), defaulting to `origin`.
 	The remote branch used defaults to `master`, but the branch name may
 	be overridden by setting the `submodule.<name>.branch` option in
@@ -324,6 +330,12 @@
 	only in the submodules of the current repo, but also
 	in any nested submodules inside those submodules (and so on).
 
+--depth::
+	This option is valid for add and update commands. Create a 'shallow'
+	clone with a history truncated to the specified number of revisions.
+	See linkgit:git-clone[1]
+
+
 <path>...::
 	Paths to submodule(s). When specified this will restrict the command
 	to only operate on the submodules found at the specified paths.
diff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt
index 7706d41..4dd3bcb 100644
--- a/Documentation/git-svn.txt
+++ b/Documentation/git-svn.txt
@@ -85,6 +85,10 @@
 	When passed to 'init' or 'clone' this regular expression will
 	be preserved as a config key.  See 'fetch' for a description
 	of '--ignore-paths'.
+--include-paths=<regex>;;
+	When passed to 'init' or 'clone' this regular expression will
+	be preserved as a config key.  See 'fetch' for a description
+	of '--include-paths'.
 --no-minimize-url;;
 	When tracking multiple directories (using --stdlayout,
 	--branches, or --tags options), git svn will attempt to connect
@@ -146,6 +150,14 @@
 ------------------------------------------------------------------------
 --
 
+--include-paths=<regex>;;
+	This allows one to specify a Perl regular expression that will
+	cause the inclusion of only matching paths from checkout from SVN.
+	The '--include-paths' option should match for every 'fetch'
+	(including automatic fetches due to 'clone', 'dcommit',
+	'rebase', etc) on a given repository. '--ignore-paths' takes
+	precedence over '--include-paths'.
+
 --log-window-size=<n>;;
     Fetch <n> log entries per request when scanning Subversion history.
     The default is 100. For very large Subversion repositories, larger
@@ -244,7 +256,7 @@
 	For each patch, one may answer "yes" (accept this patch), "no" (discard this
 	patch), "all" (accept all patches), or "quit".
 	+
-	'git svn dcommit' returns immediately if answer if "no" or "quit", without
+       'git svn dcommit' returns immediately if answer is "no" or "quit", without
 	committing anything to SVN.
 
 'branch'::
@@ -259,13 +271,15 @@
 	Create a tag by using the tags_subdir instead of the branches_subdir
 	specified during git svn init.
 
--d;;
---destination;;
+-d<path>;;
+--destination=<path>;;
+
 	If more than one --branches (or --tags) option was given to the 'init'
 	or 'clone' command, you must provide the location of the branch (or
-	tag) you wish to create in the SVN repository.  The value of this
-	option must match one of the paths specified by a --branches (or
-	--tags) option.  You can see these paths with the commands
+	tag) you wish to create in the SVN repository.  <path> specifies which
+	path to use to create the branch or tag and should match the pattern
+	on the left-hand side of one of the configured branches or tags
+	refspecs.  You can see these refspecs with the commands
 +
 	git config --get-all svn-remote.<name>.branches
 	git config --get-all svn-remote.<name>.tags
@@ -286,6 +300,11 @@
 	git config --get-all svn-remote.<name>.commiturl
 +
 
+--parents;;
+	Create parent folders. This parameter is equivalent to the parameter
+	--parents on svn cp commands and is useful for non-standard repository
+	layouts.
+
 'tag'::
 	Create a tag in the SVN repository. This is a shorthand for
 	'branch -t'.
@@ -1020,6 +1039,25 @@
 	tags = tags/{1.0,2.0}/src:refs/remotes/tags/*
 ------------------------------------------------------------------------
 
+Multiple fetch, branches, and tags keys are supported:
+
+------------------------------------------------------------------------
+[svn-remote "messy-repo"]
+	url = http://server.org/svn
+	fetch = trunk/project-a:refs/remotes/project-a/trunk
+	fetch = branches/demos/june-project-a-demo:refs/remotes/project-a/demos/june-demo
+	branches = branches/server/*:refs/remotes/project-a/branches/*
+	branches = branches/demos/2011/*:refs/remotes/project-a/2011-demos/*
+	tags = tags/server/*:refs/remotes/project-a/tags/*
+------------------------------------------------------------------------
+
+Creating a branch in such a configuration requires disambiguating which
+location to use using the -d or --destination flag:
+
+------------------------------------------------------------------------
+$ git svn branch -d branches/server release-2-3-0
+------------------------------------------------------------------------
+
 Note that git-svn keeps track of the highest revision in which a branch
 or tag has appeared. If the subset of branches or tags is changed after
 fetching, then .git/svn/.metadata must be manually edited to remove (or
diff --git a/Documentation/git-tag.txt b/Documentation/git-tag.txt
index 22894cb..c418c44 100644
--- a/Documentation/git-tag.txt
+++ b/Documentation/git-tag.txt
@@ -42,6 +42,17 @@
 GnuPG key for signing. 	The configuration variable `gpg.program`
 is used to specify custom GnuPG binary.
 
+Tag objects (created with `-a`, `s`, or `-u`) are called "annotated"
+tags; they contain a creation date, the tagger name and e-mail, a
+tagging message, and an optional GnuPG signature. Whereas a
+"lightweight" tag is simply a name for an object (usually a commit
+object).
+
+Annotated tags are meant for release while lightweight tags are meant
+for private or temporary object labels. For this reason, some git
+commands for naming objects (like `git describe`) will ignore
+lightweight tags by default.
+
 
 OPTIONS
 -------
diff --git a/Documentation/git-update-index.txt b/Documentation/git-update-index.txt
index 670e9fb..e0a8702 100644
--- a/Documentation/git-update-index.txt
+++ b/Documentation/git-update-index.txt
@@ -14,8 +14,8 @@
 	     [--refresh] [-q] [--unmerged] [--ignore-missing]
 	     [(--cacheinfo <mode> <object> <file>)...]
 	     [--chmod=(+|-)x]
-	     [--assume-unchanged | --no-assume-unchanged]
-	     [--skip-worktree | --no-skip-worktree]
+	     [--[no-]assume-unchanged]
+	     [--[no-]skip-worktree]
 	     [--ignore-submodules]
 	     [--really-refresh] [--unresolve] [--again | -g]
 	     [--info-only] [--index-info]
@@ -77,8 +77,7 @@
 --chmod=(+|-)x::
         Set the execute permissions on the updated files.
 
---assume-unchanged::
---no-assume-unchanged::
+--[no-]assume-unchanged::
 	When these flags are specified, the object names recorded
 	for the paths are not updated.  Instead, these options
 	set and unset the "assume unchanged" bit for the
@@ -102,8 +101,7 @@
 	Like '--refresh', but checks stat information unconditionally,
 	without regard to the "assume unchanged" setting.
 
---skip-worktree::
---no-skip-worktree::
+--[no-]skip-worktree::
 	When one of these flags is specified, the object name recorded
 	for the paths are not updated. Instead, these options
 	set and unset the "skip-worktree" bit for the paths. See
diff --git a/Documentation/git-web--browse.txt b/Documentation/git-web--browse.txt
index ba79cb4..5aec4ec 100644
--- a/Documentation/git-web--browse.txt
+++ b/Documentation/git-web--browse.txt
@@ -34,6 +34,7 @@
 * dillo
 * open (this is the default under Mac OS X GUI)
 * start (this is the default under MinGW)
+* cygstart (this is the default under Cygwin)
 
 Custom commands may also be specified.
 
diff --git a/Documentation/git.txt b/Documentation/git.txt
index 8438c07..dca11cc 100644
--- a/Documentation/git.txt
+++ b/Documentation/git.txt
@@ -43,11 +43,26 @@
 branch of the `git.git` repository.
 Documentation for older releases are available here:
 
-* link:v1.8.2.2/git.html[documentation for release 1.8.2.2]
+* link:v1.8.4/git.html[documentation for release 1.8.4]
 
 * release notes for
-  link:RelNotes/1.8.2.2.txt[1.8.2.2].
-  link:RelNotes/1.8.2.1.txt[1.8.2.1].
+  link:RelNotes/1.8.4.txt[1.8.4].
+
+* link:v1.8.3.4/git.html[documentation for release 1.8.3.4]
+
+* release notes for
+  link:RelNotes/1.8.3.4.txt[1.8.3.4],
+  link:RelNotes/1.8.3.3.txt[1.8.3.3],
+  link:RelNotes/1.8.3.2.txt[1.8.3.2],
+  link:RelNotes/1.8.3.1.txt[1.8.3.1],
+  link:RelNotes/1.8.3.txt[1.8.3].
+
+* link:v1.8.2.3/git.html[documentation for release 1.8.2.3]
+
+* release notes for
+  link:RelNotes/1.8.2.3.txt[1.8.2.3],
+  link:RelNotes/1.8.2.2.txt[1.8.2.2],
+  link:RelNotes/1.8.2.1.txt[1.8.2.1],
   link:RelNotes/1.8.2.txt[1.8.2].
 
 * link:v1.8.1.6/git.html[documentation for release 1.8.1.6]
@@ -676,9 +691,7 @@
 	The '--git-dir' command-line option also sets this value.
 
 'GIT_WORK_TREE'::
-	Set the path to the working tree.  The value will not be
-	used in combination with repositories found automatically in
-	a .git directory (i.e. $GIT_DIR is not set).
+	Set the path to the root of the working tree.
 	This can also be controlled by the '--work-tree' command line
 	option and the core.worktree configuration variable.
 
@@ -810,8 +823,9 @@
 'GIT_FLUSH'::
 	If this environment variable is set to "1", then commands such
 	as 'git blame' (in incremental mode), 'git rev-list', 'git log',
-	and 'git whatchanged' will force a flush of the output stream
-	after each commit-oriented record have been flushed.   If this
+	'git check-attr', 'git check-ignore', and 'git whatchanged' will
+	force a flush of the output stream after each record have been
+	flushed. If this
 	variable is set to "0", the output of these commands will be done
 	using completely buffered I/O.   If this environment variable is
 	not set, Git will choose buffered or record-oriented flushing
@@ -831,6 +845,19 @@
 	as a file path and will try to write the trace messages
 	into it.
 
+'GIT_TRACE_PACK_ACCESS'::
+	If this variable is set to a path, a file will be created at
+	the given path logging all accesses to any packs. For each
+	access, the pack file name and an offset in the pack is
+	recorded. This may be helpful for troubleshooting some
+	pack-related performance problems.
+
+'GIT_TRACE_PACKET'::
+	If this variable is set, it shows a trace of all packets
+	coming in or out of a given program. This can help with
+	debugging object negotiation or other protocol issues. Tracing
+	is turned off at a packet starting with "PACK".
+
 GIT_LITERAL_PATHSPECS::
 	Setting this variable to `1` will cause Git to treat all
 	pathspecs literally, rather than as glob patterns. For example,
diff --git a/Documentation/gitdiffcore.txt b/Documentation/gitdiffcore.txt
index 568d757..c8b3e51 100644
--- a/Documentation/gitdiffcore.txt
+++ b/Documentation/gitdiffcore.txt
@@ -222,26 +222,35 @@
 diffcore-pickaxe: For Detecting Addition/Deletion of Specified String
 ---------------------------------------------------------------------
 
-This transformation is used to find filepairs that represent
-changes that touch a specified string, and is controlled by the
--S option and the `--pickaxe-all` option to the 'git diff-*'
-commands.
+This transformation limits the set of filepairs to those that change
+specified strings between the preimage and the postimage in a certain
+way.  -S<block of text> and -G<regular expression> options are used to
+specify different ways these strings are sought.
 
-When diffcore-pickaxe is in use, it checks if there are
-filepairs whose "result" side and whose "origin" side have
-different number of specified string.  Such a filepair represents
-"the string appeared in this changeset".  It also checks for the
-opposite case that loses the specified string.
+"-S<block of text>" detects filepairs whose preimage and postimage
+have different number of occurrences of the specified block of text.
+By definition, it will not detect in-file moves.  Also, when a
+changeset moves a file wholesale without affecting the interesting
+string, diffcore-rename kicks in as usual, and `-S` omits the filepair
+(since the number of occurrences of that string didn't change in that
+rename-detected filepair).  When used with `--pickaxe-regex`, treat
+the <block of text> as an extended POSIX regular expression to match,
+instead of a literal string.
 
-When `--pickaxe-all` is not in effect, diffcore-pickaxe leaves
-only such filepairs that touch the specified string in its
-output.  When `--pickaxe-all` is used, diffcore-pickaxe leaves all
-filepairs intact if there is such a filepair, or makes the
-output empty otherwise.  The latter behaviour is designed to
-make reviewing of the changes in the context of the whole
+"-G<regular expression>" (mnemonic: grep) detects filepairs whose
+textual diff has an added or a deleted line that matches the given
+regular expression.  This means that it will detect in-file (or what
+rename-detection considers the same file) moves, which is noise.  The
+implementation runs diff twice and greps, and this can be quite
+expensive.
+
+When `-S` or `-G` are used without `--pickaxe-all`, only filepairs
+that match their respective criterion are kept in the output.  When
+`--pickaxe-all` is used, if even one filepair matches their respective
+criterion in a changeset, the entire changeset is kept.  This behavior
+is designed to make reviewing changes in the context of the whole
 changeset easier.
 
-
 diffcore-order: For Sorting the Output Based on Filenames
 ---------------------------------------------------------
 
diff --git a/Documentation/gitremote-helpers.txt b/Documentation/gitremote-helpers.txt
index da74641..0827f69 100644
--- a/Documentation/gitremote-helpers.txt
+++ b/Documentation/gitremote-helpers.txt
@@ -159,11 +159,11 @@
 	carried out.
 
 'refspec' <refspec>::
-	This modifies the 'import' capability, allowing the produced
-	fast-import stream to modify refs in a private namespace
-	instead of writing to refs/heads or refs/remotes directly.
+	For remote helpers that implement 'import' or 'export', this capability
+	allows the refs to be constrained to a private namespace, instead of
+	writing to refs/heads or refs/remotes directly.
 	It is recommended that all importers providing the 'import'
-	capability use this.
+	capability use this. It's mandatory for 'export'.
 +
 A helper advertising the capability
 `refspec refs/heads/*:refs/svn/origin/branches/*`
@@ -174,8 +174,8 @@
 This capability can be advertised multiple times.  The first
 applicable refspec takes precedence.  The left-hand of refspecs
 advertised with this capability must cover all refs reported by
-the list command.  If a helper does not need a specific 'refspec'
-capability then it should advertise `refspec *:*`.
+the list command.  If no 'refspec' capability is advertised,
+there is an implied `refspec *:*`.
 
 'bidi-import'::
 	This modifies the 'import' capability.
diff --git a/Documentation/gitrepository-layout.txt b/Documentation/gitrepository-layout.txt
index d6f3393..aa03882 100644
--- a/Documentation/gitrepository-layout.txt
+++ b/Documentation/gitrepository-layout.txt
@@ -211,6 +211,9 @@
 	and maintained by shallow clone mechanism.  See `--depth`
 	option to linkgit:git-clone[1] and linkgit:git-fetch[1].
 
+modules::
+	Contains the git-repositories of the submodules.
+
 SEE ALSO
 --------
 linkgit:git-init[1],
diff --git a/Documentation/gitweb.conf.txt b/Documentation/gitweb.conf.txt
index ea0526e..305db63 100644
--- a/Documentation/gitweb.conf.txt
+++ b/Documentation/gitweb.conf.txt
@@ -336,8 +336,26 @@
 	used as the first component of gitweb's "breadcrumb trail":
 	`<home link> / <project> / <action>`.  Can be set at build time using
 	the `GITWEB_HOME_LINK_STR` variable.  By default it is set to "projects",
-	as this link leads to the list of projects.  Other popular choice it to
-	set it to the name of site.
+	as this link leads to the list of projects.  Another popular choice is to
+	set it to the name of site.  Note that it is treated as raw HTML so it
+	should not be set from untrusted sources.
+
+@extra_breadcrumbs::
+	Additional links to be added to the start of the breadcrumb trail before
+	the home link, to pages that are logically "above" the gitweb projects
+	list, such as the organization and department which host the gitweb
+	server. Each element of the list is a reference to an array, in which
+	element 0 is the link text (equivalent to `$home_link_str`) and element
+	1 is the target URL (equivalent to `$home_link`).
++
+For example, the following setting produces a breadcrumb trail like
+"home / dev / projects / ..." where "projects" is the home link.
+----------------------------------------------------------------------------
+    our @extra_breadcrumbs = (
+      [ 'home' => 'https://www.example.org/' ],
+      [ 'dev'  => 'https://dev.example.org/' ],
+    );
+----------------------------------------------------------------------------
 
 $logo_url::
 $logo_label::
diff --git a/Documentation/gitweb.txt b/Documentation/gitweb.txt
index 40969f1..cca14b8 100644
--- a/Documentation/gitweb.txt
+++ b/Documentation/gitweb.txt
@@ -504,7 +504,7 @@
 
 The above configuration expects your public repositories to live under
 '/pub/git' and will serve them as `http://git.domain.org/dir-under-pub-git`,
-both as cloneable Git URL and as browseable gitweb interface.  If you then
+both as clonable Git URL and as browseable gitweb interface.  If you then
 start your linkgit:git-daemon[1] with `--base-path=/pub/git --export-all`
 then you can even use the `git://` URL with exactly the same path.
 
diff --git a/Documentation/glossary-content.txt b/Documentation/glossary-content.txt
index 68a18e1..dba5062 100644
--- a/Documentation/glossary-content.txt
+++ b/Documentation/glossary-content.txt
@@ -113,7 +113,7 @@
 while the HEAD is detached. They update the HEAD to point at the tip
 of the updated history without affecting any branch.  Commands that
 update or inquire information _about_ the current branch (e.g. `git
-branch --set-upstream-to` that sets what remote tracking branch the
+branch --set-upstream-to` that sets what remote-tracking branch the
 current branch integrates with) obviously do not work, as there is no
 (real) current branch to ask about in this state.
 
@@ -267,7 +267,7 @@
 	The default upstream <<def_repository,repository>>. Most projects have
 	at least one upstream project which they track. By default
 	'origin' is used for that purpose. New upstream updates
-	will be fetched into remote <<def_remote_tracking_branch,remote-tracking branches>> named
+	will be fetched into <<def_remote_tracking_branch,remote-tracking branches>> named
 	origin/name-of-upstream-branch, which you can see using
 	`git branch -r`.
 
@@ -400,12 +400,13 @@
 	<<def_ref,ref>> and local ref.
 
 [[def_remote_tracking_branch]]remote-tracking branch::
-	A regular Git <<def_branch,branch>> that is used to follow changes from
-	another <<def_repository,repository>>. A remote-tracking
-	branch should not contain direct modifications or have local commits
-	made to it. A remote-tracking branch can usually be
-	identified as the right-hand-side <<def_ref,ref>> in a Pull:
-	<<def_refspec,refspec>>.
+	A <<def_ref,ref>> that is used to follow changes from another
+	<<def_repository,repository>>. It typically looks like
+	'refs/remotes/foo/bar' (indicating that it tracks a branch named
+	'bar' in a remote named 'foo'), and matches the right-hand-side of
+	a configured fetch <<def_refspec,refspec>>. A remote-tracking
+	branch should not contain direct modifications or have local
+	commits made to it.
 
 [[def_repository]]repository::
 	A collection of <<def_ref,refs>> together with an
diff --git a/Documentation/howto/new-command.txt b/Documentation/howto/new-command.txt
index 2abc3a0..d7de5a3 100644
--- a/Documentation/howto/new-command.txt
+++ b/Documentation/howto/new-command.txt
@@ -94,7 +94,7 @@
 6. There is a file command-list.txt in the distribution main directory
 that categorizes commands by type, so they can be listed in appropriate
 subsections in the documentation's summary command list.  Add an entry
-for yours.  To understand the categories, look at git-cmmands.txt
+for yours.  To understand the categories, look at git-commands.txt
 in the main directory.
 
 7. Give the maintainer one paragraph to include in the RelNotes file
diff --git a/Documentation/howto/revert-branch-rebase.txt b/Documentation/howto/revert-branch-rebase.txt
index 84dd839..0d5419e 100644
--- a/Documentation/howto/revert-branch-rebase.txt
+++ b/Documentation/howto/revert-branch-rebase.txt
@@ -12,7 +12,7 @@
 ================================
 
 One of the changes I pulled into the 'master' branch turns out to
-break building Git with GCC 2.95.  While they were well intentioned
+break building Git with GCC 2.95.  While they were well-intentioned
 portability fixes, keeping things working with gcc-2.95 was also
 important.  Here is what I did to revert the change in the 'master'
 branch and to adjust the 'pu' branch, using core Git tools and
diff --git a/Documentation/line-range-format.txt b/Documentation/line-range-format.txt
new file mode 100644
index 0000000..3e7ce72
--- /dev/null
+++ b/Documentation/line-range-format.txt
@@ -0,0 +1,25 @@
+- number
++
+If <start> or <end> is a number, it specifies an
+absolute line number (lines count from 1).
++
+
+- /regex/
++
+This form will use the first line matching the given
+POSIX regex.  If <end> is a regex, it will search
+starting at the line given by <start>.
++
+
+- +offset or -offset
++
+This is only valid for <end> and will specify a number
+of lines before or after the line given by <start>.
++
+
+- :regex
++
+If the option's argument is of the form :regex, it denotes the range
+from the first funcname line that matches <regex>, up to the next
+funcname line.
++
diff --git a/Documentation/merge-options.txt b/Documentation/merge-options.txt
index 2adccf8..afba8d4 100644
--- a/Documentation/merge-options.txt
+++ b/Documentation/merge-options.txt
@@ -8,12 +8,13 @@
 inspect and further tweak the merge result before committing.
 
 --edit::
+-e::
 --no-edit::
 	Invoke an editor before committing successful mechanical merge to
 	further edit the auto-generated merge message, so that the user
 	can explain and justify the merge. The `--no-edit` option can be
 	used to accept the auto-generated message (this is generally
-	discouraged). The `--edit` option is still useful if you are
+	discouraged). The `--edit` (or `-e`) option is still useful if you are
 	giving a draft message with the `-m` option from the command line
 	and want to edit it in the editor.
 +
diff --git a/Documentation/pretty-options.txt b/Documentation/pretty-options.txt
index 5e49942..eea0e30 100644
--- a/Documentation/pretty-options.txt
+++ b/Documentation/pretty-options.txt
@@ -28,7 +28,7 @@
 	This is a shorthand for "--pretty=oneline --abbrev-commit"
 	used together.
 
---encoding[=<encoding>]::
+--encoding=<encoding>::
 	The commit objects record the encoding used for the log message
 	in their encoding header; this option can be used to tell the
 	command to re-code the commit log message in the encoding
diff --git a/Documentation/pull-fetch-param.txt b/Documentation/pull-fetch-param.txt
index 94a9d32..18cffc2 100644
--- a/Documentation/pull-fetch-param.txt
+++ b/Documentation/pull-fetch-param.txt
@@ -68,6 +68,11 @@
 +
 * `tag <tag>` means the same as `refs/tags/<tag>:refs/tags/<tag>`;
   it requests fetching everything up to the given tag.
-* A parameter <ref> without a colon is equivalent to
-  <ref>: when pulling/fetching, so it merges <ref> into the current
-  branch without storing the remote branch anywhere locally
+ifndef::git-pull[]
+* A parameter <ref> without a colon fetches that ref into FETCH_HEAD,
+endif::git-pull[]
+ifdef::git-pull[]
+* A parameter <ref> without a colon merges <ref> into the current
+  branch,
+endif::git-pull[]
+  and updates the remote-tracking branches (if any).
diff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt
index 3bdbf5e..5bdfb42 100644
--- a/Documentation/rev-list-options.txt
+++ b/Documentation/rev-list-options.txt
@@ -119,7 +119,7 @@
 --no-min-parents::
 --no-max-parents::
 
-	Show only commits which have at least (or at most) that many
+	Show only commits which have at least (or at most) that many parent
 	commits. In particular, `--max-parents=1` is the same as `--no-merges`,
 	`--min-parents=2` is the same as `--merges`.  `--max-parents=0`
 	gives all root commits and `--min-parents=3` all octopus merges.
@@ -271,8 +271,8 @@
 
 --boundary::
 
-	Output uninteresting commits at the boundary, which are usually
-	not shown.
+	Output excluded boundary commits. Boundary commits are
+	prefixed with `-`.
 
 --
 
@@ -342,13 +342,13 @@
 illustrate the differences between simplification settings.  We assume
 that you are filtering for a file `foo` in this commit graph:
 -----------------------------------------------------------------------
-	  .-A---M---N---O---P
-	 /     /   /   /   /
-	I     B   C   D   E
-	 \   /   /   /   /
-	  `-------------'
+	  .-A---M---N---O---P---Q
+	 /     /   /   /   /   /
+	I     B   C   D   E   Y
+	 \   /   /   /   /   /
+	  `-------------'   X
 -----------------------------------------------------------------------
-The horizontal line of history A---P is taken to be the first parent of
+The horizontal line of history A---Q is taken to be the first parent of
 each merge.  The commits are:
 
 * `I` is the initial commit, in which `foo` exists with contents
@@ -367,8 +367,11 @@
   `N` and `D` to "foobarbaz"; i.e., it is not TREESAME to any parent.
 
 * `E` changes `quux` to "xyzzy", and its merge `P` combines the
-  strings to "quux xyzzy".  Despite appearing interesting, `P` is
-  TREESAME to all parents.
+  strings to "quux xyzzy".  `P` is TREESAME to `O`, but not to `E`.
+
+* `X` is an independent root commit that added a new file `side`, and `Y`
+  modified it. `Y` is TREESAME to `X`. Its merge `Q` added `side` to `P`, and
+  `Q` is TREESAME to `P`, but not to `Y`.
 
 'rev-list' walks backwards through history, including or excluding
 commits based on whether '\--full-history' and/or parent rewriting
@@ -410,10 +413,10 @@
 	the example, we get
 +
 -----------------------------------------------------------------------
-	I  A  B  N  D  O
+	I  A  B  N  D  O  P  Q
 -----------------------------------------------------------------------
 +
-`P` and `M` were excluded because they are TREESAME to a parent.  `E`,
+`M` was excluded because it is TREESAME to both parents.  `E`,
 `C` and `B` were all walked, but only `B` was !TREESAME, so the others
 do not appear.
 +
@@ -431,7 +434,7 @@
 themselves.  This results in
 +
 -----------------------------------------------------------------------
-	  .-A---M---N---O---P
+	  .-A---M---N---O---P---Q
 	 /     /   /   /   /
 	I     B   /   D   /
 	 \   /   /   /   /
@@ -441,7 +444,7 @@
 Compare to '\--full-history' without rewriting above.  Note that `E`
 was pruned away because it is TREESAME, but the parent list of P was
 rewritten to contain `E`'s parent `I`.  The same happened for `C` and
-`N`.  Note also that `P` was included despite being TREESAME.
+`N`, and `X`, `Y` and `Q`.
 
 In addition to the above settings, you can change whether TREESAME
 affects inclusion:
@@ -471,8 +474,9 @@
 * Set `C'` to `C`.
 +
 * Replace each parent `P` of `C'` with its simplification `P'`.  In
-  the process, drop parents that are ancestors of other parents, and
-  remove duplicates.
+  the process, drop parents that are ancestors of other parents or that are
+  root commits TREESAME to an empty tree, and remove duplicates, but take care
+  to never drop all parents that we are TREESAME to.
 +
 * If after this parent rewriting, `C'` is a root or merge commit (has
   zero or >1 parents), a boundary commit, or !TREESAME, it remains.
@@ -490,7 +494,7 @@
 	  `---------'
 -----------------------------------------------------------------------
 +
-Note the major differences in `N` and `P` over '--full-history':
+Note the major differences in `N`, `P` and `Q` over '--full-history':
 +
 --
 * `N`'s parent list had `I` removed, because it is an ancestor of the
@@ -498,6 +502,10 @@
 +
 * `P`'s parent list similarly had `I` removed.  `P` was then
   removed completely, because it had one parent and is TREESAME.
++
+* `Q`'s parent list had `Y` simplified to `X`. `X` was then removed, because it
+  was a TREESAME root. `Q` was then removed completely, because it had one
+  parent and is TREESAME.
 --
 
 Finally, there is a fifth simplification mode available:
@@ -617,6 +625,10 @@
 	Show no parents before all of its children are shown, but
 	otherwise show commits in the commit timestamp order.
 
+--author-date-order::
+	Show no parents before all of its children are shown, but
+	otherwise show commits in the author timestamp order.
+
 --topo-order::
 	Show no parents before all of its children are shown, and
 	avoid showing commits on multiple lines of history
@@ -837,7 +849,4 @@
 -t::
 
 	Show the tree objects in the diff output. This implies '-r'.
-
--s::
-	Suppress diff output.
 endif::git-rev-list[]
diff --git a/Documentation/technical/api-builtin.txt b/Documentation/technical/api-builtin.txt
index 4a4228b..f3c1357 100644
--- a/Documentation/technical/api-builtin.txt
+++ b/Documentation/technical/api-builtin.txt
@@ -39,7 +39,7 @@
 	on bare repositories.
 	This only makes sense when `RUN_SETUP` is also set.
 
-. Add `builtin-foo.o` to `BUILTIN_OBJS` in `Makefile`.
+. Add `builtin/foo.o` to `BUILTIN_OBJS` in `Makefile`.
 
 Additionally, if `foo` is a new command, there are 3 more things to do:
 
diff --git a/Documentation/technical/api-parse-options.txt b/Documentation/technical/api-parse-options.txt
index 32ddc1c..0be2b51 100644
--- a/Documentation/technical/api-parse-options.txt
+++ b/Documentation/technical/api-parse-options.txt
@@ -41,6 +41,8 @@
 * Boolean long options can be 'negated' (or 'unset') by prepending
   `no-`, e.g. `--no-abbrev` instead of `--abbrev`. Conversely,
   options that begin with `no-` can be 'negated' by removing it.
+  Other long options can be unset (e.g., set string to NULL, set
+  integer to 0) by prepending `no-`.
 
 * Options and non-option arguments can clearly be separated using the `--`
   option, e.g. `-a -b --option -- --this-is-a-file` indicates that
@@ -174,6 +176,10 @@
 	Introduce an option with date argument, see `approxidate()`.
 	The timestamp is put into `int_var`.
 
+`OPT_EXPIRY_DATE(short, long, &int_var, description)`::
+	Introduce an option with expiry date argument, see `parse_expiry_date()`.
+	The timestamp is put into `int_var`.
+
 `OPT_CALLBACK(short, long, &var, arg_str, description, func_ptr)`::
 	Introduce an option with argument.
 	The argument will be fed into the function given by `func_ptr`
@@ -269,10 +275,10 @@
 --------
 
 See `test-parse-options.c` and
-`builtin-add.c`,
-`builtin-clone.c`,
-`builtin-commit.c`,
-`builtin-fetch.c`,
-`builtin-fsck.c`,
-`builtin-rm.c`
+`builtin/add.c`,
+`builtin/clone.c`,
+`builtin/commit.c`,
+`builtin/fetch.c`,
+`builtin/fsck.c`,
+`builtin/rm.c`
 for real-world examples.
diff --git a/Documentation/technical/api-revision-walking.txt b/Documentation/technical/api-revision-walking.txt
index b7d0d9a..55b878a 100644
--- a/Documentation/technical/api-revision-walking.txt
+++ b/Documentation/technical/api-revision-walking.txt
@@ -59,7 +59,7 @@
 `reset_revision_walk`::
 
 	Reset the flags used by the revision walking api. You can use
-	this to do multiple sequencial revision walks.
+	this to do multiple sequential revision walks.
 
 Data structures
 ---------------
diff --git a/Documentation/technical/index-format.txt b/Documentation/technical/index-format.txt
index 0810251..f352a9b 100644
--- a/Documentation/technical/index-format.txt
+++ b/Documentation/technical/index-format.txt
@@ -175,7 +175,7 @@
 
   A conflict is represented in the index as a set of higher stage entries.
   When a conflict is resolved (e.g. with "git add path"), these higher
-  stage entries will be removed and a stage-0 entry with proper resoluton
+  stage entries will be removed and a stage-0 entry with proper resolution
   is added.
 
   When these higher stage entries are removed, they are saved in the
diff --git a/Documentation/technical/pack-protocol.txt b/Documentation/technical/pack-protocol.txt
index f1a51ed..b898e97 100644
--- a/Documentation/technical/pack-protocol.txt
+++ b/Documentation/technical/pack-protocol.txt
@@ -228,8 +228,7 @@
 The client MUST write all obj-ids which it only has shallow copies
 of (meaning that it does not have the parents of a commit) as
 'shallow' lines so that the server is aware of the limitations of
-the client's history. Clients MUST NOT mention an obj-id which
-it does not know exists on the server.
+the client's history.
 
 The client now sends the maximum commit history depth it wants for
 this transaction, which is the number of commits it wants from the
diff --git a/Documentation/technical/protocol-capabilities.txt b/Documentation/technical/protocol-capabilities.txt
index b15517f..fd8ffa5 100644
--- a/Documentation/technical/protocol-capabilities.txt
+++ b/Documentation/technical/protocol-capabilities.txt
@@ -18,11 +18,12 @@
 and server advertised.  As a consequence of these rules, server MUST
 NOT advertise capabilities it does not understand.
 
-The 'report-status' and 'delete-refs' capabilities are sent and
+The 'report-status', 'delete-refs', and 'quiet' capabilities are sent and
 recognized by the receive-pack (push to server) process.
 
-The 'ofs-delta' capability is sent and recognized by both upload-pack
-and receive-pack protocols.
+The 'ofs-delta' and 'side-band-64k' capabilities are sent and recognized
+by both upload-pack and receive-pack protocols.  The 'agent' capability
+may optionally be sent in both protocols.
 
 All other capabilities are only recognized by the upload-pack (fetch
 from server) process.
@@ -123,6 +124,20 @@
 its base by position in pack rather than by an obj-id.  That is, they can
 send/read OBJ_OFS_DELTA (aka type 6) in a packfile.
 
+agent
+-----
+
+The server may optionally send a capability of the form `agent=X` to
+notify the client that the server is running version `X`. The client may
+optionally return its own agent string by responding with an `agent=Y`
+capability (but it MUST NOT do so if the server did not mention the
+agent capability). The `X` and `Y` strings may contain any printable
+ASCII characters except space (i.e., the byte range 32 < x < 127), and
+are typically of the form "package/version" (e.g., "git/1.8.3.1"). The
+agent strings are purely informative for statistics and debugging
+purposes, and MUST NOT be used to programatically assume the presence
+or absence of particular features.
+
 shallow
 -------
 
@@ -168,7 +183,7 @@
 report-status
 -------------
 
-The upload-pack process can receive a 'report-status' capability,
+The receive-pack process can receive a 'report-status' capability,
 which tells it that the client wants a report of what happened after
 a packfile upload and reference update.  If the pushing client requests
 this capability, after unpacking and updating references the server
@@ -185,3 +200,20 @@
 value of a reference update.  It is not sent back by the client, it
 simply informs the client that it can be sent zero-id values
 to delete references.
+
+quiet
+-----
+
+If the receive-pack server advertises the 'quiet' capability, it is
+capable of silencing human-readable progress output which otherwise may
+be shown when processing the received pack. A send-pack client should
+respond with the 'quiet' capability to suppress server-side progress
+reporting if the local progress reporting is also being suppressed
+(e.g., via `push -q`, or if stderr does not go to a tty).
+
+allow-tip-sha1-in-want
+----------------------
+
+If the upload-pack server advertises this capability, fetch-pack may
+send "want" lines with SHA-1s that exist at the server but are not
+advertised by upload-pack.
diff --git a/Documentation/technical/racy-git.txt b/Documentation/technical/racy-git.txt
index 6dc82ca..242a044 100644
--- a/Documentation/technical/racy-git.txt
+++ b/Documentation/technical/racy-git.txt
@@ -46,7 +46,7 @@
 on-disk timestamps, resulting in meaningless changes when an
 inode is evicted from the inode cache.  See commit 8ce13b0
 of git://git.kernel.org/pub/scm/linux/kernel/git/tglx/history.git
-([PATCH] Sync in core time granuality with filesystems,
+([PATCH] Sync in core time granularity with filesystems,
 2005-01-04).
 
 Racy Git
@@ -135,9 +135,9 @@
   $ git ls-files | git update-index --stdin
   $ touch -r .datestamp .git/index
 
-This will make all index entries racily clean.  The linux-2.6
-project, for example, there are over 20,000 files in the working
-tree.  On my Athlon 64 X2 3800+, after the above:
+This will make all index entries racily clean.  The linux project, for
+example, there are over 20,000 files in the working tree.  On my
+Athlon 64 X2 3800+, after the above:
 
   $ /usr/bin/time git diff-files
   1.68user 0.54system 0:02.22elapsed 100%CPU (0avgtext+0avgdata 0maxresident)k
diff --git a/Documentation/urls.txt b/Documentation/urls.txt
index 3ca122f..9ccb246 100644
--- a/Documentation/urls.txt
+++ b/Documentation/urls.txt
@@ -11,6 +11,9 @@
 and pushing, but these are inefficient and deprecated; do not use
 them).
 
+The native transport (i.e. git:// URL) does no authentication and
+should be used with caution on unsecured networks.
+
 The following syntaxes may be used with them:
 
 - ssh://{startsb}user@{endsb}host.xz{startsb}:port{endsb}/path/to/repo.git/
@@ -23,6 +26,12 @@
 
 - {startsb}user@{endsb}host.xz:path/to/repo.git/
 
+This syntax is only recognized if there are no slashes before the
+first colon. This helps differentiate a local path that contains a
+colon. For example the local path `foo:bar` could be specified as an
+absolute path or `./foo:bar` to avoid being misinterpreted as an ssh
+url.
+
 The ssh and git protocols additionally support ~username expansion:
 
 - ssh://{startsb}user@{endsb}host.xz{startsb}:port{endsb}/~{startsb}user{endsb}/path/to/repo.git/
@@ -33,7 +42,7 @@
 syntaxes may be used:
 
 - /path/to/repo.git/
-- file:///path/to/repo.git/
+- \file:///path/to/repo.git/
 
 ifndef::git-clone[]
 These two syntaxes are mostly equivalent, except when cloning, when
diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt
index e831cc2..fe723e4 100644
--- a/Documentation/user-manual.txt
+++ b/Documentation/user-manual.txt
@@ -57,17 +57,17 @@
 project in mind, here are some interesting examples:
 
 ------------------------------------------------
-	# Git itself (approx. 10MB download):
+	# Git itself (approx. 40MB download):
 $ git clone git://git.kernel.org/pub/scm/git/git.git
-	# the Linux kernel (approx. 150MB download):
-$ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
+	# the Linux kernel (approx. 640MB download):
+$ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
 ------------------------------------------------
 
 The initial clone may be time-consuming for a large project, but you
 will only need to clone once.
 
-The clone command creates a new directory named after the project (`git`
-or `linux-2.6` in the examples above).  After you cd into this
+The clone command creates a new directory named after the project
+(`git` or `linux` in the examples above).  After you cd into this
 directory, you will see that it contains a copy of the project files,
 called the <<def_working_tree,working tree>>, together with a special
 top-level directory named `.git`, which contains all the information
@@ -431,19 +431,25 @@
 cloned from, using linkgit:git-remote[1]:
 
 -------------------------------------------------
-$ git remote add linux-nfs git://linux-nfs.org/pub/nfs-2.6.git
-$ git fetch linux-nfs
-* refs/remotes/linux-nfs/master: storing branch 'master' ...
-  commit: bf81b46
+$ git remote add staging git://git.kernel.org/.../gregkh/staging.git
+$ git fetch staging
+...
+From git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging
+ * [new branch]      master     -> staging/master
+ * [new branch]      staging-linus -> staging/staging-linus
+ * [new branch]      staging-next -> staging/staging-next
 -------------------------------------------------
 
 New remote-tracking branches will be stored under the shorthand name
-that you gave `git remote add`, in this case `linux-nfs`:
+that you gave `git remote add`, in this case `staging`:
 
 -------------------------------------------------
 $ git branch -r
-linux-nfs/master
-origin/master
+  origin/HEAD -> origin/master
+  origin/master
+  staging/master
+  staging/staging-linus
+  staging/staging-next
 -------------------------------------------------
 
 If you run `git fetch <remote>` later, the remote-tracking branches
@@ -455,9 +461,9 @@
 -------------------------------------------------
 $ cat .git/config
 ...
-[remote "linux-nfs"]
-	url = git://linux-nfs.org/pub/nfs-2.6.git
-	fetch = +refs/heads/*:refs/remotes/linux-nfs/*
+[remote "staging"]
+	url = git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging.git
+	fetch = +refs/heads/*:refs/remotes/staging/*
 ...
 -------------------------------------------------
 
@@ -1835,7 +1841,7 @@
 resolution, instead of creating a new commit, just run
 
 -------------------------------------------------
-$ git am --resolved
+$ git am --continue
 -------------------------------------------------
 
 and Git will create the commit for you and continue applying the
@@ -2156,7 +2162,7 @@
 tree:
 
 -------------------------------------------------
-$ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git work
+$ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git work
 $ cd work
 -------------------------------------------------
 
@@ -2198,7 +2204,7 @@
 -------------------------------------------------
 $ cat >> .git/config <<EOF
 [remote "mytree"]
-	url =  master.kernel.org:/pub/scm/linux/kernel/git/aegl/linux-2.6.git
+	url =  master.kernel.org:/pub/scm/linux/kernel/git/aegl/linux.git
 	push = release
 	push = test
 EOF
@@ -4256,15 +4262,16 @@
 Nowadays, `git log` is a builtin, which means that it is _contained_ in the
 command `git`.  The source side of a builtin is
 
-- a function called `cmd_<bla>`, typically defined in `builtin-<bla>.c`,
-  and declared in `builtin.h`,
+- a function called `cmd_<bla>`, typically defined in `builtin/<bla.c>`
+  (note that older versions of Git used to have it in `builtin-<bla>.c`
+  instead), and declared in `builtin.h`.
 
 - an entry in the `commands[]` array in `git.c`, and
 
 - an entry in `BUILTIN_OBJECTS` in the `Makefile`.
 
 Sometimes, more than one builtin is contained in one source file.  For
-example, `cmd_whatchanged()` and `cmd_log()` both reside in `builtin-log.c`,
+example, `cmd_whatchanged()` and `cmd_log()` both reside in `builtin/log.c`,
 since they share quite a bit of code.  In that case, the commands which are
 _not_ named like the `.c` file in which they live have to be listed in
 `BUILT_INS` in the `Makefile`.
@@ -4287,10 +4294,10 @@
 - is plumbing, and
 
 - was around even in the initial commit (it literally went only through
-  some 20 revisions as `cat-file.c`, was renamed to `builtin-cat-file.c`
+  some 20 revisions as `cat-file.c`, was renamed to `builtin/cat-file.c`
   when made a builtin, and then saw less than 10 versions).
 
-So, look into `builtin-cat-file.c`, search for `cmd_cat_file()` and look what
+So, look into `builtin/cat-file.c`, search for `cmd_cat_file()` and look what
 it does.
 
 ------------------------------------------------------------------
@@ -4366,7 +4373,7 @@
 builtin:
 
 -------------------------------------------------
-$ git log --no-merges --diff-filter=A builtin-*.c
+$ git log --no-merges --diff-filter=A builtin/*.c
 -------------------------------------------------
 
 You see, Git is actually the best tool to find out about the source of Git
@@ -4668,5 +4675,5 @@
 Alternates, clone -reference, etc.
 
 More on recovery from repository corruption.  See:
-	http://marc.theaimsgroup.com/?l=git&m=117263864820799&w=2
-	http://marc.theaimsgroup.com/?l=git&m=117147855503798&w=2
+	http://marc.info/?l=git&m=117263864820799&w=2
+	http://marc.info/?l=git&m=117147855503798&w=2
diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN
index 7a24aca..06026ea 100755
--- a/GIT-VERSION-GEN
+++ b/GIT-VERSION-GEN
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v1.8.3-rc1
+DEF_VER=v1.8.4
 
 LF='
 '
@@ -11,7 +11,7 @@
 if test -f version
 then
 	VN=$(cat version) || VN="$DEF_VER"
-elif test -d .git -o -f .git &&
+elif test -d ${GIT_DIR:-.git} -o -f .git &&
 	VN=$(git describe --match "v[0-9]*" --abbrev=7 HEAD 2>/dev/null) &&
 	case "$VN" in
 	*$LF*) (exit 1) ;;
diff --git a/Makefile b/Makefile
index 0f931a2..4026211 100644
--- a/Makefile
+++ b/Makefile
@@ -106,7 +106,7 @@
 # Define NO_FNMATCH_CASEFOLD if your fnmatch function doesn't have the
 # FNM_CASEFOLD GNU extension.
 #
-# Define USE_WILDMATCH if you want to use Git's wildmatch
+# Define NO_WILDMATCH if you do not want to use Git's wildmatch
 # implementation as fnmatch
 #
 # Define NO_GECOS_IN_PWENT if you don't have pw_gecos in struct passwd
@@ -137,6 +137,10 @@
 # specify your own (or DarwinPort's) include directories and
 # library directories by defining CFLAGS and LDFLAGS appropriately.
 #
+# Define NO_APPLE_COMMON_CRYPTO if you are building on Darwin/Mac OS X
+# and do not want to use Apple's CommonCrypto library.  This allows you
+# to provide your own OpenSSL library, for example from MacPorts.
+#
 # Define BLK_SHA1 environment variable to make use of the bundled
 # optimized C SHA1 routine.
 #
@@ -290,10 +294,6 @@
 #
 # Define NO_REGEX if you have no or inferior regex support in your C library.
 #
-# Define CYGWIN_V15_WIN32API if you are using Cygwin v1.7.x but are not
-# using the current w32api packages. The recommended approach, however,
-# is to update your installation if compilation errors occur.
-#
 # Define HAVE_DEV_TTY if your system can open /dev/tty to interact with the
 # user.
 #
@@ -460,6 +460,7 @@
 SCRIPT_SH += git-pull.sh
 SCRIPT_SH += git-quiltimport.sh
 SCRIPT_SH += git-rebase.sh
+SCRIPT_SH += git-remote-testgit.sh
 SCRIPT_SH += git-repack.sh
 SCRIPT_SH += git-request-pull.sh
 SCRIPT_SH += git-stash.sh
@@ -487,11 +488,18 @@
 SCRIPT_PYTHON += git-remote-testpy.py
 SCRIPT_PYTHON += git-p4.py
 
+NO_INSTALL += git-remote-testgit
+NO_INSTALL += git-remote-testpy
+
 # Generated files for scripts
 SCRIPT_SH_GEN = $(patsubst %.sh,%,$(SCRIPT_SH))
 SCRIPT_PERL_GEN = $(patsubst %.perl,%,$(SCRIPT_PERL))
 SCRIPT_PYTHON_GEN = $(patsubst %.py,%,$(SCRIPT_PYTHON))
 
+SCRIPT_SH_INS = $(filter-out $(NO_INSTALL),$(SCRIPT_SH_GEN))
+SCRIPT_PERL_INS = $(filter-out $(NO_INSTALL),$(SCRIPT_PERL_GEN))
+SCRIPT_PYTHON_INS = $(filter-out $(NO_INSTALL),$(SCRIPT_PYTHON_GEN))
+
 # Individual rules to allow e.g.
 # "make -C ../.. SCRIPT_PERL=contrib/foo/bar.perl build-perl-script"
 # from subdirectories like contrib/*/
@@ -501,12 +509,12 @@
 build-python-script: $(SCRIPT_PYTHON_GEN)
 
 .PHONY: install-perl-script install-sh-script install-python-script
-install-sh-script: $(SCRIPT_SH_GEN)
-	$(INSTALL) $(SCRIPT_SH_GEN) '$(DESTDIR_SQ)$(gitexec_instdir_SQ)'
-install-perl-script: $(SCRIPT_PERL_GEN)
-	$(INSTALL) $(SCRIPT_PERL_GEN) '$(DESTDIR_SQ)$(gitexec_instdir_SQ)'
-install-python-script: $(SCRIPT_PYTHON_GEN)
-	$(INSTALL) $(SCRIPT_PYTHON_GEN) '$(DESTDIR_SQ)$(gitexec_instdir_SQ)'
+install-sh-script: $(SCRIPT_SH_INS)
+	$(INSTALL) $^ '$(DESTDIR_SQ)$(gitexec_instdir_SQ)'
+install-perl-script: $(SCRIPT_PERL_INS)
+	$(INSTALL) $^ '$(DESTDIR_SQ)$(gitexec_instdir_SQ)'
+install-python-script: $(SCRIPT_PYTHON_INS)
+	$(INSTALL) $^ '$(DESTDIR_SQ)$(gitexec_instdir_SQ)'
 
 .PHONY: clean-perl-script clean-sh-script clean-python-script
 clean-sh-script:
@@ -516,9 +524,9 @@
 clean-python-script:
 	$(RM) $(SCRIPT_PYTHON_GEN)
 
-SCRIPTS = $(SCRIPT_SH_GEN) \
-	  $(SCRIPT_PERL_GEN) \
-	  $(SCRIPT_PYTHON_GEN) \
+SCRIPTS = $(SCRIPT_SH_INS) \
+	  $(SCRIPT_PERL_INS) \
+	  $(SCRIPT_PYTHON_INS) \
 	  git-instaweb
 
 ETAGS_TARGET = TAGS
@@ -558,6 +566,8 @@
 TEST_PROGRAMS_NEED_X += test-mktemp
 TEST_PROGRAMS_NEED_X += test-parse-options
 TEST_PROGRAMS_NEED_X += test-path-utils
+TEST_PROGRAMS_NEED_X += test-prio-queue
+TEST_PROGRAMS_NEED_X += test-read-cache
 TEST_PROGRAMS_NEED_X += test-regex
 TEST_PROGRAMS_NEED_X += test-revision-walking
 TEST_PROGRAMS_NEED_X += test-run-command
@@ -641,7 +651,6 @@
 LIB_H += column.h
 LIB_H += commit.h
 LIB_H += compat/bswap.h
-LIB_H += compat/cygwin.h
 LIB_H += compat/mingw.h
 LIB_H += compat/obstack.h
 LIB_H += compat/poll/poll.h
@@ -673,6 +682,8 @@
 LIB_H += http.h
 LIB_H += kwset.h
 LIB_H += levenshtein.h
+LIB_H += line-log.h
+LIB_H += line-range.h
 LIB_H += list-objects.h
 LIB_H += ll-merge.h
 LIB_H += log-tree.h
@@ -682,15 +693,16 @@
 LIB_H += mergesort.h
 LIB_H += notes-cache.h
 LIB_H += notes-merge.h
+LIB_H += notes-utils.h
 LIB_H += notes.h
 LIB_H += object.h
-LIB_H += pack-refs.h
 LIB_H += pack-revindex.h
 LIB_H += pack.h
 LIB_H += parse-options.h
 LIB_H += patch-ids.h
 LIB_H += pathspec.h
 LIB_H += pkt-line.h
+LIB_H += prio-queue.h
 LIB_H += progress.h
 LIB_H += prompt.h
 LIB_H += quote.h
@@ -801,6 +813,8 @@
 LIB_OBJS += ident.o
 LIB_OBJS += kwset.o
 LIB_OBJS += levenshtein.o
+LIB_OBJS += line-log.o
+LIB_OBJS += line-range.o
 LIB_OBJS += list-objects.o
 LIB_OBJS += ll-merge.o
 LIB_OBJS += lockfile.o
@@ -815,9 +829,9 @@
 LIB_OBJS += notes.o
 LIB_OBJS += notes-cache.o
 LIB_OBJS += notes-merge.o
+LIB_OBJS += notes-utils.o
 LIB_OBJS += object.o
 LIB_OBJS += pack-check.o
-LIB_OBJS += pack-refs.o
 LIB_OBJS += pack-revindex.o
 LIB_OBJS += pack-write.o
 LIB_OBJS += pager.o
@@ -830,6 +844,7 @@
 LIB_OBJS += pkt-line.o
 LIB_OBJS += preload-index.o
 LIB_OBJS += pretty.o
+LIB_OBJS += prio-queue.o
 LIB_OBJS += progress.o
 LIB_OBJS += prompt.o
 LIB_OBJS += quote.o
@@ -893,6 +908,7 @@
 BUILTIN_OBJS += builtin/cat-file.o
 BUILTIN_OBJS += builtin/check-attr.o
 BUILTIN_OBJS += builtin/check-ignore.o
+BUILTIN_OBJS += builtin/check-mailmap.o
 BUILTIN_OBJS += builtin/check-ref-format.o
 BUILTIN_OBJS += builtin/checkout-index.o
 BUILTIN_OBJS += builtin/checkout.o
@@ -1054,6 +1070,11 @@
 			BASIC_LDFLAGS += -L/opt/local/lib
 		endif
 	endif
+	ifndef NO_APPLE_COMMON_CRYPTO
+		APPLE_COMMON_CRYPTO = YesPlease
+		COMPAT_CFLAGS += -DAPPLE_COMMON_CRYPTO
+	endif
+	NO_REGEX = YesPlease
 	PTHREAD_LIBS =
 endif
 
@@ -1261,7 +1282,7 @@
 	COMPAT_OBJS += compat/fnmatch/fnmatch.o
 endif
 endif
-ifdef USE_WILDMATCH
+ifndef NO_WILDMATCH
 	COMPAT_CFLAGS += -DUSE_WILDMATCH
 endif
 ifdef NO_SETENV
@@ -1388,10 +1409,16 @@
 	LIB_OBJS += ppc/sha1.o ppc/sha1ppc.o
 	LIB_H += ppc/sha1.h
 else
+ifdef APPLE_COMMON_CRYPTO
+	COMPAT_CFLAGS += -DCOMMON_DIGEST_FOR_OPENSSL
+	SHA1_HEADER = <CommonCrypto/CommonDigest.h>
+else
 	SHA1_HEADER = <openssl/sha.h>
 	EXTLIBS += $(LIB_4_CRYPTO)
 endif
 endif
+endif
+
 ifdef NO_PERL_MAKEMAKER
 	export NO_PERL_MAKEMAKER
 endif
@@ -1449,9 +1476,6 @@
 	COMPAT_CFLAGS += -Icompat/regex
 	COMPAT_OBJS += compat/regex/regex.o
 endif
-ifdef CYGWIN_V15_WIN32API
-	COMPAT_CFLAGS += -DCYGWIN_V15_WIN32API
-endif
 
 ifdef USE_NED_ALLOCATOR
        COMPAT_CFLAGS += -Icompat/nedmalloc
@@ -1503,6 +1527,7 @@
 	QUIET_MSGFMT   = @echo '   ' MSGFMT $@;
 	QUIET_GCOV     = @echo '   ' GCOV $@;
 	QUIET_SP       = @echo '   ' SP $<;
+	QUIET_RC       = @echo '   ' RC $@;
 	QUIET_SUBDIR0  = +@subdir=
 	QUIET_SUBDIR1  = ;$(NO_SUBDIR) echo '   ' SUBDIR $$subdir; \
 			 $(MAKE) $(PRINT_DIR) -C $$subdir
@@ -1645,7 +1670,7 @@
 shell_compatibility_test: please_set_SHELL_PATH_to_a_more_modern_shell
 
 strip: $(PROGRAMS) git$X
-	$(STRIP) $(STRIP_OPTS) $(PROGRAMS) git$X
+	$(STRIP) $(STRIP_OPTS) $^
 
 ### Target-specific flags and dependencies
 
@@ -1705,9 +1730,9 @@
 
 $(BUILT_INS): git$X
 	$(QUIET_BUILT_IN)$(RM) $@ && \
-	ln git$X $@ 2>/dev/null || \
-	ln -s git$X $@ 2>/dev/null || \
-	cp git$X $@
+	ln $< $@ 2>/dev/null || \
+	ln -s $< $@ 2>/dev/null || \
+	cp $< $@
 
 common-cmds.h: ./generate-cmdlist.sh command-list.txt
 
@@ -1748,6 +1773,11 @@
 	$(QUIET_GEN)$(cmd_munge_script) && \
 	mv $@+ $@
 
+git.res: git.rc GIT-VERSION-FILE
+	$(QUIET_RC)$(RC) \
+	  $(join -DMAJOR= -DMINOR= -DPATCH=, $(wordlist 1,3,$(subst -, ,$(subst ., ,$(GIT_VERSION))))) \
+	  -DGIT_VERSION="\\\"$(GIT_VERSION)\\\"" $< -o $@
+
 ifndef NO_PERL
 $(patsubst %.perl,%,$(SCRIPT_PERL)): perl/perl.mak
 
@@ -1772,7 +1802,7 @@
 	    -e '	x' \
 	    -e '}' \
 	    -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \
-	    $@.perl >$@+ && \
+	    $< >$@+ && \
 	chmod +x $@+ && \
 	mv $@+ $@
 
@@ -1796,8 +1826,8 @@
 endif # NO_PERL
 
 ifndef NO_PYTHON
-$(patsubst %.py,%,$(SCRIPT_PYTHON)): GIT-CFLAGS GIT-PREFIX GIT-PYTHON-VARS
-$(patsubst %.py,%,$(SCRIPT_PYTHON)): % : %.py
+$(SCRIPT_PYTHON_GEN): GIT-CFLAGS GIT-PREFIX GIT-PYTHON-VARS
+$(SCRIPT_PYTHON_GEN): % : %.py
 	$(QUIET_GEN)$(RM) $@ $@+ && \
 	INSTLIBDIR=`MAKEFLAGS= $(MAKE) -C git_remote_helpers -s \
 		--no-print-directory prefix='$(prefix_SQ)' DESTDIR='$(DESTDIR_SQ)' \
@@ -1805,11 +1835,11 @@
 	sed -e '1s|#!.*python|#!$(PYTHON_PATH_SQ)|' \
 	    -e 's|\(os\.getenv("GITPYTHONLIB"\)[^)]*)|\1,"@@INSTLIBDIR@@")|' \
 	    -e 's|@@INSTLIBDIR@@|'"$$INSTLIBDIR"'|g' \
-	    $@.py >$@+ && \
+	    $< >$@+ && \
 	chmod +x $@+ && \
 	mv $@+ $@
 else # NO_PYTHON
-$(patsubst %.py,%,$(SCRIPT_PYTHON)): % : unimplemented.sh
+$(SCRIPT_PYTHON_GEN): % : unimplemented.sh
 	$(QUIET_GEN)$(RM) $@ $@+ && \
 	sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \
 	    -e 's|@@REASON@@|NO_PYTHON=$(NO_PYTHON)|g' \
@@ -2004,6 +2034,7 @@
 ifdef USE_NED_ALLOCATOR
 compat/nedmalloc/nedmalloc.sp compat/nedmalloc/nedmalloc.o: EXTRA_CPPFLAGS = \
 	-DNDEBUG -DOVERRIDE_STRDUP -DREPLACE_SYSTEM_ALLOCATOR
+compat/nedmalloc/nedmalloc.sp: SPARSE_FLAGS += -Wno-non-pointer-null
 endif
 
 git-%$X: %.o GIT-LDFLAGS $(GITLIBS)
@@ -2035,13 +2066,13 @@
 		$(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)
 
 $(LIB_FILE): $(LIB_OBJS)
-	$(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIB_OBJS)
+	$(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $^
 
 $(XDIFF_LIB): $(XDIFF_OBJS)
-	$(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(XDIFF_OBJS)
+	$(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $^
 
 $(VCSSVN_LIB): $(VCSSVN_OBJS)
-	$(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(VCSSVN_OBJS)
+	$(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $^
 
 export DEFAULT_EDITOR DEFAULT_PAGER
 
@@ -2159,6 +2190,9 @@
 	@echo NO_PERL=\''$(subst ','\'',$(subst ','\'',$(NO_PERL)))'\' >>$@
 	@echo NO_PYTHON=\''$(subst ','\'',$(subst ','\'',$(NO_PYTHON)))'\' >>$@
 	@echo NO_UNIX_SOCKETS=\''$(subst ','\'',$(subst ','\'',$(NO_UNIX_SOCKETS)))'\' >>$@
+ifdef TEST_OUTPUT_DIRECTORY
+	@echo TEST_OUTPUT_DIRECTORY=\''$(subst ','\'',$(subst ','\'',$(TEST_OUTPUT_DIRECTORY)))'\' >>$@
+endif
 ifdef GIT_TEST_OPTS
 	@echo GIT_TEST_OPTS=\''$(subst ','\'',$(subst ','\'',$(GIT_TEST_OPTS)))'\' >>$@
 endif
@@ -2198,6 +2232,7 @@
 test_bindir_programs := $(patsubst %,bin-wrappers/%,$(BINDIR_PROGRAMS_NEED_X) $(BINDIR_PROGRAMS_NO_X) $(TEST_PROGRAMS_NEED_X))
 
 all:: $(TEST_PROGRAMS) $(test_bindir_programs)
+all:: $(NO_INSTALL)
 
 bin-wrappers/%: wrap-for-bin.sh
 	@mkdir -p bin-wrappers
@@ -2262,9 +2297,6 @@
 		exit 1; \
 	fi
 
-remove-dashes:
-	./fixup-builtins $(BUILT_INS) $(PROGRAMS) $(SCRIPTS)
-
 ### Installation rules
 
 ifneq ($(filter /%,$(firstword $(template_dir))),)
@@ -2443,11 +2475,11 @@
 	$(RM) $(addsuffix *.gcda,$(addprefix $(PROFILE_DIR)/, $(object_dirs)))
 	$(RM) $(addsuffix *.gcno,$(addprefix $(PROFILE_DIR)/, $(object_dirs)))
 
-clean: profile-clean
-	$(RM) *.o block-sha1/*.o ppc/*.o compat/*.o compat/*/*.o xdiff/*.o vcs-svn/*.o \
+clean: profile-clean coverage-clean
+	$(RM) *.o *.res block-sha1/*.o ppc/*.o compat/*.o compat/*/*.o xdiff/*.o vcs-svn/*.o \
 		builtin/*.o $(LIB_FILE) $(XDIFF_LIB) $(VCSSVN_LIB)
 	$(RM) $(ALL_PROGRAMS) $(SCRIPT_LIB) $(BUILT_INS) git$X
-	$(RM) $(TEST_PROGRAMS)
+	$(RM) $(TEST_PROGRAMS) $(NO_INSTALL)
 	$(RM) -r bin-wrappers $(dep_dirs)
 	$(RM) -r po/build/
 	$(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo common-cmds.h $(ETAGS_TARGET) tags cscope*
@@ -2524,29 +2556,34 @@
 
 ### Test suite coverage testing
 #
-.PHONY: coverage coverage-clean coverage-build coverage-report
+.PHONY: coverage coverage-clean coverage-compile coverage-test coverage-report
+.PHONY: coverage-clean-results
 
 coverage:
-	$(MAKE) coverage-build
-	$(MAKE) coverage-report
+	$(MAKE) coverage-test
+	$(MAKE) coverage-untested-functions
 
 object_dirs := $(sort $(dir $(OBJECTS)))
-coverage-clean:
+coverage-clean-results:
 	$(RM) $(addsuffix *.gcov,$(object_dirs))
 	$(RM) $(addsuffix *.gcda,$(object_dirs))
-	$(RM) $(addsuffix *.gcno,$(object_dirs))
 	$(RM) coverage-untested-functions
 	$(RM) -r cover_db/
 	$(RM) -r cover_db_html/
 
+coverage-clean: coverage-clean-results
+	$(RM) $(addsuffix *.gcno,$(object_dirs))
+
 COVERAGE_CFLAGS = $(CFLAGS) -O0 -ftest-coverage -fprofile-arcs
 COVERAGE_LDFLAGS = $(CFLAGS)  -O0 -lgcov
 GCOVFLAGS = --preserve-paths --branch-probabilities --all-blocks
 
-coverage-build: coverage-clean
+coverage-compile:
 	$(MAKE) CFLAGS="$(COVERAGE_CFLAGS)" LDFLAGS="$(COVERAGE_LDFLAGS)" all
+
+coverage-test: coverage-clean-results coverage-compile
 	$(MAKE) CFLAGS="$(COVERAGE_CFLAGS)" LDFLAGS="$(COVERAGE_LDFLAGS)" \
-		-j1 test
+		DEFAULT_TEST_TARGET=test -j1 test
 
 coverage-report:
 	$(QUIET_GCOV)for dir in $(object_dirs); do \
diff --git a/RelNotes b/RelNotes
index 80b7e38..d573a27 120000
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes/1.8.3.txt
\ No newline at end of file
+Documentation/RelNotes/1.8.4.1.txt
\ No newline at end of file
diff --git a/abspath.c b/abspath.c
index 40cdc46..64adbe2 100644
--- a/abspath.c
+++ b/abspath.c
@@ -216,7 +216,7 @@
 const char *prefix_filename(const char *pfx, int pfx_len, const char *arg)
 {
 	static char path[PATH_MAX];
-#ifndef WIN32
+#ifndef GIT_WINDOWS_NATIVE
 	if (!pfx_len || is_absolute_path(arg))
 		return arg;
 	memcpy(path, pfx, pfx_len);
diff --git a/advice.c b/advice.c
index a8deee6..3eca9f5 100644
--- a/advice.c
+++ b/advice.c
@@ -14,6 +14,8 @@
 int advice_implicit_identity = 1;
 int advice_detached_head = 1;
 int advice_set_upstream_failure = 1;
+int advice_object_name_warning = 1;
+int advice_rm_hints = 1;
 
 static struct {
 	const char *name;
@@ -33,6 +35,8 @@
 	{ "implicitidentity", &advice_implicit_identity },
 	{ "detachedhead", &advice_detached_head },
 	{ "setupstreamfailure", &advice_set_upstream_failure },
+	{ "objectnamewarning", &advice_object_name_warning },
+	{ "rmhints", &advice_rm_hints },
 
 	/* make this an alias for backward compatibility */
 	{ "pushnonfastforward", &advice_push_update_rejected }
diff --git a/advice.h b/advice.h
index 94caa32..08fbc8e 100644
--- a/advice.h
+++ b/advice.h
@@ -17,8 +17,11 @@
 extern int advice_implicit_identity;
 extern int advice_detached_head;
 extern int advice_set_upstream_failure;
+extern int advice_object_name_warning;
+extern int advice_rm_hints;
 
 int git_default_advice_config(const char *var, const char *value);
+__attribute__((format (printf, 1, 2)))
 void advise(const char *advice, ...);
 int error_resolve_conflict(const char *me);
 extern void NORETURN die_resolve_conflict(const char *me);
diff --git a/archive-zip.c b/archive-zip.c
index b2c4fe0..4bde019 100644
--- a/archive-zip.c
+++ b/archive-zip.c
@@ -232,7 +232,6 @@
 		size = 0;
 		compressed_size = 0;
 		buffer = NULL;
-		size = 0;
 	} else if (S_ISREG(mode) || S_ISLNK(mode)) {
 		enum object_type type = sha1_object_info(sha1, &size);
 
diff --git a/argv-array.h b/argv-array.h
index 40248d4..85ba438 100644
--- a/argv-array.h
+++ b/argv-array.h
@@ -15,6 +15,7 @@
 void argv_array_push(struct argv_array *, const char *);
 __attribute__((format (printf,2,3)))
 void argv_array_pushf(struct argv_array *, const char *fmt, ...);
+LAST_ARG_MUST_BE_NULL
 void argv_array_pushl(struct argv_array *, ...);
 void argv_array_pop(struct argv_array *);
 void argv_array_clear(struct argv_array *);
diff --git a/bisect.c b/bisect.c
index 374d9e2..71c1958 100644
--- a/bisect.c
+++ b/bisect.c
@@ -15,7 +15,7 @@
 static struct sha1_array good_revs;
 static struct sha1_array skipped_revs;
 
-static const unsigned char *current_bad_sha1;
+static unsigned char *current_bad_sha1;
 
 static const char *argv_checkout[] = {"checkout", "-q", NULL, "--", NULL};
 static const char *argv_show_branch[] = {"show-branch", NULL, NULL};
@@ -404,7 +404,8 @@
 			int flags, void *cb_data)
 {
 	if (!strcmp(refname, "bad")) {
-		current_bad_sha1 = sha1;
+		current_bad_sha1 = xmalloc(20);
+		hashcpy(current_bad_sha1, sha1);
 	} else if (!prefixcmp(refname, "good-")) {
 		sha1_array_append(&good_revs, sha1);
 	} else if (!prefixcmp(refname, "skip-")) {
diff --git a/branch.c b/branch.c
index 97c72bf..c5c6984 100644
--- a/branch.c
+++ b/branch.c
@@ -197,6 +197,21 @@
 	return 1;
 }
 
+static int check_tracking_branch(struct remote *remote, void *cb_data)
+{
+	char *tracking_branch = cb_data;
+	struct refspec query;
+	memset(&query, 0, sizeof(struct refspec));
+	query.dst = tracking_branch;
+	return !(remote_find_tracking(remote, &query) ||
+		 prefixcmp(query.src, "refs/heads/"));
+}
+
+static int validate_remote_tracking_branch(char *ref)
+{
+	return !for_each_remote(check_tracking_branch, ref);
+}
+
 static const char upstream_not_branch[] =
 N_("Cannot setup tracking information; starting point '%s' is not a branch.");
 static const char upstream_missing[] =
@@ -259,7 +274,7 @@
 	case 1:
 		/* Unique completion -- good, only if it is a real branch */
 		if (prefixcmp(real_ref, "refs/heads/") &&
-		    prefixcmp(real_ref, "refs/remotes/")) {
+		    validate_remote_tracking_branch(real_ref)) {
 			if (explicit_tracking)
 				die(_(upstream_not_branch), start_name);
 			else
diff --git a/builtin.h b/builtin.h
index faef559..8afa2de 100644
--- a/builtin.h
+++ b/builtin.h
@@ -5,13 +5,15 @@
 #include "strbuf.h"
 #include "cache.h"
 #include "commit.h"
-#include "notes.h"
 
 #define DEFAULT_MERGE_LOG_LEN 20
 
 extern const char git_usage_string[];
 extern const char git_more_info_string[];
 
+#define PRUNE_PACKED_DRY_RUN 01
+#define PRUNE_PACKED_VERBOSE 02
+
 extern void prune_packed_objects(int);
 
 struct fmt_merge_msg_opts {
@@ -23,21 +25,6 @@
 extern int fmt_merge_msg(struct strbuf *in, struct strbuf *out,
 			 struct fmt_merge_msg_opts *);
 
-struct notes_rewrite_cfg {
-	struct notes_tree **trees;
-	const char *cmd;
-	int enabled;
-	combine_notes_fn combine;
-	struct string_list *refs;
-	int refs_from_env;
-	int mode_from_env;
-};
-
-struct notes_rewrite_cfg *init_copy_notes_for_rewrite(const char *cmd);
-int copy_note_for_rewrite(struct notes_rewrite_cfg *c,
-			  const unsigned char *from_obj, const unsigned char *to_obj);
-void finish_copy_notes_for_rewrite(struct notes_rewrite_cfg *c);
-
 extern int textconv_object(const char *path, unsigned mode, const unsigned char *sha1, int sha1_valid, char **buf, unsigned long *buf_size);
 
 extern int cmd_add(int argc, const char **argv, const char *prefix);
@@ -53,6 +40,7 @@
 extern int cmd_checkout_index(int argc, const char **argv, const char *prefix);
 extern int cmd_check_attr(int argc, const char **argv, const char *prefix);
 extern int cmd_check_ignore(int argc, const char **argv, const char *prefix);
+extern int cmd_check_mailmap(int argc, const char **argv, const char *prefix);
 extern int cmd_check_ref_format(int argc, const char **argv, const char *prefix);
 extern int cmd_cherry(int argc, const char **argv, const char *prefix);
 extern int cmd_cherry_pick(int argc, const char **argv, const char *prefix);
diff --git a/builtin/add.c b/builtin/add.c
index f45d9d4..8266a9c 100644
--- a/builtin/add.c
+++ b/builtin/add.c
@@ -343,6 +343,7 @@
 
 	argc = setup_revisions(argc, argv, &rev, NULL);
 	rev.diffopt.output_format = DIFF_FORMAT_PATCH;
+	rev.diffopt.use_color = 0;
 	DIFF_OPT_SET(&rev.diffopt, IGNORE_DIRTY_SUBMODULES);
 	out = open(file, O_CREAT | O_WRONLY, 0666);
 	if (out < 0)
diff --git a/builtin/apply.c b/builtin/apply.c
index 30eefc3..50912c9 100644
--- a/builtin/apply.c
+++ b/builtin/apply.c
@@ -473,7 +473,7 @@
 
 	/*
 	 * Proposed "new-style" GNU patch/diff format; see
-	 * http://marc.theaimsgroup.com/?l=git&m=112927316408690&w=2
+	 * http://marc.info/?l=git&m=112927316408690&w=2
 	 */
 	if (unquote_c_style(&name, line, NULL)) {
 		strbuf_release(&name);
@@ -722,7 +722,7 @@
 
 static char *find_name_traditional(const char *line, char *def, int p_value)
 {
-	size_t len = strlen(line);
+	size_t len;
 	size_t date_len;
 
 	if (*line == '"') {
@@ -906,7 +906,7 @@
 			patch->old_name = name;
 		} else {
 			patch->old_name = name;
-			patch->new_name = xstrdup(name);
+			patch->new_name = null_strdup(name);
 		}
 	}
 	if (!name)
@@ -2999,7 +2999,7 @@
 	return 0;
 }
 
-static int read_file_or_gitlink(struct cache_entry *ce, struct strbuf *buf)
+static int read_file_or_gitlink(const struct cache_entry *ce, struct strbuf *buf)
 {
 	if (!ce)
 		return 0;
@@ -3117,7 +3117,7 @@
 	return previous;
 }
 
-static int verify_index_match(struct cache_entry *ce, struct stat *st)
+static int verify_index_match(const struct cache_entry *ce, struct stat *st)
 {
 	if (S_ISGITLINK(ce->ce_mode)) {
 		if (!S_ISDIR(st->st_mode))
@@ -3130,7 +3130,7 @@
 #define SUBMODULE_PATCH_WITHOUT_INDEX 1
 
 static int load_patch_target(struct strbuf *buf,
-			     struct cache_entry *ce,
+			     const struct cache_entry *ce,
 			     struct stat *st,
 			     const char *name,
 			     unsigned expected_mode)
@@ -3160,7 +3160,8 @@
  * we read from the result of a previous diff.
  */
 static int load_preimage(struct image *image,
-			 struct patch *patch, struct stat *st, struct cache_entry *ce)
+			 struct patch *patch, struct stat *st,
+			 const struct cache_entry *ce)
 {
 	struct strbuf buf = STRBUF_INIT;
 	size_t len;
@@ -3273,7 +3274,7 @@
 }
 
 static int try_threeway(struct image *image, struct patch *patch,
-			struct stat *st, struct cache_entry *ce)
+			struct stat *st, const struct cache_entry *ce)
 {
 	unsigned char pre_sha1[20], post_sha1[20], our_sha1[20];
 	struct strbuf buf = STRBUF_INIT;
@@ -3343,7 +3344,7 @@
 	return 0;
 }
 
-static int apply_data(struct patch *patch, struct stat *st, struct cache_entry *ce)
+static int apply_data(struct patch *patch, struct stat *st, const struct cache_entry *ce)
 {
 	struct image image;
 
@@ -3525,7 +3526,7 @@
 		ok_if_exists = 0;
 
 	if (new_name &&
-	    ((0 < patch->is_new) | (0 < patch->is_rename) | patch->is_copy)) {
+	    ((0 < patch->is_new) || patch->is_rename || patch->is_copy)) {
 		int err = check_to_create(new_name, ok_if_exists);
 
 		if (err && threeway) {
@@ -3847,7 +3848,7 @@
 		const char *s = buf;
 
 		if (get_sha1_hex(s + strlen("Subproject commit "), ce->sha1))
-			die(_("corrupt patch for subproject %s"), path);
+			die(_("corrupt patch for submodule %s"), path);
 	} else {
 		if (!cached) {
 			if (lstat(path, &st) < 0)
diff --git a/builtin/blame.c b/builtin/blame.c
index 57a487e..079dcd3 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -21,6 +21,7 @@
 #include "parse-options.h"
 #include "utf8.h"
 #include "userdiff.h"
+#include "line-range.h"
 
 static char blame_usage[] = N_("git blame [options] [rev-opts] [rev] [--] file");
 
@@ -566,11 +567,16 @@
 	dst->score = 0;
 }
 
-static const char *nth_line(struct scoreboard *sb, int lno)
+static const char *nth_line(struct scoreboard *sb, long lno)
 {
 	return sb->final_buf + sb->lineno[lno];
 }
 
+static const char *nth_line_cb(void *data, long lno)
+{
+	return nth_line((struct scoreboard *)data, lno);
+}
+
 /*
  * It is known that lines between tlno to same came from parent, and e
  * has an overlap with that range.  it also is known that parent's
@@ -1932,83 +1938,6 @@
 }
 
 /*
- * Parsing of (comma separated) one item in the -L option
- */
-static const char *parse_loc(const char *spec,
-			     struct scoreboard *sb, long lno,
-			     long begin, long *ret)
-{
-	char *term;
-	const char *line;
-	long num;
-	int reg_error;
-	regex_t regexp;
-	regmatch_t match[1];
-
-	/* Allow "-L <something>,+20" to mean starting at <something>
-	 * for 20 lines, or "-L <something>,-5" for 5 lines ending at
-	 * <something>.
-	 */
-	if (1 < begin && (spec[0] == '+' || spec[0] == '-')) {
-		num = strtol(spec + 1, &term, 10);
-		if (term != spec + 1) {
-			if (spec[0] == '-')
-				num = 0 - num;
-			if (0 < num)
-				*ret = begin + num - 2;
-			else if (!num)
-				*ret = begin;
-			else
-				*ret = begin + num;
-			return term;
-		}
-		return spec;
-	}
-	num = strtol(spec, &term, 10);
-	if (term != spec) {
-		*ret = num;
-		return term;
-	}
-	if (spec[0] != '/')
-		return spec;
-
-	/* it could be a regexp of form /.../ */
-	for (term = (char *) spec + 1; *term && *term != '/'; term++) {
-		if (*term == '\\')
-			term++;
-	}
-	if (*term != '/')
-		return spec;
-
-	/* try [spec+1 .. term-1] as regexp */
-	*term = 0;
-	begin--; /* input is in human terms */
-	line = nth_line(sb, begin);
-
-	if (!(reg_error = regcomp(&regexp, spec + 1, REG_NEWLINE)) &&
-	    !(reg_error = regexec(&regexp, line, 1, match, 0))) {
-		const char *cp = line + match[0].rm_so;
-		const char *nline;
-
-		while (begin++ < lno) {
-			nline = nth_line(sb, begin);
-			if (line <= cp && cp < nline)
-				break;
-			line = nline;
-		}
-		*ret = begin;
-		regfree(&regexp);
-		*term++ = '/';
-		return term;
-	}
-	else {
-		char errbuf[1024];
-		regerror(reg_error, &regexp, errbuf, 1024);
-		die("-L parameter '%s': %s", spec + 1, errbuf);
-	}
-}
-
-/*
  * Parsing of -L option
  */
 static void prepare_blame_range(struct scoreboard *sb,
@@ -2016,15 +1945,7 @@
 				long lno,
 				long *bottom, long *top)
 {
-	const char *term;
-
-	term = parse_loc(bottomtop, sb, lno, 1, bottom);
-	if (*term == ',') {
-		term = parse_loc(term + 1, sb, lno, *bottom + 1, top);
-		if (*term)
-			usage(blame_usage);
-	}
-	if (*term)
+	if (parse_range_arg(bottomtop, nth_line_cb, sb, lno, bottom, top, sb->path))
 		usage(blame_usage);
 }
 
@@ -2574,10 +2495,6 @@
 	bottom = top = 0;
 	if (bottomtop)
 		prepare_blame_range(&sb, bottomtop, lno, &bottom, &top);
-	if (bottom && top && top < bottom) {
-		long tmp;
-		tmp = top; top = bottom; bottom = tmp;
-	}
 	if (bottom < 1)
 		bottom = 1;
 	if (top < 1)
diff --git a/builtin/cat-file.c b/builtin/cat-file.c
index 045cee7..4253460 100644
--- a/builtin/cat-file.c
+++ b/builtin/cat-file.c
@@ -13,9 +13,6 @@
 #include "userdiff.h"
 #include "streaming.h"
 
-#define BATCH 1
-#define BATCH_CHECK 2
-
 static int cat_one_file(int opt, const char *exp_type, const char *obj_name)
 {
 	unsigned char sha1[20];
@@ -117,54 +114,166 @@
 	return 0;
 }
 
-static int batch_one_object(const char *obj_name, int print_contents)
-{
+struct expand_data {
 	unsigned char sha1[20];
-	enum object_type type = 0;
+	enum object_type type;
 	unsigned long size;
-	void *contents = NULL;
+	unsigned long disk_size;
+
+	/*
+	 * If mark_query is true, we do not expand anything, but rather
+	 * just mark the object_info with items we wish to query.
+	 */
+	int mark_query;
+
+	/*
+	 * After a mark_query run, this object_info is set up to be
+	 * passed to sha1_object_info_extended. It will point to the data
+	 * elements above, so you can retrieve the response from there.
+	 */
+	struct object_info info;
+};
+
+static int is_atom(const char *atom, const char *s, int slen)
+{
+	int alen = strlen(atom);
+	return alen == slen && !memcmp(atom, s, alen);
+}
+
+static void expand_atom(struct strbuf *sb, const char *atom, int len,
+			void *vdata)
+{
+	struct expand_data *data = vdata;
+
+	if (is_atom("objectname", atom, len)) {
+		if (!data->mark_query)
+			strbuf_addstr(sb, sha1_to_hex(data->sha1));
+	} else if (is_atom("objecttype", atom, len)) {
+		if (data->mark_query)
+			data->info.typep = &data->type;
+		else
+			strbuf_addstr(sb, typename(data->type));
+	} else if (is_atom("objectsize", atom, len)) {
+		if (data->mark_query)
+			data->info.sizep = &data->size;
+		else
+			strbuf_addf(sb, "%lu", data->size);
+	} else if (is_atom("objectsize:disk", atom, len)) {
+		if (data->mark_query)
+			data->info.disk_sizep = &data->disk_size;
+		else
+			strbuf_addf(sb, "%lu", data->disk_size);
+	} else
+		die("unknown format element: %.*s", len, atom);
+}
+
+static size_t expand_format(struct strbuf *sb, const char *start, void *data)
+{
+	const char *end;
+
+	if (*start != '(')
+		return 0;
+	end = strchr(start + 1, ')');
+	if (!end)
+		die("format element '%s' does not end in ')'", start);
+
+	expand_atom(sb, start + 1, end - start - 1, data);
+
+	return end - start + 1;
+}
+
+static void print_object_or_die(int fd, const unsigned char *sha1,
+				enum object_type type, unsigned long size)
+{
+	if (type == OBJ_BLOB) {
+		if (stream_blob_to_fd(fd, sha1, NULL, 0) < 0)
+			die("unable to stream %s to stdout", sha1_to_hex(sha1));
+	}
+	else {
+		enum object_type rtype;
+		unsigned long rsize;
+		void *contents;
+
+		contents = read_sha1_file(sha1, &rtype, &rsize);
+		if (!contents)
+			die("object %s disappeared", sha1_to_hex(sha1));
+		if (rtype != type)
+			die("object %s changed type!?", sha1_to_hex(sha1));
+		if (rsize != size)
+			die("object %s change size!?", sha1_to_hex(sha1));
+
+		write_or_die(fd, contents, size);
+		free(contents);
+	}
+}
+
+struct batch_options {
+	int enabled;
+	int print_contents;
+	const char *format;
+};
+
+static int batch_one_object(const char *obj_name, struct batch_options *opt,
+			    struct expand_data *data)
+{
+	struct strbuf buf = STRBUF_INIT;
 
 	if (!obj_name)
 	   return 1;
 
-	if (get_sha1(obj_name, sha1)) {
+	if (get_sha1(obj_name, data->sha1)) {
 		printf("%s missing\n", obj_name);
 		fflush(stdout);
 		return 0;
 	}
 
-	if (print_contents == BATCH)
-		contents = read_sha1_file(sha1, &type, &size);
-	else
-		type = sha1_object_info(sha1, &size);
-
-	if (type <= 0) {
+	if (sha1_object_info_extended(data->sha1, &data->info) < 0) {
 		printf("%s missing\n", obj_name);
 		fflush(stdout);
-		if (print_contents == BATCH)
-			free(contents);
 		return 0;
 	}
 
-	printf("%s %s %lu\n", sha1_to_hex(sha1), typename(type), size);
-	fflush(stdout);
+	strbuf_expand(&buf, opt->format, expand_format, data);
+	strbuf_addch(&buf, '\n');
+	write_or_die(1, buf.buf, buf.len);
+	strbuf_release(&buf);
 
-	if (print_contents == BATCH) {
-		write_or_die(1, contents, size);
-		printf("\n");
-		fflush(stdout);
-		free(contents);
+	if (opt->print_contents) {
+		print_object_or_die(1, data->sha1, data->type, data->size);
+		write_or_die(1, "\n", 1);
 	}
-
 	return 0;
 }
 
-static int batch_objects(int print_contents)
+static int batch_objects(struct batch_options *opt)
 {
 	struct strbuf buf = STRBUF_INIT;
+	struct expand_data data;
+
+	if (!opt->format)
+		opt->format = "%(objectname) %(objecttype) %(objectsize)";
+
+	/*
+	 * Expand once with our special mark_query flag, which will prime the
+	 * object_info to be handed to sha1_object_info_extended for each
+	 * object.
+	 */
+	memset(&data, 0, sizeof(data));
+	data.mark_query = 1;
+	strbuf_expand(&buf, opt->format, expand_format, &data);
+	data.mark_query = 0;
+
+	/*
+	 * We are going to call get_sha1 on a potentially very large number of
+	 * objects. In most large cases, these will be actual object sha1s. The
+	 * cost to double-check that each one is not also a ref (just so we can
+	 * warn) ends up dwarfing the actual cost of the object lookups
+	 * themselves. We can work around it by just turning off the warning.
+	 */
+	warn_on_object_refname_ambiguity = 0;
 
 	while (strbuf_getline(&buf, stdin, '\n') != EOF) {
-		int error = batch_one_object(buf.buf, print_contents);
+		int error = batch_one_object(buf.buf, opt, &data);
 		if (error)
 			return error;
 	}
@@ -186,10 +295,29 @@
 	return git_default_config(var, value, cb);
 }
 
+static int batch_option_callback(const struct option *opt,
+				 const char *arg,
+				 int unset)
+{
+	struct batch_options *bo = opt->value;
+
+	if (unset) {
+		memset(bo, 0, sizeof(*bo));
+		return 0;
+	}
+
+	bo->enabled = 1;
+	bo->print_contents = !strcmp(opt->long_name, "batch");
+	bo->format = arg;
+
+	return 0;
+}
+
 int cmd_cat_file(int argc, const char **argv, const char *prefix)
 {
-	int opt = 0, batch = 0;
+	int opt = 0;
 	const char *exp_type = NULL, *obj_name = NULL;
+	struct batch_options batch = {0};
 
 	const struct option options[] = {
 		OPT_GROUP(N_("<type> can be one of: blob, tree, commit, tag")),
@@ -200,12 +328,12 @@
 		OPT_SET_INT('p', NULL, &opt, N_("pretty-print object's content"), 'p'),
 		OPT_SET_INT(0, "textconv", &opt,
 			    N_("for blob objects, run textconv on object's content"), 'c'),
-		OPT_SET_INT(0, "batch", &batch,
-			    N_("show info and content of objects fed from the standard input"),
-			    BATCH),
-		OPT_SET_INT(0, "batch-check", &batch,
-			    N_("show info about objects fed from the standard input"),
-			    BATCH_CHECK),
+		{ OPTION_CALLBACK, 0, "batch", &batch, "format",
+			N_("show info and content of objects fed from the standard input"),
+			PARSE_OPT_OPTARG, batch_option_callback },
+		{ OPTION_CALLBACK, 0, "batch-check", &batch, "format",
+			N_("show info about objects fed from the standard input"),
+			PARSE_OPT_OPTARG, batch_option_callback },
 		OPT_END()
 	};
 
@@ -222,19 +350,19 @@
 		else
 			usage_with_options(cat_file_usage, options);
 	}
-	if (!opt && !batch) {
+	if (!opt && !batch.enabled) {
 		if (argc == 2) {
 			exp_type = argv[0];
 			obj_name = argv[1];
 		} else
 			usage_with_options(cat_file_usage, options);
 	}
-	if (batch && (opt || argc)) {
+	if (batch.enabled && (opt || argc)) {
 		usage_with_options(cat_file_usage, options);
 	}
 
-	if (batch)
-		return batch_objects(batch);
+	if (batch.enabled)
+		return batch_objects(&batch);
 
 	return cat_one_file(opt, exp_type, obj_name);
 }
diff --git a/builtin/check-ignore.c b/builtin/check-ignore.c
index 854a88a..4a8fc70 100644
--- a/builtin/check-ignore.c
+++ b/builtin/check-ignore.c
@@ -5,7 +5,7 @@
 #include "pathspec.h"
 #include "parse-options.h"
 
-static int quiet, verbose, stdin_paths;
+static int quiet, verbose, stdin_paths, show_non_matching;
 static const char * const check_ignore_usage[] = {
 "git check-ignore [options] pathname...",
 "git check-ignore [options] --stdin < <list-of-paths>",
@@ -22,21 +22,28 @@
 		    N_("read file names from stdin")),
 	OPT_BOOLEAN('z', NULL, &null_term_line,
 		    N_("input paths are terminated by a null character")),
+	OPT_BOOLEAN('n', "non-matching", &show_non_matching,
+		    N_("show non-matching input paths")),
 	OPT_END()
 };
 
 static void output_exclude(const char *path, struct exclude *exclude)
 {
-	char *bang  = exclude->flags & EXC_FLAG_NEGATIVE  ? "!" : "";
-	char *slash = exclude->flags & EXC_FLAG_MUSTBEDIR ? "/" : "";
+	char *bang  = (exclude && exclude->flags & EXC_FLAG_NEGATIVE)  ? "!" : "";
+	char *slash = (exclude && exclude->flags & EXC_FLAG_MUSTBEDIR) ? "/" : "";
 	if (!null_term_line) {
 		if (!verbose) {
 			write_name_quoted(path, stdout, '\n');
 		} else {
-			quote_c_style(exclude->el->src, NULL, stdout, 0);
-			printf(":%d:%s%s%s\t",
-			       exclude->srcpos,
-			       bang, exclude->pattern, slash);
+			if (exclude) {
+				quote_c_style(exclude->el->src, NULL, stdout, 0);
+				printf(":%d:%s%s%s\t",
+				       exclude->srcpos,
+				       bang, exclude->pattern, slash);
+			}
+			else {
+				printf("::\t");
+			}
 			quote_c_style(path, NULL, stdout, 0);
 			fputc('\n', stdout);
 		}
@@ -44,30 +51,26 @@
 		if (!verbose) {
 			printf("%s%c", path, '\0');
 		} else {
-			printf("%s%c%d%c%s%s%s%c%s%c",
-			       exclude->el->src, '\0',
-			       exclude->srcpos, '\0',
-			       bang, exclude->pattern, slash, '\0',
-			       path, '\0');
+			if (exclude)
+				printf("%s%c%d%c%s%s%s%c%s%c",
+				       exclude->el->src, '\0',
+				       exclude->srcpos, '\0',
+				       bang, exclude->pattern, slash, '\0',
+				       path, '\0');
+			else
+				printf("%c%c%c%s%c", '\0', '\0', '\0', path, '\0');
 		}
 	}
 }
 
-static int check_ignore(const char *prefix, const char **pathspec)
+static int check_ignore(struct dir_struct *dir,
+			const char *prefix, const char **pathspec)
 {
-	struct dir_struct dir;
 	const char *path, *full_path;
 	char *seen;
 	int num_ignored = 0, dtype = DT_UNKNOWN, i;
 	struct exclude *exclude;
 
-	/* read_cache() is only necessary so we can watch out for submodules. */
-	if (read_cache() < 0)
-		die(_("index file corrupt"));
-
-	memset(&dir, 0, sizeof(dir));
-	setup_standard_excludes(&dir);
-
 	if (!pathspec || !*pathspec) {
 		if (!quiet)
 			fprintf(stderr, "no pathspec given.\n");
@@ -86,28 +89,26 @@
 					? strlen(prefix) : 0, path);
 		full_path = check_path_for_gitlink(full_path);
 		die_if_path_beyond_symlink(full_path, prefix);
+		exclude = NULL;
 		if (!seen[i]) {
-			exclude = last_exclude_matching(&dir, full_path, &dtype);
-			if (exclude) {
-				if (!quiet)
-					output_exclude(path, exclude);
-				num_ignored++;
-			}
+			exclude = last_exclude_matching(dir, full_path, &dtype);
 		}
+		if (!quiet && (exclude || show_non_matching))
+			output_exclude(path, exclude);
+		if (exclude)
+			num_ignored++;
 	}
 	free(seen);
-	clear_directory(&dir);
 
 	return num_ignored;
 }
 
-static int check_ignore_stdin_paths(const char *prefix)
+static int check_ignore_stdin_paths(struct dir_struct *dir, const char *prefix)
 {
 	struct strbuf buf, nbuf;
-	char **pathspec = NULL;
-	size_t nr = 0, alloc = 0;
+	char *pathspec[2] = { NULL, NULL };
 	int line_termination = null_term_line ? 0 : '\n';
-	int num_ignored;
+	int num_ignored = 0;
 
 	strbuf_init(&buf, 0);
 	strbuf_init(&nbuf, 0);
@@ -118,23 +119,19 @@
 				die("line is badly quoted");
 			strbuf_swap(&buf, &nbuf);
 		}
-		ALLOC_GROW(pathspec, nr + 1, alloc);
-		pathspec[nr] = xcalloc(strlen(buf.buf) + 1, sizeof(*buf.buf));
-		strcpy(pathspec[nr++], buf.buf);
+		pathspec[0] = buf.buf;
+		num_ignored += check_ignore(dir, prefix, (const char **)pathspec);
+		maybe_flush_or_die(stdout, "check-ignore to stdout");
 	}
-	ALLOC_GROW(pathspec, nr + 1, alloc);
-	pathspec[nr] = NULL;
-	num_ignored = check_ignore(prefix, (const char **)pathspec);
-	maybe_flush_or_die(stdout, "attribute to stdout");
 	strbuf_release(&buf);
 	strbuf_release(&nbuf);
-	free(pathspec);
 	return num_ignored;
 }
 
 int cmd_check_ignore(int argc, const char **argv, const char *prefix)
 {
 	int num_ignored;
+	struct dir_struct dir;
 
 	git_config(git_default_config, NULL);
 
@@ -156,13 +153,24 @@
 		if (verbose)
 			die(_("cannot have both --quiet and --verbose"));
 	}
+	if (show_non_matching && !verbose)
+		die(_("--non-matching is only valid with --verbose"));
+
+	/* read_cache() is only necessary so we can watch out for submodules. */
+	if (read_cache() < 0)
+		die(_("index file corrupt"));
+
+	memset(&dir, 0, sizeof(dir));
+	setup_standard_excludes(&dir);
 
 	if (stdin_paths) {
-		num_ignored = check_ignore_stdin_paths(prefix);
+		num_ignored = check_ignore_stdin_paths(&dir, prefix);
 	} else {
-		num_ignored = check_ignore(prefix, argv);
+		num_ignored = check_ignore(&dir, prefix, argv);
 		maybe_flush_or_die(stdout, "ignore to stdout");
 	}
 
+	clear_directory(&dir);
+
 	return !num_ignored;
 }
diff --git a/builtin/check-mailmap.c b/builtin/check-mailmap.c
new file mode 100644
index 0000000..8f4d809
--- /dev/null
+++ b/builtin/check-mailmap.c
@@ -0,0 +1,66 @@
+#include "builtin.h"
+#include "mailmap.h"
+#include "parse-options.h"
+#include "string-list.h"
+
+static int use_stdin;
+static const char * const check_mailmap_usage[] = {
+N_("git check-mailmap [options] <contact>..."),
+NULL
+};
+
+static const struct option check_mailmap_options[] = {
+	OPT_BOOL(0, "stdin", &use_stdin, N_("also read contacts from stdin")),
+	OPT_END()
+};
+
+static void check_mailmap(struct string_list *mailmap, const char *contact)
+{
+	const char *name, *mail;
+	size_t namelen, maillen;
+	struct ident_split ident;
+
+	if (split_ident_line(&ident, contact, strlen(contact)))
+		die(_("unable to parse contact: %s"), contact);
+
+	name = ident.name_begin;
+	namelen = ident.name_end - ident.name_begin;
+	mail = ident.mail_begin;
+	maillen = ident.mail_end - ident.mail_begin;
+
+	map_user(mailmap, &mail, &maillen, &name, &namelen);
+
+	if (namelen)
+		printf("%.*s ", (int)namelen, name);
+	printf("<%.*s>\n", (int)maillen, mail);
+}
+
+int cmd_check_mailmap(int argc, const char **argv, const char *prefix)
+{
+	int i;
+	struct string_list mailmap = STRING_LIST_INIT_NODUP;
+
+	git_config(git_default_config, NULL);
+	argc = parse_options(argc, argv, prefix, check_mailmap_options,
+			     check_mailmap_usage, 0);
+	if (argc == 0 && !use_stdin)
+		die(_("no contacts specified"));
+
+	read_mailmap(&mailmap, NULL);
+
+	for (i = 0; i < argc; ++i)
+		check_mailmap(&mailmap, argv[i]);
+	maybe_flush_or_die(stdout, "stdout");
+
+	if (use_stdin) {
+		struct strbuf buf = STRBUF_INIT;
+		while (strbuf_getline(&buf, stdin, '\n') != EOF) {
+			check_mailmap(&mailmap, buf.buf);
+			maybe_flush_or_die(stdout, "stdout");
+		}
+		strbuf_release(&buf);
+	}
+
+	clear_mailmap(&mailmap);
+	return 0;
+}
diff --git a/builtin/checkout.c b/builtin/checkout.c
index 81b4419..7025938 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -97,7 +97,7 @@
 	return 0;
 }
 
-static int skip_same_name(struct cache_entry *ce, int pos)
+static int skip_same_name(const struct cache_entry *ce, int pos)
 {
 	while (++pos < active_nr &&
 	       !strcmp(active_cache[pos]->name, ce->name))
@@ -105,7 +105,7 @@
 	return pos;
 }
 
-static int check_stage(int stage, struct cache_entry *ce, int pos)
+static int check_stage(int stage, const struct cache_entry *ce, int pos)
 {
 	while (pos < active_nr &&
 	       !strcmp(active_cache[pos]->name, ce->name)) {
@@ -119,7 +119,7 @@
 		return error(_("path '%s' does not have their version"), ce->name);
 }
 
-static int check_stages(unsigned stages, struct cache_entry *ce, int pos)
+static int check_stages(unsigned stages, const struct cache_entry *ce, int pos)
 {
 	unsigned seen = 0;
 	const char *name = ce->name;
@@ -321,7 +321,7 @@
 
 	/* Any unmerged paths? */
 	for (pos = 0; pos < active_nr; pos++) {
-		struct cache_entry *ce = active_cache[pos];
+		const struct cache_entry *ce = active_cache[pos];
 		if (ce->ce_flags & CE_MATCHED) {
 			if (!ce_stage(ce))
 				continue;
@@ -587,7 +587,7 @@
 				   struct branch_info *new)
 {
 	struct strbuf msg = STRBUF_INIT;
-	const char *old_desc;
+	const char *old_desc, *reflog_msg;
 	if (opts->new_branch) {
 		if (opts->new_orphan_branch) {
 			if (opts->new_branch_log && !log_all_ref_updates) {
@@ -620,8 +620,13 @@
 	old_desc = old->name;
 	if (!old_desc && old->commit)
 		old_desc = sha1_to_hex(old->commit->object.sha1);
-	strbuf_addf(&msg, "checkout: moving from %s to %s",
-		    old_desc ? old_desc : "(invalid)", new->name);
+
+	reflog_msg = getenv("GIT_REFLOG_ACTION");
+	if (!reflog_msg)
+		strbuf_addf(&msg, "checkout: moving from %s to %s",
+			old_desc ? old_desc : "(invalid)", new->name);
+	else
+		strbuf_insert(&msg, 0, reflog_msg, strlen(reflog_msg));
 
 	if (!strcmp(new->name, "HEAD") && !new->path && !opts->force_detach) {
 		/* Nothing to do. */
@@ -825,38 +830,43 @@
 }
 
 struct tracking_name_data {
-	const char *name;
-	char *remote;
+	/* const */ char *src_ref;
+	char *dst_ref;
+	unsigned char *dst_sha1;
 	int unique;
 };
 
-static int check_tracking_name(const char *refname, const unsigned char *sha1,
-			       int flags, void *cb_data)
+static int check_tracking_name(struct remote *remote, void *cb_data)
 {
 	struct tracking_name_data *cb = cb_data;
-	const char *slash;
-
-	if (prefixcmp(refname, "refs/remotes/"))
+	struct refspec query;
+	memset(&query, 0, sizeof(struct refspec));
+	query.src = cb->src_ref;
+	if (remote_find_tracking(remote, &query) ||
+	    get_sha1(query.dst, cb->dst_sha1)) {
+		free(query.dst);
 		return 0;
-	slash = strchr(refname + 13, '/');
-	if (!slash || strcmp(slash + 1, cb->name))
-		return 0;
-	if (cb->remote) {
+	}
+	if (cb->dst_ref) {
+		free(query.dst);
 		cb->unique = 0;
 		return 0;
 	}
-	cb->remote = xstrdup(refname);
+	cb->dst_ref = query.dst;
 	return 0;
 }
 
-static const char *unique_tracking_name(const char *name)
+static const char *unique_tracking_name(const char *name, unsigned char *sha1)
 {
-	struct tracking_name_data cb_data = { NULL, NULL, 1 };
-	cb_data.name = name;
-	for_each_ref(check_tracking_name, &cb_data);
+	struct tracking_name_data cb_data = { NULL, NULL, NULL, 1 };
+	char src_ref[PATH_MAX];
+	snprintf(src_ref, PATH_MAX, "refs/heads/%s", name);
+	cb_data.src_ref = src_ref;
+	cb_data.dst_sha1 = sha1;
+	for_each_remote(check_tracking_name, &cb_data);
 	if (cb_data.unique)
-		return cb_data.remote;
-	free(cb_data.remote);
+		return cb_data.dst_ref;
+	free(cb_data.dst_ref);
 	return NULL;
 }
 
@@ -919,8 +929,8 @@
 		if (dwim_new_local_branch_ok &&
 		    !check_filename(NULL, arg) &&
 		    argc == 1) {
-			const char *remote = unique_tracking_name(arg);
-			if (!remote || get_sha1(remote, rev))
+			const char *remote = unique_tracking_name(arg, rev);
+			if (!remote)
 				return argcount;
 			*new_branch = arg;
 			arg = remote;
diff --git a/builtin/clean.c b/builtin/clean.c
index 04e396b..3c85e15 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -13,11 +13,16 @@
 #include "refs.h"
 #include "string-list.h"
 #include "quote.h"
+#include "column.h"
+#include "color.h"
 
 static int force = -1; /* unset */
+static int interactive;
+static struct string_list del_list = STRING_LIST_INIT_DUP;
+static unsigned int colopts;
 
 static const char *const builtin_clean_usage[] = {
-	N_("git clean [-d] [-f] [-n] [-q] [-e <pattern>] [-x | -X] [--] <paths>..."),
+	N_("git clean [-d] [-f] [-i] [-n] [-q] [-e <pattern>] [-x | -X] [--] <paths>..."),
 	NULL
 };
 
@@ -27,11 +32,112 @@
 static const char *msg_would_skip_git_dir = N_("Would skip repository %s\n");
 static const char *msg_warn_remove_failed = N_("failed to remove %s");
 
+static int clean_use_color = -1;
+static char clean_colors[][COLOR_MAXLEN] = {
+	GIT_COLOR_RESET,
+	GIT_COLOR_NORMAL,	/* PLAIN */
+	GIT_COLOR_BOLD_BLUE,	/* PROMPT */
+	GIT_COLOR_BOLD,		/* HEADER */
+	GIT_COLOR_BOLD_RED,	/* HELP */
+	GIT_COLOR_BOLD_RED,	/* ERROR */
+};
+enum color_clean {
+	CLEAN_COLOR_RESET = 0,
+	CLEAN_COLOR_PLAIN = 1,
+	CLEAN_COLOR_PROMPT = 2,
+	CLEAN_COLOR_HEADER = 3,
+	CLEAN_COLOR_HELP = 4,
+	CLEAN_COLOR_ERROR = 5,
+};
+
+#define MENU_OPTS_SINGLETON		01
+#define MENU_OPTS_IMMEDIATE		02
+#define MENU_OPTS_LIST_ONLY		04
+
+struct menu_opts {
+	const char *header;
+	const char *prompt;
+	int flags;
+};
+
+#define MENU_RETURN_NO_LOOP		10
+
+struct menu_item {
+	char hotkey;
+	const char *title;
+	int selected;
+	int (*fn)();
+};
+
+enum menu_stuff_type {
+	MENU_STUFF_TYPE_STRING_LIST = 1,
+	MENU_STUFF_TYPE_MENU_ITEM
+};
+
+struct menu_stuff {
+	enum menu_stuff_type type;
+	int nr;
+	void *stuff;
+};
+
+static int parse_clean_color_slot(const char *var)
+{
+	if (!strcasecmp(var, "reset"))
+		return CLEAN_COLOR_RESET;
+	if (!strcasecmp(var, "plain"))
+		return CLEAN_COLOR_PLAIN;
+	if (!strcasecmp(var, "prompt"))
+		return CLEAN_COLOR_PROMPT;
+	if (!strcasecmp(var, "header"))
+		return CLEAN_COLOR_HEADER;
+	if (!strcasecmp(var, "help"))
+		return CLEAN_COLOR_HELP;
+	if (!strcasecmp(var, "error"))
+		return CLEAN_COLOR_ERROR;
+	return -1;
+}
+
 static int git_clean_config(const char *var, const char *value, void *cb)
 {
-	if (!strcmp(var, "clean.requireforce"))
+	if (!prefixcmp(var, "column."))
+		return git_column_config(var, value, "clean", &colopts);
+
+	/* honors the color.interactive* config variables which also
+	   applied in git-add--interactive and git-stash */
+	if (!strcmp(var, "color.interactive")) {
+		clean_use_color = git_config_colorbool(var, value);
+		return 0;
+	}
+	if (!prefixcmp(var, "color.interactive.")) {
+		int slot = parse_clean_color_slot(var +
+						  strlen("color.interactive."));
+		if (slot < 0)
+			return 0;
+		if (!value)
+			return config_error_nonbool(var);
+		color_parse(value, var, clean_colors[slot]);
+		return 0;
+	}
+
+	if (!strcmp(var, "clean.requireforce")) {
 		force = !git_config_bool(var, value);
-	return git_default_config(var, value, cb);
+		return 0;
+	}
+
+	/* inspect the color.ui config variable and others */
+	return git_color_default_config(var, value, cb);
+}
+
+static const char *clean_get_color(enum color_clean ix)
+{
+	if (want_color(clean_use_color))
+		return clean_colors[ix];
+	return "";
+}
+
+static void clean_print_color(enum color_clean ix)
+{
+	printf("%s", clean_get_color(ix));
 }
 
 static int exclude_cb(const struct option *opt, const char *arg, int unset)
@@ -56,7 +162,7 @@
 	if ((force_flag & REMOVE_DIR_KEEP_NESTED_GIT) &&
 			!resolve_gitlink_ref(path->buf, "HEAD", submodule_head)) {
 		if (!quiet) {
-			quote_path_relative(path->buf, strlen(path->buf), &quoted, prefix);
+			quote_path_relative(path->buf, prefix, &quoted);
 			printf(dry_run ?  _(msg_would_skip_git_dir) : _(msg_skip_git_dir),
 					quoted.buf);
 		}
@@ -70,7 +176,7 @@
 		/* an empty dir could be removed even if it is unreadble */
 		res = dry_run ? 0 : rmdir(path->buf);
 		if (res) {
-			quote_path_relative(path->buf, strlen(path->buf), &quoted, prefix);
+			quote_path_relative(path->buf, prefix, &quoted);
 			warning(_(msg_warn_remove_failed), quoted.buf);
 			*dir_gone = 0;
 		}
@@ -94,7 +200,7 @@
 			if (remove_dirs(path, prefix, force_flag, dry_run, quiet, &gone))
 				ret = 1;
 			if (gone) {
-				quote_path_relative(path->buf, strlen(path->buf), &quoted, prefix);
+				quote_path_relative(path->buf, prefix, &quoted);
 				string_list_append(&dels, quoted.buf);
 			} else
 				*dir_gone = 0;
@@ -102,10 +208,10 @@
 		} else {
 			res = dry_run ? 0 : unlink(path->buf);
 			if (!res) {
-				quote_path_relative(path->buf, strlen(path->buf), &quoted, prefix);
+				quote_path_relative(path->buf, prefix, &quoted);
 				string_list_append(&dels, quoted.buf);
 			} else {
-				quote_path_relative(path->buf, strlen(path->buf), &quoted, prefix);
+				quote_path_relative(path->buf, prefix, &quoted);
 				warning(_(msg_warn_remove_failed), quoted.buf);
 				*dir_gone = 0;
 				ret = 1;
@@ -127,7 +233,7 @@
 		if (!res)
 			*dir_gone = 1;
 		else {
-			quote_path_relative(path->buf, strlen(path->buf), &quoted, prefix);
+			quote_path_relative(path->buf, prefix, &quoted);
 			warning(_(msg_warn_remove_failed), quoted.buf);
 			*dir_gone = 0;
 			ret = 1;
@@ -142,24 +248,633 @@
 	return ret;
 }
 
+static void pretty_print_dels(void)
+{
+	struct string_list list = STRING_LIST_INIT_DUP;
+	struct string_list_item *item;
+	struct strbuf buf = STRBUF_INIT;
+	const char *qname;
+	struct column_options copts;
+
+	for_each_string_list_item(item, &del_list) {
+		qname = quote_path_relative(item->string, NULL, &buf);
+		string_list_append(&list, qname);
+	}
+
+	/*
+	 * always enable column display, we only consult column.*
+	 * about layout strategy and stuff
+	 */
+	colopts = (colopts & ~COL_ENABLE_MASK) | COL_ENABLED;
+	memset(&copts, 0, sizeof(copts));
+	copts.indent = "  ";
+	copts.padding = 2;
+	print_columns(&list, colopts, &copts);
+	strbuf_release(&buf);
+	string_list_clear(&list, 0);
+}
+
+static void pretty_print_menus(struct string_list *menu_list)
+{
+	unsigned int local_colopts = 0;
+	struct column_options copts;
+
+	local_colopts = COL_ENABLED | COL_ROW;
+	memset(&copts, 0, sizeof(copts));
+	copts.indent = "  ";
+	copts.padding = 2;
+	print_columns(menu_list, local_colopts, &copts);
+}
+
+static void prompt_help_cmd(int singleton)
+{
+	clean_print_color(CLEAN_COLOR_HELP);
+	printf_ln(singleton ?
+		  _("Prompt help:\n"
+		    "1          - select a numbered item\n"
+		    "foo        - select item based on unique prefix\n"
+		    "           - (empty) select nothing") :
+		  _("Prompt help:\n"
+		    "1          - select a single item\n"
+		    "3-5        - select a range of items\n"
+		    "2-3,6-9    - select multiple ranges\n"
+		    "foo        - select item based on unique prefix\n"
+		    "-...       - unselect specified items\n"
+		    "*          - choose all items\n"
+		    "           - (empty) finish selecting"));
+	clean_print_color(CLEAN_COLOR_RESET);
+}
+
+/*
+ * display menu stuff with number prefix and hotkey highlight
+ */
+static void print_highlight_menu_stuff(struct menu_stuff *stuff, int **chosen)
+{
+	struct string_list menu_list = STRING_LIST_INIT_DUP;
+	struct strbuf menu = STRBUF_INIT;
+	struct strbuf buf = STRBUF_INIT;
+	struct menu_item *menu_item;
+	struct string_list_item *string_list_item;
+	int i;
+
+	switch (stuff->type) {
+	default:
+		die("Bad type of menu_staff when print menu");
+	case MENU_STUFF_TYPE_MENU_ITEM:
+		menu_item = (struct menu_item *)stuff->stuff;
+		for (i = 0; i < stuff->nr; i++, menu_item++) {
+			const char *p;
+			int highlighted = 0;
+
+			p = menu_item->title;
+			if ((*chosen)[i] < 0)
+				(*chosen)[i] = menu_item->selected ? 1 : 0;
+			strbuf_addf(&menu, "%s%2d: ", (*chosen)[i] ? "*" : " ", i+1);
+			for (; *p; p++) {
+				if (!highlighted && *p == menu_item->hotkey) {
+					strbuf_addstr(&menu, clean_get_color(CLEAN_COLOR_PROMPT));
+					strbuf_addch(&menu, *p);
+					strbuf_addstr(&menu, clean_get_color(CLEAN_COLOR_RESET));
+					highlighted = 1;
+				} else {
+					strbuf_addch(&menu, *p);
+				}
+			}
+			string_list_append(&menu_list, menu.buf);
+			strbuf_reset(&menu);
+		}
+		break;
+	case MENU_STUFF_TYPE_STRING_LIST:
+		i = 0;
+		for_each_string_list_item(string_list_item, (struct string_list *)stuff->stuff) {
+			if ((*chosen)[i] < 0)
+				(*chosen)[i] = 0;
+			strbuf_addf(&menu, "%s%2d: %s",
+				    (*chosen)[i] ? "*" : " ", i+1, string_list_item->string);
+			string_list_append(&menu_list, menu.buf);
+			strbuf_reset(&menu);
+			i++;
+		}
+		break;
+	}
+
+	pretty_print_menus(&menu_list);
+
+	strbuf_release(&menu);
+	strbuf_release(&buf);
+	string_list_clear(&menu_list, 0);
+}
+
+static int find_unique(const char *choice, struct menu_stuff *menu_stuff)
+{
+	struct menu_item *menu_item;
+	struct string_list_item *string_list_item;
+	int i, len, found = 0;
+
+	len = strlen(choice);
+	switch (menu_stuff->type) {
+	default:
+		die("Bad type of menu_stuff when parse choice");
+	case MENU_STUFF_TYPE_MENU_ITEM:
+
+		menu_item = (struct menu_item *)menu_stuff->stuff;
+		for (i = 0; i < menu_stuff->nr; i++, menu_item++) {
+			if (len == 1 && *choice == menu_item->hotkey) {
+				found = i + 1;
+				break;
+			}
+			if (!strncasecmp(choice, menu_item->title, len)) {
+				if (found) {
+					if (len == 1) {
+						/* continue for hotkey matching */
+						found = -1;
+					} else {
+						found = 0;
+						break;
+					}
+				} else {
+					found = i + 1;
+				}
+			}
+		}
+		break;
+	case MENU_STUFF_TYPE_STRING_LIST:
+		string_list_item = ((struct string_list *)menu_stuff->stuff)->items;
+		for (i = 0; i < menu_stuff->nr; i++, string_list_item++) {
+			if (!strncasecmp(choice, string_list_item->string, len)) {
+				if (found) {
+					found = 0;
+					break;
+				}
+				found = i + 1;
+			}
+		}
+		break;
+	}
+	return found;
+}
+
+
+/*
+ * Parse user input, and return choice(s) for menu (menu_stuff).
+ *
+ * Input
+ *     (for single choice)
+ *         1          - select a numbered item
+ *         foo        - select item based on menu title
+ *                    - (empty) select nothing
+ *
+ *     (for multiple choice)
+ *         1          - select a single item
+ *         3-5        - select a range of items
+ *         2-3,6-9    - select multiple ranges
+ *         foo        - select item based on menu title
+ *         -...       - unselect specified items
+ *         *          - choose all items
+ *                    - (empty) finish selecting
+ *
+ * The parse result will be saved in array **chosen, and
+ * return number of total selections.
+ */
+static int parse_choice(struct menu_stuff *menu_stuff,
+			int is_single,
+			struct strbuf input,
+			int **chosen)
+{
+	struct strbuf **choice_list, **ptr;
+	int nr = 0;
+	int i;
+
+	if (is_single) {
+		choice_list = strbuf_split_max(&input, '\n', 0);
+	} else {
+		char *p = input.buf;
+		do {
+			if (*p == ',')
+				*p = ' ';
+		} while (*p++);
+		choice_list = strbuf_split_max(&input, ' ', 0);
+	}
+
+	for (ptr = choice_list; *ptr; ptr++) {
+		char *p;
+		int choose = 1;
+		int bottom = 0, top = 0;
+		int is_range, is_number;
+
+		strbuf_trim(*ptr);
+		if (!(*ptr)->len)
+			continue;
+
+		/* Input that begins with '-'; unchoose */
+		if (*(*ptr)->buf == '-') {
+			choose = 0;
+			strbuf_remove((*ptr), 0, 1);
+		}
+
+		is_range = 0;
+		is_number = 1;
+		for (p = (*ptr)->buf; *p; p++) {
+			if ('-' == *p) {
+				if (!is_range) {
+					is_range = 1;
+					is_number = 0;
+				} else {
+					is_number = 0;
+					is_range = 0;
+					break;
+				}
+			} else if (!isdigit(*p)) {
+				is_number = 0;
+				is_range = 0;
+				break;
+			}
+		}
+
+		if (is_number) {
+			bottom = atoi((*ptr)->buf);
+			top = bottom;
+		} else if (is_range) {
+			bottom = atoi((*ptr)->buf);
+			/* a range can be specified like 5-7 or 5- */
+			if (!*(strchr((*ptr)->buf, '-') + 1))
+				top = menu_stuff->nr;
+			else
+				top = atoi(strchr((*ptr)->buf, '-') + 1);
+		} else if (!strcmp((*ptr)->buf, "*")) {
+			bottom = 1;
+			top = menu_stuff->nr;
+		} else {
+			bottom = find_unique((*ptr)->buf, menu_stuff);
+			top = bottom;
+		}
+
+		if (top <= 0 || bottom <= 0 || top > menu_stuff->nr || bottom > top ||
+		    (is_single && bottom != top)) {
+			clean_print_color(CLEAN_COLOR_ERROR);
+			printf_ln(_("Huh (%s)?"), (*ptr)->buf);
+			clean_print_color(CLEAN_COLOR_RESET);
+			continue;
+		}
+
+		for (i = bottom; i <= top; i++)
+			(*chosen)[i-1] = choose;
+	}
+
+	strbuf_list_free(choice_list);
+
+	for (i = 0; i < menu_stuff->nr; i++)
+		nr += (*chosen)[i];
+	return nr;
+}
+
+/*
+ * Implement a git-add-interactive compatible UI, which is borrowed
+ * from git-add--interactive.perl.
+ *
+ * Return value:
+ *
+ *   - Return an array of integers
+ *   - , and it is up to you to free the allocated memory.
+ *   - The array ends with EOF.
+ *   - If user pressed CTRL-D (i.e. EOF), no selection returned.
+ */
+static int *list_and_choose(struct menu_opts *opts, struct menu_stuff *stuff)
+{
+	struct strbuf choice = STRBUF_INIT;
+	int *chosen, *result;
+	int nr = 0;
+	int eof = 0;
+	int i;
+
+	chosen = xmalloc(sizeof(int) * stuff->nr);
+	/* set chosen as uninitialized */
+	for (i = 0; i < stuff->nr; i++)
+		chosen[i] = -1;
+
+	for (;;) {
+		if (opts->header) {
+			printf_ln("%s%s%s",
+				  clean_get_color(CLEAN_COLOR_HEADER),
+				  _(opts->header),
+				  clean_get_color(CLEAN_COLOR_RESET));
+		}
+
+		/* chosen will be initialized by print_highlight_menu_stuff */
+		print_highlight_menu_stuff(stuff, &chosen);
+
+		if (opts->flags & MENU_OPTS_LIST_ONLY)
+			break;
+
+		if (opts->prompt) {
+			printf("%s%s%s%s",
+			       clean_get_color(CLEAN_COLOR_PROMPT),
+			       _(opts->prompt),
+			       opts->flags & MENU_OPTS_SINGLETON ? "> " : ">> ",
+			       clean_get_color(CLEAN_COLOR_RESET));
+		}
+
+		if (strbuf_getline(&choice, stdin, '\n') != EOF) {
+			strbuf_trim(&choice);
+		} else {
+			eof = 1;
+			break;
+		}
+
+		/* help for prompt */
+		if (!strcmp(choice.buf, "?")) {
+			prompt_help_cmd(opts->flags & MENU_OPTS_SINGLETON);
+			continue;
+		}
+
+		/* for a multiple-choice menu, press ENTER (empty) will return back */
+		if (!(opts->flags & MENU_OPTS_SINGLETON) && !choice.len)
+			break;
+
+		nr = parse_choice(stuff,
+				  opts->flags & MENU_OPTS_SINGLETON,
+				  choice,
+				  &chosen);
+
+		if (opts->flags & MENU_OPTS_SINGLETON) {
+			if (nr)
+				break;
+		} else if (opts->flags & MENU_OPTS_IMMEDIATE) {
+			break;
+		}
+	}
+
+	if (eof) {
+		result = xmalloc(sizeof(int));
+		*result = EOF;
+	} else {
+		int j = 0;
+
+		/*
+		 * recalculate nr, if return back from menu directly with
+		 * default selections.
+		 */
+		if (!nr) {
+			for (i = 0; i < stuff->nr; i++)
+				nr += chosen[i];
+		}
+
+		result = xmalloc(sizeof(int) * (nr + 1));
+		memset(result, 0, sizeof(int) * (nr + 1));
+		for (i = 0; i < stuff->nr && j < nr; i++) {
+			if (chosen[i])
+				result[j++] = i;
+		}
+		result[j] = EOF;
+	}
+
+	free(chosen);
+	strbuf_release(&choice);
+	return result;
+}
+
+static int clean_cmd(void)
+{
+	return MENU_RETURN_NO_LOOP;
+}
+
+static int filter_by_patterns_cmd(void)
+{
+	struct dir_struct dir;
+	struct strbuf confirm = STRBUF_INIT;
+	struct strbuf **ignore_list;
+	struct string_list_item *item;
+	struct exclude_list *el;
+	int changed = -1, i;
+
+	for (;;) {
+		if (!del_list.nr)
+			break;
+
+		if (changed)
+			pretty_print_dels();
+
+		clean_print_color(CLEAN_COLOR_PROMPT);
+		printf(_("Input ignore patterns>> "));
+		clean_print_color(CLEAN_COLOR_RESET);
+		if (strbuf_getline(&confirm, stdin, '\n') != EOF)
+			strbuf_trim(&confirm);
+		else
+			putchar('\n');
+
+		/* quit filter_by_pattern mode if press ENTER or Ctrl-D */
+		if (!confirm.len)
+			break;
+
+		memset(&dir, 0, sizeof(dir));
+		el = add_exclude_list(&dir, EXC_CMDL, "manual exclude");
+		ignore_list = strbuf_split_max(&confirm, ' ', 0);
+
+		for (i = 0; ignore_list[i]; i++) {
+			strbuf_trim(ignore_list[i]);
+			if (!ignore_list[i]->len)
+				continue;
+
+			add_exclude(ignore_list[i]->buf, "", 0, el, -(i+1));
+		}
+
+		changed = 0;
+		for_each_string_list_item(item, &del_list) {
+			int dtype = DT_UNKNOWN;
+
+			if (is_excluded(&dir, item->string, &dtype)) {
+				*item->string = '\0';
+				changed++;
+			}
+		}
+
+		if (changed) {
+			string_list_remove_empty_items(&del_list, 0);
+		} else {
+			clean_print_color(CLEAN_COLOR_ERROR);
+			printf_ln(_("WARNING: Cannot find items matched by: %s"), confirm.buf);
+			clean_print_color(CLEAN_COLOR_RESET);
+		}
+
+		strbuf_list_free(ignore_list);
+		clear_directory(&dir);
+	}
+
+	strbuf_release(&confirm);
+	return 0;
+}
+
+static int select_by_numbers_cmd(void)
+{
+	struct menu_opts menu_opts;
+	struct menu_stuff menu_stuff;
+	struct string_list_item *items;
+	int *chosen;
+	int i, j;
+
+	menu_opts.header = NULL;
+	menu_opts.prompt = N_("Select items to delete");
+	menu_opts.flags = 0;
+
+	menu_stuff.type = MENU_STUFF_TYPE_STRING_LIST;
+	menu_stuff.stuff = &del_list;
+	menu_stuff.nr = del_list.nr;
+
+	chosen = list_and_choose(&menu_opts, &menu_stuff);
+	items = del_list.items;
+	for (i = 0, j = 0; i < del_list.nr; i++) {
+		if (i < chosen[j]) {
+			*(items[i].string) = '\0';
+		} else if (i == chosen[j]) {
+			/* delete selected item */
+			j++;
+			continue;
+		} else {
+			/* end of chosen (chosen[j] == EOF), won't delete */
+			*(items[i].string) = '\0';
+		}
+	}
+
+	string_list_remove_empty_items(&del_list, 0);
+
+	free(chosen);
+	return 0;
+}
+
+static int ask_each_cmd(void)
+{
+	struct strbuf confirm = STRBUF_INIT;
+	struct strbuf buf = STRBUF_INIT;
+	struct string_list_item *item;
+	const char *qname;
+	int changed = 0, eof = 0;
+
+	for_each_string_list_item(item, &del_list) {
+		/* Ctrl-D should stop removing files */
+		if (!eof) {
+			qname = quote_path_relative(item->string, NULL, &buf);
+			printf(_("remove %s? "), qname);
+			if (strbuf_getline(&confirm, stdin, '\n') != EOF) {
+				strbuf_trim(&confirm);
+			} else {
+				putchar('\n');
+				eof = 1;
+			}
+		}
+		if (!confirm.len || strncasecmp(confirm.buf, "yes", confirm.len)) {
+			*item->string = '\0';
+			changed++;
+		}
+	}
+
+	if (changed)
+		string_list_remove_empty_items(&del_list, 0);
+
+	strbuf_release(&buf);
+	strbuf_release(&confirm);
+	return MENU_RETURN_NO_LOOP;
+}
+
+static int quit_cmd(void)
+{
+	string_list_clear(&del_list, 0);
+	printf_ln(_("Bye."));
+	return MENU_RETURN_NO_LOOP;
+}
+
+static int help_cmd(void)
+{
+	clean_print_color(CLEAN_COLOR_HELP);
+	printf_ln(_(
+		    "clean               - start cleaning\n"
+		    "filter by pattern   - exclude items from deletion\n"
+		    "select by numbers   - select items to be deleted by numbers\n"
+		    "ask each            - confirm each deletion (like \"rm -i\")\n"
+		    "quit                - stop cleaning\n"
+		    "help                - this screen\n"
+		    "?                   - help for prompt selection"
+		   ));
+	clean_print_color(CLEAN_COLOR_RESET);
+	return 0;
+}
+
+static void interactive_main_loop(void)
+{
+	while (del_list.nr) {
+		struct menu_opts menu_opts;
+		struct menu_stuff menu_stuff;
+		struct menu_item menus[] = {
+			{'c', "clean",			0, clean_cmd},
+			{'f', "filter by pattern",	0, filter_by_patterns_cmd},
+			{'s', "select by numbers",	0, select_by_numbers_cmd},
+			{'a', "ask each",		0, ask_each_cmd},
+			{'q', "quit",			0, quit_cmd},
+			{'h', "help",			0, help_cmd},
+		};
+		int *chosen;
+
+		menu_opts.header = N_("*** Commands ***");
+		menu_opts.prompt = N_("What now");
+		menu_opts.flags = MENU_OPTS_SINGLETON;
+
+		menu_stuff.type = MENU_STUFF_TYPE_MENU_ITEM;
+		menu_stuff.stuff = menus;
+		menu_stuff.nr = sizeof(menus) / sizeof(struct menu_item);
+
+		clean_print_color(CLEAN_COLOR_HEADER);
+		printf_ln(Q_("Would remove the following item:",
+			     "Would remove the following items:",
+			     del_list.nr));
+		clean_print_color(CLEAN_COLOR_RESET);
+
+		pretty_print_dels();
+
+		chosen = list_and_choose(&menu_opts, &menu_stuff);
+
+		if (*chosen != EOF) {
+			int ret;
+			ret = menus[*chosen].fn();
+			if (ret != MENU_RETURN_NO_LOOP) {
+				free(chosen);
+				chosen = NULL;
+				if (!del_list.nr) {
+					clean_print_color(CLEAN_COLOR_ERROR);
+					printf_ln(_("No more files to clean, exiting."));
+					clean_print_color(CLEAN_COLOR_RESET);
+					break;
+				}
+				continue;
+			}
+		} else {
+			quit_cmd();
+		}
+
+		free(chosen);
+		chosen = NULL;
+		break;
+	}
+}
+
 int cmd_clean(int argc, const char **argv, const char *prefix)
 {
 	int i, res;
 	int dry_run = 0, remove_directories = 0, quiet = 0, ignored = 0;
 	int ignored_only = 0, config_set = 0, errors = 0, gone = 1;
 	int rm_flags = REMOVE_DIR_KEEP_NESTED_GIT;
-	struct strbuf directory = STRBUF_INIT;
+	struct strbuf abs_path = STRBUF_INIT;
 	struct dir_struct dir;
 	static const char **pathspec;
 	struct strbuf buf = STRBUF_INIT;
 	struct string_list exclude_list = STRING_LIST_INIT_NODUP;
 	struct exclude_list *el;
+	struct string_list_item *item;
 	const char *qname;
 	char *seen = NULL;
 	struct option options[] = {
 		OPT__QUIET(&quiet, N_("do not print names of files removed")),
 		OPT__DRY_RUN(&dry_run, N_("dry run")),
 		OPT__FORCE(&force, N_("force")),
+		OPT_BOOL('i', "interactive", &interactive, N_("interactive cleaning")),
 		OPT_BOOLEAN('d', NULL, &remove_directories,
 				N_("remove whole directories")),
 		{ OPTION_CALLBACK, 'e', "exclude", &exclude_list, N_("pattern"),
@@ -186,12 +901,12 @@
 	if (ignored && ignored_only)
 		die(_("-x and -X cannot be used together"));
 
-	if (!dry_run && !force) {
+	if (!interactive && !dry_run && !force) {
 		if (config_set)
-			die(_("clean.requireForce set to true and neither -n nor -f given; "
+			die(_("clean.requireForce set to true and neither -i, -n nor -f given; "
 				  "refusing to clean"));
 		else
-			die(_("clean.requireForce defaults to true and neither -n nor -f given; "
+			die(_("clean.requireForce defaults to true and neither -i, -n nor -f given; "
 				  "refusing to clean"));
 	}
 
@@ -221,8 +936,9 @@
 		struct dir_entry *ent = dir.entries[i];
 		int len, pos;
 		int matches = 0;
-		struct cache_entry *ce;
+		const struct cache_entry *ce;
 		struct stat st;
+		const char *rel;
 
 		/*
 		 * Remove the '/' at the end that directory
@@ -242,13 +958,8 @@
 				continue; /* Yup, this one exists unmerged */
 		}
 
-		/*
-		 * we might have removed this as part of earlier
-		 * recursive directory removal, so lstat() here could
-		 * fail with ENOENT.
-		 */
 		if (lstat(ent->name, &st))
-			continue;
+			die_errno("Cannot lstat '%s'", ent->name);
 
 		if (pathspec) {
 			memset(seen, 0, argc > 0 ? argc : 1);
@@ -257,33 +968,62 @@
 		}
 
 		if (S_ISDIR(st.st_mode)) {
-			strbuf_addstr(&directory, ent->name);
 			if (remove_directories || (matches == MATCHED_EXACTLY)) {
-				if (remove_dirs(&directory, prefix, rm_flags, dry_run, quiet, &gone))
-					errors++;
-				if (gone && !quiet) {
-					qname = quote_path_relative(directory.buf, directory.len, &buf, prefix);
-					printf(dry_run ? _(msg_would_remove) : _(msg_remove), qname);
-				}
+				rel = relative_path(ent->name, prefix, &buf);
+				string_list_append(&del_list, rel);
 			}
-			strbuf_reset(&directory);
 		} else {
 			if (pathspec && !matches)
 				continue;
-			res = dry_run ? 0 : unlink(ent->name);
+			rel = relative_path(ent->name, prefix, &buf);
+			string_list_append(&del_list, rel);
+		}
+	}
+
+	if (interactive && del_list.nr > 0)
+		interactive_main_loop();
+
+	for_each_string_list_item(item, &del_list) {
+		struct stat st;
+
+		if (prefix)
+			strbuf_addstr(&abs_path, prefix);
+
+		strbuf_addstr(&abs_path, item->string);
+
+		/*
+		 * we might have removed this as part of earlier
+		 * recursive directory removal, so lstat() here could
+		 * fail with ENOENT.
+		 */
+		if (lstat(abs_path.buf, &st))
+			continue;
+
+		if (S_ISDIR(st.st_mode)) {
+			if (remove_dirs(&abs_path, prefix, rm_flags, dry_run, quiet, &gone))
+				errors++;
+			if (gone && !quiet) {
+				qname = quote_path_relative(item->string, NULL, &buf);
+				printf(dry_run ? _(msg_would_remove) : _(msg_remove), qname);
+			}
+		} else {
+			res = dry_run ? 0 : unlink(abs_path.buf);
 			if (res) {
-				qname = quote_path_relative(ent->name, -1, &buf, prefix);
+				qname = quote_path_relative(item->string, NULL, &buf);
 				warning(_(msg_warn_remove_failed), qname);
 				errors++;
 			} else if (!quiet) {
-				qname = quote_path_relative(ent->name, -1, &buf, prefix);
+				qname = quote_path_relative(item->string, NULL, &buf);
 				printf(dry_run ? _(msg_would_remove) : _(msg_remove), qname);
 			}
 		}
+		strbuf_reset(&abs_path);
 	}
 	free(seen);
 
-	strbuf_release(&directory);
+	strbuf_release(&abs_path);
+	strbuf_release(&buf);
+	string_list_clear(&del_list, 0);
 	string_list_clear(&exclude_list, 0);
 	return (errors != 0);
 }
diff --git a/builtin/clone.c b/builtin/clone.c
index 035ab64..430307b 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -18,7 +18,6 @@
 #include "transport.h"
 #include "strbuf.h"
 #include "dir.h"
-#include "pack-refs.h"
 #include "sigchain.h"
 #include "branch.h"
 #include "remote.h"
@@ -494,13 +493,16 @@
 {
 	const struct ref *r;
 
+	lock_packed_refs(LOCK_DIE_ON_ERROR);
+
 	for (r = local_refs; r; r = r->next) {
 		if (!r->peer_ref)
 			continue;
 		add_packed_ref(r->peer_ref->name, r->old_sha1);
 	}
 
-	pack_refs(PACK_REFS_ALL);
+	if (commit_packed_refs())
+		die_errno("unable to overwrite old ref-pack file");
 }
 
 static void write_followtags(const struct ref *refs, const char *msg)
@@ -542,12 +544,21 @@
 			       const struct ref *mapped_refs,
 			       const struct ref *remote_head_points_at,
 			       const char *branch_top,
-			       const char *msg)
+			       const char *msg,
+			       struct transport *transport,
+			       int check_connectivity)
 {
 	const struct ref *rm = mapped_refs;
 
-	if (check_everything_connected(iterate_ref_map, 0, &rm))
-		die(_("remote did not send all necessary objects"));
+	if (check_connectivity) {
+		if (0 <= option_verbosity)
+			printf(_("Checking connectivity... "));
+		if (check_everything_connected_with_transport(iterate_ref_map,
+							      0, &rm, transport))
+			die(_("remote did not send all necessary objects"));
+		if (0 <= option_verbosity)
+			printf(_("done\n"));
+	}
 
 	if (refs) {
 		write_remote_refs(mapped_refs);
@@ -693,7 +704,7 @@
 			/*
 			 * otherwise, the next "git fetch" will
 			 * simply fetch from HEAD without updating
-			 * any remote tracking branch, which is what
+			 * any remote-tracking branch, which is what
 			 * we want.
 			 */
 		} else {
@@ -783,6 +794,8 @@
 	is_local = option_local != 0 && path && !is_bundle;
 	if (is_local && option_depth)
 		warning(_("--depth is ignored in local clones; use file:// instead."));
+	if (option_local > 0 && !is_local)
+		warning(_("--local is ignored"));
 
 	if (argc == 2)
 		dir = xstrdup(argv[1]);
@@ -889,6 +902,9 @@
 		if (option_upload_pack)
 			transport_set_option(transport, TRANS_OPT_UPLOADPACK,
 					     option_upload_pack);
+
+		if (transport->smart_options && !option_depth)
+			transport->smart_options->check_self_contained_and_connected = 1;
 	}
 
 	refs = transport_get_remote_refs(transport);
@@ -950,7 +966,7 @@
 		transport_fetch_refs(transport, mapped_refs);
 
 	update_remote_refs(refs, mapped_refs, remote_head_points_at,
-			   branch_top.buf, reflog_msg.buf);
+			   branch_top.buf, reflog_msg.buf, transport, !is_local);
 
 	update_head(our_head_points_at, remote_head, reflog_msg.buf);
 
diff --git a/builtin/commit.c b/builtin/commit.c
index d2f30d9..10acc53 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -29,6 +29,7 @@
 #include "gpg-interface.h"
 #include "column.h"
 #include "sequencer.h"
+#include "notes-utils.h"
 
 static const char * const builtin_commit_usage[] = {
 	N_("git commit [options] [--] <pathspec>..."),
@@ -62,8 +63,18 @@
 "If you wish to commit it anyway, use:\n"
 "\n"
 "    git commit --allow-empty\n"
+"\n");
+
+static const char empty_cherry_pick_advice_single[] =
+N_("Otherwise, please use 'git reset'\n");
+
+static const char empty_cherry_pick_advice_multi[] =
+N_("If you wish to skip this commit, use:\n"
 "\n"
-"Otherwise, please use 'git reset'\n");
+"    git reset\n"
+"\n"
+"Then \"git cherry-pick --continue\" will resume cherry-picking\n"
+"the remaining commits.\n");
 
 static const char *use_message_buffer;
 static const char commit_editmsg[] = "COMMIT_EDITMSG";
@@ -106,24 +117,29 @@
 static const char *cleanup_arg;
 
 static enum commit_whence whence;
+static int sequencer_in_use;
 static int use_editor = 1, include_status = 1;
-static int show_ignored_in_status;
+static int show_ignored_in_status, have_option_m;
 static const char *only_include_assumed;
 static struct strbuf message = STRBUF_INIT;
 
-static enum {
+static enum status_format {
 	STATUS_FORMAT_NONE = 0,
 	STATUS_FORMAT_LONG,
 	STATUS_FORMAT_SHORT,
-	STATUS_FORMAT_PORCELAIN
-} status_format;
+	STATUS_FORMAT_PORCELAIN,
+
+	STATUS_FORMAT_UNSPECIFIED
+} status_format = STATUS_FORMAT_UNSPECIFIED;
 
 static int opt_parse_m(const struct option *opt, const char *arg, int unset)
 {
 	struct strbuf *buf = opt->value;
-	if (unset)
+	if (unset) {
+		have_option_m = 0;
 		strbuf_setlen(buf, 0);
-	else {
+	} else {
+		have_option_m = 1;
 		if (buf->len)
 			strbuf_addch(buf, '\n');
 		strbuf_addstr(buf, arg);
@@ -136,8 +152,11 @@
 {
 	if (file_exists(git_path("MERGE_HEAD")))
 		whence = FROM_MERGE;
-	else if (file_exists(git_path("CHERRY_PICK_HEAD")))
+	else if (file_exists(git_path("CHERRY_PICK_HEAD"))) {
 		whence = FROM_CHERRY_PICK;
+		if (file_exists(git_path("sequencer")))
+			sequencer_in_use = 1;
+	}
 	else
 		whence = FROM_COMMIT;
 	if (s)
@@ -202,7 +221,7 @@
 	}
 
 	for (i = 0; i < active_nr; i++) {
-		struct cache_entry *ce = active_cache[i];
+		const struct cache_entry *ce = active_cache[i];
 		struct string_list_item *item;
 
 		if (ce->ce_flags & CE_UPDATE)
@@ -457,6 +476,9 @@
 	case STATUS_FORMAT_PORCELAIN:
 		wt_porcelain_print(s);
 		break;
+	case STATUS_FORMAT_UNSPECIFIED:
+		die("BUG: finalize_deferred_config() should have been called");
+		break;
 	case STATUS_FORMAT_NONE:
 	case STATUS_FORMAT_LONG:
 		wt_status_print(s);
@@ -526,7 +548,6 @@
 					(lb - strlen(" ") -
 					 (a + strlen("\nauthor "))));
 		email = xmemdupz(lb + strlen("<"), rb - (lb + strlen("<")));
-		date = xmemdupz(rb + strlen("> "), eol - (rb + strlen("> ")));
 		len = eol - (rb + strlen("> "));
 		date = xmalloc(len + 2);
 		*date = '@';
@@ -803,8 +824,13 @@
 		run_status(stdout, index_file, prefix, 0, s);
 		if (amend)
 			fputs(_(empty_amend_advice), stderr);
-		else if (whence == FROM_CHERRY_PICK)
+		else if (whence == FROM_CHERRY_PICK) {
 			fputs(_(empty_cherry_pick_advice), stderr);
+			if (!sequencer_in_use)
+				fputs(_(empty_cherry_pick_advice_single), stderr);
+			else
+				fputs(_(empty_cherry_pick_advice_multi), stderr);
+		}
 		return 0;
 	}
 
@@ -958,6 +984,42 @@
 	return logmsg_reencode(commit, NULL, out_enc);
 }
 
+/*
+ * Enumerate what needs to be propagated when --porcelain
+ * is not in effect here.
+ */
+static struct status_deferred_config {
+	enum status_format status_format;
+	int show_branch;
+} status_deferred_config = {
+	STATUS_FORMAT_UNSPECIFIED,
+	-1 /* unspecified */
+};
+
+static void finalize_deferred_config(struct wt_status *s)
+{
+	int use_deferred_config = (status_format != STATUS_FORMAT_PORCELAIN &&
+				   !s->null_termination);
+
+	if (s->null_termination) {
+		if (status_format == STATUS_FORMAT_NONE ||
+		    status_format == STATUS_FORMAT_UNSPECIFIED)
+			status_format = STATUS_FORMAT_PORCELAIN;
+		else if (status_format == STATUS_FORMAT_LONG)
+			die(_("--long and -z are incompatible"));
+	}
+
+	if (use_deferred_config && status_format == STATUS_FORMAT_UNSPECIFIED)
+		status_format = status_deferred_config.status_format;
+	if (status_format == STATUS_FORMAT_UNSPECIFIED)
+		status_format = STATUS_FORMAT_NONE;
+
+	if (use_deferred_config && s->show_branch < 0)
+		s->show_branch = status_deferred_config.show_branch;
+	if (s->show_branch < 0)
+		s->show_branch = 0;
+}
+
 static int parse_and_validate_options(int argc, const char *argv[],
 				      const struct option *options,
 				      const char * const usage[],
@@ -968,6 +1030,7 @@
 	int f = 0;
 
 	argc = parse_options(argc, argv, prefix, options, usage, 0);
+	finalize_deferred_config(s);
 
 	if (force_author && !strchr(force_author, '>'))
 		force_author = find_author_by_nickname(force_author);
@@ -975,7 +1038,7 @@
 	if (force_author && renew_authorship)
 		die(_("Using both --reset-author and --author does not make sense"));
 
-	if (logfile || message.len || use_message || fixup_message)
+	if (logfile || have_option_m || use_message || fixup_message)
 		use_editor = 0;
 	if (0 <= edit_flag)
 		use_editor = edit_flag;
@@ -1052,12 +1115,6 @@
 	if (all && argc > 0)
 		die(_("Paths with -a does not make sense."));
 
-	if (s->null_termination) {
-		if (status_format == STATUS_FORMAT_NONE)
-			status_format = STATUS_FORMAT_PORCELAIN;
-		else if (status_format == STATUS_FORMAT_LONG)
-			die(_("--long and -z are incompatible"));
-	}
 	if (status_format != STATUS_FORMAT_NONE)
 		dry_run = 1;
 
@@ -1110,6 +1167,17 @@
 			s->submodule_summary = -1;
 		return 0;
 	}
+	if (!strcmp(k, "status.short")) {
+		if (git_config_bool(k, v))
+			status_deferred_config.status_format = STATUS_FORMAT_SHORT;
+		else
+			status_deferred_config.status_format = STATUS_FORMAT_NONE;
+		return 0;
+	}
+	if (!strcmp(k, "status.branch")) {
+		status_deferred_config.show_branch = git_config_bool(k, v);
+		return 0;
+	}
 	if (!strcmp(k, "status.color") || !strcmp(k, "color.status")) {
 		s->use_color = git_config_colorbool(k, v);
 		return 0;
@@ -1152,8 +1220,8 @@
 		OPT__VERBOSE(&verbose, N_("be verbose")),
 		OPT_SET_INT('s', "short", &status_format,
 			    N_("show status concisely"), STATUS_FORMAT_SHORT),
-		OPT_BOOLEAN('b', "branch", &s.show_branch,
-			    N_("show branch information")),
+		OPT_BOOL('b', "branch", &s.show_branch,
+			 N_("show branch information")),
 		OPT_SET_INT(0, "porcelain", &status_format,
 			    N_("machine-readable output"),
 			    STATUS_FORMAT_PORCELAIN),
@@ -1186,13 +1254,7 @@
 			     builtin_status_options,
 			     builtin_status_usage, 0);
 	finalize_colopts(&s.colopts, -1);
-
-	if (s.null_termination) {
-		if (status_format == STATUS_FORMAT_NONE)
-			status_format = STATUS_FORMAT_PORCELAIN;
-		else if (status_format == STATUS_FORMAT_LONG)
-			die(_("--long and -z are incompatible"));
-	}
+	finalize_deferred_config(&s);
 
 	handle_untracked_files_arg(&s);
 	if (show_ignored_in_status)
@@ -1221,6 +1283,9 @@
 	case STATUS_FORMAT_PORCELAIN:
 		wt_porcelain_print(&s);
 		break;
+	case STATUS_FORMAT_UNSPECIFIED:
+		die("BUG: finalize_deferred_config() should have been called");
+		break;
 	case STATUS_FORMAT_NONE:
 	case STATUS_FORMAT_LONG:
 		s.verbose = verbose;
@@ -1389,7 +1454,7 @@
 		OPT_BOOLEAN(0, "dry-run", &dry_run, N_("show what would be committed")),
 		OPT_SET_INT(0, "short", &status_format, N_("show status concisely"),
 			    STATUS_FORMAT_SHORT),
-		OPT_BOOLEAN(0, "branch", &s.show_branch, N_("show branch information")),
+		OPT_BOOL(0, "branch", &s.show_branch, N_("show branch information")),
 		OPT_SET_INT(0, "porcelain", &status_format,
 			    N_("machine-readable output"), STATUS_FORMAT_PORCELAIN),
 		OPT_SET_INT(0, "long", &status_format,
@@ -1430,6 +1495,7 @@
 	wt_status_prepare(&s);
 	gitmodules_config();
 	git_config(git_commit_config, &s);
+	status_format = STATUS_FORMAT_NONE; /* Ignore status.short */
 	determine_whence(&s);
 	s.colopts = 0;
 
@@ -1591,7 +1657,7 @@
 		if (cfg) {
 			/* we are amending, so current_head is not NULL */
 			copy_note_for_rewrite(cfg, current_head->object.sha1, sha1);
-			finish_copy_notes_for_rewrite(cfg);
+			finish_copy_notes_for_rewrite(cfg, "Notes added by 'git commit --amend'");
 		}
 		run_rewrite_hook(current_head->object.sha1, sha1);
 	}
diff --git a/builtin/config.c b/builtin/config.c
index 33c9bf9..4010c43 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -21,6 +21,7 @@
 
 static int use_global_config, use_system_config, use_local_config;
 static const char *given_config_file;
+static const char *given_config_blob;
 static int actions, types;
 static const char *get_color_slot, *get_colorbool_slot;
 static int end_null;
@@ -53,6 +54,7 @@
 	OPT_BOOLEAN(0, "system", &use_system_config, N_("use system config file")),
 	OPT_BOOLEAN(0, "local", &use_local_config, N_("use repository config file")),
 	OPT_STRING('f', "file", &given_config_file, N_("file"), N_("use given config file")),
+	OPT_STRING(0, "blob", &given_config_blob, N_("blob-id"), N_("read config from given blob object")),
 	OPT_GROUP(N_("Action")),
 	OPT_BIT(0, "get", &actions, N_("get value: name [value-regex]"), ACTION_GET),
 	OPT_BIT(0, "get-all", &actions, N_("get all values: key [value-regex]"), ACTION_GET_ALL),
@@ -218,7 +220,8 @@
 	}
 
 	git_config_with_options(collect_config, &values,
-				given_config_file, respect_includes);
+				given_config_file, given_config_blob,
+				respect_includes);
 
 	ret = !values.nr;
 
@@ -302,7 +305,8 @@
 	get_color_found = 0;
 	parsed_color[0] = '\0';
 	git_config_with_options(git_get_color_config, NULL,
-				given_config_file, respect_includes);
+				given_config_file, given_config_blob,
+				respect_includes);
 
 	if (!get_color_found && def_color)
 		color_parse(def_color, "command line", parsed_color);
@@ -329,8 +333,10 @@
 {
 	get_colorbool_found = -1;
 	get_diff_color_found = -1;
+	get_color_ui_found = -1;
 	git_config_with_options(git_get_colorbool_config, NULL,
-				given_config_file, respect_includes);
+				given_config_file, given_config_blob,
+				respect_includes);
 
 	if (get_colorbool_found < 0) {
 		if (!strcmp(get_colorbool_slot, "color.diff"))
@@ -339,6 +345,10 @@
 			get_colorbool_found = get_color_ui_found;
 	}
 
+	if (get_colorbool_found < 0)
+		/* default value if none found in config */
+		get_colorbool_found = GIT_COLOR_AUTO;
+
 	get_colorbool_found = want_color(get_colorbool_found);
 
 	if (print) {
@@ -348,6 +358,12 @@
 		return get_colorbool_found ? 0 : 1;
 }
 
+static void check_blob_write(void)
+{
+	if (given_config_blob)
+		die("writing config blobs is not supported");
+}
+
 int cmd_config(int argc, const char **argv, const char *prefix)
 {
 	int nongit = !startup_info->have_repository;
@@ -359,7 +375,8 @@
 			     builtin_config_usage,
 			     PARSE_OPT_STOP_AT_NON_OPTION);
 
-	if (use_global_config + use_system_config + use_local_config + !!given_config_file > 1) {
+	if (use_global_config + use_system_config + use_local_config +
+	    !!given_config_file + !!given_config_blob > 1) {
 		error("only one config file at a time.");
 		usage_with_options(builtin_config_usage, builtin_config_options);
 	}
@@ -379,8 +396,8 @@
 			 */
 			die("$HOME not set");
 
-		if (access_or_warn(user_config, R_OK) &&
-		    xdg_config && !access_or_warn(xdg_config, R_OK))
+		if (access_or_warn(user_config, R_OK, 0) &&
+		    xdg_config && !access_or_warn(xdg_config, R_OK, 0))
 			given_config_file = xdg_config;
 		else
 			given_config_file = user_config;
@@ -438,6 +455,7 @@
 		check_argc(argc, 0, 0);
 		if (git_config_with_options(show_all_config, NULL,
 					    given_config_file,
+					    given_config_blob,
 					    respect_includes) < 0) {
 			if (given_config_file)
 				die_errno("unable to read config file '%s'",
@@ -450,6 +468,8 @@
 		check_argc(argc, 0, 0);
 		if (!given_config_file && nongit)
 			die("not in a git directory");
+		if (given_config_blob)
+			die("editing blobs is not supported");
 		git_config(git_default_config, NULL);
 		launch_editor(given_config_file ?
 			      given_config_file : git_path("config"),
@@ -457,6 +477,7 @@
 	}
 	else if (actions == ACTION_SET) {
 		int ret;
+		check_blob_write();
 		check_argc(argc, 2, 2);
 		value = normalize_value(argv[0], argv[1]);
 		ret = git_config_set_in_file(given_config_file, argv[0], value);
@@ -466,18 +487,21 @@
 		return ret;
 	}
 	else if (actions == ACTION_SET_ALL) {
+		check_blob_write();
 		check_argc(argc, 2, 3);
 		value = normalize_value(argv[0], argv[1]);
 		return git_config_set_multivar_in_file(given_config_file,
 						       argv[0], value, argv[2], 0);
 	}
 	else if (actions == ACTION_ADD) {
+		check_blob_write();
 		check_argc(argc, 2, 2);
 		value = normalize_value(argv[0], argv[1]);
 		return git_config_set_multivar_in_file(given_config_file,
 						       argv[0], value, "^$", 0);
 	}
 	else if (actions == ACTION_REPLACE_ALL) {
+		check_blob_write();
 		check_argc(argc, 2, 3);
 		value = normalize_value(argv[0], argv[1]);
 		return git_config_set_multivar_in_file(given_config_file,
@@ -500,6 +524,7 @@
 		return get_value(argv[0], argv[1]);
 	}
 	else if (actions == ACTION_UNSET) {
+		check_blob_write();
 		check_argc(argc, 1, 2);
 		if (argc == 2)
 			return git_config_set_multivar_in_file(given_config_file,
@@ -509,12 +534,14 @@
 						      argv[0], NULL);
 	}
 	else if (actions == ACTION_UNSET_ALL) {
+		check_blob_write();
 		check_argc(argc, 1, 2);
 		return git_config_set_multivar_in_file(given_config_file,
 						       argv[0], NULL, argv[1], 1);
 	}
 	else if (actions == ACTION_RENAME_SECTION) {
 		int ret;
+		check_blob_write();
 		check_argc(argc, 2, 2);
 		ret = git_config_rename_section_in_file(given_config_file,
 							argv[0], argv[1]);
@@ -525,6 +552,7 @@
 	}
 	else if (actions == ACTION_REMOVE_SECTION) {
 		int ret;
+		check_blob_write();
 		check_argc(argc, 1, 1);
 		ret = git_config_rename_section_in_file(given_config_file,
 							argv[0], NULL);
diff --git a/builtin/describe.c b/builtin/describe.c
index 6636a68..7d73722 100644
--- a/builtin/describe.c
+++ b/builtin/describe.c
@@ -7,6 +7,7 @@
 #include "parse-options.h"
 #include "diff.h"
 #include "hash.h"
+#include "argv-array.h"
 
 #define SEEN		(1u<<0)
 #define MAX_TAGS	(FLAG_BITS - 1)
@@ -21,6 +22,7 @@
 static int all;	/* Any valid ref can be used */
 static int tags;	/* Allow lightweight tags */
 static int longformat;
+static int first_parent;
 static int abbrev = -1; /* unspecified */
 static int max_candidates = 10;
 static struct hash_table names;
@@ -42,7 +44,7 @@
 	unsigned prio:2; /* annotated tag = 2, tag = 1, head = 0 */
 	unsigned name_checked:1;
 	unsigned char sha1[20];
-	const char *path;
+	char *path;
 };
 static const char *prio_names[] = {
 	"head", "lightweight", "annotated",
@@ -126,12 +128,14 @@
 			} else {
 				e->next = NULL;
 			}
+			e->path = NULL;
 		}
 		e->tag = tag;
 		e->prio = prio;
 		e->name_checked = 0;
 		hashcpy(e->sha1, sha1);
-		e->path = path;
+		free(e->path);
+		e->path = xstrdup(path);
 	}
 }
 
@@ -336,6 +340,9 @@
 				commit_list_insert_by_date(p, &list);
 			p->object.flags |= c->object.flags;
 			parents = parents->next;
+
+			if (first_parent)
+				break;
 		}
 	}
 
@@ -404,6 +411,7 @@
 		OPT_BOOLEAN(0, "all",        &all, N_("use any ref")),
 		OPT_BOOLEAN(0, "tags",       &tags, N_("use any tag, even unannotated")),
 		OPT_BOOLEAN(0, "long",       &longformat, N_("always use long format")),
+		OPT_BOOLEAN(0, "first-parent", &first_parent, N_("only follow first parent")),
 		OPT__ABBREV(&abbrev),
 		OPT_SET_INT(0, "exact-match", &max_candidates,
 			    N_("only output exact matches"), 0),
@@ -435,24 +443,24 @@
 		die(_("--long is incompatible with --abbrev=0"));
 
 	if (contains) {
-		const char **args = xmalloc((7 + argc) * sizeof(char *));
-		int i = 0;
-		args[i++] = "name-rev";
-		args[i++] = "--name-only";
-		args[i++] = "--no-undefined";
+		struct argv_array args;
+
+		argv_array_init(&args);
+		argv_array_pushl(&args, "name-rev",
+				 "--peel-tag", "--name-only", "--no-undefined",
+				 NULL);
 		if (always)
-			args[i++] = "--always";
+			argv_array_push(&args, "--always");
 		if (!all) {
-			args[i++] = "--tags";
-			if (pattern) {
-				char *s = xmalloc(strlen("--refs=refs/tags/") + strlen(pattern) + 1);
-				sprintf(s, "--refs=refs/tags/%s", pattern);
-				args[i++] = s;
-			}
+			argv_array_push(&args, "--tags");
+			if (pattern)
+				argv_array_pushf(&args, "--refs=refs/tags/%s", pattern);
 		}
-		memcpy(args + i, argv, argc * sizeof(char *));
-		args[i + argc] = NULL;
-		return cmd_name_rev(i + argc, args, prefix);
+		while (*argv) {
+			argv_array_push(&args, *argv);
+			argv++;
+		}
+		return cmd_name_rev(args.argc, args.argv, prefix);
 	}
 
 	init_hash(&names);
diff --git a/builtin/diff.c b/builtin/diff.c
index 8c2af6c..9fc273d 100644
--- a/builtin/diff.c
+++ b/builtin/diff.c
@@ -153,7 +153,8 @@
 
 static int builtin_diff_tree(struct rev_info *revs,
 			     int argc, const char **argv,
-			     struct object_array_entry *ent)
+			     struct object_array_entry *ent0,
+			     struct object_array_entry *ent1)
 {
 	const unsigned char *(sha1[2]);
 	int swap = 0;
@@ -161,13 +162,14 @@
 	if (argc > 1)
 		usage(builtin_diff_usage);
 
-	/* We saw two trees, ent[0] and ent[1].
-	 * if ent[1] is uninteresting, they are swapped
+	/*
+	 * We saw two trees, ent0 and ent1.  If ent1 is uninteresting,
+	 * swap them.
 	 */
-	if (ent[1].item->flags & UNINTERESTING)
+	if (ent1->item->flags & UNINTERESTING)
 		swap = 1;
-	sha1[swap] = ent[0].item->sha1;
-	sha1[1-swap] = ent[1].item->sha1;
+	sha1[swap] = ent0->item->sha1;
+	sha1[1-swap] = ent1->item->sha1;
 	diff_tree_sha1(sha1[0], sha1[1], "", &revs->diffopt);
 	log_tree_diff_flush(revs);
 	return 0;
@@ -251,8 +253,8 @@
 {
 	int i;
 	struct rev_info rev;
-	struct object_array_entry ent[100];
-	int ents = 0, blobs = 0, paths = 0;
+	struct object_array ent = OBJECT_ARRAY_INIT;
+	int blobs = 0, paths = 0;
 	const char *path = NULL;
 	struct blobinfo blob[2];
 	int nongit;
@@ -337,9 +339,9 @@
 	}
 
 	for (i = 0; i < rev.pending.nr; i++) {
-		struct object_array_entry *list = rev.pending.objects+i;
-		struct object *obj = list->item;
-		const char *name = list->name;
+		struct object_array_entry *entry = &rev.pending.objects[i];
+		struct object *obj = entry->item;
+		const char *name = entry->name;
 		int flags = (obj->flags & UNINTERESTING);
 		if (!obj->parsed)
 			obj = parse_object(obj->sha1);
@@ -348,27 +350,21 @@
 			die(_("invalid object '%s' given."), name);
 		if (obj->type == OBJ_COMMIT)
 			obj = &((struct commit *)obj)->tree->object;
+
 		if (obj->type == OBJ_TREE) {
-			if (ARRAY_SIZE(ent) <= ents)
-				die(_("more than %d trees given: '%s'"),
-				    (int) ARRAY_SIZE(ent), name);
 			obj->flags |= flags;
-			ent[ents].item = obj;
-			ent[ents].name = name;
-			ents++;
-			continue;
-		}
-		if (obj->type == OBJ_BLOB) {
+			add_object_array(obj, name, &ent);
+		} else if (obj->type == OBJ_BLOB) {
 			if (2 <= blobs)
 				die(_("more than two blobs given: '%s'"), name);
 			hashcpy(blob[blobs].sha1, obj->sha1);
 			blob[blobs].name = name;
-			blob[blobs].mode = list->mode;
+			blob[blobs].mode = entry->mode;
 			blobs++;
-			continue;
 
+		} else {
+			die(_("unhandled object '%s' given."), name);
 		}
-		die(_("unhandled object '%s' given."), name);
 	}
 	if (rev.prune_data.nr) {
 		if (!path)
@@ -379,7 +375,7 @@
 	/*
 	 * Now, do the arguments look reasonable?
 	 */
-	if (!ents) {
+	if (!ent.nr) {
 		switch (blobs) {
 		case 0:
 			result = builtin_diff_files(&rev, argc, argv);
@@ -400,23 +396,26 @@
 	}
 	else if (blobs)
 		usage(builtin_diff_usage);
-	else if (ents == 1)
+	else if (ent.nr == 1)
 		result = builtin_diff_index(&rev, argc, argv);
-	else if (ents == 2)
-		result = builtin_diff_tree(&rev, argc, argv, ent);
-	else if (ent[0].item->flags & UNINTERESTING) {
+	else if (ent.nr == 2)
+		result = builtin_diff_tree(&rev, argc, argv,
+					   &ent.objects[0], &ent.objects[1]);
+	else if (ent.objects[0].item->flags & UNINTERESTING) {
 		/*
 		 * diff A...B where there is at least one merge base
-		 * between A and B.  We have ent[0] == merge-base,
-		 * ent[ents-2] == A, and ent[ents-1] == B.  Show diff
-		 * between the base and B.  Note that we pick one
-		 * merge base at random if there are more than one.
+		 * between A and B.  We have ent.objects[0] ==
+		 * merge-base, ent.objects[ents-2] == A, and
+		 * ent.objects[ents-1] == B.  Show diff between the
+		 * base and B.  Note that we pick one merge base at
+		 * random if there are more than one.
 		 */
-		ent[1] = ent[ents-1];
-		result = builtin_diff_tree(&rev, argc, argv, ent);
+		result = builtin_diff_tree(&rev, argc, argv,
+					   &ent.objects[0],
+					   &ent.objects[ent.nr-1]);
 	} else
 		result = builtin_diff_combined(&rev, argc, argv,
-					       ent, ents);
+					       ent.objects, ent.nr);
 	result = diff_result_code(&rev.diffopt, result);
 	if (1 < rev.diffopt.skip_stat_unmatch)
 		refresh_index_quietly();
diff --git a/builtin/fast-export.c b/builtin/fast-export.c
index d60d675..8e19058 100644
--- a/builtin/fast-export.c
+++ b/builtin/fast-export.c
@@ -379,7 +379,7 @@
 	int tagged_mark;
 	struct commit *p;
 
-	/* Trees have no identifer in fast-export output, thus we have no way
+	/* Trees have no identifier in fast-export output, thus we have no way
 	 * to output tags of trees, tags of tags of trees, etc.  Simply omit
 	 * such tags.
 	 */
@@ -613,6 +613,8 @@
 		char *line_end, *mark_end;
 		unsigned char sha1[20];
 		struct object *object;
+		struct commit *commit;
+		enum object_type type;
 
 		line_end = strchr(line, '\n');
 		if (line[0] != ':' || !line_end)
@@ -621,23 +623,29 @@
 
 		mark = strtoumax(line + 1, &mark_end, 10);
 		if (!mark || mark_end == line + 1
-			|| *mark_end != ' ' || get_sha1(mark_end + 1, sha1))
+			|| *mark_end != ' ' || get_sha1_hex(mark_end + 1, sha1))
 			die("corrupt mark line: %s", line);
 
 		if (last_idnum < mark)
 			last_idnum = mark;
 
-		object = parse_object(sha1);
-		if (!object)
+		type = sha1_object_info(sha1, NULL);
+		if (type < 0)
+			die("object not found: %s", sha1_to_hex(sha1));
+
+		if (type != OBJ_COMMIT)
+			/* only commits */
 			continue;
 
+		commit = lookup_commit(sha1);
+		if (!commit)
+			die("not a commit? can't happen: %s", sha1_to_hex(sha1));
+
+		object = &commit->object;
+
 		if (object->flags & SHOWN)
 			error("Object %s already has a mark", sha1_to_hex(sha1));
 
-		if (object->type != OBJ_COMMIT)
-			/* only commits */
-			continue;
-
 		mark_object(object, mark);
 
 		object->flags |= SHOWN;
diff --git a/builtin/fetch.c b/builtin/fetch.c
index 4b6b1df..5647055 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -36,7 +36,8 @@
 static const char *depth;
 static const char *upload_pack;
 static struct strbuf default_rla = STRBUF_INIT;
-static struct transport *transport;
+static struct transport *gtransport;
+static struct transport *gsecondary;
 static const char *submodule_prefix = "";
 static const char *recurse_submodules_default;
 
@@ -95,8 +96,10 @@
 
 static void unlock_pack(void)
 {
-	if (transport)
-		transport_unlock_pack(transport);
+	if (gtransport)
+		transport_unlock_pack(gtransport);
+	if (gsecondary)
+		transport_unlock_pack(gsecondary);
 }
 
 static void unlock_pack_on_signal(int signo)
@@ -119,7 +122,7 @@
 
 		for (rm = *head; rm; rm = rm->next) {
 			if (branch_merge_matches(branch, i, rm->name)) {
-				rm->merge = 1;
+				rm->fetch_head_status = FETCH_HEAD_MERGE;
 				break;
 			}
 		}
@@ -140,7 +143,7 @@
 		refspec.src = branch->merge[i]->src;
 		get_fetch_map(remote_refs, &refspec, tail, 1);
 		for (rm = *old_tail; rm; rm = rm->next)
-			rm->merge = 1;
+			rm->fetch_head_status = FETCH_HEAD_MERGE;
 	}
 }
 
@@ -160,6 +163,8 @@
 	const struct ref *remote_refs = transport_get_remote_refs(transport);
 
 	if (ref_count || tags == TAGS_SET) {
+		struct ref **old_tail;
+
 		for (i = 0; i < ref_count; i++) {
 			get_fetch_map(remote_refs, &refs[i], &tail, 0);
 			if (refs[i].dst && refs[i].dst[0])
@@ -167,9 +172,23 @@
 		}
 		/* Merge everything on the command line, but not --tags */
 		for (rm = ref_map; rm; rm = rm->next)
-			rm->merge = 1;
+			rm->fetch_head_status = FETCH_HEAD_MERGE;
 		if (tags == TAGS_SET)
 			get_fetch_map(remote_refs, tag_refspec, &tail, 0);
+
+		/*
+		 * For any refs that we happen to be fetching via command-line
+		 * arguments, take the opportunity to update their configured
+		 * counterparts. However, we do not want to mention these
+		 * entries in FETCH_HEAD at all, as they would simply be
+		 * duplicates of existing entries.
+		 */
+		old_tail = tail;
+		for (i = 0; i < transport->remote->fetch_refspec_nr; i++)
+			get_fetch_map(ref_map, &transport->remote->fetch[i],
+				      &tail, 1);
+		for (rm = *old_tail; rm; rm = rm->next)
+			rm->fetch_head_status = FETCH_HEAD_IGNORE;
 	} else {
 		/* Use the defaults */
 		struct remote *remote = transport->remote;
@@ -186,7 +205,7 @@
 					*autotags = 1;
 				if (!i && !has_merge && ref_map &&
 				    !remote->fetch[0].pattern)
-					ref_map->merge = 1;
+					ref_map->fetch_head_status = FETCH_HEAD_MERGE;
 			}
 			/*
 			 * if the remote we're fetching from is the same
@@ -202,7 +221,7 @@
 			ref_map = get_remote_ref(remote_refs, "HEAD");
 			if (!ref_map)
 				die(_("Couldn't find remote ref HEAD"));
-			ref_map->merge = 1;
+			ref_map->fetch_head_status = FETCH_HEAD_MERGE;
 			tail = &ref_map->next;
 		}
 	}
@@ -389,7 +408,7 @@
 	const char *what, *kind;
 	struct ref *rm;
 	char *url, *filename = dry_run ? "/dev/null" : git_path("FETCH_HEAD");
-	int want_merge;
+	int want_status;
 
 	fp = fopen(filename, "a");
 	if (!fp)
@@ -407,19 +426,22 @@
 	}
 
 	/*
-	 * The first pass writes objects to be merged and then the
-	 * second pass writes the rest, in order to allow using
-	 * FETCH_HEAD as a refname to refer to the ref to be merged.
+	 * We do a pass for each fetch_head_status type in their enum order, so
+	 * merged entries are written before not-for-merge. That lets readers
+	 * use FETCH_HEAD as a refname to refer to the ref to be merged.
 	 */
-	for (want_merge = 1; 0 <= want_merge; want_merge--) {
+	for (want_status = FETCH_HEAD_MERGE;
+	     want_status <= FETCH_HEAD_IGNORE;
+	     want_status++) {
 		for (rm = ref_map; rm; rm = rm->next) {
 			struct ref *ref = NULL;
+			const char *merge_status_marker = "";
 
 			commit = lookup_commit_reference_gently(rm->old_sha1, 1);
 			if (!commit)
-				rm->merge = 0;
+				rm->fetch_head_status = FETCH_HEAD_NOT_FOR_MERGE;
 
-			if (rm->merge != want_merge)
+			if (rm->fetch_head_status != want_status)
 				continue;
 
 			if (rm->peer_ref) {
@@ -465,16 +487,26 @@
 					strbuf_addf(&note, "%s ", kind);
 				strbuf_addf(&note, "'%s' of ", what);
 			}
-			fprintf(fp, "%s\t%s\t%s",
-				sha1_to_hex(rm->old_sha1),
-				rm->merge ? "" : "not-for-merge",
-				note.buf);
-			for (i = 0; i < url_len; ++i)
-				if ('\n' == url[i])
-					fputs("\\n", fp);
-				else
-					fputc(url[i], fp);
-			fputc('\n', fp);
+			switch (rm->fetch_head_status) {
+			case FETCH_HEAD_NOT_FOR_MERGE:
+				merge_status_marker = "not-for-merge";
+				/* fall-through */
+			case FETCH_HEAD_MERGE:
+				fprintf(fp, "%s\t%s\t%s",
+					sha1_to_hex(rm->old_sha1),
+					merge_status_marker,
+					note.buf);
+				for (i = 0; i < url_len; ++i)
+					if ('\n' == url[i])
+						fputs("\\n", fp);
+					else
+						fputc(url[i], fp);
+				fputc('\n', fp);
+				break;
+			default:
+				/* do not write anything to FETCH_HEAD */
+				break;
+			}
 
 			strbuf_reset(&note);
 			if (ref) {
@@ -571,7 +603,8 @@
 {
 	struct string_list *list = (struct string_list *)cbdata;
 	struct string_list_item *item = string_list_insert(list, refname);
-	item->util = (void *)sha1;
+	item->util = xmalloc(20);
+	hashcpy(item->util, sha1);
 	return 0;
 }
 
@@ -590,7 +623,7 @@
 			struct ref **head,
 			struct ref ***tail)
 {
-	struct string_list existing_refs = STRING_LIST_INIT_NODUP;
+	struct string_list existing_refs = STRING_LIST_INIT_DUP;
 	struct string_list remote_refs = STRING_LIST_INIT_NODUP;
 	const struct ref *ref;
 	struct string_list_item *item = NULL;
@@ -636,7 +669,7 @@
 		item = string_list_insert(&remote_refs, ref->name);
 		item->util = (void *)ref->old_sha1;
 	}
-	string_list_clear(&existing_refs, 0);
+	string_list_clear(&existing_refs, 1);
 
 	/*
 	 * We may have a final lightweight tag that needs to be
@@ -690,14 +723,56 @@
 	return 0;
 }
 
+static void set_option(struct transport *transport, const char *name, const char *value)
+{
+	int r = transport_set_option(transport, name, value);
+	if (r < 0)
+		die(_("Option \"%s\" value \"%s\" is not valid for %s"),
+		    name, value, transport->url);
+	if (r > 0)
+		warning(_("Option \"%s\" is ignored for %s\n"),
+			name, transport->url);
+}
+
+static struct transport *prepare_transport(struct remote *remote)
+{
+	struct transport *transport;
+	transport = transport_get(remote, NULL);
+	transport_set_verbosity(transport, verbosity, progress);
+	if (upload_pack)
+		set_option(transport, TRANS_OPT_UPLOADPACK, upload_pack);
+	if (keep)
+		set_option(transport, TRANS_OPT_KEEP, "yes");
+	if (depth)
+		set_option(transport, TRANS_OPT_DEPTH, depth);
+	return transport;
+}
+
+static void backfill_tags(struct transport *transport, struct ref *ref_map)
+{
+	if (transport->cannot_reuse) {
+		gsecondary = prepare_transport(transport->remote);
+		transport = gsecondary;
+	}
+
+	transport_set_option(transport, TRANS_OPT_FOLLOWTAGS, NULL);
+	transport_set_option(transport, TRANS_OPT_DEPTH, "0");
+	fetch_refs(transport, ref_map);
+
+	if (gsecondary) {
+		transport_disconnect(gsecondary);
+		gsecondary = NULL;
+	}
+}
+
 static int do_fetch(struct transport *transport,
 		    struct refspec *refs, int ref_count)
 {
-	struct string_list existing_refs = STRING_LIST_INIT_NODUP;
-	struct string_list_item *peer_item = NULL;
+	struct string_list existing_refs = STRING_LIST_INIT_DUP;
 	struct ref *ref_map;
 	struct ref *rm;
 	int autotags = (transport->remote->fetch_tags == 1);
+	int retcode = 0;
 
 	for_each_ref(add_existing, &existing_refs);
 
@@ -713,9 +788,9 @@
 
 	/* if not appending, truncate FETCH_HEAD */
 	if (!append && !dry_run) {
-		int errcode = truncate_fetch_head();
-		if (errcode)
-			return errcode;
+		retcode = truncate_fetch_head();
+		if (retcode)
+			goto cleanup;
 	}
 
 	ref_map = get_ref_map(transport, refs, ref_count, tags, &autotags);
@@ -724,8 +799,9 @@
 
 	for (rm = ref_map; rm; rm = rm->next) {
 		if (rm->peer_ref) {
-			peer_item = string_list_lookup(&existing_refs,
-						       rm->peer_ref->name);
+			struct string_list_item *peer_item =
+				string_list_lookup(&existing_refs,
+						   rm->peer_ref->name);
 			if (peer_item)
 				hashcpy(rm->peer_ref->old_sha1,
 					peer_item->util);
@@ -736,7 +812,8 @@
 		transport_set_option(transport, TRANS_OPT_FOLLOWTAGS, "1");
 	if (fetch_refs(transport, ref_map)) {
 		free_refs(ref_map);
-		return 1;
+		retcode = 1;
+		goto cleanup;
 	}
 	if (prune) {
 		/* If --tags was specified, pretend the user gave us the canonical tags refspec */
@@ -771,26 +848,14 @@
 		struct ref **tail = &ref_map;
 		ref_map = NULL;
 		find_non_local_tags(transport, &ref_map, &tail);
-		if (ref_map) {
-			transport_set_option(transport, TRANS_OPT_FOLLOWTAGS, NULL);
-			transport_set_option(transport, TRANS_OPT_DEPTH, "0");
-			fetch_refs(transport, ref_map);
-		}
+		if (ref_map)
+			backfill_tags(transport, ref_map);
 		free_refs(ref_map);
 	}
 
-	return 0;
-}
-
-static void set_option(const char *name, const char *value)
-{
-	int r = transport_set_option(transport, name, value);
-	if (r < 0)
-		die(_("Option \"%s\" value \"%s\" is not valid for %s"),
-			name, value, transport->url);
-	if (r > 0)
-		warning(_("Option \"%s\" is ignored for %s\n"),
-			name, transport->url);
+ cleanup:
+	string_list_clear(&existing_refs, 1);
+	return retcode;
 }
 
 static int get_one_remote_for_fetch(struct remote *remote, void *priv)
@@ -915,15 +980,7 @@
 		die(_("No remote repository specified.  Please, specify either a URL or a\n"
 		    "remote name from which new revisions should be fetched."));
 
-	transport = transport_get(remote, NULL);
-	transport_set_verbosity(transport, verbosity, progress);
-	if (upload_pack)
-		set_option(TRANS_OPT_UPLOADPACK, upload_pack);
-	if (keep)
-		set_option(TRANS_OPT_KEEP, "yes");
-	if (depth)
-		set_option(TRANS_OPT_DEPTH, depth);
-
+	gtransport = prepare_transport(remote);
 	if (argc > 0) {
 		int j = 0;
 		refs = xcalloc(argc + 1, sizeof(const char *));
@@ -949,10 +1006,10 @@
 	sigchain_push_common(unlock_pack_on_signal);
 	atexit(unlock_pack);
 	refspec = parse_fetch_refspec(ref_nr, refs);
-	exit_code = do_fetch(transport, refspec, ref_nr);
+	exit_code = do_fetch(gtransport, refspec, ref_nr);
 	free_refspec(ref_nr, refspec);
-	transport_disconnect(transport);
-	transport = NULL;
+	transport_disconnect(gtransport);
+	gtransport = NULL;
 	return exit_code;
 }
 
diff --git a/builtin/fsck.c b/builtin/fsck.c
index bb9a2cd..9909b6d 100644
--- a/builtin/fsck.c
+++ b/builtin/fsck.c
@@ -112,7 +112,7 @@
 		return 1;
 	}
 
-	add_object_array(obj, (void *) parent, &pending);
+	add_object_array(obj, NULL, &pending);
 	return 0;
 }
 
diff --git a/builtin/grep.c b/builtin/grep.c
index 159e65d..d3b3b1d 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -286,8 +286,7 @@
 	struct strbuf pathbuf = STRBUF_INIT;
 
 	if (opt->relative && opt->prefix_length) {
-		quote_path_relative(filename + tree_name_len, -1, &pathbuf,
-				    opt->prefix);
+		quote_path_relative(filename + tree_name_len, opt->prefix, &pathbuf);
 		strbuf_insert(&pathbuf, 0, filename, tree_name_len);
 	} else {
 		strbuf_addstr(&pathbuf, filename);
@@ -318,7 +317,7 @@
 	struct strbuf buf = STRBUF_INIT;
 
 	if (opt->relative && opt->prefix_length)
-		quote_path_relative(filename, -1, &buf, opt->prefix);
+		quote_path_relative(filename, opt->prefix, &buf);
 	else
 		strbuf_addstr(&buf, filename);
 
@@ -376,7 +375,7 @@
 	read_cache();
 
 	for (nr = 0; nr < active_nr; nr++) {
-		struct cache_entry *ce = active_cache[nr];
+		const struct cache_entry *ce = active_cache[nr];
 		if (!S_ISREG(ce->ce_mode))
 			continue;
 		if (!match_pathspec_depth(pathspec, ce->name, ce_namelen(ce), 0, NULL))
diff --git a/builtin/help.c b/builtin/help.c
index 062957f..f1e236b 100644
--- a/builtin/help.c
+++ b/builtin/help.c
@@ -1,6 +1,4 @@
 /*
- * builtin-help.c
- *
  * Builtin help command
  */
 #include "cache.h"
diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index 79dfe47..9c1cfac 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -77,8 +77,10 @@
 
 static int from_stdin;
 static int strict;
+static int do_fsck_object;
 static int verbose;
 static int show_stat;
+static int check_self_contained_and_connected;
 
 static struct progress *progress;
 
@@ -187,13 +189,13 @@
 
 /* The content of each linked object must have been checked
    or it must be already present in the object database */
-static void check_object(struct object *obj)
+static unsigned check_object(struct object *obj)
 {
 	if (!obj)
-		return;
+		return 0;
 
 	if (!(obj->flags & FLAG_LINK))
-		return;
+		return 0;
 
 	if (!(obj->flags & FLAG_CHECKED)) {
 		unsigned long size;
@@ -201,17 +203,20 @@
 		if (type != obj->type || type <= 0)
 			die(_("object of unexpected type"));
 		obj->flags |= FLAG_CHECKED;
-		return;
+		return 1;
 	}
+
+	return 0;
 }
 
-static void check_objects(void)
+static unsigned check_objects(void)
 {
-	unsigned i, max;
+	unsigned i, max, foreign_nr = 0;
 
 	max = get_max_object_index();
 	for (i = 0; i < max; i++)
-		check_object(get_indexed_object(i));
+		foreign_nr += check_object(get_indexed_object(i));
+	return foreign_nr;
 }
 
 
@@ -747,8 +752,7 @@
 			int eaten;
 			void *buf = (void *) data;
 
-			if (!buf)
-				buf = new_data = get_data_from_pack(obj_entry);
+			assert(data && "data can only be NULL for large _blobs_");
 
 			/*
 			 * we do not need to free the memory here, as the
@@ -757,7 +761,8 @@
 			obj = parse_object_buffer(sha1, type, size, buf, &eaten);
 			if (!obj)
 				die(_("invalid %s"), typename(type));
-			if (fsck_object(obj, 1, fsck_error_function))
+			if (do_fsck_object &&
+			    fsck_object(obj, 1, fsck_error_function))
 				die(_("Error in object"));
 			if (fsck_walk(obj, mark_link, NULL))
 				die(_("Not all child objects of %s are reachable"), sha1_to_hex(obj->sha1));
@@ -1491,6 +1496,7 @@
 	struct pack_idx_entry **idx_objects;
 	struct pack_idx_option opts;
 	unsigned char pack_sha1[20];
+	unsigned foreign_nr = 1;	/* zero is a "good" value, assume bad */
 
 	if (argc == 2 && !strcmp(argv[1], "-h"))
 		usage(index_pack_usage);
@@ -1512,6 +1518,10 @@
 				fix_thin_pack = 1;
 			} else if (!strcmp(arg, "--strict")) {
 				strict = 1;
+				do_fsck_object = 1;
+			} else if (!strcmp(arg, "--check-self-contained-and-connected")) {
+				strict = 1;
+				check_self_contained_and_connected = 1;
 			} else if (!strcmp(arg, "--verify")) {
 				verify = 1;
 			} else if (!strcmp(arg, "--verify-stat")) {
@@ -1625,7 +1635,7 @@
 	conclude_pack(fix_thin_pack, curr_pack, pack_sha1);
 	free(deltas);
 	if (strict)
-		check_objects();
+		foreign_nr = check_objects();
 
 	if (show_stat)
 		show_pack_info(stat_only);
@@ -1651,5 +1661,11 @@
 	if (index_name == NULL)
 		free((void *) curr_index);
 
+	/*
+	 * Let the caller know this pack is not self contained
+	 */
+	if (check_self_contained_and_connected && foreign_nr)
+		return 1;
+
 	return 0;
 }
diff --git a/builtin/log.c b/builtin/log.c
index 6e56a50..2625f98 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -19,6 +19,7 @@
 #include "remote.h"
 #include "string-list.h"
 #include "parse-options.h"
+#include "line-log.h"
 #include "branch.h"
 #include "streaming.h"
 #include "version.h"
@@ -42,6 +43,12 @@
 	NULL
 };
 
+struct line_opt_callback_data {
+	struct rev_info *rev;
+	const char *prefix;
+	struct string_list args;
+};
+
 static int parse_decoration_style(const char *var, const char *value)
 {
 	switch (git_config_maybe_bool(var, value)) {
@@ -76,6 +83,19 @@
 	return 0;
 }
 
+static int log_line_range_callback(const struct option *option, const char *arg, int unset)
+{
+	struct line_opt_callback_data *data = option->value;
+
+	if (!arg)
+		return -1;
+
+	data->rev->line_level_traverse = 1;
+	string_list_append(&data->args, arg);
+
+	return 0;
+}
+
 static void cmd_log_init_defaults(struct rev_info *rev)
 {
 	if (fmt_pretty)
@@ -98,6 +118,7 @@
 {
 	struct userformat_want w;
 	int quiet = 0, source = 0, mailmap = 0;
+	static struct line_opt_callback_data line_cb = {NULL, NULL, STRING_LIST_INIT_DUP};
 
 	const struct option builtin_log_options[] = {
 		OPT_BOOL(0, "quiet", &quiet, N_("suppress diff output")),
@@ -105,9 +126,15 @@
 		OPT_BOOL(0, "use-mailmap", &mailmap, N_("Use mail map file")),
 		{ OPTION_CALLBACK, 0, "decorate", NULL, NULL, N_("decorate options"),
 		  PARSE_OPT_OPTARG, decorate_callback},
+		OPT_CALLBACK('L', NULL, &line_cb, "n,m:file",
+			     "Process line range n,m in file, counting from 1",
+			     log_line_range_callback),
 		OPT_END()
 	};
 
+	line_cb.rev = rev;
+	line_cb.prefix = prefix;
+
 	mailmap = use_mailmap_config;
 	argc = parse_options(argc, argv, prefix,
 			     builtin_log_options, builtin_log_usage,
@@ -161,6 +188,10 @@
 		rev->show_decorations = 1;
 		load_ref_decorations(decoration_style);
 	}
+
+	if (rev->line_level_traverse)
+		line_log_init(rev, line_cb.prefix, &line_cb.args);
+
 	setup_pager();
 }
 
@@ -206,7 +237,7 @@
 	int i = revs->early_output;
 	int show_header = 1;
 
-	sort_in_topological_order(&list, revs->lifo);
+	sort_in_topological_order(&list, revs->sort_order);
 	while (list && i) {
 		struct commit *commit = list->item;
 		switch (simplify_commit(revs, commit)) {
@@ -1081,6 +1112,21 @@
 	return 0;
 }
 
+static int from_callback(const struct option *opt, const char *arg, int unset)
+{
+	char **from = opt->value;
+
+	free(*from);
+
+	if (unset)
+		*from = NULL;
+	else if (arg)
+		*from = xstrdup(arg);
+	else
+		*from = xstrdup(git_committer_info(IDENT_NO_DATE));
+	return 0;
+}
+
 int cmd_format_patch(int argc, const char **argv, const char *prefix)
 {
 	struct commit *commit;
@@ -1103,6 +1149,7 @@
 	int quiet = 0;
 	int reroll_count = -1;
 	char *branch_name = NULL;
+	char *from = NULL;
 	const struct option builtin_format_patch_options[] = {
 		{ OPTION_CALLBACK, 'n', "numbered", &numbered, NULL,
 			    N_("use [PATCH n/m] even with a single patch"),
@@ -1146,6 +1193,9 @@
 			    0, to_callback },
 		{ OPTION_CALLBACK, 0, "cc", NULL, N_("email"), N_("add Cc: header"),
 			    0, cc_callback },
+		{ OPTION_CALLBACK, 0, "from", &from, N_("ident"),
+			    N_("set From address to <ident> (or committer ident if absent)"),
+			    PARSE_OPT_OPTARG, from_callback },
 		OPT_STRING(0, "in-reply-to", &in_reply_to, N_("message-id"),
 			    N_("make first mail a reply to <message-id>")),
 		{ OPTION_CALLBACK, 0, "attach", &rev, N_("boundary"),
@@ -1233,6 +1283,11 @@
 
 	rev.extra_headers = strbuf_detach(&buf, NULL);
 
+	if (from) {
+		if (split_ident_line(&rev.from_ident, from, strlen(from)))
+			die(_("invalid ident line: %s"), from);
+	}
+
 	if (start_number < 0)
 		start_number = 1;
 
diff --git a/builtin/ls-files.c b/builtin/ls-files.c
index 2202072..5cf3e31 100644
--- a/builtin/ls-files.c
+++ b/builtin/ls-files.c
@@ -46,10 +46,14 @@
 static const char *tag_skip_worktree = "";
 static const char *tag_resolve_undo = "";
 
-static void write_name(const char* name, size_t len)
+static void write_name(const char *name)
 {
-	write_name_quoted_relative(name, len, prefix, prefix_len, stdout,
-			line_terminator);
+	/*
+	 * With "--full-name", prefix_len=0; this caller needs to pass
+	 * an empty string in that case (a NULL is good for "").
+	 */
+	write_name_quoted_relative(name, prefix_len ? prefix : NULL,
+				   stdout, line_terminator);
 }
 
 static void show_dir_entry(const char *tag, struct dir_entry *ent)
@@ -63,7 +67,7 @@
 		return;
 
 	fputs(tag, stdout);
-	write_name(ent->name, ent->len);
+	write_name(ent->name);
 }
 
 static void show_other_files(struct dir_struct *dir)
@@ -127,7 +131,7 @@
 	}
 }
 
-static void show_ce_entry(const char *tag, struct cache_entry *ce)
+static void show_ce_entry(const char *tag, const struct cache_entry *ce)
 {
 	int len = max_prefix_len;
 
@@ -163,13 +167,15 @@
 		       find_unique_abbrev(ce->sha1,abbrev),
 		       ce_stage(ce));
 	}
-	write_name(ce->name, ce_namelen(ce));
+	write_name(ce->name);
 	if (debug_mode) {
-		printf("  ctime: %d:%d\n", ce->ce_ctime.sec, ce->ce_ctime.nsec);
-		printf("  mtime: %d:%d\n", ce->ce_mtime.sec, ce->ce_mtime.nsec);
-		printf("  dev: %d\tino: %d\n", ce->ce_dev, ce->ce_ino);
-		printf("  uid: %d\tgid: %d\n", ce->ce_uid, ce->ce_gid);
-		printf("  size: %d\tflags: %x\n", ce->ce_size, ce->ce_flags);
+		const struct stat_data *sd = &ce->ce_stat_data;
+
+		printf("  ctime: %d:%d\n", sd->sd_ctime.sec, sd->sd_ctime.nsec);
+		printf("  mtime: %d:%d\n", sd->sd_mtime.sec, sd->sd_mtime.nsec);
+		printf("  dev: %d\tino: %d\n", sd->sd_dev, sd->sd_ino);
+		printf("  uid: %d\tgid: %d\n", sd->sd_uid, sd->sd_gid);
+		printf("  size: %d\tflags: %x\n", sd->sd_size, ce->ce_flags);
 	}
 }
 
@@ -196,12 +202,12 @@
 			printf("%s%06o %s %d\t", tag_resolve_undo, ui->mode[i],
 			       find_unique_abbrev(ui->sha1[i], abbrev),
 			       i + 1);
-			write_name(path, len);
+			write_name(path);
 		}
 	}
 }
 
-static int ce_excluded(struct dir_struct *dir, struct cache_entry *ce)
+static int ce_excluded(struct dir_struct *dir, const struct cache_entry *ce)
 {
 	int dtype = ce_to_dtype(ce);
 	return is_excluded(dir, ce->name, &dtype);
@@ -219,9 +225,9 @@
 		if (show_killed)
 			show_killed_files(dir);
 	}
-	if (show_cached | show_stage) {
+	if (show_cached || show_stage) {
 		for (i = 0; i < active_nr; i++) {
-			struct cache_entry *ce = active_cache[i];
+			const struct cache_entry *ce = active_cache[i];
 			if ((dir->flags & DIR_SHOW_IGNORED) &&
 			    !ce_excluded(dir, ce))
 				continue;
@@ -233,9 +239,9 @@
 				(ce_skip_worktree(ce) ? tag_skip_worktree : tag_cached), ce);
 		}
 	}
-	if (show_deleted | show_modified) {
+	if (show_deleted || show_modified) {
 		for (i = 0; i < active_nr; i++) {
-			struct cache_entry *ce = active_cache[i];
+			const struct cache_entry *ce = active_cache[i];
 			struct stat st;
 			int err;
 			if ((dir->flags & DIR_SHOW_IGNORED) &&
@@ -271,7 +277,7 @@
 	last = active_nr;
 	while (last > first) {
 		int next = (last + first) >> 1;
-		struct cache_entry *ce = active_cache[next];
+		const struct cache_entry *ce = active_cache[next];
 		if (!strncmp(ce->name, prefix, max_prefix_len)) {
 			first = next+1;
 			continue;
@@ -389,7 +395,7 @@
 		if (found_dup)
 			continue;
 
-		name = quote_path_relative(pathspec[num], -1, &sb, prefix);
+		name = quote_path_relative(pathspec[num], prefix, &sb);
 		error("pathspec '%s' did not match any file(s) known to git.",
 		      name);
 		errors++;
@@ -571,8 +577,8 @@
 		die("ls-files --ignored needs some exclude pattern");
 
 	/* With no flags, we default to showing the cached files */
-	if (!(show_stage | show_deleted | show_others | show_unmerged |
-	      show_killed | show_modified | show_resolve_undo))
+	if (!(show_stage || show_deleted || show_others || show_unmerged ||
+	      show_killed || show_modified || show_resolve_undo))
 		show_cached = 1;
 
 	if (max_prefix)
diff --git a/builtin/merge-base.c b/builtin/merge-base.c
index 1bc7991..0c4cd2f 100644
--- a/builtin/merge-base.c
+++ b/builtin/merge-base.c
@@ -107,7 +107,7 @@
 	argc = parse_options(argc, argv, prefix, options, merge_base_usage, 0);
 	if (!octopus && !reduce && argc < 2)
 		usage_with_options(merge_base_usage, options);
-	if (is_ancestor && (show_all | octopus | reduce))
+	if (is_ancestor && (show_all || octopus || reduce))
 		die("--is-ancestor cannot be used with other options");
 	if (is_ancestor)
 		return handle_is_ancestor(argc, argv);
diff --git a/builtin/merge-index.c b/builtin/merge-index.c
index be5e514..b416d92 100644
--- a/builtin/merge-index.c
+++ b/builtin/merge-index.c
@@ -16,7 +16,7 @@
 		die("git merge-index: %s not in the cache", path);
 	found = 0;
 	do {
-		struct cache_entry *ce = active_cache[pos];
+		const struct cache_entry *ce = active_cache[pos];
 		int stage = ce_stage(ce);
 
 		if (strcmp(ce->name, path))
@@ -58,7 +58,7 @@
 {
 	int i;
 	for (i = 0; i < active_nr; i++) {
-		struct cache_entry *ce = active_cache[i];
+		const struct cache_entry *ce = active_cache[i];
 		if (!ce_stage(ce))
 			continue;
 		i += merge_entry(i, ce->name)-1;
diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c
index ec49917..61cbde4 100644
--- a/builtin/merge-tree.c
+++ b/builtin/merge-tree.c
@@ -251,7 +251,11 @@
 
 	for (i = 0; i < 3; i++) {
 		mask |= (1 << i);
-		if (n[i].mode && S_ISDIR(n[i].mode))
+		/*
+		 * Treat missing entries as directories so that we return
+		 * after unresolved_directory has handled this.
+		 */
+		if (!n[i].mode || S_ISDIR(n[i].mode))
 			dirmask |= (1 << i);
 	}
 
diff --git a/builtin/merge.c b/builtin/merge.c
index 3e2daa3..34a6166 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -47,8 +47,8 @@
 };
 
 static int show_diffstat = 1, shortlog_len = -1, squash;
-static int option_commit = 1, allow_fast_forward = 1;
-static int fast_forward_only, option_edit = -1;
+static int option_commit = 1;
+static int option_edit = -1;
 static int allow_trivial = 1, have_message, verify_signatures;
 static int overwrite_ignore = 1;
 static struct strbuf merge_msg = STRBUF_INIT;
@@ -76,6 +76,14 @@
 
 static const char *pull_twohead, *pull_octopus;
 
+enum ff_type {
+	FF_NO,
+	FF_ALLOW,
+	FF_ONLY
+};
+
+static enum ff_type fast_forward = FF_ALLOW;
+
 static int option_parse_message(const struct option *opt,
 				const char *arg, int unset)
 {
@@ -178,6 +186,13 @@
 	return 0;
 }
 
+static int option_parse_ff_only(const struct option *opt,
+			  const char *arg, int unset)
+{
+	fast_forward = FF_ONLY;
+	return 0;
+}
+
 static struct option builtin_merge_options[] = {
 	{ OPTION_CALLBACK, 'n', NULL, NULL, NULL,
 		N_("do not show a diffstat at the end of the merge"),
@@ -194,10 +209,10 @@
 		N_("perform a commit if the merge succeeds (default)")),
 	OPT_BOOL('e', "edit", &option_edit,
 		N_("edit message before committing")),
-	OPT_BOOLEAN(0, "ff", &allow_fast_forward,
-		N_("allow fast-forward (default)")),
-	OPT_BOOLEAN(0, "ff-only", &fast_forward_only,
-		N_("abort if fast-forward is not possible")),
+	OPT_SET_INT(0, "ff", &fast_forward, N_("allow fast-forward (default)"), FF_ALLOW),
+	{ OPTION_CALLBACK, 0, "ff-only", NULL, NULL,
+		N_("abort if fast-forward is not possible"),
+		PARSE_OPT_NOARG | PARSE_OPT_NONEG, option_parse_ff_only },
 	OPT_RERERE_AUTOUPDATE(&allow_rerere_auto),
 	OPT_BOOL(0, "verify-signatures", &verify_signatures,
 		N_("Verify that the named commit has a valid GPG signature")),
@@ -581,10 +596,9 @@
 	else if (!strcmp(k, "merge.ff")) {
 		int boolval = git_config_maybe_bool(k, v);
 		if (0 <= boolval) {
-			allow_fast_forward = boolval;
+			fast_forward = boolval ? FF_ALLOW : FF_NO;
 		} else if (v && !strcmp(v, "only")) {
-			allow_fast_forward = 1;
-			fast_forward_only = 1;
+			fast_forward = FF_ONLY;
 		} /* do not barf on values from future versions of git */
 		return 0;
 	} else if (!strcmp(k, "merge.defaulttoupstream")) {
@@ -863,7 +877,7 @@
 
 	free_commit_list(common);
 	parents = remoteheads;
-	if (!head_subsumed || !allow_fast_forward)
+	if (!head_subsumed || fast_forward == FF_NO)
 		commit_list_insert(head, &parents);
 	strbuf_addch(&merge_msg, '\n');
 	prepare_to_commit(remoteheads);
@@ -889,7 +903,7 @@
 		die_errno(_("Could not open '%s' for writing"), filename);
 	fprintf(fp, "\nConflicts:\n");
 	for (pos = 0; pos < active_nr; pos++) {
-		struct cache_entry *ce = active_cache[pos];
+		const struct cache_entry *ce = active_cache[pos];
 
 		if (ce_stage(ce)) {
 			fprintf(fp, "\t%s\n", ce->name);
@@ -948,7 +962,7 @@
 }
 
 /*
- * Pretend as if the user told us to merge with the tracking
+ * Pretend as if the user told us to merge with the remote-tracking
  * branch we have for the upstream of the current branch
  */
 static int setup_with_upstream(const char ***argv)
@@ -967,7 +981,7 @@
 	args = xcalloc(branch->merge_nr + 1, sizeof(char *));
 	for (i = 0; i < branch->merge_nr; i++) {
 		if (!branch->merge[i]->dst)
-			die(_("No remote tracking branch for %s from %s"),
+			die(_("No remote-tracking branch for %s from %s"),
 			    branch->merge[i]->src, branch->remote_name);
 		args[i] = branch->merge[i]->dst;
 	}
@@ -1008,7 +1022,7 @@
 	if (fd < 0)
 		die_errno(_("Could not open '%s' for writing"), filename);
 	strbuf_reset(&buf);
-	if (!allow_fast_forward)
+	if (fast_forward == FF_NO)
 		strbuf_addf(&buf, "no-ff");
 	if (write_in_full(fd, buf.buf, buf.len) != buf.len)
 		die_errno(_("Could not write to '%s'"), filename);
@@ -1054,7 +1068,8 @@
 	for (i = 0; i < argc; i++) {
 		struct commit *commit = get_merge_parent(argv[i]);
 		if (!commit)
-			die(_("%s - not something we can merge"), argv[i]);
+			help_unknown_ref(argv[i], "merge",
+					 "not something we can merge");
 		remotes = &commit_list_insert(commit, remotes)->next;
 	}
 	*remotes = NULL;
@@ -1156,14 +1171,11 @@
 		show_diffstat = 0;
 
 	if (squash) {
-		if (!allow_fast_forward)
+		if (fast_forward == FF_NO)
 			die(_("You cannot combine --squash with --no-ff."));
 		option_commit = 0;
 	}
 
-	if (!allow_fast_forward && fast_forward_only)
-		die(_("You cannot combine --no-ff with --ff-only."));
-
 	if (!abort_current_merge) {
 		if (!argc) {
 			if (default_to_upstream)
@@ -1205,7 +1217,7 @@
 				"empty head"));
 		if (squash)
 			die(_("Squash commit into empty head not supported yet"));
-		if (!allow_fast_forward)
+		if (fast_forward == FF_NO)
 			die(_("Non-fast-forward commit does not make sense into "
 			    "an empty head"));
 		remoteheads = collect_parents(head_commit, &head_subsumed, argc, argv);
@@ -1293,11 +1305,11 @@
 			    sha1_to_hex(commit->object.sha1));
 		setenv(buf.buf, merge_remote_util(commit)->name, 1);
 		strbuf_reset(&buf);
-		if (!fast_forward_only &&
+		if (fast_forward != FF_ONLY &&
 		    merge_remote_util(commit) &&
 		    merge_remote_util(commit)->obj &&
 		    merge_remote_util(commit)->obj->type == OBJ_TAG)
-			allow_fast_forward = 0;
+			fast_forward = FF_NO;
 	}
 
 	if (option_edit < 0)
@@ -1314,7 +1326,7 @@
 
 	for (i = 0; i < use_strategies_nr; i++) {
 		if (use_strategies[i]->attr & NO_FAST_FORWARD)
-			allow_fast_forward = 0;
+			fast_forward = FF_NO;
 		if (use_strategies[i]->attr & NO_TRIVIAL)
 			allow_trivial = 0;
 	}
@@ -1344,7 +1356,7 @@
 		 */
 		finish_up_to_date("Already up-to-date.");
 		goto done;
-	} else if (allow_fast_forward && !remoteheads->next &&
+	} else if (fast_forward != FF_NO && !remoteheads->next &&
 			!common->next &&
 			!hashcmp(common->item->object.sha1, head_commit->object.sha1)) {
 		/* Again the most common case of merging one remote. */
@@ -1391,7 +1403,7 @@
 		 * only one common.
 		 */
 		refresh_cache(REFRESH_QUIET);
-		if (allow_trivial && !fast_forward_only) {
+		if (allow_trivial && fast_forward != FF_ONLY) {
 			/* See if it is really trivial. */
 			git_committer_info(IDENT_STRICT);
 			printf(_("Trying really trivial in-index merge...\n"));
@@ -1432,7 +1444,7 @@
 		}
 	}
 
-	if (fast_forward_only)
+	if (fast_forward == FF_ONLY)
 		die(_("Not possible to fast-forward, aborting."));
 
 	/* We are going to make a new commit. */
diff --git a/builtin/name-rev.c b/builtin/name-rev.c
index 6238247..0aaa19e 100644
--- a/builtin/name-rev.c
+++ b/builtin/name-rev.c
@@ -4,6 +4,7 @@
 #include "tag.h"
 #include "refs.h"
 #include "parse-options.h"
+#include "sha1-lookup.h"
 
 #define CUTOFF_DATE_SLOP 86400 /* one day */
 
@@ -82,23 +83,88 @@
 	}
 }
 
+static int subpath_matches(const char *path, const char *filter)
+{
+	const char *subpath = path;
+
+	while (subpath) {
+		if (!fnmatch(filter, subpath, 0))
+			return subpath - path;
+		subpath = strchr(subpath, '/');
+		if (subpath)
+			subpath++;
+	}
+	return -1;
+}
+
+static const char *name_ref_abbrev(const char *refname, int shorten_unambiguous)
+{
+	if (shorten_unambiguous)
+		refname = shorten_unambiguous_ref(refname, 0);
+	else if (!prefixcmp(refname, "refs/heads/"))
+		refname = refname + 11;
+	else if (!prefixcmp(refname, "refs/"))
+		refname = refname + 5;
+	return refname;
+}
+
 struct name_ref_data {
 	int tags_only;
 	int name_only;
 	const char *ref_filter;
 };
 
+static struct tip_table {
+	struct tip_table_entry {
+		unsigned char sha1[20];
+		const char *refname;
+	} *table;
+	int nr;
+	int alloc;
+	int sorted;
+} tip_table;
+
+static void add_to_tip_table(const unsigned char *sha1, const char *refname,
+			     int shorten_unambiguous)
+{
+	refname = name_ref_abbrev(refname, shorten_unambiguous);
+
+	ALLOC_GROW(tip_table.table, tip_table.nr + 1, tip_table.alloc);
+	hashcpy(tip_table.table[tip_table.nr].sha1, sha1);
+	tip_table.table[tip_table.nr].refname = xstrdup(refname);
+	tip_table.nr++;
+	tip_table.sorted = 0;
+}
+
+static int tipcmp(const void *a_, const void *b_)
+{
+	const struct tip_table_entry *a = a_, *b = b_;
+	return hashcmp(a->sha1, b->sha1);
+}
+
 static int name_ref(const char *path, const unsigned char *sha1, int flags, void *cb_data)
 {
 	struct object *o = parse_object(sha1);
 	struct name_ref_data *data = cb_data;
+	int can_abbreviate_output = data->tags_only && data->name_only;
 	int deref = 0;
 
 	if (data->tags_only && prefixcmp(path, "refs/tags/"))
 		return 0;
 
-	if (data->ref_filter && fnmatch(data->ref_filter, path, 0))
-		return 0;
+	if (data->ref_filter) {
+		switch (subpath_matches(path, data->ref_filter)) {
+		case -1: /* did not match */
+			return 0;
+		case 0:  /* matched fully */
+			break;
+		default: /* matched subpath */
+			can_abbreviate_output = 1;
+			break;
+		}
+	}
+
+	add_to_tip_table(sha1, path, can_abbreviate_output);
 
 	while (o && o->type == OBJ_TAG) {
 		struct tag *t = (struct tag *) o;
@@ -110,20 +176,38 @@
 	if (o && o->type == OBJ_COMMIT) {
 		struct commit *commit = (struct commit *)o;
 
-		if (!prefixcmp(path, "refs/heads/"))
-			path = path + 11;
-		else if (data->tags_only
-		    && data->name_only
-		    && !prefixcmp(path, "refs/tags/"))
-			path = path + 10;
-		else if (!prefixcmp(path, "refs/"))
-			path = path + 5;
-
+		path = name_ref_abbrev(path, can_abbreviate_output);
 		name_rev(commit, xstrdup(path), 0, 0, deref);
 	}
 	return 0;
 }
 
+static const unsigned char *nth_tip_table_ent(size_t ix, void *table_)
+{
+	struct tip_table_entry *table = table_;
+	return table[ix].sha1;
+}
+
+static const char *get_exact_ref_match(const struct object *o)
+{
+	int found;
+
+	if (!tip_table.table || !tip_table.nr)
+		return NULL;
+
+	if (!tip_table.sorted) {
+		qsort(tip_table.table, tip_table.nr, sizeof(*tip_table.table),
+		      tipcmp);
+		tip_table.sorted = 1;
+	}
+
+	found = sha1_pos(o->sha1, tip_table.table, tip_table.nr,
+			 nth_tip_table_ent);
+	if (0 <= found)
+		return tip_table.table[found].refname;
+	return NULL;
+}
+
 /* returns a static buffer */
 static const char *get_rev_name(const struct object *o)
 {
@@ -132,7 +216,7 @@
 	struct commit *c;
 
 	if (o->type != OBJ_COMMIT)
-		return NULL;
+		return get_exact_ref_match(o);
 	c = (struct commit *) o;
 	n = c->util;
 	if (!n)
@@ -223,7 +307,7 @@
 int cmd_name_rev(int argc, const char **argv, const char *prefix)
 {
 	struct object_array revs = OBJECT_ARRAY_INIT;
-	int all = 0, transform_stdin = 0, allow_undefined = 1, always = 0;
+	int all = 0, transform_stdin = 0, allow_undefined = 1, always = 0, peel_tag = 0;
 	struct name_ref_data data = { 0, 0, NULL };
 	struct option opts[] = {
 		OPT_BOOLEAN(0, "name-only", &data.name_only, N_("print only names (no SHA-1)")),
@@ -236,6 +320,12 @@
 		OPT_BOOLEAN(0, "undefined", &allow_undefined, N_("allow to print `undefined` names")),
 		OPT_BOOLEAN(0, "always",     &always,
 			   N_("show abbreviated commit object as fallback")),
+		{
+			/* A Hidden OPT_BOOL */
+			OPTION_SET_INT, 0, "peel-tag", &peel_tag, NULL,
+			N_("dereference tags in the input (internal use)"),
+			PARSE_OPT_NOARG | PARSE_OPT_HIDDEN, NULL, 1,
+		},
 		OPT_END(),
 	};
 
@@ -250,7 +340,7 @@
 
 	for (; argc; argc--, argv++) {
 		unsigned char sha1[20];
-		struct object *o;
+		struct object *object;
 		struct commit *commit;
 
 		if (get_sha1(*argv, sha1)) {
@@ -259,17 +349,34 @@
 			continue;
 		}
 
-		o = deref_tag(parse_object(sha1), *argv, 0);
-		if (!o || o->type != OBJ_COMMIT) {
-			fprintf(stderr, "Could not get commit for %s. Skipping.\n",
+		commit = NULL;
+		object = parse_object(sha1);
+		if (object) {
+			struct object *peeled = deref_tag(object, *argv, 0);
+			if (peeled && peeled->type == OBJ_COMMIT)
+				commit = (struct commit *)peeled;
+		}
+
+		if (!object) {
+			fprintf(stderr, "Could not get object for %s. Skipping.\n",
 					*argv);
 			continue;
 		}
 
-		commit = (struct commit *)o;
-		if (cutoff > commit->date)
-			cutoff = commit->date;
-		add_object_array((struct object *)commit, *argv, &revs);
+		if (commit) {
+			if (cutoff > commit->date)
+				cutoff = commit->date;
+		}
+
+		if (peel_tag) {
+			if (!commit) {
+				fprintf(stderr, "Could not get commit for %s. Skipping.\n",
+					*argv);
+				continue;
+			}
+			object = (struct object *)commit;
+		}
+		add_object_array(object, *argv, &revs);
 	}
 
 	if (cutoff)
diff --git a/builtin/notes.c b/builtin/notes.c
index 57748a6..e4100c4 100644
--- a/builtin/notes.c
+++ b/builtin/notes.c
@@ -4,7 +4,7 @@
  * Copyright (c) 2010 Johan Herland <johan@herland.net>
  *
  * Based on git-notes.sh by Johannes Schindelin,
- * and builtin-tag.c by Kristian Høgsberg and Carlos Rica.
+ * and builtin/tag.c by Kristian Høgsberg and Carlos Rica.
  */
 
 #include "cache.h"
@@ -18,9 +18,7 @@
 #include "parse-options.h"
 #include "string-list.h"
 #include "notes-merge.h"
-
-static void commit_notes(struct notes_tree *t, const char *msg);
-static combine_notes_fn parse_combine_notes_fn(const char *v);
+#include "notes-utils.h"
 
 static const char * const git_notes_usage[] = {
 	N_("git notes [--ref <notes_ref>] [list [<object>]]"),
@@ -287,139 +285,13 @@
 	return parse_reuse_arg(opt, arg, unset);
 }
 
-static void commit_notes(struct notes_tree *t, const char *msg)
-{
-	struct strbuf buf = STRBUF_INIT;
-	unsigned char commit_sha1[20];
-
-	if (!t)
-		t = &default_notes_tree;
-	if (!t->initialized || !t->ref || !*t->ref)
-		die(_("Cannot commit uninitialized/unreferenced notes tree"));
-	if (!t->dirty)
-		return; /* don't have to commit an unchanged tree */
-
-	/* Prepare commit message and reflog message */
-	strbuf_addstr(&buf, msg);
-	if (buf.buf[buf.len - 1] != '\n')
-		strbuf_addch(&buf, '\n'); /* Make sure msg ends with newline */
-
-	create_notes_commit(t, NULL, &buf, commit_sha1);
-	strbuf_insert(&buf, 0, "notes: ", 7); /* commit message starts at index 7 */
-	update_ref(buf.buf, t->ref, commit_sha1, NULL, 0, DIE_ON_ERR);
-
-	strbuf_release(&buf);
-}
-
-static combine_notes_fn parse_combine_notes_fn(const char *v)
-{
-	if (!strcasecmp(v, "overwrite"))
-		return combine_notes_overwrite;
-	else if (!strcasecmp(v, "ignore"))
-		return combine_notes_ignore;
-	else if (!strcasecmp(v, "concatenate"))
-		return combine_notes_concatenate;
-	else if (!strcasecmp(v, "cat_sort_uniq"))
-		return combine_notes_cat_sort_uniq;
-	else
-		return NULL;
-}
-
-static int notes_rewrite_config(const char *k, const char *v, void *cb)
-{
-	struct notes_rewrite_cfg *c = cb;
-	if (!prefixcmp(k, "notes.rewrite.") && !strcmp(k+14, c->cmd)) {
-		c->enabled = git_config_bool(k, v);
-		return 0;
-	} else if (!c->mode_from_env && !strcmp(k, "notes.rewritemode")) {
-		if (!v)
-			config_error_nonbool(k);
-		c->combine = parse_combine_notes_fn(v);
-		if (!c->combine) {
-			error(_("Bad notes.rewriteMode value: '%s'"), v);
-			return 1;
-		}
-		return 0;
-	} else if (!c->refs_from_env && !strcmp(k, "notes.rewriteref")) {
-		/* note that a refs/ prefix is implied in the
-		 * underlying for_each_glob_ref */
-		if (!prefixcmp(v, "refs/notes/"))
-			string_list_add_refs_by_glob(c->refs, v);
-		else
-			warning(_("Refusing to rewrite notes in %s"
-				" (outside of refs/notes/)"), v);
-		return 0;
-	}
-
-	return 0;
-}
-
-
-struct notes_rewrite_cfg *init_copy_notes_for_rewrite(const char *cmd)
-{
-	struct notes_rewrite_cfg *c = xmalloc(sizeof(struct notes_rewrite_cfg));
-	const char *rewrite_mode_env = getenv(GIT_NOTES_REWRITE_MODE_ENVIRONMENT);
-	const char *rewrite_refs_env = getenv(GIT_NOTES_REWRITE_REF_ENVIRONMENT);
-	c->cmd = cmd;
-	c->enabled = 1;
-	c->combine = combine_notes_concatenate;
-	c->refs = xcalloc(1, sizeof(struct string_list));
-	c->refs->strdup_strings = 1;
-	c->refs_from_env = 0;
-	c->mode_from_env = 0;
-	if (rewrite_mode_env) {
-		c->mode_from_env = 1;
-		c->combine = parse_combine_notes_fn(rewrite_mode_env);
-		if (!c->combine)
-			/* TRANSLATORS: The first %s is the name of the
-			   environment variable, the second %s is its value */
-			error(_("Bad %s value: '%s'"), GIT_NOTES_REWRITE_MODE_ENVIRONMENT,
-					rewrite_mode_env);
-	}
-	if (rewrite_refs_env) {
-		c->refs_from_env = 1;
-		string_list_add_refs_from_colon_sep(c->refs, rewrite_refs_env);
-	}
-	git_config(notes_rewrite_config, c);
-	if (!c->enabled || !c->refs->nr) {
-		string_list_clear(c->refs, 0);
-		free(c->refs);
-		free(c);
-		return NULL;
-	}
-	c->trees = load_notes_trees(c->refs);
-	string_list_clear(c->refs, 0);
-	free(c->refs);
-	return c;
-}
-
-int copy_note_for_rewrite(struct notes_rewrite_cfg *c,
-			  const unsigned char *from_obj, const unsigned char *to_obj)
-{
-	int ret = 0;
-	int i;
-	for (i = 0; c->trees[i]; i++)
-		ret = copy_note(c->trees[i], from_obj, to_obj, 1, c->combine) || ret;
-	return ret;
-}
-
-void finish_copy_notes_for_rewrite(struct notes_rewrite_cfg *c)
-{
-	int i;
-	for (i = 0; c->trees[i]; i++) {
-		commit_notes(c->trees[i], "Notes added by 'git notes copy'");
-		free_notes(c->trees[i]);
-	}
-	free(c->trees);
-	free(c);
-}
-
 static int notes_copy_from_stdin(int force, const char *rewrite_cmd)
 {
 	struct strbuf buf = STRBUF_INIT;
 	struct notes_rewrite_cfg *c = NULL;
 	struct notes_tree *t = NULL;
 	int ret = 0;
+	const char *msg = "Notes added by 'git notes copy'";
 
 	if (rewrite_cmd) {
 		c = init_copy_notes_for_rewrite(rewrite_cmd);
@@ -461,10 +333,10 @@
 	}
 
 	if (!rewrite_cmd) {
-		commit_notes(t, "Notes added by 'git notes copy'");
+		commit_notes(t, msg);
 		free_notes(t);
 	} else {
-		finish_copy_notes_for_rewrite(c);
+		finish_copy_notes_for_rewrite(c, msg);
 	}
 	return ret;
 }
diff --git a/builtin/pack-refs.c b/builtin/pack-refs.c
index b5a0f88..b20b1ec 100644
--- a/builtin/pack-refs.c
+++ b/builtin/pack-refs.c
@@ -1,6 +1,6 @@
 #include "builtin.h"
 #include "parse-options.h"
-#include "pack-refs.h"
+#include "refs.h"
 
 static char const * const pack_refs_usage[] = {
 	N_("git pack-refs [options]"),
diff --git a/builtin/prune-packed.c b/builtin/prune-packed.c
index 83382c1..fa6ce42 100644
--- a/builtin/prune-packed.c
+++ b/builtin/prune-packed.c
@@ -8,9 +8,6 @@
 	NULL
 };
 
-#define DRY_RUN 01
-#define VERBOSE 02
-
 static struct progress *progress;
 
 static void prune_dir(int i, DIR *dir, char *pathname, int len, int opts)
@@ -29,7 +26,7 @@
 		if (!has_sha1_pack(sha1))
 			continue;
 		memcpy(pathname + len, de->d_name, 38);
-		if (opts & DRY_RUN)
+		if (opts & PRUNE_PACKED_DRY_RUN)
 			printf("rm -f %s\n", pathname);
 		else
 			unlink_or_warn(pathname);
@@ -44,7 +41,7 @@
 	const char *dir = get_object_directory();
 	int len = strlen(dir);
 
-	if (opts == VERBOSE)
+	if (opts & PRUNE_PACKED_VERBOSE)
 		progress = start_progress_delay("Removing duplicate objects",
 			256, 95, 2);
 
@@ -71,10 +68,12 @@
 
 int cmd_prune_packed(int argc, const char **argv, const char *prefix)
 {
-	int opts = isatty(2) ? VERBOSE : 0;
+	int opts = isatty(2) ? PRUNE_PACKED_VERBOSE : 0;
 	const struct option prune_packed_options[] = {
-		OPT_BIT('n', "dry-run", &opts, N_("dry run"), DRY_RUN),
-		OPT_NEGBIT('q', "quiet", &opts, N_("be quiet"), VERBOSE),
+		OPT_BIT('n', "dry-run", &opts, N_("dry run"),
+			PRUNE_PACKED_DRY_RUN),
+		OPT_NEGBIT('q', "quiet", &opts, N_("be quiet"),
+			   PRUNE_PACKED_VERBOSE),
 		OPT_END()
 	};
 
diff --git a/builtin/prune.c b/builtin/prune.c
index 85843d4..6366917 100644
--- a/builtin/prune.c
+++ b/builtin/prune.c
@@ -132,8 +132,8 @@
 		OPT__DRY_RUN(&show_only, N_("do not remove, show only")),
 		OPT__VERBOSE(&verbose, N_("report pruned objects")),
 		OPT_BOOL(0, "progress", &show_progress, N_("show progress")),
-		OPT_DATE(0, "expire", &expire,
-			 N_("expire objects older than <time>")),
+		OPT_EXPIRY_DATE(0, "expire", &expire,
+				N_("expire objects older than <time>")),
 		OPT_END()
 	};
 	char *s;
@@ -165,7 +165,7 @@
 	stop_progress(&progress);
 	prune_object_dir(get_object_directory());
 
-	prune_packed_objects(show_only);
+	prune_packed_objects(show_only ? PRUNE_PACKED_DRY_RUN : 0);
 	remove_temporary_files(get_object_directory());
 	s = mkpathdup("%s/pack", get_object_directory());
 	remove_temporary_files(s);
diff --git a/builtin/push.c b/builtin/push.c
index 909c34d..04f0eaf 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -92,7 +92,7 @@
 	if (!short_upstream)
 		short_upstream = branch->merge[0]->src;
 	/*
-	 * Don't show advice for people who explicitely set
+	 * Don't show advice for people who explicitly set
 	 * push.default.
 	 */
 	if (push_default == PUSH_DEFAULT_UNSPECIFIED)
@@ -113,17 +113,20 @@
 	    remote->name, branch->name, advice_maybe);
 }
 
-static void setup_push_upstream(struct remote *remote, int simple)
+static const char message_detached_head_die[] =
+	N_("You are not currently on a branch.\n"
+	   "To push the history leading to the current (detached HEAD)\n"
+	   "state now, use\n"
+	   "\n"
+	   "    git push %s HEAD:<name-of-remote-branch>\n");
+
+static void setup_push_upstream(struct remote *remote, struct branch *branch,
+				int triangular)
 {
 	struct strbuf refspec = STRBUF_INIT;
-	struct branch *branch = branch_get(NULL);
+
 	if (!branch)
-		die(_("You are not currently on a branch.\n"
-		    "To push the history leading to the current (detached HEAD)\n"
-		    "state now, use\n"
-		    "\n"
-		    "    git push %s HEAD:<name-of-remote-branch>\n"),
-		    remote->name);
+		die(_(message_detached_head_die), remote->name);
 	if (!branch->merge_nr || !branch->merge || !branch->remote_name)
 		die(_("The current branch %s has no upstream branch.\n"
 		    "To push the current branch and set the remote as upstream, use\n"
@@ -135,18 +138,29 @@
 	if (branch->merge_nr != 1)
 		die(_("The current branch %s has multiple upstream branches, "
 		    "refusing to push."), branch->name);
-	if (strcmp(branch->remote_name, remote->name))
+	if (triangular)
 		die(_("You are pushing to remote '%s', which is not the upstream of\n"
 		      "your current branch '%s', without telling me what to push\n"
 		      "to update which remote branch."),
 		    remote->name, branch->name);
-	if (simple && strcmp(branch->refname, branch->merge[0]->src))
-		die_push_simple(branch, remote);
+
+	if (push_default == PUSH_DEFAULT_SIMPLE) {
+		/* Additional safety */
+		if (strcmp(branch->refname, branch->merge[0]->src))
+			die_push_simple(branch, remote);
+	}
 
 	strbuf_addf(&refspec, "%s:%s", branch->name, branch->merge[0]->src);
 	add_refspec(refspec.buf);
 }
 
+static void setup_push_current(struct remote *remote, struct branch *branch)
+{
+	if (!branch)
+		die(_(message_detached_head_die), remote->name);
+	add_refspec(branch->name);
+}
+
 static char warn_unspecified_push_default_msg[] =
 N_("push.default is unset; its implicit value is changing in\n"
    "Git 2.0 from 'matching' to 'simple'. To squelch this message\n"
@@ -171,8 +185,17 @@
 	warning("%s\n", _(warn_unspecified_push_default_msg));
 }
 
+static int is_workflow_triangular(struct remote *remote)
+{
+	struct remote *fetch_remote = remote_get(NULL);
+	return (fetch_remote && fetch_remote != remote);
+}
+
 static void setup_default_push_refspecs(struct remote *remote)
 {
+	struct branch *branch = branch_get(NULL);
+	int triangular = is_workflow_triangular(remote);
+
 	switch (push_default) {
 	default:
 	case PUSH_DEFAULT_UNSPECIFIED:
@@ -184,15 +207,18 @@
 		break;
 
 	case PUSH_DEFAULT_SIMPLE:
-		setup_push_upstream(remote, 1);
+		if (triangular)
+			setup_push_current(remote, branch);
+		else
+			setup_push_upstream(remote, branch, triangular);
 		break;
 
 	case PUSH_DEFAULT_UPSTREAM:
-		setup_push_upstream(remote, 0);
+		setup_push_upstream(remote, branch, triangular);
 		break;
 
 	case PUSH_DEFAULT_CURRENT:
-		add_refspec("HEAD");
+		setup_push_current(remote, branch);
 		break;
 
 	case PUSH_DEFAULT_NOTHING:
@@ -204,8 +230,8 @@
 
 static const char message_advice_pull_before_push[] =
 	N_("Updates were rejected because the tip of your current branch is behind\n"
-	   "its remote counterpart. Merge the remote changes (e.g. 'git pull')\n"
-	   "before pushing again.\n"
+	   "its remote counterpart. Integrate the remote changes (e.g.\n"
+	   "'git pull ...') before pushing again.\n"
 	   "See the 'Note about fast-forwards' in 'git push --help' for details.");
 
 static const char message_advice_use_upstream[] =
@@ -216,15 +242,15 @@
 
 static const char message_advice_checkout_pull_push[] =
 	N_("Updates were rejected because a pushed branch tip is behind its remote\n"
-	   "counterpart. Check out this branch and merge the remote changes\n"
-	   "(e.g. 'git pull') before pushing again.\n"
+	   "counterpart. Check out this branch and integrate the remote changes\n"
+	   "(e.g. 'git pull ...') before pushing again.\n"
 	   "See the 'Note about fast-forwards' in 'git push --help' for details.");
 
 static const char message_advice_ref_fetch_first[] =
 	N_("Updates were rejected because the remote contains work that you do\n"
 	   "not have locally. This is usually caused by another repository pushing\n"
-	   "to the same ref. You may want to first merge the remote changes (e.g.,\n"
-	   "'git pull') before pushing again.\n"
+	   "to the same ref. You may want to first integrate the remote changes\n"
+	   "(e.g., 'git pull ...') before pushing again.\n"
 	   "See the 'Note about fast-forwards' in 'git push --help' for details.");
 
 static const char message_advice_ref_already_exists[] =
diff --git a/builtin/read-tree.c b/builtin/read-tree.c
index 042ac1b..0f5d7fe 100644
--- a/builtin/read-tree.c
+++ b/builtin/read-tree.c
@@ -66,7 +66,7 @@
 	return 0;
 }
 
-static void debug_stage(const char *label, struct cache_entry *ce,
+static void debug_stage(const char *label, const struct cache_entry *ce,
 			struct unpack_trees_options *o)
 {
 	printf("%s ", label);
@@ -80,7 +80,8 @@
 		       sha1_to_hex(ce->sha1));
 }
 
-static int debug_merge(struct cache_entry **stages, struct unpack_trees_options *o)
+static int debug_merge(const struct cache_entry * const *stages,
+		       struct unpack_trees_options *o)
 {
 	int i;
 
diff --git a/builtin/reflog.c b/builtin/reflog.c
index 72a0af7..54184b3 100644
--- a/builtin/reflog.c
+++ b/builtin/reflog.c
@@ -496,11 +496,9 @@
 {
 	if (!value)
 		return config_error_nonbool(var);
-	if (!strcmp(value, "never") || !strcmp(value, "false")) {
-		*expire = 0;
-		return 0;
-	}
-	*expire = approxidate(value);
+	if (parse_expiry_date(value, expire))
+		return error(_("%s' for '%s' is not a valid timestamp"),
+			     value, var);
 	return 0;
 }
 
@@ -614,11 +612,13 @@
 		if (!strcmp(arg, "--dry-run") || !strcmp(arg, "-n"))
 			cb.dry_run = 1;
 		else if (!prefixcmp(arg, "--expire=")) {
-			cb.expire_total = approxidate(arg + 9);
+			if (parse_expiry_date(arg + 9, &cb.expire_total))
+				die(_("'%s' is not a valid timestamp"), arg);
 			explicit_expiry |= EXPIRE_TOTAL;
 		}
 		else if (!prefixcmp(arg, "--expire-unreachable=")) {
-			cb.expire_unreachable = approxidate(arg + 21);
+			if (parse_expiry_date(arg + 21, &cb.expire_unreachable))
+				die(_("'%s' is not a valid timestamp"), arg);
 			explicit_expiry |= EXPIRE_UNREACH;
 		}
 		else if (!strcmp(arg, "--stale-fix"))
diff --git a/builtin/replace.c b/builtin/replace.c
index 398ccd5..59d3115 100644
--- a/builtin/replace.c
+++ b/builtin/replace.c
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2008 Christian Couder <chriscool@tuxfamily.org>
  *
- * Based on builtin-tag.c by Kristian Høgsberg <krh@redhat.com>
+ * Based on builtin/tag.c by Kristian Høgsberg <krh@redhat.com>
  * and Carlos Rica <jasampler@gmail.com> that was itself based on
  * git-tag.sh and mktag.c by Linus Torvalds.
  */
diff --git a/builtin/reset.c b/builtin/reset.c
index 6032131..afa6e02 100644
--- a/builtin/reset.c
+++ b/builtin/reset.c
@@ -93,10 +93,12 @@
 static void print_new_head_line(struct commit *commit)
 {
 	const char *hex, *body;
+	char *msg;
 
 	hex = find_unique_abbrev(commit->object.sha1, DEFAULT_ABBREV);
 	printf(_("HEAD is now at %s"), hex);
-	body = strstr(commit->buffer, "\n\n");
+	msg = logmsg_reencode(commit, NULL, get_log_output_encoding());
+	body = strstr(msg, "\n\n");
 	if (body) {
 		const char *eol;
 		size_t len;
@@ -107,6 +109,7 @@
 	}
 	else
 		printf("\n");
+	logmsg_free(msg, commit);
 }
 
 static void update_index_from_diff(struct diff_queue_struct *q,
diff --git a/builtin/rev-list.c b/builtin/rev-list.c
index 67701be..a5ec30d 100644
--- a/builtin/rev-list.c
+++ b/builtin/rev-list.c
@@ -111,6 +111,7 @@
 		ctx.date_mode = revs->date_mode;
 		ctx.date_mode_explicit = revs->date_mode_explicit;
 		ctx.fmt = revs->commit_format;
+		ctx.output_encoding = get_log_output_encoding();
 		pretty_print_commit(&ctx, commit, &buf);
 		if (revs->graph) {
 			if (buf.len) {
diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c
index f267a1d..de894c7 100644
--- a/builtin/rev-parse.c
+++ b/builtin/rev-parse.c
@@ -212,11 +212,17 @@
 	show(buffer);
 }
 
-static int show_file(const char *arg)
+static int show_file(const char *arg, int output_prefix)
 {
 	show_default();
 	if ((filter & (DO_NONFLAGS|DO_NOREV)) == (DO_NONFLAGS|DO_NOREV)) {
-		show(arg);
+		if (output_prefix) {
+			const char *prefix = startup_info->prefix;
+			show(prefix_filename(prefix,
+					     prefix ? strlen(prefix) : 0,
+					     arg));
+		} else
+			show(arg);
 		return 1;
 	}
 	return 0;
@@ -470,6 +476,7 @@
 int cmd_rev_parse(int argc, const char **argv, const char *prefix)
 {
 	int i, as_is = 0, verify = 0, quiet = 0, revs_count = 0, type = 0;
+	int output_prefix = 0;
 	unsigned char sha1[20];
 	const char *name = NULL;
 
@@ -503,7 +510,7 @@
 		const char *arg = argv[i];
 
 		if (as_is) {
-			if (show_file(arg) && as_is < 2)
+			if (show_file(arg, output_prefix) && as_is < 2)
 				verify_filename(prefix, arg, 0);
 			continue;
 		}
@@ -527,7 +534,7 @@
 				as_is = 2;
 				/* Pass on the "--" if we show anything but files.. */
 				if (filter & (DO_FLAGS | DO_REVS))
-					show_file(arg);
+					show_file(arg, 0);
 				continue;
 			}
 			if (!strcmp(arg, "--default")) {
@@ -535,6 +542,13 @@
 				i++;
 				continue;
 			}
+			if (!strcmp(arg, "--prefix")) {
+				prefix = argv[i+1];
+				startup_info->prefix = prefix;
+				output_prefix = 1;
+				i++;
+				continue;
+			}
 			if (!strcmp(arg, "--revs-only")) {
 				filter &= ~DO_NOREV;
 				continue;
@@ -754,7 +768,7 @@
 		if (verify)
 			die_no_single_rev(quiet);
 		as_is = 1;
-		if (!show_file(arg))
+		if (!show_file(arg, output_prefix))
 			continue;
 		verify_filename(prefix, arg, 1);
 	}
diff --git a/builtin/revert.c b/builtin/revert.c
index 0401fdb..1d2648b 100644
--- a/builtin/revert.c
+++ b/builtin/revert.c
@@ -54,6 +54,7 @@
 	return 0;
 }
 
+LAST_ARG_MUST_BE_NULL
 static void verify_opt_compatible(const char *me, const char *base_opt, ...)
 {
 	const char *this_opt;
@@ -70,6 +71,7 @@
 		die(_("%s: %s cannot be used with %s"), me, this_opt, base_opt);
 }
 
+LAST_ARG_MUST_BE_NULL
 static void verify_opt_mutually_compatible(const char *me, ...)
 {
 	const char *opt1, *opt2 = NULL;
diff --git a/builtin/rm.c b/builtin/rm.c
index 7b91d52..0df0b4d 100644
--- a/builtin/rm.c
+++ b/builtin/rm.c
@@ -9,6 +9,7 @@
 #include "cache-tree.h"
 #include "tree-walk.h"
 #include "parse-options.h"
+#include "string-list.h"
 #include "submodule.h"
 
 static const char * const builtin_rm_usage[] = {
@@ -36,15 +37,52 @@
 	return -1;
 }
 
+static void print_error_files(struct string_list *files_list,
+			      const char *main_msg,
+			      const char *hints_msg,
+			      int *errs)
+{
+	if (files_list->nr) {
+		int i;
+		struct strbuf err_msg = STRBUF_INIT;
+
+		strbuf_addstr(&err_msg, main_msg);
+		for (i = 0; i < files_list->nr; i++)
+			strbuf_addf(&err_msg,
+				    "\n    %s",
+				    files_list->items[i].string);
+		if (advice_rm_hints)
+			strbuf_addstr(&err_msg, hints_msg);
+		*errs = error("%s", err_msg.buf);
+		strbuf_release(&err_msg);
+	}
+}
+
+static void error_removing_concrete_submodules(struct string_list *files, int *errs)
+{
+	print_error_files(files,
+			  Q_("the following submodule (or one of its nested "
+			     "submodules)\n"
+			     "uses a .git directory:",
+			     "the following submodules (or one of its nested "
+			     "submodules)\n"
+			     "use a .git directory:", files->nr),
+			  _("\n(use 'rm -rf' if you really want to remove "
+			    "it including all of its history)"),
+			  errs);
+	string_list_clear(files, 0);
+}
+
 static int check_submodules_use_gitfiles(void)
 {
 	int i;
 	int errs = 0;
+	struct string_list files = STRING_LIST_INIT_NODUP;
 
 	for (i = 0; i < list.nr; i++) {
 		const char *name = list.entry[i].name;
 		int pos;
-		struct cache_entry *ce;
+		const struct cache_entry *ce;
 		struct stat st;
 
 		pos = cache_name_pos(name, strlen(name));
@@ -61,12 +99,11 @@
 			continue;
 
 		if (!submodule_uses_gitfile(name))
-			errs = error(_("submodule '%s' (or one of its nested "
-				     "submodules) uses a .git directory\n"
-				     "(use 'rm -rf' if you really want to remove "
-				     "it including all of its history)"), name);
+			string_list_append(&files, name);
 	}
 
+	error_removing_concrete_submodules(&files, &errs);
+
 	return errs;
 }
 
@@ -81,12 +118,16 @@
 	 */
 	int i, no_head;
 	int errs = 0;
+	struct string_list files_staged = STRING_LIST_INIT_NODUP;
+	struct string_list files_cached = STRING_LIST_INIT_NODUP;
+	struct string_list files_submodule = STRING_LIST_INIT_NODUP;
+	struct string_list files_local = STRING_LIST_INIT_NODUP;
 
 	no_head = is_null_sha1(head);
 	for (i = 0; i < list.nr; i++) {
 		struct stat st;
 		int pos;
-		struct cache_entry *ce;
+		const struct cache_entry *ce;
 		const char *name = list.entry[i].name;
 		unsigned char sha1[20];
 		unsigned mode;
@@ -171,29 +212,50 @@
 		 */
 		if (local_changes && staged_changes) {
 			if (!index_only || !(ce->ce_flags & CE_INTENT_TO_ADD))
-				errs = error(_("'%s' has staged content different "
-					     "from both the file and the HEAD\n"
-					     "(use -f to force removal)"), name);
+				string_list_append(&files_staged, name);
 		}
 		else if (!index_only) {
 			if (staged_changes)
-				errs = error(_("'%s' has changes staged in the index\n"
-					     "(use --cached to keep the file, "
-					     "or -f to force removal)"), name);
+				string_list_append(&files_cached, name);
 			if (local_changes) {
 				if (S_ISGITLINK(ce->ce_mode) &&
-				    !submodule_uses_gitfile(name)) {
-					errs = error(_("submodule '%s' (or one of its nested "
-						     "submodules) uses a .git directory\n"
-						     "(use 'rm -rf' if you really want to remove "
-						     "it including all of its history)"), name);
-				} else
-					errs = error(_("'%s' has local modifications\n"
-						     "(use --cached to keep the file, "
-						     "or -f to force removal)"), name);
+				    !submodule_uses_gitfile(name))
+					string_list_append(&files_submodule, name);
+				else
+					string_list_append(&files_local, name);
 			}
 		}
 	}
+	print_error_files(&files_staged,
+			  Q_("the following file has staged content different "
+			     "from both the\nfile and the HEAD:",
+			     "the following files have staged content different"
+			     " from both the\nfile and the HEAD:",
+			     files_staged.nr),
+			  _("\n(use -f to force removal)"),
+			  &errs);
+	string_list_clear(&files_staged, 0);
+	print_error_files(&files_cached,
+			  Q_("the following file has changes "
+			     "staged in the index:",
+			     "the following files have changes "
+			     "staged in the index:", files_cached.nr),
+			  _("\n(use --cached to keep the file,"
+			    " or -f to force removal)"),
+			  &errs);
+	string_list_clear(&files_cached, 0);
+
+	error_removing_concrete_submodules(&files_submodule, &errs);
+
+	print_error_files(&files_local,
+			  Q_("the following file has local modifications:",
+			     "the following files have local modifications:",
+			     files_local.nr),
+			  _("\n(use --cached to keep the file,"
+			    " or -f to force removal)"),
+			  &errs);
+	string_list_clear(&files_local, 0);
+
 	return errs;
 }
 
@@ -258,7 +320,7 @@
 	seen = xcalloc(i, 1);
 
 	for (i = 0; i < active_nr; i++) {
-		struct cache_entry *ce = active_cache[i];
+		const struct cache_entry *ce = active_cache[i];
 		if (!match_pathspec(pathspec, ce->name, ce_namelen(ce), 0, seen))
 			continue;
 		ALLOC_GROW(list.entry, list.nr + 1, list.alloc);
diff --git a/builtin/shortlog.c b/builtin/shortlog.c
index 1fd6f8a..1434f8f 100644
--- a/builtin/shortlog.c
+++ b/builtin/shortlog.c
@@ -137,6 +137,7 @@
 		ctx.subject = "";
 		ctx.after_subject = "";
 		ctx.date_mode = DATE_NORMAL;
+		ctx.output_encoding = get_log_output_encoding();
 		pretty_print_commit(&ctx, commit, &ufbuf);
 		buffer = ufbuf.buf;
 	} else if (*buffer) {
diff --git a/builtin/show-branch.c b/builtin/show-branch.c
index 90fc6b1..9788eb1 100644
--- a/builtin/show-branch.c
+++ b/builtin/show-branch.c
@@ -630,7 +630,7 @@
 	int num_rev, i, extra = 0;
 	int all_heads = 0, all_remotes = 0;
 	int all_mask, all_revs;
-	int lifo = 1;
+	enum rev_sort_order sort_order = REV_SORT_IN_GRAPH_ORDER;
 	char head[128];
 	const char *head_p;
 	int head_len;
@@ -665,15 +665,17 @@
 			    N_("show possible merge bases")),
 		OPT_BOOLEAN(0, "independent", &independent,
 			    N_("show refs unreachable from any other ref")),
-		OPT_BOOLEAN(0, "topo-order", &lifo,
-			    N_("show commits in topological order")),
+		OPT_SET_INT(0, "topo-order", &sort_order,
+			    N_("show commits in topological order"),
+			    REV_SORT_IN_GRAPH_ORDER),
 		OPT_BOOLEAN(0, "topics", &topics,
 			    N_("show only commits not on the first branch")),
 		OPT_SET_INT(0, "sparse", &dense,
 			    N_("show merges reachable from only one tip"), 0),
-		OPT_SET_INT(0, "date-order", &lifo,
-			    N_("show commits where no parent comes before its "
-			       "children"), 0),
+		OPT_SET_INT(0, "date-order", &sort_order,
+			    N_("topologically sort, maintaining date order "
+			       "where possible"),
+			    REV_SORT_BY_COMMIT_DATE),
 		{ OPTION_CALLBACK, 'g', "reflog", &reflog_base, N_("<n>[,<base>]"),
 			    N_("show <n> most recent ref-log entries starting at "
 			       "base"),
@@ -900,7 +902,7 @@
 		exit(0);
 
 	/* Sort topologically */
-	sort_in_topological_order(&seen, lifo);
+	sort_in_topological_order(&seen, sort_order);
 
 	/* Give names to commits */
 	if (!sha1_name && !no_name)
diff --git a/builtin/show-ref.c b/builtin/show-ref.c
index 8d9b76a..87806ad 100644
--- a/builtin/show-ref.c
+++ b/builtin/show-ref.c
@@ -31,6 +31,9 @@
 	const char *hex;
 	unsigned char peeled[20];
 
+	if (show_head && !strcmp(refname, "HEAD"))
+		goto match;
+
 	if (tags_only || heads_only) {
 		int match;
 
@@ -103,7 +106,7 @@
  */
 static int exclude_existing(const char *match)
 {
-	static struct string_list existing_refs = STRING_LIST_INIT_NODUP;
+	static struct string_list existing_refs = STRING_LIST_INIT_DUP;
 	char buf[1024];
 	int matchlen = match ? strlen(match) : 0;
 
@@ -167,9 +170,10 @@
 	OPT_BOOLEAN(0, "verify", &verify, N_("stricter reference checking, "
 		    "requires exact ref path")),
 	{ OPTION_BOOLEAN, 'h', NULL, &show_head, NULL,
-	  N_("show the HEAD reference"),
+	  N_("show the HEAD reference, even if it would be filtered out"),
 	  PARSE_OPT_NOARG | PARSE_OPT_HIDDEN },
-	OPT_BOOLEAN(0, "head", &show_head, N_("show the HEAD reference")),
+	OPT_BOOLEAN(0, "head", &show_head,
+	  N_("show the HEAD reference, even if it would be filtered out")),
 	OPT_BOOLEAN('d', "dereference", &deref_tags,
 		    N_("dereference tags into object IDs")),
 	{ OPTION_CALLBACK, 's', "hash", &abbrev, N_("n"),
diff --git a/builtin/update-index.c b/builtin/update-index.c
index 5c7762e..c317981 100644
--- a/builtin/update-index.c
+++ b/builtin/update-index.c
@@ -83,7 +83,7 @@
 	return error("lstat(\"%s\"): %s", path, strerror(errno));
 }
 
-static int add_one_path(struct cache_entry *old, const char *path, int len, struct stat *st)
+static int add_one_path(const struct cache_entry *old, const char *path, int len, struct stat *st)
 {
 	int option, size;
 	struct cache_entry *ce;
@@ -142,7 +142,7 @@
 
 	/* Exact match: file or existing gitlink */
 	if (pos >= 0) {
-		struct cache_entry *ce = active_cache[pos];
+		const struct cache_entry *ce = active_cache[pos];
 		if (S_ISGITLINK(ce->ce_mode)) {
 
 			/* Do nothing to the index if there is no HEAD! */
@@ -158,7 +158,7 @@
 	/* Inexact match: is there perhaps a subdirectory match? */
 	pos = -pos-1;
 	while (pos < active_nr) {
-		struct cache_entry *ce = active_cache[pos++];
+		const struct cache_entry *ce = active_cache[pos++];
 
 		if (strncmp(ce->name, path, len))
 			break;
@@ -183,7 +183,7 @@
 {
 	int pos, len;
 	struct stat st;
-	struct cache_entry *ce;
+	const struct cache_entry *ce;
 
 	len = strlen(path);
 	if (has_symlink_leading_path(path, len))
@@ -448,7 +448,7 @@
 		/* already merged */
 		pos = unmerge_cache_entry_at(pos);
 		if (pos < active_nr) {
-			struct cache_entry *ce = active_cache[pos];
+			const struct cache_entry *ce = active_cache[pos];
 			if (ce_stage(ce) &&
 			    ce_namelen(ce) == namelen &&
 			    !memcmp(ce->name, path, namelen))
@@ -462,7 +462,7 @@
 		 */
 		pos = -pos-1;
 		if (pos < active_nr) {
-			struct cache_entry *ce = active_cache[pos];
+			const struct cache_entry *ce = active_cache[pos];
 			if (ce_namelen(ce) == namelen &&
 			    !memcmp(ce->name, path, namelen)) {
 				fprintf(stderr,
@@ -558,7 +558,7 @@
 		has_head = 0;
  redo:
 	for (pos = 0; pos < active_nr; pos++) {
-		struct cache_entry *ce = active_cache[pos];
+		const struct cache_entry *ce = active_cache[pos];
 		struct cache_entry *old = NULL;
 		int save_nr;
 
diff --git a/bulk-checkin.c b/bulk-checkin.c
index 6b0b6d4..118c625 100644
--- a/bulk-checkin.c
+++ b/bulk-checkin.c
@@ -114,7 +114,7 @@
 
 		if (size && !s.avail_in) {
 			ssize_t rsize = size < sizeof(ibuf) ? size : sizeof(ibuf);
-			if (xread(fd, ibuf, rsize) != rsize)
+			if (read_in_full(fd, ibuf, rsize) != rsize)
 				die("failed to read %d bytes from '%s'",
 				    (int)rsize, path);
 			offset += rsize;
diff --git a/bundle.c b/bundle.c
index 4b0e5cd..3d64311 100644
--- a/bundle.c
+++ b/bundle.c
@@ -281,7 +281,7 @@
 			if (!get_sha1_hex(buf.buf + 1, sha1)) {
 				struct object *object = parse_object_or_die(sha1, buf.buf);
 				object->flags |= UNINTERESTING;
-				add_pending_object(&revs, object, xstrdup(buf.buf));
+				add_pending_object(&revs, object, buf.buf);
 			}
 		} else if (!get_sha1_hex(buf.buf, sha1)) {
 			struct object *object = parse_object_or_die(sha1, buf.buf);
diff --git a/cache-tree.c b/cache-tree.c
index 37e4d00..0bbec43 100644
--- a/cache-tree.c
+++ b/cache-tree.c
@@ -149,7 +149,7 @@
 		cache_tree_invalidate_path(down->cache_tree, slash + 1);
 }
 
-static int verify_cache(struct cache_entry **cache,
+static int verify_cache(const struct cache_entry * const *cache,
 			int entries, int flags)
 {
 	int i, funny;
@@ -158,7 +158,7 @@
 	/* Verify that the tree is merged */
 	funny = 0;
 	for (i = 0; i < entries; i++) {
-		struct cache_entry *ce = cache[i];
+		const struct cache_entry *ce = cache[i];
 		if (ce_stage(ce)) {
 			if (silent)
 				return -1;
@@ -234,7 +234,7 @@
 }
 
 static int update_one(struct cache_tree *it,
-		      struct cache_entry **cache,
+		      const struct cache_entry * const *cache,
 		      int entries,
 		      const char *base,
 		      int baselen,
@@ -265,7 +265,7 @@
 	 */
 	i = 0;
 	while (i < entries) {
-		struct cache_entry *ce = cache[i];
+		const struct cache_entry *ce = cache[i];
 		struct cache_tree_sub *sub;
 		const char *path, *slash;
 		int pathlen, sublen, subcnt, subskip;
@@ -312,7 +312,7 @@
 
 	i = 0;
 	while (i < entries) {
-		struct cache_entry *ce = cache[i];
+		const struct cache_entry *ce = cache[i];
 		struct cache_tree_sub *sub;
 		const char *path, *slash;
 		int pathlen, entlen;
@@ -397,7 +397,7 @@
 }
 
 int cache_tree_update(struct cache_tree *it,
-		      struct cache_entry **cache,
+		      const struct cache_entry * const *cache,
 		      int entries,
 		      int flags)
 {
@@ -599,8 +599,8 @@
 	was_valid = cache_tree_fully_valid(active_cache_tree);
 	if (!was_valid) {
 		if (cache_tree_update(active_cache_tree,
-				      active_cache, active_nr,
-				      flags) < 0)
+				      (const struct cache_entry * const *)active_cache,
+				      active_nr, flags) < 0)
 			return WRITE_TREE_UNMERGED_INDEX;
 		if (0 <= newfd) {
 			if (!write_cache(newfd, active_cache, active_nr) &&
@@ -701,5 +701,6 @@
 	if (!the_index.cache_tree)
 		the_index.cache_tree = cache_tree();
 	return cache_tree_update(the_index.cache_tree,
-				 the_index.cache, the_index.cache_nr, flags);
+				 (const struct cache_entry * const *)the_index.cache,
+				 the_index.cache_nr, flags);
 }
diff --git a/cache-tree.h b/cache-tree.h
index 55d0f59..f1923ad 100644
--- a/cache-tree.h
+++ b/cache-tree.h
@@ -30,7 +30,7 @@
 struct cache_tree *cache_tree_read(const char *buffer, unsigned long size);
 
 int cache_tree_fully_valid(struct cache_tree *);
-int cache_tree_update(struct cache_tree *, struct cache_entry **, int, int);
+int cache_tree_update(struct cache_tree *, const struct cache_entry * const *, int, int);
 
 int update_main_cache_tree(int);
 
diff --git a/cache.h b/cache.h
index 94ca1ac..85b544f 100644
--- a/cache.h
+++ b/cache.h
@@ -119,15 +119,19 @@
 	unsigned int nsec;
 };
 
+struct stat_data {
+	struct cache_time sd_ctime;
+	struct cache_time sd_mtime;
+	unsigned int sd_dev;
+	unsigned int sd_ino;
+	unsigned int sd_uid;
+	unsigned int sd_gid;
+	unsigned int sd_size;
+};
+
 struct cache_entry {
-	struct cache_time ce_ctime;
-	struct cache_time ce_mtime;
-	unsigned int ce_dev;
-	unsigned int ce_ino;
+	struct stat_data ce_stat_data;
 	unsigned int ce_mode;
-	unsigned int ce_uid;
-	unsigned int ce_gid;
-	unsigned int ce_size;
 	unsigned int ce_flags;
 	unsigned int ce_namelen;
 	unsigned char sha1[20];
@@ -190,7 +194,8 @@
  * another. But we never change the name, or the hash state!
  */
 #define CE_STATE_MASK (CE_HASHED | CE_UNHASHED)
-static inline void copy_cache_entry(struct cache_entry *dst, struct cache_entry *src)
+static inline void copy_cache_entry(struct cache_entry *dst,
+				    const struct cache_entry *src)
 {
 	unsigned int state = dst->ce_flags & CE_STATE_MASK;
 
@@ -222,7 +227,8 @@
 		return S_IFGITLINK;
 	return S_IFREG | ce_permissions(mode);
 }
-static inline unsigned int ce_mode_from_stat(struct cache_entry *ce, unsigned int mode)
+static inline unsigned int ce_mode_from_stat(const struct cache_entry *ce,
+					     unsigned int mode)
 {
 	extern int trust_executable_bit, has_symlinks;
 	if (!has_symlinks && S_ISREG(mode) &&
@@ -419,6 +425,8 @@
 extern int set_git_dir_init(const char *git_dir, const char *real_git_dir, int);
 extern int init_db(const char *template_dir, unsigned int flags);
 
+extern void sanitize_stdfds(void);
+
 #define alloc_nr(x) (((x)+16)*3/2)
 
 /*
@@ -470,7 +478,7 @@
 extern int add_to_index(struct index_state *, const char *path, struct stat *, int flags);
 extern int add_file_to_index(struct index_state *, const char *path, int flags);
 extern struct cache_entry *make_cache_entry(unsigned int mode, const unsigned char *sha1, const char *path, int stage, int refresh);
-extern int ce_same_name(struct cache_entry *a, struct cache_entry *b);
+extern int ce_same_name(const struct cache_entry *a, const struct cache_entry *b);
 extern int index_name_is_other(const struct index_state *, const char *, int);
 extern void *read_blob_data_from_index(struct index_state *, const char *, unsigned long *);
 
@@ -480,10 +488,10 @@
 #define CE_MATCH_RACY_IS_DIRTY		02
 /* do stat comparison even if CE_SKIP_WORKTREE is true */
 #define CE_MATCH_IGNORE_SKIP_WORKTREE	04
-extern int ie_match_stat(const struct index_state *, struct cache_entry *, struct stat *, unsigned int);
-extern int ie_modified(const struct index_state *, struct cache_entry *, struct stat *, unsigned int);
+extern int ie_match_stat(const struct index_state *, const struct cache_entry *, struct stat *, unsigned int);
+extern int ie_modified(const struct index_state *, const struct cache_entry *, struct stat *, unsigned int);
 
-#define PATHSPEC_ONESTAR 1	/* the pathspec pattern sastisfies GFNM_ONESTAR */
+#define PATHSPEC_ONESTAR 1	/* the pathspec pattern satisfies GFNM_ONESTAR */
 
 struct pathspec {
 	const char **raw; /* get_pathspec() result, not freed by free_pathspec() */
@@ -509,6 +517,21 @@
 #define HASH_FORMAT_CHECK 2
 extern int index_fd(unsigned char *sha1, int fd, struct stat *st, enum object_type type, const char *path, unsigned flags);
 extern int index_path(unsigned char *sha1, const char *path, struct stat *st, unsigned flags);
+
+/*
+ * Record to sd the data from st that we use to check whether a file
+ * might have changed.
+ */
+extern void fill_stat_data(struct stat_data *sd, struct stat *st);
+
+/*
+ * Return 0 if st is consistent with a file not having been changed
+ * since sd was filled.  If there are differences, return a
+ * combination of MTIME_CHANGED, CTIME_CHANGED, OWNER_CHANGED,
+ * INODE_CHANGED, and DATA_CHANGED.
+ */
+extern int match_stat_data(const struct stat_data *sd, struct stat *st);
+
 extern void fill_stat_cache_info(struct cache_entry *ce, struct stat *st);
 
 #define REFRESH_REALLY		0x0001	/* ignore_valid */
@@ -554,6 +577,7 @@
 extern int prefer_symlink_refs;
 extern int log_all_ref_updates;
 extern int warn_ambiguous_refs;
+extern int warn_on_object_refname_ambiguity;
 extern int shared_repository;
 extern const char *apply_default_whitespace;
 extern const char *apply_default_ignorewhitespace;
@@ -737,7 +761,7 @@
 const char *real_path(const char *path);
 const char *real_path_if_valid(const char *path);
 const char *absolute_path(const char *path);
-const char *relative_path(const char *abs, const char *base);
+const char *relative_path(const char *in, const char *prefix, struct strbuf *sb);
 int normalize_path_copy(char *dst, const char *src);
 int longest_ancestor_length(const char *path, struct string_list *prefixes);
 char *strip_path_suffix(const char *path, const char *suffix);
@@ -772,9 +796,6 @@
 /* global flag to enable extra checks when accessing packed objects */
 extern int do_check_packed_object_crc;
 
-/* for development: log offset of pack access */
-extern const char *log_pack_access;
-
 extern int check_sha1_signature(const unsigned char *sha1, void *buf, unsigned long size, const char *type);
 
 extern int move_temp_to_file(const char *tmpfile, const char *filename);
@@ -910,6 +931,7 @@
 			struct strbuf *timebuf);
 int parse_date(const char *date, char *buf, int bufsize);
 int parse_date_basic(const char *date, unsigned long *timestamp, int *offset);
+int parse_expiry_date(const char *date, unsigned long *timestamp);
 void datestamp(char *buf, int bufsize);
 #define approxidate(s) approxidate_careful((s), NULL)
 unsigned long approxidate_careful(const char *, int *);
@@ -1024,9 +1046,21 @@
 	unsigned int
 		force:1,
 		forced_update:1,
-		merge:1,
 		deletion:1,
 		matched:1;
+
+	/*
+	 * Order is important here, as we write to FETCH_HEAD
+	 * in numeric order. And the default NOT_FOR_MERGE
+	 * should be 0, so that xcalloc'd structures get it
+	 * by default.
+	 */
+	enum {
+		FETCH_HEAD_MERGE = -1,
+		FETCH_HEAD_NOT_FOR_MERGE = 0,
+		FETCH_HEAD_IGNORE = 1
+	} fetch_head_status;
+
 	enum {
 		REF_STATUS_NONE = 0,
 		REF_STATUS_OK,
@@ -1098,7 +1132,9 @@
 
 struct object_info {
 	/* Request */
+	enum object_type *typep;
 	unsigned long *sizep;
+	unsigned long *disk_sizep;
 
 	/* Response */
 	enum {
@@ -1142,11 +1178,15 @@
 typedef int (*config_fn_t)(const char *, const char *, void *);
 extern int git_default_config(const char *, const char *, void *);
 extern int git_config_from_file(config_fn_t fn, const char *, void *);
+extern int git_config_from_buf(config_fn_t fn, const char *name,
+			       const char *buf, size_t len, void *data);
 extern void git_config_push_parameter(const char *text);
 extern int git_config_from_parameters(config_fn_t fn, void *data);
 extern int git_config(config_fn_t fn, void *);
 extern int git_config_with_options(config_fn_t fn, void *,
-				   const char *filename, int respect_includes);
+				   const char *filename,
+				   const char *blob_ref,
+				   int respect_includes);
 extern int git_config_early(config_fn_t fn, void *, const char *repo_config);
 extern int git_parse_ulong(const char *, unsigned long *);
 extern int git_config_int(const char *, const char *);
@@ -1326,4 +1366,31 @@
 
 int sane_execvp(const char *file, char *const argv[]);
 
+/*
+ * A struct to encapsulate the concept of whether a file has changed
+ * since we last checked it. This uses criteria similar to those used
+ * for the index.
+ */
+struct stat_validity {
+	struct stat_data *sd;
+};
+
+void stat_validity_clear(struct stat_validity *sv);
+
+/*
+ * Returns 1 if the path is a regular file (or a symlink to a regular
+ * file) and matches the saved stat_validity, 0 otherwise.  A missing
+ * or inaccessible file is considered a match if the struct was just
+ * initialized, or if the previous update found an inaccessible file.
+ */
+int stat_validity_check(struct stat_validity *sv, const char *path);
+
+/*
+ * Update the stat_validity from a file opened at descriptor fd. If
+ * the file is missing, inaccessible, or not a regular file, then
+ * future calls to stat_validity_check will match iff one of those
+ * conditions continues to be true.
+ */
+void stat_validity_update(struct stat_validity *sv, int fd);
+
 #endif /* CACHE_H */
diff --git a/color.c b/color.c
index e8e2681..f672885 100644
--- a/color.c
+++ b/color.c
@@ -1,7 +1,7 @@
 #include "cache.h"
 #include "color.h"
 
-static int git_use_color_default = 0;
+static int git_use_color_default = GIT_COLOR_AUTO;
 int color_stdout_is_tty = -1;
 
 /*
diff --git a/combine-diff.c b/combine-diff.c
index 77d7872..4fc16ad 100644
--- a/combine-diff.c
+++ b/combine-diff.c
@@ -10,6 +10,7 @@
 #include "refs.h"
 #include "userdiff.h"
 #include "sha1-array.h"
+#include "revision.h"
 
 static struct combine_diff_path *intersect_paths(struct combine_diff_path *curr, int n, int num_parent)
 {
@@ -165,7 +166,7 @@
 
 	/*
 	 * Coalesce new lines into base by finding the LCS
-	 * - Create the table to run dynamic programing
+	 * - Create the table to run dynamic programming
 	 * - Compute the LCS
 	 * - Then reverse read the direction structure:
 	 *   - If we have MATCH, assign parent to base flag, and consume
@@ -518,8 +519,11 @@
 		unsigned long k;
 
 		/* Paint a few lines before the first interesting line. */
-		while (j < i)
-			sline[j++].flag |= mark | no_pre_delete;
+		while (j < i) {
+			if (!(sline[j].flag & mark))
+				sline[j].flag |= no_pre_delete;
+			sline[j++].flag |= mark;
+		}
 
 	again:
 		/* we know up to i is to be included.  where does the
@@ -1302,6 +1306,7 @@
 	int i, num_paths, needsep, show_log_first, num_parent = parents->nr;
 
 	diffopts = *opt;
+	diff_tree_setup_paths(diffopts.pathspec.raw, &diffopts);
 	diffopts.output_format = DIFF_FORMAT_NO_OUTPUT;
 	DIFF_OPT_SET(&diffopts, RECURSIVE);
 	DIFF_OPT_CLR(&diffopts, ALLOW_EXTERNAL);
@@ -1372,12 +1377,14 @@
 		paths = paths->next;
 		free(tmp);
 	}
+
+	diff_tree_release_paths(&diffopts);
 }
 
 void diff_tree_combined_merge(const struct commit *commit, int dense,
 			      struct rev_info *rev)
 {
-	struct commit_list *parent = commit->parents;
+	struct commit_list *parent = get_saved_parents(rev, commit);
 	struct sha1_array parents = SHA1_ARRAY_INIT;
 
 	while (parent) {
diff --git a/command-list.txt b/command-list.txt
index bf83303..08b04e2 100644
--- a/command-list.txt
+++ b/command-list.txt
@@ -13,6 +13,7 @@
 git-cat-file                            plumbinginterrogators
 git-check-attr                          purehelpers
 git-check-ignore                        purehelpers
+git-check-mailmap                       purehelpers
 git-checkout                            mainporcelain common
 git-checkout-index                      plumbingmanipulators
 git-check-ref-format                    purehelpers
diff --git a/commit-slab.h b/commit-slab.h
new file mode 100644
index 0000000..d4c8286
--- /dev/null
+++ b/commit-slab.h
@@ -0,0 +1,97 @@
+#ifndef COMMIT_SLAB_H
+#define COMMIT_SLAB_H
+
+/*
+ * define_commit_slab(slabname, elemtype) creates boilerplate code to define
+ * a new struct (struct slabname) that is used to associate a piece of data
+ * of elemtype to commits, and a few functions to use that struct.
+ *
+ * After including this header file, using:
+ *
+ * define_commit_slab(indegee, int);
+ *
+ * will let you call the following functions:
+ *
+ * - int *indegree_at(struct indegree *, struct commit *);
+ *
+ *   This function locates the data associated with the given commit in
+ *   the indegree slab, and returns the pointer to it.
+ *
+ * - void init_indegree(struct indegree *);
+ *   void init_indegree_with_stride(struct indegree *, int);
+ *
+ *   Initializes the indegree slab that associates an array of integers
+ *   to each commit. 'stride' specifies how big each array is.  The slab
+ *   that id initialied by the variant without "_with_stride" associates
+ *   each commit with an array of one integer.
+ */
+
+/* allocate ~512kB at once, allowing for malloc overhead */
+#ifndef COMMIT_SLAB_SIZE
+#define COMMIT_SLAB_SIZE (512*1024-32)
+#endif
+
+#define define_commit_slab(slabname, elemtype) 				\
+									\
+struct slabname {							\
+	unsigned slab_size;						\
+	unsigned stride;						\
+	unsigned slab_count;						\
+	elemtype **slab;						\
+};									\
+static int stat_ ##slabname## realloc;					\
+									\
+static void init_ ##slabname## _with_stride(struct slabname *s,		\
+					    unsigned stride)		\
+{									\
+	unsigned int elem_size;						\
+	if (!stride)							\
+		stride = 1;						\
+	s->stride = stride;						\
+	elem_size = sizeof(elemtype) * stride;				\
+	s->slab_size = COMMIT_SLAB_SIZE / elem_size;			\
+	s->slab_count = 0;						\
+	s->slab = NULL;							\
+}									\
+									\
+static void init_ ##slabname(struct slabname *s)			\
+{									\
+	init_ ##slabname## _with_stride(s, 1);				\
+}									\
+									\
+static void clear_ ##slabname(struct slabname *s)			\
+{									\
+	int i;								\
+	for (i = 0; i < s->slab_count; i++)				\
+		free(s->slab[i]);					\
+	s->slab_count = 0;						\
+	free(s->slab);							\
+	s->slab = NULL;							\
+}									\
+									\
+static elemtype *slabname## _at(struct slabname *s,			\
+				const struct commit *c)			\
+{									\
+	int nth_slab, nth_slot;						\
+									\
+	nth_slab = c->index / s->slab_size;				\
+	nth_slot = c->index % s->slab_size;				\
+									\
+	if (s->slab_count <= nth_slab) {				\
+		int i;							\
+		s->slab = xrealloc(s->slab,				\
+				   (nth_slab + 1) * sizeof(s->slab));	\
+		stat_ ##slabname## realloc++;				\
+		for (i = s->slab_count; i <= nth_slab; i++)		\
+			s->slab[i] = NULL;				\
+		s->slab_count = nth_slab + 1;				\
+	}								\
+	if (!s->slab[nth_slab])						\
+		s->slab[nth_slab] = xcalloc(s->slab_size,		\
+					    sizeof(**s->slab) * s->stride);		\
+	return &s->slab[nth_slab][nth_slot * s->stride];				\
+}									\
+									\
+static int stat_ ##slabname## realloc
+
+#endif /* COMMIT_SLAB_H */
diff --git a/commit.c b/commit.c
index 888e02a..de16a3c 100644
--- a/commit.c
+++ b/commit.c
@@ -8,12 +8,15 @@
 #include "notes.h"
 #include "gpg-interface.h"
 #include "mergesort.h"
+#include "commit-slab.h"
+#include "prio-queue.h"
 
 static struct commit_extra_header *read_commit_extra_header_lines(const char *buf, size_t len, const char **);
 
 int save_commit_buffer = 1;
 
 const char *commit_type = "commit";
+static int commit_count;
 
 static struct commit *check_commit(struct object *obj,
 				   const unsigned char *sha1,
@@ -58,8 +61,11 @@
 struct commit *lookup_commit(const unsigned char *sha1)
 {
 	struct object *obj = lookup_object(sha1);
-	if (!obj)
-		return create_object(sha1, OBJ_COMMIT, alloc_commit_node());
+	if (!obj) {
+		struct commit *c = alloc_commit_node();
+		c->index = commit_count++;
+		return create_object(sha1, OBJ_COMMIT, c);
+	}
 	if (!obj->type)
 		obj->type = OBJ_COMMIT;
 	return check_commit(obj, sha1, 0);
@@ -371,6 +377,22 @@
 	return c;
 }
 
+struct commit_list *copy_commit_list(struct commit_list *list)
+{
+	struct commit_list *head = NULL;
+	struct commit_list **pp = &head;
+	while (list) {
+		struct commit_list *new;
+		new = xmalloc(sizeof(struct commit_list));
+		new->item = list->item;
+		new->next = NULL;
+		*pp = new;
+		pp = &new->next;
+		list = list->next;
+	}
+	return head;
+}
+
 void free_commit_list(struct commit_list *list)
 {
 	while (list) {
@@ -507,32 +529,136 @@
 }
 
 /*
+ * Topological sort support
+ */
+
+/* count number of children that have not been emitted */
+define_commit_slab(indegree_slab, int);
+
+/* record author-date for each commit object */
+define_commit_slab(author_date_slab, unsigned long);
+
+static void record_author_date(struct author_date_slab *author_date,
+			       struct commit *commit)
+{
+	const char *buf, *line_end;
+	char *buffer = NULL;
+	struct ident_split ident;
+	char *date_end;
+	unsigned long date;
+
+	if (!commit->buffer) {
+		unsigned long size;
+		enum object_type type;
+		buffer = read_sha1_file(commit->object.sha1, &type, &size);
+		if (!buffer)
+			return;
+	}
+
+	for (buf = commit->buffer ? commit->buffer : buffer;
+	     buf;
+	     buf = line_end + 1) {
+		line_end = strchrnul(buf, '\n');
+		if (prefixcmp(buf, "author ")) {
+			if (!line_end[0] || line_end[1] == '\n')
+				return; /* end of header */
+			continue;
+		}
+		if (split_ident_line(&ident,
+				     buf + strlen("author "),
+				     line_end - (buf + strlen("author "))) ||
+		    !ident.date_begin || !ident.date_end)
+			goto fail_exit; /* malformed "author" line */
+		break;
+	}
+
+	date = strtoul(ident.date_begin, &date_end, 10);
+	if (date_end != ident.date_end)
+		goto fail_exit; /* malformed date */
+	*(author_date_slab_at(author_date, commit)) = date;
+
+fail_exit:
+	free(buffer);
+}
+
+static int compare_commits_by_author_date(const void *a_, const void *b_,
+					  void *cb_data)
+{
+	const struct commit *a = a_, *b = b_;
+	struct author_date_slab *author_date = cb_data;
+	unsigned long a_date = *(author_date_slab_at(author_date, a));
+	unsigned long b_date = *(author_date_slab_at(author_date, b));
+
+	/* newer commits with larger date first */
+	if (a_date < b_date)
+		return 1;
+	else if (a_date > b_date)
+		return -1;
+	return 0;
+}
+
+int compare_commits_by_commit_date(const void *a_, const void *b_, void *unused)
+{
+	const struct commit *a = a_, *b = b_;
+	/* newer commits with larger date first */
+	if (a->date < b->date)
+		return 1;
+	else if (a->date > b->date)
+		return -1;
+	return 0;
+}
+
+/*
  * Performs an in-place topological sort on the list supplied.
  */
-void sort_in_topological_order(struct commit_list ** list, int lifo)
+void sort_in_topological_order(struct commit_list **list, enum rev_sort_order sort_order)
 {
 	struct commit_list *next, *orig = *list;
-	struct commit_list *work, **insert;
 	struct commit_list **pptr;
+	struct indegree_slab indegree;
+	struct prio_queue queue;
+	struct commit *commit;
+	struct author_date_slab author_date;
 
 	if (!orig)
 		return;
 	*list = NULL;
 
+	init_indegree_slab(&indegree);
+	memset(&queue, '\0', sizeof(queue));
+
+	switch (sort_order) {
+	default: /* REV_SORT_IN_GRAPH_ORDER */
+		queue.compare = NULL;
+		break;
+	case REV_SORT_BY_COMMIT_DATE:
+		queue.compare = compare_commits_by_commit_date;
+		break;
+	case REV_SORT_BY_AUTHOR_DATE:
+		init_author_date_slab(&author_date);
+		queue.compare = compare_commits_by_author_date;
+		queue.cb_data = &author_date;
+		break;
+	}
+
 	/* Mark them and clear the indegree */
 	for (next = orig; next; next = next->next) {
 		struct commit *commit = next->item;
-		commit->indegree = 1;
+		*(indegree_slab_at(&indegree, commit)) = 1;
+		/* also record the author dates, if needed */
+		if (sort_order == REV_SORT_BY_AUTHOR_DATE)
+			record_author_date(&author_date, commit);
 	}
 
 	/* update the indegree */
 	for (next = orig; next; next = next->next) {
-		struct commit_list * parents = next->item->parents;
+		struct commit_list *parents = next->item->parents;
 		while (parents) {
 			struct commit *parent = parents->item;
+			int *pi = indegree_slab_at(&indegree, parent);
 
-			if (parent->indegree)
-				parent->indegree++;
+			if (*pi)
+				(*pi)++;
 			parents = parents->next;
 		}
 	}
@@ -544,34 +670,33 @@
 	 *
 	 * the tips serve as a starting set for the work queue.
 	 */
-	work = NULL;
-	insert = &work;
 	for (next = orig; next; next = next->next) {
 		struct commit *commit = next->item;
 
-		if (commit->indegree == 1)
-			insert = &commit_list_insert(commit, insert)->next;
+		if (*(indegree_slab_at(&indegree, commit)) == 1)
+			prio_queue_put(&queue, commit);
 	}
 
-	/* process the list in topological order */
-	if (!lifo)
-		commit_list_sort_by_date(&work);
+	/*
+	 * This is unfortunate; the initial tips need to be shown
+	 * in the order given from the revision traversal machinery.
+	 */
+	if (sort_order == REV_SORT_IN_GRAPH_ORDER)
+		prio_queue_reverse(&queue);
+
+	/* We no longer need the commit list */
+	free_commit_list(orig);
 
 	pptr = list;
 	*list = NULL;
-	while (work) {
-		struct commit *commit;
-		struct commit_list *parents, *work_item;
+	while ((commit = prio_queue_get(&queue)) != NULL) {
+		struct commit_list *parents;
 
-		work_item = work;
-		work = work_item->next;
-		work_item->next = NULL;
-
-		commit = work_item->item;
 		for (parents = commit->parents; parents ; parents = parents->next) {
 			struct commit *parent = parents->item;
+			int *pi = indegree_slab_at(&indegree, parent);
 
-			if (!parent->indegree)
+			if (!*pi)
 				continue;
 
 			/*
@@ -579,21 +704,22 @@
 			 * when all their children have been emitted thereby
 			 * guaranteeing topological order.
 			 */
-			if (--parent->indegree == 1) {
-				if (!lifo)
-					commit_list_insert_by_date(parent, &work);
-				else
-					commit_list_insert(parent, &work);
-			}
+			if (--(*pi) == 1)
+				prio_queue_put(&queue, parent);
 		}
 		/*
-		 * work_item is a commit all of whose children
-		 * have already been emitted. we can emit it now.
+		 * all children of commit have already been
+		 * emitted. we can emit it now.
 		 */
-		commit->indegree = 0;
-		*pptr = work_item;
-		pptr = &work_item->next;
+		*(indegree_slab_at(&indegree, commit)) = 0;
+
+		pptr = &commit_list_insert(commit, pptr)->next;
 	}
+
+	clear_indegree_slab(&indegree);
+	clear_prio_queue(&queue);
+	if (sort_order == REV_SORT_BY_AUTHOR_DATE)
+		clear_author_date_slab(&author_date);
 }
 
 /* merge-base stuff */
@@ -1240,10 +1366,15 @@
 static int find_invalid_utf8(const char *buf, int len)
 {
 	int offset = 0;
+	static const unsigned int max_codepoint[] = {
+		0x7f, 0x7ff, 0xffff, 0x10ffff
+	};
 
 	while (len) {
 		unsigned char c = *buf++;
 		int bytes, bad_offset;
+		unsigned int codepoint;
+		unsigned int min_val, max_val;
 
 		len--;
 		offset++;
@@ -1264,24 +1395,48 @@
 			bytes++;
 		}
 
-		/* Must be between 1 and 5 more bytes */
-		if (bytes < 1 || bytes > 5)
+		/*
+		 * Must be between 1 and 3 more bytes.  Longer sequences result in
+		 * codepoints beyond U+10FFFF, which are guaranteed never to exist.
+		 */
+		if (bytes < 1 || 3 < bytes)
 			return bad_offset;
 
 		/* Do we *have* that many bytes? */
 		if (len < bytes)
 			return bad_offset;
 
+		/*
+		 * Place the encoded bits at the bottom of the value and compute the
+		 * valid range.
+		 */
+		codepoint = (c & 0x7f) >> bytes;
+		min_val = max_codepoint[bytes-1] + 1;
+		max_val = max_codepoint[bytes];
+
 		offset += bytes;
 		len -= bytes;
 
 		/* And verify that they are good continuation bytes */
 		do {
+			codepoint <<= 6;
+			codepoint |= *buf & 0x3f;
 			if ((*buf++ & 0xc0) != 0x80)
 				return bad_offset;
 		} while (--bytes);
 
-		/* We could/should check the value and length here too */
+		/* Reject codepoints that are out of range for the sequence length. */
+		if (codepoint < min_val || codepoint > max_val)
+			return bad_offset;
+		/* Surrogates are only for UTF-16 and cannot be encoded in UTF-8. */
+		if ((codepoint & 0x1ff800) == 0xd800)
+			return bad_offset;
+		/* U+xxFFFE and U+xxFFFF are guaranteed non-characters. */
+		if ((codepoint & 0xfffe) == 0xfffe)
+			return bad_offset;
+		/* So are anything in the range U+FDD0..U+FDEF. */
+		if (codepoint >= 0xfdd0 && codepoint <= 0xfdef)
+			return bad_offset;
 	}
 	return -1;
 }
@@ -1291,9 +1446,6 @@
  *
  * If it isn't, it assumes any non-utf8 characters are Latin1,
  * and does the conversion.
- *
- * Fixme: we should probably also disallow overlong forms and
- * invalid characters. But we don't do that currently.
  */
 static int verify_utf8(struct strbuf *buf)
 {
diff --git a/commit.h b/commit.h
index 67bd509..f9504f7 100644
--- a/commit.h
+++ b/commit.h
@@ -6,6 +6,7 @@
 #include "strbuf.h"
 #include "decorate.h"
 #include "gpg-interface.h"
+#include "string-list.h"
 
 struct commit_list {
 	struct commit *item;
@@ -15,7 +16,7 @@
 struct commit {
 	struct object object;
 	void *util;
-	unsigned int indegree;
+	unsigned int index;
 	unsigned long date;
 	struct commit_list *parents;
 	struct tree *tree;
@@ -61,6 +62,9 @@
 				    struct commit_list **list);
 void commit_list_sort_by_date(struct commit_list **list);
 
+/* Shallow copy of the input list */
+struct commit_list *copy_commit_list(struct commit_list *list);
+
 void free_commit_list(struct commit_list *list);
 
 /* Commit formats */
@@ -79,6 +83,9 @@
 };
 
 struct pretty_print_context {
+	/*
+	 * Callers should tweak these to change the behavior of pp_* functions.
+	 */
 	enum cmit_fmt fmt;
 	int abbrev;
 	const char *subject;
@@ -92,6 +99,13 @@
 	const char *output_encoding;
 	struct string_list *mailmap;
 	int color;
+	struct ident_split *from_ident;
+
+	/*
+	 * Fields below here are manipulated internally by pp_* functions and
+	 * should not be counted on by callers.
+	 */
+	struct string_list in_body_headers;
 };
 
 struct userformat_want {
@@ -111,20 +125,20 @@
 extern void format_commit_message(const struct commit *commit,
 				  const char *format, struct strbuf *sb,
 				  const struct pretty_print_context *context);
-extern void pretty_print_commit(const struct pretty_print_context *pp,
+extern void pretty_print_commit(struct pretty_print_context *pp,
 				const struct commit *commit,
 				struct strbuf *sb);
 extern void pp_commit_easy(enum cmit_fmt fmt, const struct commit *commit,
 			   struct strbuf *sb);
-void pp_user_info(const struct pretty_print_context *pp,
+void pp_user_info(struct pretty_print_context *pp,
 		  const char *what, struct strbuf *sb,
 		  const char *line, const char *encoding);
-void pp_title_line(const struct pretty_print_context *pp,
+void pp_title_line(struct pretty_print_context *pp,
 		   const char **msg_p,
 		   struct strbuf *sb,
 		   const char *encoding,
 		   int need_8bit_cte);
-void pp_remainder(const struct pretty_print_context *pp,
+void pp_remainder(struct pretty_print_context *pp,
 		  const char **msg_p,
 		  struct strbuf *sb,
 		  int indent);
@@ -142,15 +156,24 @@
 void clear_commit_marks_many(int nr, struct commit **commit, unsigned int mark);
 void clear_commit_marks_for_object_array(struct object_array *a, unsigned mark);
 
+
+enum rev_sort_order {
+	REV_SORT_IN_GRAPH_ORDER = 0,
+	REV_SORT_BY_COMMIT_DATE,
+	REV_SORT_BY_AUTHOR_DATE
+};
+
 /*
  * Performs an in-place topological sort of list supplied.
  *
  *   invariant of resulting list is:
  *      a reachable from b => ord(b) < ord(a)
- *   in addition, when lifo == 0, commits on parallel tracks are
- *   sorted in the dates order.
+ *   sort_order further specifies:
+ *   REV_SORT_IN_GRAPH_ORDER: try to show a commit on a single-parent
+ *                            chain together.
+ *   REV_SORT_BY_COMMIT_DATE: show eligible commits in committer-date order.
  */
-void sort_in_topological_order(struct commit_list ** list, int lifo);
+void sort_in_topological_order(struct commit_list **, enum rev_sort_order);
 
 struct commit_graft {
 	unsigned char sha1[20];
@@ -176,6 +199,8 @@
 extern int is_repository_shallow(void);
 extern struct commit_list *get_shallow_commits(struct object_array *heads,
 		int depth, int shallow_flag, int not_shallow_flag);
+extern void check_shallow_file_for_update(void);
+extern void set_alternate_shallow_file(const char *path);
 
 int is_descendant_of(struct commit *, struct commit_list *);
 int in_merge_bases(struct commit *, struct commit *);
@@ -243,4 +268,6 @@
  */
 extern void check_commit_signature(const struct commit* commit, struct signature_check *sigc);
 
+int compare_commits_by_commit_date(const void *a_, const void *b_, void *unused);
+
 #endif /* COMMIT_H */
diff --git a/compat/cygwin.c b/compat/cygwin.c
deleted file mode 100644
index 871b41d..0000000
--- a/compat/cygwin.c
+++ /dev/null
@@ -1,162 +0,0 @@
-#define CYGWIN_C
-#define WIN32_LEAN_AND_MEAN
-#ifdef CYGWIN_V15_WIN32API
-#include "../git-compat-util.h"
-#include "win32.h"
-#else
-#include <sys/stat.h>
-#include <sys/errno.h>
-#include "win32.h"
-#include "../git-compat-util.h"
-#endif
-#include "../cache.h" /* to read configuration */
-
-/*
- * Return POSIX permission bits, regardless of core.ignorecygwinfstricks
- */
-int cygwin_get_st_mode_bits(const char *path, int *mode)
-{
-	struct stat st;
-	if (lstat(path, &st) < 0)
-		return -1;
-	*mode = st.st_mode;
-	return 0;
-}
-
-static inline void filetime_to_timespec(const FILETIME *ft, struct timespec *ts)
-{
-	long long winTime = ((long long)ft->dwHighDateTime << 32) +
-			ft->dwLowDateTime;
-	winTime -= 116444736000000000LL; /* Windows to Unix Epoch conversion */
-	/* convert 100-nsecond interval to seconds and nanoseconds */
-	ts->tv_sec = (time_t)(winTime/10000000);
-	ts->tv_nsec = (long)(winTime - ts->tv_sec*10000000LL) * 100;
-}
-
-#define size_to_blocks(s) (((s)+511)/512)
-
-/* do_stat is a common implementation for cygwin_lstat and cygwin_stat.
- *
- * To simplify its logic, in the case of cygwin symlinks, this implementation
- * falls back to the cygwin version of stat/lstat, which is provided as the
- * last argument.
- */
-static int do_stat(const char *file_name, struct stat *buf, stat_fn_t cygstat)
-{
-	WIN32_FILE_ATTRIBUTE_DATA fdata;
-
-	if (file_name[0] == '/')
-		return cygstat (file_name, buf);
-
-	if (!(errno = get_file_attr(file_name, &fdata))) {
-		/*
-		 * If the system attribute is set and it is not a directory then
-		 * it could be a symbol link created in the nowinsymlinks mode.
-		 * Normally, Cygwin works in the winsymlinks mode, so this situation
-		 * is very unlikely. For the sake of simplicity of our code, let's
-		 * Cygwin to handle it.
-		 */
-		if ((fdata.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) &&
-		    !(fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
-			return cygstat(file_name, buf);
-
-		/* fill out the stat structure */
-		buf->st_dev = buf->st_rdev = 0; /* not used by Git */
-		buf->st_ino = 0;
-		buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes);
-		buf->st_nlink = 1;
-		buf->st_uid = buf->st_gid = 0;
-#ifdef __CYGWIN_USE_BIG_TYPES__
-		buf->st_size = ((_off64_t)fdata.nFileSizeHigh << 32) +
-			fdata.nFileSizeLow;
-#else
-		buf->st_size = (off_t)fdata.nFileSizeLow;
-#endif
-		buf->st_blocks = size_to_blocks(buf->st_size);
-		filetime_to_timespec(&fdata.ftLastAccessTime, &buf->st_atim);
-		filetime_to_timespec(&fdata.ftLastWriteTime, &buf->st_mtim);
-		filetime_to_timespec(&fdata.ftCreationTime, &buf->st_ctim);
-		return 0;
-	} else if (errno == ENOENT) {
-		/*
-		 * In the winsymlinks mode (which is the default), Cygwin
-		 * emulates symbol links using Windows shortcut files. These
-		 * files are formed by adding .lnk extension. So, if we have
-		 * not found the specified file name, it could be that it is
-		 * a symbol link. Let's Cygwin to deal with that.
-		 */
-		return cygstat(file_name, buf);
-	}
-	return -1;
-}
-
-/* We provide our own lstat/stat functions, since the provided Cygwin versions
- * of these functions are too slow. These stat functions are tailored for Git's
- * usage, and therefore they are not meant to be complete and correct emulation
- * of lstat/stat functionality.
- */
-static int cygwin_lstat(const char *path, struct stat *buf)
-{
-	return do_stat(path, buf, lstat);
-}
-
-static int cygwin_stat(const char *path, struct stat *buf)
-{
-	return do_stat(path, buf, stat);
-}
-
-
-/*
- * At start up, we are trying to determine whether Win32 API or cygwin stat
- * functions should be used. The choice is determined by core.ignorecygwinfstricks.
- * Reading this option is not always possible immediately as git_dir may
- * not be set yet. So until it is set, use cygwin lstat/stat functions.
- * However, if core.filemode is set, we must use the Cygwin posix
- * stat/lstat as the Windows stat functions do not determine posix filemode.
- *
- * Note that git_cygwin_config() does NOT call git_default_config() and this
- * is deliberate.  Many commands read from config to establish initial
- * values in variables and later tweak them from elsewhere (e.g. command line).
- * init_stat() is called lazily on demand, typically much late in the program,
- * and calling git_default_config() from here would break such variables.
- */
-static int native_stat = 1;
-static int core_filemode = 1; /* matches trust_executable_bit default */
-
-static int git_cygwin_config(const char *var, const char *value, void *cb)
-{
-	if (!strcmp(var, "core.ignorecygwinfstricks"))
-		native_stat = git_config_bool(var, value);
-	else if (!strcmp(var, "core.filemode"))
-		core_filemode = git_config_bool(var, value);
-	return 0;
-}
-
-static int init_stat(void)
-{
-	if (have_git_dir() && git_config(git_cygwin_config,NULL)) {
-		if (!core_filemode && native_stat) {
-			cygwin_stat_fn = cygwin_stat;
-			cygwin_lstat_fn = cygwin_lstat;
-		} else {
-			cygwin_stat_fn = stat;
-			cygwin_lstat_fn = lstat;
-		}
-		return 0;
-	}
-	return 1;
-}
-
-static int cygwin_stat_stub(const char *file_name, struct stat *buf)
-{
-	return (init_stat() ? stat : *cygwin_stat_fn)(file_name, buf);
-}
-
-static int cygwin_lstat_stub(const char *file_name, struct stat *buf)
-{
-	return (init_stat() ? lstat : *cygwin_lstat_fn)(file_name, buf);
-}
-
-stat_fn_t cygwin_stat_fn = cygwin_stat_stub;
-stat_fn_t cygwin_lstat_fn = cygwin_lstat_stub;
-
diff --git a/compat/cygwin.h b/compat/cygwin.h
deleted file mode 100644
index c04965a..0000000
--- a/compat/cygwin.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#include <sys/types.h>
-#include <sys/stat.h>
-
-typedef int (*stat_fn_t)(const char*, struct stat*);
-extern stat_fn_t cygwin_stat_fn;
-extern stat_fn_t cygwin_lstat_fn;
-int cygwin_get_st_mode_bits(const char *path, int *mode);
-
-#define get_st_mode_bits(p,m) cygwin_get_st_mode_bits((p),(m))
-#ifndef CYGWIN_C
-/* cygwin.c needs the original lstat() */
-#define stat(path, buf) (*cygwin_stat_fn)(path, buf)
-#define lstat(path, buf) (*cygwin_lstat_fn)(path, buf)
-#endif
diff --git a/compat/fnmatch/fnmatch.c b/compat/fnmatch/fnmatch.c
index 5ef0685..378c467 100644
--- a/compat/fnmatch/fnmatch.c
+++ b/compat/fnmatch/fnmatch.c
@@ -25,6 +25,7 @@
 # define _GNU_SOURCE	1
 #endif
 
+#include <stddef.h>
 #include <errno.h>
 #include <fnmatch.h>
 #include <ctype.h>
@@ -121,7 +122,7 @@
    whose names are inconsistent.  */
 
 # if !defined _LIBC && !defined getenv
-extern char *getenv ();
+extern char *getenv (const char *name);
 # endif
 
 # ifndef errno
diff --git a/compat/mingw.c b/compat/mingw.c
index b673625..bb92c43 100644
--- a/compat/mingw.c
+++ b/compat/mingw.c
@@ -841,8 +841,8 @@
 	struct pinfo_t *next;
 	pid_t pid;
 	HANDLE proc;
-} pinfo_t;
-struct pinfo_t *pinfo = NULL;
+};
+static struct pinfo_t *pinfo = NULL;
 CRITICAL_SECTION pinfo_cs;
 
 static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **env,
@@ -1253,7 +1253,7 @@
 	else
 		sin->sin_addr.s_addr = INADDR_LOOPBACK;
 	ai->ai_addr = (struct sockaddr *)sin;
-	ai->ai_next = 0;
+	ai->ai_next = NULL;
 	return 0;
 }
 
@@ -1677,14 +1677,16 @@
 #undef signal
 sig_handler_t mingw_signal(int sig, sig_handler_t handler)
 {
-	sig_handler_t old = timer_fn;
+	sig_handler_t old;
 
 	switch (sig) {
 	case SIGALRM:
+		old = timer_fn;
 		timer_fn = handler;
 		break;
 
 	case SIGINT:
+		old = sigint_fn;
 		sigint_fn = handler;
 		break;
 
diff --git a/compat/mingw.h b/compat/mingw.h
index 685cd2c..bd0a88b 100644
--- a/compat/mingw.h
+++ b/compat/mingw.h
@@ -334,13 +334,20 @@
 void free_environ(char **env);
 
 /*
+ * A critical section used in the implementation of the spawn
+ * functions (mingw_spawnv[p]e()) and waitpid(). Intialised in
+ * the replacement main() macro below.
+ */
+extern CRITICAL_SECTION pinfo_cs;
+
+/*
  * A replacement of main() that ensures that argv[0] has a path
  * and that default fmode and std(in|out|err) are in binary mode
  */
 
 #define main(c,v) dummy_decl_mingw_main(); \
-static int mingw_main(); \
-int main(int argc, const char **argv) \
+static int mingw_main(c,v); \
+int main(int argc, char **argv) \
 { \
 	extern CRITICAL_SECTION pinfo_cs; \
 	_fmode = _O_BINARY; \
diff --git a/compat/nedmalloc/Readme.txt b/compat/nedmalloc/Readme.txt
index e46d8f1..07cbf50 100644
--- a/compat/nedmalloc/Readme.txt
+++ b/compat/nedmalloc/Readme.txt
@@ -97,7 +97,7 @@
 
 v1.04alpha_svn915 7th October 2006:
  * Fixed failure to unlock thread cache list if allocating a new list failed.
-Thanks to Dmitry Chichkov for reporting this. Futher thanks to Aleksey Sanin.
+Thanks to Dmitry Chichkov for reporting this. Further thanks to Aleksey Sanin.
  * Fixed realloc(0, <size>) segfaulting. Thanks to Dmitry Chichkov for
 reporting this.
  * Made config defines #ifndef so they can be overridden by the build system.
diff --git a/compat/nedmalloc/malloc.c.h b/compat/nedmalloc/malloc.c.h
index 1401a67..ed4f1fa 100644
--- a/compat/nedmalloc/malloc.c.h
+++ b/compat/nedmalloc/malloc.c.h
@@ -484,6 +484,10 @@
 #define DLMALLOC_VERSION 20804
 #endif /* DLMALLOC_VERSION */
 
+#if defined(linux)
+#define _GNU_SOURCE 1
+#endif
+
 #ifndef WIN32
 #ifdef _WIN32
 #define WIN32 1
@@ -1802,7 +1806,7 @@
 
 static MLOCK_T malloc_global_mutex = { 0, 0, 0};
 
-static FORCEINLINE long win32_getcurrentthreadid() {
+static FORCEINLINE long win32_getcurrentthreadid(void) {
 #ifdef _MSC_VER
 #if defined(_M_IX86)
   long *threadstruct=(long *)__readfsdword(0x18);
@@ -3598,8 +3602,8 @@
      and choose its bk node as its replacement.
   2. If x was the last node of its size, but not a leaf node, it must
      be replaced with a leaf node (not merely one with an open left or
-     right), to make sure that lefts and rights of descendents
-     correspond properly to bit masks.  We use the rightmost descendent
+     right), to make sure that lefts and rights of descendants
+     correspond properly to bit masks.  We use the rightmost descendant
      of x.  We could use any other leaf, but this is easy to locate and
      tends to counteract removal of leftmosts elsewhere, and so keeps
      paths shorter than minimally guaranteed.  This doesn't loop much
diff --git a/compat/nedmalloc/nedmalloc.c b/compat/nedmalloc/nedmalloc.c
index 91c4e7f..609ebba 100644
--- a/compat/nedmalloc/nedmalloc.c
+++ b/compat/nedmalloc/nedmalloc.c
@@ -159,8 +159,8 @@
 #endif
 int    nedmallopt(int parno, int value) THROWSPEC	{ return nedpmallopt(0, parno, value); }
 int    nedmalloc_trim(size_t pad) THROWSPEC			{ return nedpmalloc_trim(0, pad); }
-void   nedmalloc_stats() THROWSPEC					{ nedpmalloc_stats(0); }
-size_t nedmalloc_footprint() THROWSPEC				{ return nedpmalloc_footprint(0); }
+void   nedmalloc_stats(void) THROWSPEC					{ nedpmalloc_stats(0); }
+size_t nedmalloc_footprint(void) THROWSPEC				{ return nedpmalloc_footprint(0); }
 void **nedindependent_calloc(size_t elemsno, size_t elemsize, void **chunks) THROWSPEC	{ return nedpindependent_calloc(0, elemsno, elemsize, chunks); }
 void **nedindependent_comalloc(size_t elems, size_t *sizes, void **chunks) THROWSPEC	{ return nedpindependent_comalloc(0, elems, sizes, chunks); }
 
diff --git a/compat/poll/poll.c b/compat/poll/poll.c
index 7d226ec..4410310 100644
--- a/compat/poll/poll.c
+++ b/compat/poll/poll.c
@@ -576,7 +576,7 @@
 	{
 	  /* It's a socket.  */
 	  WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
-	  WSAEventSelect ((SOCKET) h, 0, 0);
+	  WSAEventSelect ((SOCKET) h, NULL, 0);
 
 	  /* If we're lucky, WSAEnumNetworkEvents already provided a way
 	     to distinguish FD_READ and FD_ACCEPT; this saves a recv later.  */
diff --git a/compat/regex/regcomp.c b/compat/regex/regcomp.c
index d0025bd..b2c5d46 100644
--- a/compat/regex/regcomp.c
+++ b/compat/regex/regcomp.c
@@ -2617,7 +2617,7 @@
      Build the range expression which starts from START_ELEM, and ends
      at END_ELEM.  The result are written to MBCSET and SBCSET.
      RANGE_ALLOC is the allocated size of mbcset->range_starts, and
-     mbcset->range_ends, is a pointer argument sinse we may
+     mbcset->range_ends, is a pointer argument since we may
      update it.  */
 
 static reg_errcode_t
@@ -2788,7 +2788,7 @@
   const int32_t *symb_table;
   const unsigned char *extra;
 
-  /* Local function for parse_bracket_exp used in _LIBC environement.
+  /* Local function for parse_bracket_exp used in _LIBC environment.
      Seek the collating symbol entry correspondings to NAME.
      Return the index of the symbol in the SYMB_TABLE.  */
 
@@ -2892,11 +2892,11 @@
       return UINT_MAX;
     }
 
-  /* Local function for parse_bracket_exp used in _LIBC environement.
+  /* Local function for parse_bracket_exp used in _LIBC environment.
      Build the range expression which starts from START_ELEM, and ends
      at END_ELEM.  The result are written to MBCSET and SBCSET.
      RANGE_ALLOC is the allocated size of mbcset->range_starts, and
-     mbcset->range_ends, is a pointer argument sinse we may
+     mbcset->range_ends, is a pointer argument since we may
      update it.  */
 
   auto inline reg_errcode_t
@@ -2976,11 +2976,11 @@
       return REG_NOERROR;
     }
 
-  /* Local function for parse_bracket_exp used in _LIBC environement.
+  /* Local function for parse_bracket_exp used in _LIBC environment.
      Build the collating element which is represented by NAME.
      The result are written to MBCSET and SBCSET.
      COLL_SYM_ALLOC is the allocated size of mbcset->coll_sym, is a
-     pointer argument sinse we may update it.  */
+     pointer argument since we may update it.  */
 
   auto inline reg_errcode_t
   __attribute ((always_inline))
@@ -3419,7 +3419,7 @@
      Build the equivalence class which is represented by NAME.
      The result are written to MBCSET and SBCSET.
      EQUIV_CLASS_ALLOC is the allocated size of mbcset->equiv_classes,
-     is a pointer argument sinse we may update it.  */
+     is a pointer argument since we may update it.  */
 
 static reg_errcode_t
 #ifdef RE_ENABLE_I18N
@@ -3515,7 +3515,7 @@
      Build the character class which is represented by NAME.
      The result are written to MBCSET and SBCSET.
      CHAR_CLASS_ALLOC is the allocated size of mbcset->char_classes,
-     is a pointer argument sinse we may update it.  */
+     is a pointer argument since we may update it.  */
 
 static reg_errcode_t
 #ifdef RE_ENABLE_I18N
diff --git a/compat/regex/regexec.c b/compat/regex/regexec.c
index 0194965..eb5e1d4 100644
--- a/compat/regex/regexec.c
+++ b/compat/regex/regexec.c
@@ -455,7 +455,7 @@
 
   rval = 0;
 
-  /* I hope we needn't fill ther regs with -1's when no match was found.  */
+  /* I hope we needn't fill their regs with -1's when no match was found.  */
   if (result != REG_NOERROR)
     rval = -1;
   else if (regs != NULL)
@@ -1071,7 +1071,7 @@
    FL_LONGEST_MATCH means we want the POSIX longest matching.
    If P_MATCH_FIRST is not NULL, and the match fails, it is set to the
    next place where we may want to try matching.
-   Note that the matcher assume that the maching starts from the current
+   Note that the matcher assume that the matching starts from the current
    index of the buffer.  */
 
 static int
@@ -2239,7 +2239,7 @@
 			    dfa->nexts[node_idx]))
     /* The node can't accept the `multi byte', or the
        destination was already thrown away, then the node
-       could't accept the current input `multi byte'.   */
+       couldn't accept the current input `multi byte'.   */
     naccepted = 0;
   /* Otherwise, it is sure that the node could accept
      `naccepted' bytes input.  */
@@ -2313,7 +2313,7 @@
 }
 
 /* Update the state_log if we need */
-re_dfastate_t *
+static re_dfastate_t *
 internal_function
 merge_state_with_log (reg_errcode_t *err, re_match_context_t *mctx,
 		      re_dfastate_t *next_state)
@@ -2326,7 +2326,7 @@
       mctx->state_log[cur_idx] = next_state;
       mctx->state_log_top = cur_idx;
     }
-  else if (mctx->state_log[cur_idx] == 0)
+  else if (mctx->state_log[cur_idx] == NULL)
     {
       mctx->state_log[cur_idx] = next_state;
     }
@@ -2392,7 +2392,7 @@
 /* Skip bytes in the input that correspond to part of a
    multi-byte match, then look in the log for a state
    from which to restart matching.  */
-re_dfastate_t *
+static re_dfastate_t *
 internal_function
 find_recover_state (reg_errcode_t *err, re_match_context_t *mctx)
 {
diff --git a/compat/terminal.c b/compat/terminal.c
index 9b5e3d1..313897d 100644
--- a/compat/terminal.c
+++ b/compat/terminal.c
@@ -3,7 +3,7 @@
 #include "sigchain.h"
 #include "strbuf.h"
 
-#if defined(HAVE_DEV_TTY) || defined(WIN32)
+#if defined(HAVE_DEV_TTY) || defined(GIT_WINDOWS_NATIVE)
 
 static void restore_term(void);
 
@@ -53,7 +53,7 @@
 	return -1;
 }
 
-#elif defined(WIN32)
+#elif defined(GIT_WINDOWS_NATIVE)
 
 #define INPUT_PATH "CONIN$"
 #define OUTPUT_PATH "CONOUT$"
diff --git a/compat/unsetenv.c b/compat/unsetenv.c
index eb29f5e..bf5fd70 100644
--- a/compat/unsetenv.c
+++ b/compat/unsetenv.c
@@ -2,7 +2,9 @@
 
 void gitunsetenv (const char *name)
 {
+#if !defined(__MINGW32__)
      extern char **environ;
+#endif
      int src, dst;
      size_t nmln;
 
diff --git a/compat/win32.h b/compat/win32.h
index 8ce9104..a97e880 100644
--- a/compat/win32.h
+++ b/compat/win32.h
@@ -2,7 +2,7 @@
 #define WIN32_H
 
 /* common Win32 functions for MinGW and Cygwin */
-#ifndef WIN32         /* Not defined by Cygwin */
+#ifndef GIT_WINDOWS_NATIVE	/* Not defined for Cygwin */
 #include <windows.h>
 #endif
 
diff --git a/compat/win32/pthread.c b/compat/win32/pthread.c
index 010e875..e18f5c6 100644
--- a/compat/win32/pthread.c
+++ b/compat/win32/pthread.c
@@ -52,7 +52,7 @@
 
 pthread_t pthread_self(void)
 {
-	pthread_t t = { 0 };
+	pthread_t t = { NULL };
 	t.tid = GetCurrentThreadId();
 	return t;
 }
diff --git a/compat/win32mmap.c b/compat/win32mmap.c
index 61d2ef8..80a8c9a 100644
--- a/compat/win32mmap.c
+++ b/compat/win32mmap.c
@@ -21,8 +21,8 @@
 	if (!(flags & MAP_PRIVATE))
 		die("Invalid usage of mmap when built with USE_WIN32_MMAP");
 
-	hmap = CreateFileMapping((HANDLE)_get_osfhandle(fd), 0, PAGE_WRITECOPY,
-		0, 0, 0);
+	hmap = CreateFileMapping((HANDLE)_get_osfhandle(fd), NULL,
+		PAGE_WRITECOPY, 0, 0, NULL);
 
 	if (!hmap)
 		return MAP_FAILED;
diff --git a/config.c b/config.c
index aefd80b..9f9bf0c 100644
--- a/config.c
+++ b/config.c
@@ -10,20 +10,69 @@
 #include "strbuf.h"
 #include "quote.h"
 
-typedef struct config_file {
-	struct config_file *prev;
-	FILE *f;
+struct config_source {
+	struct config_source *prev;
+	union {
+		FILE *file;
+		struct config_buf {
+			const char *buf;
+			size_t len;
+			size_t pos;
+		} buf;
+	} u;
 	const char *name;
+	int die_on_error;
 	int linenr;
 	int eof;
 	struct strbuf value;
 	struct strbuf var;
-} config_file;
 
-static config_file *cf;
+	int (*do_fgetc)(struct config_source *c);
+	int (*do_ungetc)(int c, struct config_source *conf);
+	long (*do_ftell)(struct config_source *c);
+};
+
+static struct config_source *cf;
 
 static int zlib_compression_seen;
 
+static int config_file_fgetc(struct config_source *conf)
+{
+	return fgetc(conf->u.file);
+}
+
+static int config_file_ungetc(int c, struct config_source *conf)
+{
+	return ungetc(c, conf->u.file);
+}
+
+static long config_file_ftell(struct config_source *conf)
+{
+	return ftell(conf->u.file);
+}
+
+
+static int config_buf_fgetc(struct config_source *conf)
+{
+	if (conf->u.buf.pos < conf->u.buf.len)
+		return conf->u.buf.buf[conf->u.buf.pos++];
+
+	return EOF;
+}
+
+static int config_buf_ungetc(int c, struct config_source *conf)
+{
+	if (conf->u.buf.pos > 0)
+		return conf->u.buf.buf[--conf->u.buf.pos];
+
+	return EOF;
+}
+
+static long config_buf_ftell(struct config_source *conf)
+{
+	return conf->u.buf.pos;
+}
+
 #define MAX_INCLUDE_DEPTH 10
 static const char include_depth_advice[] =
 "exceeded maximum include depth (%d) while including\n"
@@ -58,7 +107,7 @@
 		path = buf.buf;
 	}
 
-	if (!access_or_die(path, R_OK)) {
+	if (!access_or_die(path, R_OK, 0)) {
 		if (++inc->depth > MAX_INCLUDE_DEPTH)
 			die(include_depth_advice, MAX_INCLUDE_DEPTH, path,
 			    cf && cf->name ? cf->name : "the command line");
@@ -168,26 +217,21 @@
 
 static int get_next_char(void)
 {
-	int c;
-	FILE *f;
+	int c = cf->do_fgetc(cf);
 
-	c = '\n';
-	if (cf && ((f = cf->f) != NULL)) {
-		c = fgetc(f);
-		if (c == '\r') {
-			/* DOS like systems */
-			c = fgetc(f);
-			if (c != '\n') {
-				ungetc(c, f);
-				c = '\r';
-			}
+	if (c == '\r') {
+		/* DOS like systems */
+		c = cf->do_fgetc(cf);
+		if (c != '\n') {
+			cf->do_ungetc(c, cf);
+			c = '\r';
 		}
-		if (c == '\n')
-			cf->linenr++;
-		if (c == EOF) {
-			cf->eof = 1;
-			c = '\n';
-		}
+	}
+	if (c == '\n')
+		cf->linenr++;
+	if (c == EOF) {
+		cf->eof = 1;
+		c = '\n';
 	}
 	return c;
 }
@@ -339,7 +383,7 @@
 	}
 }
 
-static int git_parse_file(config_fn_t fn, void *data)
+static int git_parse_source(config_fn_t fn, void *data)
 {
 	int comment = 0;
 	int baselen = 0;
@@ -399,7 +443,10 @@
 		if (get_value(fn, data, var) < 0)
 			break;
 	}
-	die("bad config file line %d in %s", cf->linenr, cf->name);
+	if (cf->die_on_error)
+		die("bad config file line %d in %s", cf->linenr, cf->name);
+	else
+		return error("bad config file line %d in %s", cf->linenr, cf->name);
 }
 
 static int parse_unit_factor(const char *end, uintmax_t *val)
@@ -566,7 +613,20 @@
 		trust_ctime = git_config_bool(var, value);
 		return 0;
 	}
-	if (!strcmp(var, "core.statinfo")) {
+	if (!strcmp(var, "core.statinfo") ||
+	    !strcmp(var, "core.checkstat")) {
+		/*
+		 * NEEDSWORK: statinfo was a typo in v1.8.2 that has
+		 * never been advertised.  we will remove it at Git
+		 * 2.0 boundary.
+		 */
+		if (!strcmp(var, "core.statinfo")) {
+			static int warned;
+			if (!warned++) {
+				warning("'core.statinfo' will be removed in Git 2.0; "
+					"use 'core.checkstat' instead.");
+			}
+		}
 		if (!strcasecmp(value, "default"))
 			check_stat = 1;
 		else if (!strcasecmp(value, "minimal"))
@@ -675,9 +735,6 @@
 		return 0;
 	}
 
-	if (!strcmp(var, "core.logpackaccess"))
-		return git_config_string(&log_pack_access, var, value);
-
 	if (!strcmp(var, "core.autocrlf")) {
 		if (value && !strcasecmp(value, "input")) {
 			if (core_eol == EOL_CRLF)
@@ -896,6 +953,33 @@
 	return 0;
 }
 
+/*
+ * All source specific fields in the union, die_on_error, name and the callbacks
+ * fgetc, ungetc, ftell of top need to be initialized before calling
+ * this function.
+ */
+static int do_config_from(struct config_source *top, config_fn_t fn, void *data)
+{
+	int ret;
+
+	/* push config-file parsing state stack */
+	top->prev = cf;
+	top->linenr = 1;
+	top->eof = 0;
+	strbuf_init(&top->value, 1024);
+	strbuf_init(&top->var, 1024);
+	cf = top;
+
+	ret = git_parse_source(fn, data);
+
+	/* pop config-file parsing state stack */
+	strbuf_release(&top->value);
+	strbuf_release(&top->var);
+	cf = top->prev;
+
+	return ret;
+}
+
 int git_config_from_file(config_fn_t fn, const char *filename, void *data)
 {
 	int ret;
@@ -903,30 +987,74 @@
 
 	ret = -1;
 	if (f) {
-		config_file top;
+		struct config_source top;
 
-		/* push config-file parsing state stack */
-		top.prev = cf;
-		top.f = f;
+		top.u.file = f;
 		top.name = filename;
-		top.linenr = 1;
-		top.eof = 0;
-		strbuf_init(&top.value, 1024);
-		strbuf_init(&top.var, 1024);
-		cf = &top;
+		top.die_on_error = 1;
+		top.do_fgetc = config_file_fgetc;
+		top.do_ungetc = config_file_ungetc;
+		top.do_ftell = config_file_ftell;
 
-		ret = git_parse_file(fn, data);
-
-		/* pop config-file parsing state stack */
-		strbuf_release(&top.value);
-		strbuf_release(&top.var);
-		cf = top.prev;
+		ret = do_config_from(&top, fn, data);
 
 		fclose(f);
 	}
 	return ret;
 }
 
+int git_config_from_buf(config_fn_t fn, const char *name, const char *buf,
+			size_t len, void *data)
+{
+	struct config_source top;
+
+	top.u.buf.buf = buf;
+	top.u.buf.len = len;
+	top.u.buf.pos = 0;
+	top.name = name;
+	top.die_on_error = 0;
+	top.do_fgetc = config_buf_fgetc;
+	top.do_ungetc = config_buf_ungetc;
+	top.do_ftell = config_buf_ftell;
+
+	return do_config_from(&top, fn, data);
+}
+
+static int git_config_from_blob_sha1(config_fn_t fn,
+				     const char *name,
+				     const unsigned char *sha1,
+				     void *data)
+{
+	enum object_type type;
+	char *buf;
+	unsigned long size;
+	int ret;
+
+	buf = read_sha1_file(sha1, &type, &size);
+	if (!buf)
+		return error("unable to load config blob object '%s'", name);
+	if (type != OBJ_BLOB) {
+		free(buf);
+		return error("reference '%s' does not point to a blob", name);
+	}
+
+	ret = git_config_from_buf(fn, name, buf, size, data);
+	free(buf);
+
+	return ret;
+}
+
+static int git_config_from_blob_ref(config_fn_t fn,
+				    const char *name,
+				    void *data)
+{
+	unsigned char sha1[20];
+
+	if (get_sha1(name, sha1) < 0)
+		return error("unable to resolve config blob '%s'", name);
+	return git_config_from_blob_sha1(fn, name, sha1, data);
+}
+
 const char *git_etc_gitconfig(void)
 {
 	static const char *system_wide;
@@ -954,23 +1082,23 @@
 
 	home_config_paths(&user_config, &xdg_config, "config");
 
-	if (git_config_system() && !access_or_die(git_etc_gitconfig(), R_OK)) {
+	if (git_config_system() && !access_or_die(git_etc_gitconfig(), R_OK, 0)) {
 		ret += git_config_from_file(fn, git_etc_gitconfig(),
 					    data);
 		found += 1;
 	}
 
-	if (xdg_config && !access_or_die(xdg_config, R_OK)) {
+	if (xdg_config && !access_or_die(xdg_config, R_OK, ACCESS_EACCES_OK)) {
 		ret += git_config_from_file(fn, xdg_config, data);
 		found += 1;
 	}
 
-	if (user_config && !access_or_die(user_config, R_OK)) {
+	if (user_config && !access_or_die(user_config, R_OK, ACCESS_EACCES_OK)) {
 		ret += git_config_from_file(fn, user_config, data);
 		found += 1;
 	}
 
-	if (repo_config && !access_or_die(repo_config, R_OK)) {
+	if (repo_config && !access_or_die(repo_config, R_OK, 0)) {
 		ret += git_config_from_file(fn, repo_config, data);
 		found += 1;
 	}
@@ -992,7 +1120,9 @@
 }
 
 int git_config_with_options(config_fn_t fn, void *data,
-			    const char *filename, int respect_includes)
+			    const char *filename,
+			    const char *blob_ref,
+			    int respect_includes)
 {
 	char *repo_config = NULL;
 	int ret;
@@ -1011,6 +1141,8 @@
 	 */
 	if (filename)
 		return git_config_from_file(fn, filename, data);
+	else if (blob_ref)
+		return git_config_from_blob_ref(fn, blob_ref, data);
 
 	repo_config = git_pathdup("config");
 	ret = git_config_early(fn, data, repo_config);
@@ -1021,7 +1153,7 @@
 
 int git_config(config_fn_t fn, void *data)
 {
-	return git_config_with_options(fn, data, NULL, 1);
+	return git_config_with_options(fn, data, NULL, NULL, 1);
 }
 
 /*
@@ -1053,7 +1185,6 @@
 {
 	const char *ep;
 	size_t section_len;
-	FILE *f = cf->f;
 
 	switch (store.state) {
 	case KEY_SEEN:
@@ -1065,7 +1196,7 @@
 				return 1;
 			}
 
-			store.offset[store.seen] = ftell(f);
+			store.offset[store.seen] = cf->do_ftell(cf);
 			store.seen++;
 		}
 		break;
@@ -1092,19 +1223,19 @@
 		 * Do not increment matches: this is no match, but we
 		 * just made sure we are in the desired section.
 		 */
-		store.offset[store.seen] = ftell(f);
+		store.offset[store.seen] = cf->do_ftell(cf);
 		/* fallthru */
 	case SECTION_END_SEEN:
 	case START:
 		if (matches(key, value)) {
-			store.offset[store.seen] = ftell(f);
+			store.offset[store.seen] = cf->do_ftell(cf);
 			store.state = KEY_SEEN;
 			store.seen++;
 		} else {
 			if (strrchr(key, '.') - key == store.baselen &&
 			      !strncmp(key, store.key, store.baselen)) {
 					store.state = SECTION_SEEN;
-					store.offset[store.seen] = ftell(f);
+					store.offset[store.seen] = cf->do_ftell(cf);
 			}
 		}
 	}
diff --git a/config.mak.uname b/config.mak.uname
index d78fd3d..7d61531 100644
--- a/config.mak.uname
+++ b/config.mak.uname
@@ -158,19 +158,18 @@
 		NO_SYMLINK_HEAD = YesPlease
 		NO_IPV6 = YesPlease
 		OLD_ICONV = UnfortunatelyYes
-		CYGWIN_V15_WIN32API = YesPlease
+		NO_THREAD_SAFE_PREAD = YesPlease
+		# There are conflicting reports about this.
+		# On some boxes NO_MMAP is needed, and not so elsewhere.
+		# Try commenting this out if you suspect MMAP is more efficient
+		NO_MMAP = YesPlease
+	else
+		NO_REGEX = UnfortunatelyYes
 	endif
-	NO_THREAD_SAFE_PREAD = YesPlease
 	NEEDS_LIBICONV = YesPlease
 	NO_FAST_WORKING_DIRECTORY = UnfortunatelyYes
-	NO_TRUSTABLE_FILEMODE = UnfortunatelyYes
 	NO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease
-	# There are conflicting reports about this.
-	# On some boxes NO_MMAP is needed, and not so elsewhere.
-	# Try commenting this out if you suspect MMAP is more efficient
-	NO_MMAP = YesPlease
 	X = .exe
-	COMPAT_OBJS += compat/cygwin.o
 	UNRELIABLE_FSTAT = UnfortunatelyYes
 	SPARSE_FLAGS = -isystem /usr/include/w32api -Wno-one-bit-signed-bitfield
 endif
@@ -480,7 +479,6 @@
 	NO_FNMATCH = YesPlease
 	NO_MEMMEM = YesPlease
 	NEEDS_LIBICONV = YesPlease
-	OLD_ICONV = YesPlease
 	NO_STRTOUMAX = YesPlease
 	NO_MKDTEMP = YesPlease
 	NO_MKSTEMPS = YesPlease
@@ -500,13 +498,17 @@
 	NO_INET_PTON = YesPlease
 	NO_INET_NTOP = YesPlease
 	NO_POSIX_GOODIES = UnfortunatelyYes
+	DEFAULT_HELP_FORMAT = html
 	COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/win32
 	COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\"
 	COMPAT_OBJS += compat/mingw.o compat/winansi.o \
 		compat/win32/pthread.o compat/win32/syslog.o \
 		compat/win32/dirent.o
+	BASIC_LDFLAGS += -Wl,--large-address-aware
 	EXTLIBS += -lws2_32
+	GITLIBS += git.res
 	PTHREAD_LIBS =
+	RC = windres -O coff
 	NATIVE_CRLF = YesPlease
 	X = .exe
 	SPARSE_FLAGS = -Wno-one-bit-signed-bitfield
@@ -518,6 +520,7 @@
 	NO_R_TO_GCC_LINKER = YesPlease
 	INTERNAL_QSORT = YesPlease
 	HAVE_LIBCHARSET_H = YesPlease
+	NO_GETTEXT = YesPlease
 else
 	NO_CURL = YesPlease
 endif
diff --git a/configure.ac b/configure.ac
index f3462d9..2f43393 100644
--- a/configure.ac
+++ b/configure.ac
@@ -193,7 +193,7 @@
   [FLAGS is the value to pass to the compiler to enable POSIX Threads.]
   [The default if FLAGS is not specified is to try first -pthread]
   [and then -lpthread.]
-  [--without-pthreads will disable threading.])],
+  [--disable-pthreads will disable threading.])],
 [
 if test "x$enableval" = "xyes"; then
    AC_MSG_NOTICE([Will try -pthread then -lpthread to enable POSIX Threads])
diff --git a/connect.c b/connect.c
index f57efd0..a0783d4 100644
--- a/connect.c
+++ b/connect.c
@@ -551,8 +551,11 @@
 	path = strchr(end, c);
 	if (path && !has_dos_drive_prefix(end)) {
 		if (c == ':') {
-			protocol = PROTO_SSH;
-			*path++ = '\0';
+			if (path < strchrnul(host, '/')) {
+				protocol = PROTO_SSH;
+				*path++ = '\0';
+			} else /* '/' in the host part, assume local path */
+				path = end;
 		}
 	} else
 		path = end;
diff --git a/connected.c b/connected.c
index 1e89c1c..fae8d64 100644
--- a/connected.c
+++ b/connected.c
@@ -2,7 +2,12 @@
 #include "run-command.h"
 #include "sigchain.h"
 #include "connected.h"
+#include "transport.h"
 
+int check_everything_connected(sha1_iterate_fn fn, int quiet, void *cb_data)
+{
+	return check_everything_connected_with_transport(fn, quiet, cb_data, NULL);
+}
 /*
  * If we feed all the commits we want to verify to this command
  *
@@ -14,7 +19,10 @@
  *
  * Returns 0 if everything is connected, non-zero otherwise.
  */
-int check_everything_connected(sha1_iterate_fn fn, int quiet, void *cb_data)
+int check_everything_connected_with_transport(sha1_iterate_fn fn,
+					      int quiet,
+					      void *cb_data,
+					      struct transport *transport)
 {
 	struct child_process rev_list;
 	const char *argv[] = {"rev-list", "--objects",
@@ -22,10 +30,23 @@
 	char commit[41];
 	unsigned char sha1[20];
 	int err = 0;
+	struct packed_git *new_pack = NULL;
 
 	if (fn(cb_data, sha1))
 		return err;
 
+	if (transport && transport->smart_options &&
+	    transport->smart_options->self_contained_and_connected &&
+	    transport->pack_lockfile &&
+	    !suffixcmp(transport->pack_lockfile, ".keep")) {
+		struct strbuf idx_file = STRBUF_INIT;
+		strbuf_addstr(&idx_file, transport->pack_lockfile);
+		strbuf_setlen(&idx_file, idx_file.len - 5); /* ".keep" */
+		strbuf_addstr(&idx_file, ".idx");
+		new_pack = add_packed_git(idx_file.buf, idx_file.len, 1);
+		strbuf_release(&idx_file);
+	}
+
 	if (quiet)
 		argv[5] = "--quiet";
 
@@ -42,6 +63,17 @@
 
 	commit[40] = '\n';
 	do {
+		/*
+		 * If index-pack already checked that:
+		 * - there are no dangling pointers in the new pack
+		 * - the pack is self contained
+		 * Then if the updated ref is in the new pack, then we
+		 * are sure the ref is good and not sending it to
+		 * rev-list for verification.
+		 */
+		if (new_pack && find_pack_entry_one(sha1, new_pack))
+			continue;
+
 		memcpy(commit, sha1_to_hex(sha1), 40);
 		if (write_in_full(rev_list.in, commit, 41) < 0) {
 			if (errno != EPIPE && errno != EINVAL)
diff --git a/connected.h b/connected.h
index 7e4585a..0b060b7 100644
--- a/connected.h
+++ b/connected.h
@@ -1,6 +1,8 @@
 #ifndef CONNECTED_H
 #define CONNECTED_H
 
+struct transport;
+
 /*
  * Take callback data, and return next object name in the buffer.
  * When called after returning the name for the last object, return -1
@@ -16,5 +18,8 @@
  * Return 0 if Ok, non zero otherwise (i.e. some missing objects)
  */
 extern int check_everything_connected(sha1_iterate_fn, int quiet, void *cb_data);
+extern int check_everything_connected_with_transport(sha1_iterate_fn, int quiet,
+						     void *cb_data,
+						     struct transport *transport);
 
 #endif /* CONNECTED_H */
diff --git a/contrib/blameview/README b/contrib/blameview/README
deleted file mode 100644
index fada5ce..0000000
--- a/contrib/blameview/README
+++ /dev/null
@@ -1,9 +0,0 @@
-This is a sample program to use 'git-blame --incremental', based
-on this message.
-
-From: Jeff King <peff@peff.net>
-Subject: Re: More precise tag following
-To: Linus Torvalds <torvalds@linux-foundation.org>
-Cc: git@vger.kernel.org
-Date: Sat, 27 Jan 2007 18:52:38 -0500
-Message-ID: <20070127235238.GA28706@coredump.intra.peff.net>
diff --git a/contrib/blameview/blameview.perl b/contrib/blameview/blameview.perl
deleted file mode 100755
index 1dec001..0000000
--- a/contrib/blameview/blameview.perl
+++ /dev/null
@@ -1,155 +0,0 @@
-#!/usr/bin/perl
-
-use Gtk2 -init;
-use Gtk2::SimpleList;
-
-my $hash;
-my $fn;
-if ( @ARGV == 1 ) {
-	$hash = "HEAD";
-	$fn = shift;
-} elsif ( @ARGV == 2 ) {
-	$hash = shift;
-	$fn = shift;
-} else {
-	die "Usage blameview [<rev>] <filename>";
-}
-
-Gtk2::Rc->parse_string(<<'EOS');
-style "treeview_style"
-{
-  GtkTreeView::vertical-separator = 0
-}
-class "GtkTreeView" style "treeview_style"
-EOS
-
-my $window = Gtk2::Window->new('toplevel');
-$window->signal_connect(destroy => sub { Gtk2->main_quit });
-my $vpan = Gtk2::VPaned->new();
-$window->add($vpan);
-my $scrolled_window = Gtk2::ScrolledWindow->new;
-$vpan->pack1($scrolled_window, 1, 1);
-my $fileview = Gtk2::SimpleList->new(
-    'Commit' => 'text',
-    'FileLine' => 'text',
-    'Data' => 'text'
-);
-$scrolled_window->add($fileview);
-$fileview->get_column(0)->set_spacing(0);
-$fileview->set_size_request(1024, 768);
-$fileview->set_rules_hint(1);
-$fileview->signal_connect (row_activated => sub {
-		my ($sl, $path, $column) = @_;
-		my $row_ref = $sl->get_row_data_from_path ($path);
-		system("blameview @$row_ref[0]~1 $fn &");
-		});
-
-my $commitwindow = Gtk2::ScrolledWindow->new();
-$commitwindow->set_policy ('GTK_POLICY_AUTOMATIC','GTK_POLICY_AUTOMATIC');
-$vpan->pack2($commitwindow, 1, 1);
-my $commit_text = Gtk2::TextView->new();
-my $commit_buffer = Gtk2::TextBuffer->new();
-$commit_text->set_buffer($commit_buffer);
-$commitwindow->add($commit_text);
-
-$fileview->signal_connect (cursor_changed => sub {
-		my ($sl) = @_;
-		my ($path, $focus_column) = $sl->get_cursor();
-		my $row_ref = $sl->get_row_data_from_path ($path);
-		my $c_fh;
-		open($c_fh,  '-|', "git cat-file commit @$row_ref[0]")
-					or die "unable to find commit @$row_ref[0]";
-		my @buffer = <$c_fh>;
-		$commit_buffer->set_text("@buffer");
-		close($c_fh);
-		});
-
-my $fh;
-open($fh, '-|', "git cat-file blob $hash:$fn")
-  or die "unable to open $fn: $!";
-
-while(<$fh>) {
-  chomp;
-  $fileview->{data}->[$.] = ['HEAD', "$fn:$.", $_];
-}
-
-my $blame;
-open($blame, '-|', qw(git blame --incremental --), $fn, $hash)
-    or die "cannot start git-blame $fn";
-
-Glib::IO->add_watch(fileno($blame), 'in', \&read_blame_line);
-
-$window->show_all;
-Gtk2->main;
-exit 0;
-
-my %commitinfo = ();
-
-sub flush_blame_line {
-	my ($attr) = @_;
-
-	return unless defined $attr;
-
-	my ($commit, $s_lno, $lno, $cnt) =
-	    @{$attr}{qw(COMMIT S_LNO LNO CNT)};
-
-	my ($filename, $author, $author_time, $author_tz) =
-	    @{$commitinfo{$commit}}{qw(FILENAME AUTHOR AUTHOR-TIME AUTHOR-TZ)};
-	my $info = $author . ' ' . format_time($author_time, $author_tz);
-
-	for(my $i = 0; $i < $cnt; $i++) {
-		@{$fileview->{data}->[$lno+$i-1]}[0,1,2] =
-		(substr($commit, 0, 8), $filename . ':' . ($s_lno+$i));
-	}
-}
-
-my $buf;
-my $current;
-sub read_blame_line {
-
-	my $r = sysread($blame, $buf, 1024, length($buf));
-	die "I/O error" unless defined $r;
-
-	if ($r == 0) {
-		flush_blame_line($current);
-		$current = undef;
-		return 0;
-	}
-
-	while ($buf =~ s/([^\n]*)\n//) {
-		my $line = $1;
-
-		if (($commit, $s_lno, $lno, $cnt) =
-		    ($line =~ /^([0-9a-f]{40}) (\d+) (\d+) (\d+)$/)) {
-			flush_blame_line($current);
-			$current = +{
-				COMMIT => $1,
-				S_LNO => $2,
-				LNO => $3,
-				CNT => $4,
-			};
-			next;
-		}
-
-		# extended attribute values
-		if ($line =~ /^(author|author-mail|author-time|author-tz|committer|committer-mail|committer-time|committer-tz|summary|filename) (.*)$/) {
-			my $commit = $current->{COMMIT};
-			$commitinfo{$commit}{uc($1)} = $2;
-			next;
-		}
-	}
-	return 1;
-}
-
-sub format_time {
-  my $time = shift;
-  my $tz = shift;
-
-  my $minutes = $tz < 0 ? 0-$tz : $tz;
-  $minutes = ($minutes / 100)*60 + ($minutes % 100);
-  $minutes = $tz < 0 ? 0-$minutes : $minutes;
-  $time += $minutes * 60;
-  my @t = gmtime($time);
-  return sprintf('%04d-%02d-%02d %02d:%02d:%02d %s',
-		 $t[5] + 1900, @t[4,3,2,1,0], $tz);
-}
diff --git a/contrib/ciabot/ciabot.py b/contrib/ciabot/ciabot.py
index 36b5665..befa0c3 100755
--- a/contrib/ciabot/ciabot.py
+++ b/contrib/ciabot/ciabot.py
@@ -70,7 +70,7 @@
 
 # The template used to generate the XML messages to CIA.  You can make
 # visible changes to the IRC-bot notification lines by hacking this.
-# The default will produce a notfication line that looks like this:
+# The default will produce a notification line that looks like this:
 #
 # ${project}: ${author} ${repo}:${branch} * ${rev} ${files}: ${logmsg} ${url}
 #
diff --git a/contrib/ciabot/ciabot.sh b/contrib/ciabot/ciabot.sh
index 3fbbc53..dfb71a1 100755
--- a/contrib/ciabot/ciabot.sh
+++ b/contrib/ciabot/ciabot.sh
@@ -39,7 +39,7 @@
 #       done
 #
 # The reason for the tac call is that git rev-list emits commits from
-# most recent to least - better to ship notifactions from oldest to newest.
+# most recent to least - better to ship notifications from oldest to newest.
 #
 # Configuration variables affecting this script:
 #
@@ -64,7 +64,7 @@
 # down. It is unknown whether this is still an issue in 2010, but
 # XML-RPC would be annoying to do from sh in any case. (XML-RPC does
 # have the advantage that it guarantees notification of multiple commits
-# shpped from an update in their actual order.)
+# shipped from an update in their actual order.)
 #
 
 # The project as known to CIA. You can set this with a -p option,
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index b97162f..e1b7313 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -33,8 +33,6 @@
 # returns location of .git repo
 __gitdir ()
 {
-	# Note: this function is duplicated in git-prompt.sh
-	# When updating it, make sure you update the other one to match.
 	if [ -z "${1-}" ]; then
 		if [ -n "${__git_dir-}" ]; then
 			echo "$__git_dir"
@@ -252,106 +250,50 @@
 	# since tilde expansion is not applied.
 	# This means that COMPREPLY will be empty and Bash default
 	# completion will be used.
-	COMPREPLY=($(compgen -P "${2-}" -W "$1" -- "${3-$cur}"))
+	__gitcompadd "$1" "${2-}" "${3-$cur}" ""
 
-	# Tell Bash that compspec generates filenames.
-	compopt -o filenames 2>/dev/null
+	# use a hack to enable file mode in bash < 4
+	compopt -o filenames +o nospace 2>/dev/null ||
+	compgen -f /non-existing-dir/ > /dev/null
 }
 
-__git_index_file_list_filter_compat ()
-{
-	local path
-
-	while read -r path; do
-		case "$path" in
-		?*/*) echo "${path%%/*}/" ;;
-		*) echo "$path" ;;
-		esac
-	done
-}
-
-__git_index_file_list_filter_bash ()
-{
-	local path
-
-	while read -r path; do
-		case "$path" in
-		?*/*)
-			# XXX if we append a slash to directory names when using
-			# `compopt -o filenames`, Bash will append another slash.
-			# This is pretty stupid, and this the reason why we have to
-			# define a compatible version for this function.
-			echo "${path%%/*}" ;;
-		*)
-			echo "$path" ;;
-		esac
-	done
-}
-
-# Process path list returned by "ls-files" and "diff-index --name-only"
-# commands, in order to list only file names relative to a specified
-# directory, and append a slash to directory names.
-__git_index_file_list_filter ()
-{
-	# Default to Bash >= 4.x
-	__git_index_file_list_filter_bash
-}
-
-# Execute git ls-files, returning paths relative to the directory
-# specified in the first argument, and using the options specified in
-# the second argument.
+# Execute 'git ls-files', unless the --committable option is specified, in
+# which case it runs 'git diff-index' to find out the files that can be
+# committed.  It return paths relative to the directory specified in the first
+# argument, and using the options specified in the second argument.
 __git_ls_files_helper ()
 {
 	(
 		test -n "${CDPATH+set}" && unset CDPATH
-		# NOTE: $2 is not quoted in order to support multiple options
-		cd "$1" && git ls-files --exclude-standard $2
+		cd "$1"
+		if [ "$2" == "--committable" ]; then
+			git diff-index --name-only --relative HEAD
+		else
+			# NOTE: $2 is not quoted in order to support multiple options
+			git ls-files --exclude-standard $2
+		fi
 	) 2>/dev/null
 }
 
 
-# Execute git diff-index, returning paths relative to the directory
-# specified in the first argument, and using the tree object id
-# specified in the second argument.
-__git_diff_index_helper ()
-{
-	(
-		test -n "${CDPATH+set}" && unset CDPATH
-		cd "$1" && git diff-index --name-only --relative "$2"
-	) 2>/dev/null
-}
-
 # __git_index_files accepts 1 or 2 arguments:
 # 1: Options to pass to ls-files (required).
-#    Supported options are --cached, --modified, --deleted, --others,
-#    and --directory.
 # 2: A directory path (optional).
 #    If provided, only files within the specified directory are listed.
 #    Sub directories are never recursed.  Path must have a trailing
 #    slash.
 __git_index_files ()
 {
-	local dir="$(__gitdir)" root="${2-.}"
+	local dir="$(__gitdir)" root="${2-.}" file
 
 	if [ -d "$dir" ]; then
-		__git_ls_files_helper "$root" "$1" | __git_index_file_list_filter |
-			sort | uniq
-	fi
-}
-
-# __git_diff_index_files accepts 1 or 2 arguments:
-# 1) The id of a tree object.
-# 2) A directory path (optional).
-#    If provided, only files within the specified directory are listed.
-#    Sub directories are never recursed.  Path must have a trailing
-#    slash.
-__git_diff_index_files ()
-{
-	local dir="$(__gitdir)" root="${2-.}"
-
-	if [ -d "$dir" ]; then
-		__git_diff_index_helper "$root" "$1" | __git_index_file_list_filter |
-			sort | uniq
+		__git_ls_files_helper "$root" "$1" |
+		while read -r file; do
+			case "$file" in
+			?*/*) echo "${file%%/*}" ;;
+			*) echo "$file" ;;
+			esac
+		done | sort | uniq
 	fi
 }
 
@@ -427,14 +369,8 @@
 		done
 		;;
 	*)
-		git ls-remote "$dir" HEAD ORIG_HEAD 'refs/tags/*' 'refs/heads/*' 'refs/remotes/*' 2>/dev/null | \
-		while read -r hash i; do
-			case "$i" in
-			*^{}) ;;
-			refs/*) echo "${i#refs/*/}" ;;
-			*) echo "$i" ;;
-			esac
-		done
+		echo "HEAD"
+		git for-each-ref --format="%(refname:short)" -- "refs/remotes/$dir/" | sed -e "s#^$dir/##"
 		;;
 	esac
 }
@@ -552,44 +488,23 @@
 }
 
 
-# __git_complete_index_file requires 1 argument: the options to pass to
-# ls-file
+# __git_complete_index_file requires 1 argument:
+# 1: the options to pass to ls-file
+#
+# The exception is --committable, which finds the files appropriate commit.
 __git_complete_index_file ()
 {
-	local pfx cur_="$cur"
+	local pfx="" cur_="$cur"
 
 	case "$cur_" in
 	?*/*)
 		pfx="${cur_%/*}"
 		cur_="${cur_##*/}"
 		pfx="${pfx}/"
-
-		__gitcomp_file "$(__git_index_files "$1" "$pfx")" "$pfx" "$cur_"
-		;;
-	*)
-		__gitcomp_file "$(__git_index_files "$1")" "" "$cur_"
 		;;
 	esac
-}
 
-# __git_complete_diff_index_file requires 1 argument: the id of a tree
-# object
-__git_complete_diff_index_file ()
-{
-	local pfx cur_="$cur"
-
-	case "$cur_" in
-	?*/*)
-		pfx="${cur_%/*}"
-		cur_="${cur_##*/}"
-		pfx="${pfx}/"
-
-		__gitcomp_file "$(__git_diff_index_files "$1" "$pfx")" "$pfx" "$cur_"
-		;;
-	*)
-		__gitcomp_file "$(__git_diff_index_files "$1")" "" "$cur_"
-		;;
-	esac
+	__gitcomp_file "$(__git_index_files "$1" "$pfx")" "$pfx" "$cur_"
 }
 
 __git_complete_file ()
@@ -733,6 +648,7 @@
 		cat-file)         : plumbing;;
 		check-attr)       : plumbing;;
 		check-ignore)     : plumbing;;
+		check-mailmap)    : plumbing;;
 		check-ref-format) : plumbing;;
 		checkout-index)   : plumbing;;
 		commit-tree)      : plumbing;;
@@ -1213,7 +1129,7 @@
 	esac
 
 	if git rev-parse --verify --quiet HEAD >/dev/null; then
-		__git_complete_diff_index_file "HEAD"
+		__git_complete_index_file "--committable"
 	else
 		# This is the first commit
 		__git_complete_index_file "--cached"
@@ -1246,7 +1162,7 @@
 			--no-prefix --src-prefix= --dst-prefix=
 			--inter-hunk-context=
 			--patience --histogram --minimal
-			--raw
+			--raw --word-diff
 			--dirstat --dirstat= --dirstat-by-file
 			--dirstat-by-file= --cumulative
 			--diff-algorithm=
@@ -1294,7 +1210,7 @@
 		return
 		;;
 	esac
-	__git_complete_file
+	__git_complete_revlist_file
 }
 
 __git_fetch_options="
@@ -1831,7 +1747,7 @@
 		local remote="${prev#remote.}"
 		remote="${remote%.fetch}"
 		if [ -z "$cur" ]; then
-			__gitcompadd "refs/heads/" "" "" ""
+			__gitcomp_nl "refs/heads/" "" "" ""
 			return
 		fi
 		__gitcomp_nl "$(__git_refs_remotes "$remote")"
@@ -2042,7 +1958,6 @@
 		core.fileMode
 		core.fsyncobjectfiles
 		core.gitProxy
-		core.ignoreCygwinFSTricks
 		core.ignoreStat
 		core.ignorecase
 		core.logAllRefUpdates
@@ -2360,7 +2275,7 @@
 		return
 		;;
 	esac
-	__git_complete_file
+	__git_complete_revlist_file
 }
 
 _git_show_branch ()
@@ -2451,7 +2366,7 @@
 			--no-metadata --use-svm-props --use-svnsync-props
 			--log-window-size= --no-checkout --quiet
 			--repack-flags --use-log-author --localtime
-			--ignore-paths= $remote_opts
+			--ignore-paths= --include-paths= $remote_opts
 			"
 		local init_opts="
 			--template= --shared= --trunk= --tags=
@@ -2575,9 +2490,10 @@
 		i="${words[c]}"
 		case "$i" in
 		--git-dir=*) __git_dir="${i#--git-dir=}" ;;
+		--git-dir)   ((c++)) ; __git_dir="${words[c]}" ;;
 		--bare)      __git_dir="." ;;
 		--help) command="help"; break ;;
-		-c) c=$((++c)) ;;
+		-c|--work-tree|--namespace) ((c++)) ;;
 		-*) ;;
 		*) command="$i"; break ;;
 		esac
@@ -2595,6 +2511,7 @@
 			--exec-path
 			--exec-path=
 			--html-path
+			--man-path
 			--info-path
 			--work-tree=
 			--namespace=
@@ -2663,7 +2580,7 @@
 				--*=*|*.) ;;
 				*) c="$c " ;;
 				esac
-				array[$#array+1]="$c"
+				array[${#array[@]}+1]="$c"
 			done
 			compset -P '*[=:]'
 			compadd -Q -S '' -p "${2-}" -a -- array && _ret=0
@@ -2689,35 +2606,19 @@
 		compadd -Q -p "${2-}" -f -- ${=1} && _ret=0
 	}
 
-	__git_zsh_helper ()
-	{
-		emulate -L ksh
-		local cur cword prev
-		cur=${words[CURRENT-1]}
-		prev=${words[CURRENT-2]}
-		let cword=CURRENT-1
-		__${service}_main
-	}
-
 	_git ()
 	{
-		emulate -L zsh
-		local _ret=1
-		__git_zsh_helper
-		let _ret && _default -S '' && _ret=0
+		local _ret=1 cur cword prev
+		cur=${words[CURRENT]}
+		prev=${words[CURRENT-1]}
+		let cword=CURRENT-1
+		emulate ksh -c __${service}_main
+		let _ret && _default && _ret=0
 		return _ret
 	}
 
 	compdef _git git gitk
 	return
-elif [[ -n ${BASH_VERSION-} ]]; then
-	if ((${BASH_VERSINFO[0]} < 4)); then
-		# compopt is not supported
-		__git_index_file_list_filter ()
-		{
-			__git_index_file_list_filter_compat
-		}
-	fi
 fi
 
 __git_func_wrap ()
diff --git a/contrib/completion/git-completion.zsh b/contrib/completion/git-completion.zsh
index 2565d2e..fac5e71 100644
--- a/contrib/completion/git-completion.zsh
+++ b/contrib/completion/git-completion.zsh
@@ -4,18 +4,17 @@
 #
 # Copyright (c) 2012-2013 Felipe Contreras <felipe.contreras@gmail.com>
 #
-# You need git's bash completion script installed somewhere, by default on the
-# same directory as this script.
+# You need git's bash completion script installed somewhere, by default it
+# would be the location bash-completion uses.
 #
-# If your script is on ~/.git-completion.sh instead, you can configure it on
-# your ~/.zshrc:
+# If your script is somewhere else, you can configure it on your ~/.zshrc:
 #
 #  zstyle ':completion:*:*:git:*' script ~/.git-completion.sh
 #
-# The recommended way to install this script is to copy to
-# '~/.zsh/completion/_git', and then add the following to your ~/.zshrc file:
+# The recommended way to install this script is to copy to '~/.zsh/_git', and
+# then add the following to your ~/.zshrc file:
 #
-#  fpath=(~/.zsh/completion $fpath)
+#  fpath=(~/.zsh $fpath)
 
 complete ()
 {
@@ -27,7 +26,19 @@
 	zstyle ':completion:*:*:git:*' tag-order 'common-commands'
 
 zstyle -s ":completion:*:*:git:*" script script
-test -z "$script" && script="$(dirname ${funcsourcetrace[1]%:*})"/git-completion.bash
+if [ -z "$script" ]; then
+	local -a locations
+	local e
+	locations=(
+		'/etc/bash_completion.d/git' # fedora, old debian
+		'/usr/share/bash-completion/completions/git' # arch, ubuntu, new debian
+		'/usr/share/bash-completion/git' # gentoo
+		$(dirname ${funcsourcetrace[1]%:*})/git-completion.bash
+		)
+	for e in $locations; do
+		test -f $e && script="$e" && break
+	done
+fi
 ZSH_VERSION='' . "$script"
 
 __gitcomp ()
diff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh
index eaf5c36..d6c61b2 100644
--- a/contrib/completion/git-prompt.sh
+++ b/contrib/completion/git-prompt.sh
@@ -3,7 +3,7 @@
 # Copyright (C) 2006,2007 Shawn O. Pearce <spearce@spearce.org>
 # Distributed under the GNU General Public License, version 2.0.
 #
-# This script allows you to see the current branch in your prompt.
+# This script allows you to see repository status in your prompt.
 #
 # To enable:
 #
@@ -13,23 +13,27 @@
 #    3a) Change your PS1 to call __git_ps1 as
 #        command-substitution:
 #        Bash: PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ '
-#        ZSH:  PS1='[%n@%m %c$(__git_ps1 " (%s)")]\$ '
+#        ZSH:  setopt PROMPT_SUBST ; PS1='[%n@%m %c$(__git_ps1 " (%s)")]\$ '
 #        the optional argument will be used as format string.
-#    3b) Alternatively, if you are using bash, __git_ps1 can be
-#        used for PROMPT_COMMAND with two parameters, <pre> and
-#        <post>, which are strings you would put in $PS1 before
-#        and after the status string generated by the git-prompt
-#        machinery.  e.g.
-#           PROMPT_COMMAND='__git_ps1 "\u@\h:\w" "\\\$ "'
-#        will show username, at-sign, host, colon, cwd, then
-#        various status string, followed by dollar and SP, as
-#        your prompt.
+#    3b) Alternatively, for a slightly faster prompt, __git_ps1 can
+#        be used for PROMPT_COMMAND in Bash or for precmd() in Zsh
+#        with two parameters, <pre> and <post>, which are strings
+#        you would put in $PS1 before and after the status string
+#        generated by the git-prompt machinery.  e.g.
+#        Bash: PROMPT_COMMAND='__git_ps1 "\u@\h:\w" "\\\$ "'
+#          will show username, at-sign, host, colon, cwd, then
+#          various status string, followed by dollar and SP, as
+#          your prompt.
+#        ZSH:  precmd () { __git_ps1 "%n" ":%~$ " "|%s" }
+#          will show username, pipe, then various status string,
+#          followed by colon, cwd, dollar and SP, as your prompt.
 #        Optionally, you can supply a third argument with a printf
 #        format string to finetune the output of the branch status
 #
-# The argument to __git_ps1 will be displayed only if you are currently
-# in a git repository.  The %s token will be the name of the current
-# branch.
+# The repository status will be displayed only if you are currently in a
+# git repository. The %s token is the placeholder for the shown status.
+#
+# The prompt status always includes the current branch name.
 #
 # In addition, if you set GIT_PS1_SHOWDIRTYSTATE to a nonempty value,
 # unstaged (*) and staged (+) changes will be shown next to the branch
@@ -77,31 +81,12 @@
 #
 # If you would like a colored hint about the current dirty state, set
 # GIT_PS1_SHOWCOLORHINTS to a nonempty value. The colors are based on
-# the colored output of "git status -sb".
+# the colored output of "git status -sb" and are available only when
+# using __git_ps1 for PROMPT_COMMAND or precmd.
 
-# __gitdir accepts 0 or 1 arguments (i.e., location)
-# returns location of .git repo
-__gitdir ()
-{
-	# Note: this function is duplicated in git-completion.bash
-	# When updating it, make sure you update the other one to match.
-	if [ -z "${1-}" ]; then
-		if [ -n "${__git_dir-}" ]; then
-			echo "$__git_dir"
-		elif [ -n "${GIT_DIR-}" ]; then
-			test -d "${GIT_DIR-}" || return 1
-			echo "$GIT_DIR"
-		elif [ -d .git ]; then
-			echo .git
-		else
-			git rev-parse --git-dir 2>/dev/null
-		fi
-	elif [ -d "$1/.git" ]; then
-		echo "$1/.git"
-	else
-		echo "$1"
-	fi
-}
+# check whether printf supports -v
+__git_printf_supports_v=
+printf -v __git_printf_supports_v -- '%s' yes >/dev/null 2>&1
 
 # stores the divergence from upstream in $p
 # used by GIT_PS1_SHOWUPSTREAM
@@ -124,7 +109,7 @@
 			fi
 			;;
 		svn-remote.*.url)
-			svn_remote[ $((${#svn_remote[@]} + 1)) ]="$value"
+			svn_remote[$((${#svn_remote[@]} + 1))]="$value"
 			svn_url_pattern+="\\|$value"
 			upstream=svn+git # default upstream is SVN if available, else git
 			;;
@@ -146,10 +131,11 @@
 	svn*)
 		# get the upstream from the "git-svn-id: ..." in a commit message
 		# (git-svn uses essentially the same procedure internally)
-		local svn_upstream=($(git log --first-parent -1 \
+		local -a svn_upstream
+		svn_upstream=($(git log --first-parent -1 \
 					--grep="^git-svn-id: \(${svn_url_pattern#??}\)" 2>/dev/null))
 		if [[ 0 -ne ${#svn_upstream[@]} ]]; then
-			svn_upstream=${svn_upstream[ ${#svn_upstream[@]} - 2 ]}
+			svn_upstream=${svn_upstream[${#svn_upstream[@]} - 2]}
 			svn_upstream=${svn_upstream%@*}
 			local n_stop="${#svn_remote[@]}"
 			for ((n=1; n <= n_stop; n++)); do
@@ -222,6 +208,51 @@
 
 }
 
+# Helper function that is meant to be called from __git_ps1.  It
+# injects color codes into the appropriate gitstring variables used
+# to build a gitstring.
+__git_ps1_colorize_gitstring ()
+{
+	if [[ -n ${ZSH_VERSION-} ]]; then
+		local c_red='%F{red}'
+		local c_green='%F{green}'
+		local c_lblue='%F{blue}'
+		local c_clear='%f'
+	else
+		# Using \[ and \] around colors is necessary to prevent
+		# issues with command line editing/browsing/completion!
+		local c_red='\[\e[31m\]'
+		local c_green='\[\e[32m\]'
+		local c_lblue='\[\e[1;34m\]'
+		local c_clear='\[\e[0m\]'
+	fi
+	local bad_color=$c_red
+	local ok_color=$c_green
+	local flags_color="$c_lblue"
+
+	local branch_color=""
+	if [ $detached = no ]; then
+		branch_color="$ok_color"
+	else
+		branch_color="$bad_color"
+	fi
+	c="$branch_color$c"
+
+	z="$c_clear$z"
+	if [ "$w" = "*" ]; then
+		w="$bad_color$w"
+	fi
+	if [ -n "$i" ]; then
+		i="$ok_color$i"
+	fi
+	if [ -n "$s" ]; then
+		s="$flags_color$s"
+	fi
+	if [ -n "$u" ]; then
+		u="$bad_color$u"
+	fi
+	r="$c_clear$r"
+}
 
 # __git_ps1 accepts 0 or 1 arguments (i.e., format string)
 # when called from PS1 using command substitution
@@ -254,48 +285,83 @@
 		;;
 	esac
 
-	local g="$(__gitdir)"
-	if [ -z "$g" ]; then
+	local repo_info rev_parse_exit_code
+	repo_info="$(git rev-parse --git-dir --is-inside-git-dir \
+		--is-bare-repository --is-inside-work-tree \
+		--short HEAD 2>/dev/null)"
+	rev_parse_exit_code="$?"
+
+	if [ -z "$repo_info" ]; then
 		if [ $pcmode = yes ]; then
 			#In PC mode PS1 always needs to be set
 			PS1="$ps1pc_start$ps1pc_end"
 		fi
-	else
-		local r=""
-		local b=""
-		local step=""
-		local total=""
-		if [ -d "$g/rebase-merge" ]; then
-			b="$(cat "$g/rebase-merge/head-name")"
-			step=$(cat "$g/rebase-merge/msgnum")
-			total=$(cat "$g/rebase-merge/end")
-			if [ -f "$g/rebase-merge/interactive" ]; then
-				r="|REBASE-i"
-			else
-				r="|REBASE-m"
-			fi
-		else
-			if [ -d "$g/rebase-apply" ]; then
-				step=$(cat "$g/rebase-apply/next")
-				total=$(cat "$g/rebase-apply/last")
-				if [ -f "$g/rebase-apply/rebasing" ]; then
-					r="|REBASE"
-				elif [ -f "$g/rebase-apply/applying" ]; then
-					r="|AM"
-				else
-					r="|AM/REBASE"
-				fi
-			elif [ -f "$g/MERGE_HEAD" ]; then
-				r="|MERGING"
-			elif [ -f "$g/CHERRY_PICK_HEAD" ]; then
-				r="|CHERRY-PICKING"
-			elif [ -f "$g/REVERT_HEAD" ]; then
-				r="|REVERTING"
-			elif [ -f "$g/BISECT_LOG" ]; then
-				r="|BISECTING"
-			fi
+		return
+	fi
 
-			b="$(git symbolic-ref HEAD 2>/dev/null)" || {
+	local short_sha
+	if [ "$rev_parse_exit_code" = "0" ]; then
+		short_sha="${repo_info##*$'\n'}"
+		repo_info="${repo_info%$'\n'*}"
+	fi
+	local inside_worktree="${repo_info##*$'\n'}"
+	repo_info="${repo_info%$'\n'*}"
+	local bare_repo="${repo_info##*$'\n'}"
+	repo_info="${repo_info%$'\n'*}"
+	local inside_gitdir="${repo_info##*$'\n'}"
+	local g="${repo_info%$'\n'*}"
+
+	local r=""
+	local b=""
+	local step=""
+	local total=""
+	if [ -d "$g/rebase-merge" ]; then
+		read b 2>/dev/null <"$g/rebase-merge/head-name"
+		read step 2>/dev/null <"$g/rebase-merge/msgnum"
+		read total 2>/dev/null <"$g/rebase-merge/end"
+		if [ -f "$g/rebase-merge/interactive" ]; then
+			r="|REBASE-i"
+		else
+			r="|REBASE-m"
+		fi
+	else
+		if [ -d "$g/rebase-apply" ]; then
+			read step 2>/dev/null <"$g/rebase-apply/next"
+			read total 2>/dev/null <"$g/rebase-apply/last"
+			if [ -f "$g/rebase-apply/rebasing" ]; then
+				read b 2>/dev/null <"$g/rebase-apply/head-name"
+				r="|REBASE"
+			elif [ -f "$g/rebase-apply/applying" ]; then
+				r="|AM"
+			else
+				r="|AM/REBASE"
+			fi
+		elif [ -f "$g/MERGE_HEAD" ]; then
+			r="|MERGING"
+		elif [ -f "$g/CHERRY_PICK_HEAD" ]; then
+			r="|CHERRY-PICKING"
+		elif [ -f "$g/REVERT_HEAD" ]; then
+			r="|REVERTING"
+		elif [ -f "$g/BISECT_LOG" ]; then
+			r="|BISECTING"
+		fi
+
+		if [ -n "$b" ]; then
+			:
+		elif [ -h "$g/HEAD" ]; then
+			# symlink symbolic ref
+			b="$(git symbolic-ref HEAD 2>/dev/null)"
+		else
+			local head=""
+			if ! read head 2>/dev/null <"$g/HEAD"; then
+				if [ $pcmode = yes ]; then
+					PS1="$ps1pc_start$ps1pc_end"
+				fi
+				return
+			fi
+			# is it a symbolic ref?
+			b="${head#ref: }"
+			if [ "$head" = "$b" ]; then
 				detached=yes
 				b="$(
 				case "${GIT_PS1_DESCRIBE_STYLE-}" in
@@ -309,104 +375,75 @@
 					git describe --tags --exact-match HEAD ;;
 				esac 2>/dev/null)" ||
 
-				b="$(cut -c1-7 "$g/HEAD" 2>/dev/null)..." ||
-				b="unknown"
+				b="$short_sha..."
 				b="($b)"
-			}
-		fi
-
-		if [ -n "$step" ] && [ -n "$total" ]; then
-			r="$r $step/$total"
-		fi
-
-		local w=""
-		local i=""
-		local s=""
-		local u=""
-		local c=""
-		local p=""
-
-		if [ "true" = "$(git rev-parse --is-inside-git-dir 2>/dev/null)" ]; then
-			if [ "true" = "$(git rev-parse --is-bare-repository 2>/dev/null)" ]; then
-				c="BARE:"
-			else
-				b="GIT_DIR!"
-			fi
-		elif [ "true" = "$(git rev-parse --is-inside-work-tree 2>/dev/null)" ]; then
-			if [ -n "${GIT_PS1_SHOWDIRTYSTATE-}" ] &&
-			   [ "$(git config --bool bash.showDirtyState)" != "false" ]
-			then
-				git diff --no-ext-diff --quiet --exit-code || w="*"
-				if git rev-parse --quiet --verify HEAD >/dev/null; then
-					git diff-index --cached --quiet HEAD -- || i="+"
-				else
-					i="#"
-				fi
-			fi
-			if [ -n "${GIT_PS1_SHOWSTASHSTATE-}" ]; then
-				git rev-parse --verify refs/stash >/dev/null 2>&1 && s="$"
-			fi
-
-			if [ -n "${GIT_PS1_SHOWUNTRACKEDFILES-}" ] &&
-			   [ "$(git config --bool bash.showUntrackedFiles)" != "false" ] &&
-			   [ -n "$(git ls-files --others --exclude-standard)" ]
-			then
-				u="%${ZSH_VERSION+%}"
-			fi
-
-			if [ -n "${GIT_PS1_SHOWUPSTREAM-}" ]; then
-				__git_ps1_show_upstream
 			fi
 		fi
+	fi
 
-		local f="$w$i$s$u"
-		if [ $pcmode = yes ]; then
-			local gitstring=
-			if [ -n "${GIT_PS1_SHOWCOLORHINTS-}" ]; then
-				local c_red='\e[31m'
-				local c_green='\e[32m'
-				local c_lblue='\e[1;34m'
-				local c_clear='\e[0m'
-				local bad_color=$c_red
-				local ok_color=$c_green
-				local branch_color="$c_clear"
-				local flags_color="$c_lblue"
-				local branchstring="$c${b##refs/heads/}"
+	if [ -n "$step" ] && [ -n "$total" ]; then
+		r="$r $step/$total"
+	fi
 
-				if [ $detached = no ]; then
-					branch_color="$ok_color"
-				else
-					branch_color="$bad_color"
-				fi
+	local w=""
+	local i=""
+	local s=""
+	local u=""
+	local c=""
+	local p=""
 
-				# Setting gitstring directly with \[ and \] around colors
-				# is necessary to prevent wrapping issues!
-				gitstring="\[$branch_color\]$branchstring\[$c_clear\]"
-
-				if [ -n "$w$i$s$u$r$p" ]; then
-					gitstring="$gitstring "
-				fi
-				if [ "$w" = "*" ]; then
-					gitstring="$gitstring\[$bad_color\]$w"
-				fi
-				if [ -n "$i" ]; then
-					gitstring="$gitstring\[$ok_color\]$i"
-				fi
-				if [ -n "$s" ]; then
-					gitstring="$gitstring\[$flags_color\]$s"
-				fi
-				if [ -n "$u" ]; then
-					gitstring="$gitstring\[$bad_color\]$u"
-				fi
-				gitstring="$gitstring\[$c_clear\]$r$p"
-			else
-				gitstring="$c${b##refs/heads/}${f:+ $f}$r$p"
-			fi
-			gitstring=$(printf -- "$printf_format" "$gitstring")
-			PS1="$ps1pc_start$gitstring$ps1pc_end"
+	if [ "true" = "$inside_gitdir" ]; then
+		if [ "true" = "$bare_repo" ]; then
+			c="BARE:"
 		else
-			# NO color option unless in PROMPT_COMMAND mode
-			printf -- "$printf_format" "$c${b##refs/heads/}${f:+ $f}$r$p"
+			b="GIT_DIR!"
 		fi
+	elif [ "true" = "$inside_worktree" ]; then
+		if [ -n "${GIT_PS1_SHOWDIRTYSTATE-}" ] &&
+		   [ "$(git config --bool bash.showDirtyState)" != "false" ]
+		then
+			git diff --no-ext-diff --quiet --exit-code || w="*"
+			if [ -n "$short_sha" ]; then
+				git diff-index --cached --quiet HEAD -- || i="+"
+			else
+				i="#"
+			fi
+		fi
+		if [ -n "${GIT_PS1_SHOWSTASHSTATE-}" ] &&
+		   [ -r "$g/refs/stash" ]; then
+			s="$"
+		fi
+
+		if [ -n "${GIT_PS1_SHOWUNTRACKEDFILES-}" ] &&
+		   [ "$(git config --bool bash.showUntrackedFiles)" != "false" ] &&
+		   git ls-files --others --exclude-standard --error-unmatch -- '*' >/dev/null 2>/dev/null
+		then
+			u="%${ZSH_VERSION+%}"
+		fi
+
+		if [ -n "${GIT_PS1_SHOWUPSTREAM-}" ]; then
+			__git_ps1_show_upstream
+		fi
+	fi
+
+	local z="${GIT_PS1_STATESEPARATOR-" "}"
+
+	# NO color option unless in PROMPT_COMMAND mode
+	if [ $pcmode = yes ] && [ -n "${GIT_PS1_SHOWCOLORHINTS-}" ]; then
+		__git_ps1_colorize_gitstring
+	fi
+
+	local f="$w$i$s$u"
+	local gitstring="$c${b##refs/heads/}${f:+$z$f}$r$p"
+
+	if [ $pcmode = yes ]; then
+		if [ "${__git_printf_supports_v-}" != yes ]; then
+			gitstring=$(printf -- "$printf_format" "$gitstring")
+		else
+			printf -v gitstring -- "$printf_format" "$gitstring"
+		fi
+		PS1="$ps1pc_start$gitstring$ps1pc_end"
+	else
+		printf -- "$printf_format" "$gitstring"
 	fi
 }
diff --git a/contrib/contacts/git-contacts b/contrib/contacts/git-contacts
new file mode 100755
index 0000000..d80f7d1
--- /dev/null
+++ b/contrib/contacts/git-contacts
@@ -0,0 +1,188 @@
+#!/usr/bin/perl
+
+# List people who might be interested in a patch.  Useful as the argument to
+# git-send-email --cc-cmd option, and in other situations.
+#
+# Usage: git contacts <file | rev-list option> ...
+
+use strict;
+use warnings;
+use IPC::Open2;
+
+my $since = '5-years-ago';
+my $min_percent = 10;
+my $labels_rx = qr/Signed-off-by|Reviewed-by|Acked-by|Cc/i;
+my %seen;
+
+sub format_contact {
+	my ($name, $email) = @_;
+	return "$name <$email>";
+}
+
+sub parse_commit {
+	my ($commit, $data) = @_;
+	my $contacts = $commit->{contacts};
+	my $inbody = 0;
+	for (split(/^/m, $data)) {
+		if (not $inbody) {
+			if (/^author ([^<>]+) <(\S+)> .+$/) {
+				$contacts->{format_contact($1, $2)} = 1;
+			} elsif (/^$/) {
+				$inbody = 1;
+			}
+		} elsif (/^$labels_rx:\s+([^<>]+)\s+<(\S+?)>$/o) {
+			$contacts->{format_contact($1, $2)} = 1;
+		}
+	}
+}
+
+sub import_commits {
+	my ($commits) = @_;
+	return unless %$commits;
+	my $pid = open2 my $reader, my $writer, qw(git cat-file --batch);
+	for my $id (keys(%$commits)) {
+		print $writer "$id\n";
+		my $line = <$reader>;
+		if ($line =~ /^([0-9a-f]{40}) commit (\d+)/) {
+			my ($cid, $len) = ($1, $2);
+			die "expected $id but got $cid\n" unless $id eq $cid;
+			my $data;
+			# cat-file emits newline after data, so read len+1
+			read $reader, $data, $len + 1;
+			parse_commit($commits->{$id}, $data);
+		}
+	}
+	close $reader;
+	close $writer;
+	waitpid($pid, 0);
+	die "git-cat-file error: $?\n" if $?;
+}
+
+sub get_blame {
+	my ($commits, $source, $start, $len, $from) = @_;
+	$len = 1 unless defined($len);
+	return if $len == 0;
+	open my $f, '-|',
+		qw(git blame --porcelain -C), '-L', "$start,+$len",
+		'--since', $since, "$from^", '--', $source or die;
+	while (<$f>) {
+		if (/^([0-9a-f]{40}) \d+ \d+ \d+$/) {
+			my $id = $1;
+			$commits->{$id} = { id => $id, contacts => {} }
+				unless $seen{$id};
+			$seen{$id} = 1;
+		}
+	}
+	close $f;
+}
+
+sub scan_patches {
+	my ($commits, $id, $f) = @_;
+	my $source;
+	while (<$f>) {
+		if (/^From ([0-9a-f]{40}) Mon Sep 17 00:00:00 2001$/) {
+			$id = $1;
+			$seen{$id} = 1;
+		}
+		next unless $id;
+		if (m{^--- (?:a/(.+)|/dev/null)$}) {
+			$source = $1;
+		} elsif (/^--- /) {
+			die "Cannot parse hunk source: $_\n";
+		} elsif (/^@@ -(\d+)(?:,(\d+))?/ && $source) {
+			get_blame($commits, $source, $1, $2, $id);
+		}
+	}
+}
+
+sub scan_patch_file {
+	my ($commits, $file) = @_;
+	open my $f, '<', $file or die "read failure: $file: $!\n";
+	scan_patches($commits, undef, $f);
+	close $f;
+}
+
+sub parse_rev_args {
+	my @args = @_;
+	open my $f, '-|',
+		qw(git rev-parse --revs-only --default HEAD --symbolic), @args
+		or die;
+	my @revs;
+	while (<$f>) {
+		chomp;
+		push @revs, $_;
+	}
+	close $f;
+	return @revs if scalar(@revs) != 1;
+	return "^$revs[0]", 'HEAD' unless $revs[0] =~ /^-/;
+	return $revs[0], 'HEAD';
+}
+
+sub scan_rev_args {
+	my ($commits, $args) = @_;
+	my @revs = parse_rev_args(@$args);
+	open my $f, '-|', qw(git rev-list --reverse), @revs or die;
+	while (<$f>) {
+		chomp;
+		my $id = $_;
+		$seen{$id} = 1;
+		open my $g, '-|', qw(git show -C --oneline), $id or die;
+		scan_patches($commits, $id, $g);
+		close $g;
+	}
+	close $f;
+}
+
+sub mailmap_contacts {
+	my ($contacts) = @_;
+	my %mapped;
+	my $pid = open2 my $reader, my $writer, qw(git check-mailmap --stdin);
+	for my $contact (keys(%$contacts)) {
+		print $writer "$contact\n";
+		my $canonical = <$reader>;
+		chomp $canonical;
+		$mapped{$canonical} += $contacts->{$contact};
+	}
+	close $reader;
+	close $writer;
+	waitpid($pid, 0);
+	die "git-check-mailmap error: $?\n" if $?;
+	return \%mapped;
+}
+
+if (!@ARGV) {
+	die "No input revisions or patch files\n";
+}
+
+my (@files, @rev_args);
+for (@ARGV) {
+	if (-e) {
+		push @files, $_;
+	} else {
+		push @rev_args, $_;
+	}
+}
+
+my %commits;
+for (@files) {
+	scan_patch_file(\%commits, $_);
+}
+if (@rev_args) {
+	scan_rev_args(\%commits, \@rev_args)
+}
+import_commits(\%commits);
+
+my $contacts = {};
+for my $commit (values %commits) {
+	for my $contact (keys %{$commit->{contacts}}) {
+		$contacts->{$contact}++;
+	}
+}
+$contacts = mailmap_contacts($contacts);
+
+my $ncommits = scalar(keys %commits);
+for my $contact (keys %$contacts) {
+	my $percent = $contacts->{$contact} * 100 / $ncommits;
+	next if $percent < $min_percent;
+	print "$contact\n";
+}
diff --git a/contrib/contacts/git-contacts.txt b/contrib/contacts/git-contacts.txt
new file mode 100644
index 0000000..dd914d1
--- /dev/null
+++ b/contrib/contacts/git-contacts.txt
@@ -0,0 +1,94 @@
+git-contacts(1)
+===============
+
+NAME
+----
+git-contacts - List people who might be interested in a set of changes
+
+
+SYNOPSIS
+--------
+[verse]
+'git contacts' (<patch>|<range>|<rev>)...
+
+
+DESCRIPTION
+-----------
+
+Given a set of changes, specified as patch files or revisions, determine people
+who might be interested in those changes.  This is done by consulting the
+history of each patch or revision hunk to find people mentioned by commits
+which touched the lines of files under consideration.
+
+Input consists of one or more patch files or revision arguments.  A revision
+argument can be a range or a single `<rev>` which is interpreted as
+`<rev>..HEAD`, thus the same revision arguments are accepted as for
+linkgit:git-format-patch[1]. Patch files and revision arguments can be combined
+in the same invocation.
+
+This command can be useful for determining the list of people with whom to
+discuss proposed changes, or for finding the list of recipients to Cc: when
+submitting a patch series via `git send-email`. For the latter case, `git
+contacts` can be used as the argument to `git send-email`'s `--cc-cmd` option.
+
+
+DISCUSSION
+----------
+
+`git blame` is invoked for each hunk in a patch file or revision.  For each
+commit mentioned by `git blame`, the commit message is consulted for people who
+authored, reviewed, signed, acknowledged, or were Cc:'d.  Once the list of
+participants is known, each person's relevance is computed by considering how
+many commits mentioned that person compared with the total number of commits
+under consideration.  The final output consists only of participants who exceed
+a minimum threshold of participation.
+
+
+OUTPUT
+------
+
+For each person of interest, a single line is output, terminated by a newline.
+If the person's name is known, ``Name $$<user@host>$$'' is printed; otherwise
+only ``$$<user@host>$$'' is printed.
+
+
+EXAMPLES
+--------
+
+* Consult patch files:
++
+------------
+$ git contacts feature/*.patch
+------------
+
+* Revision range:
++
+------------
+$ git contacts R1..R2
+------------
+
+* From a single revision to `HEAD`:
++
+------------
+$ git contacts origin
+------------
+
+* Helper for `git send-email`:
++
+------------
+$ git send-email --cc-cmd='git contacts' feature/*.patch
+------------
+
+
+LIMITATIONS
+-----------
+
+Several conditions controlling a person's significance are currently
+hard-coded, such as minimum participation level (10%), blame date-limiting (5
+years), and `-C` level for detecting moved and copied lines (a single `-C`). In
+the future, these conditions may become configurable.
+
+
+GIT
+---
+Part of the linkgit:git[1] suite
diff --git a/contrib/continuous/cidaemon b/contrib/continuous/cidaemon
deleted file mode 100644
index 4009a15..0000000
--- a/contrib/continuous/cidaemon
+++ /dev/null
@@ -1,503 +0,0 @@
-#!/usr/bin/perl
-#
-# A daemon that waits for update events sent by its companion
-# post-receive-cinotify hook, checks out a new copy of source,
-# compiles it, and emails the guilty parties if the compile
-# (and optionally test suite) fails.
-#
-# To use this daemon, configure it and run it.  It will disconnect
-# from your terminal and fork into the background.  The daemon must
-# have local filesystem access to the source repositories, as it
-# uses objects/info/alternates to avoid copying objects.
-#
-# Add its companion post-receive-cinotify hook as the post-receive
-# hook to each repository that the daemon should monitor.  Yes, a
-# single daemon can monitor more than one repository.
-#
-# To use multiple daemons on the same system, give them each a
-# unique queue file and tmpdir.
-#
-# Global Config
-# -------------
-# Reads from a Git style configuration file.  This will be
-# ~/.gitconfig by default but can be overridden by setting
-# the GIT_CONFIG_FILE environment variable before starting.
-#
-# cidaemon.smtpHost
-#   Hostname of the SMTP server the daemon will send email
-#   through.  Defaults to 'localhost'.
-#
-# cidaemon.smtpUser
-#   Username to authenticate to the SMTP server as.  This
-#   variable is optional; if it is not supplied then no
-#   authentication will be performed.
-#
-# cidaemon.smtpPassword
-#   Password to authenticate to the SMTP server as.  This
-#   variable is optional.  If not supplied but smtpUser was,
-#   the daemon prompts for the password before forking into
-#   the background.
-#
-# cidaemon.smtpAuth
-#   Type of authentication to perform with the SMTP server.
-#   If set to 'login' and smtpUser was defined, this will
-#   use the AUTH LOGIN command, which is suitable for use
-#   with at least one version of Microsoft Exchange Server.
-#   If not set the daemon will use whatever auth methods
-#   are supported by your version of Net::SMTP.
-#
-# cidaemon.email
-#   Email address that daemon generated emails will be sent
-#   from.  This should be a useful email address within your
-#   organization.  Required.
-#
-# cidaemon.name
-#   Human friendly name that the daemon will send emails as.
-#   Defaults to 'cidaemon'.
-#
-# cidaemon.scanDelay
-#   Number of seconds to sleep between polls of the queue file.
-#   Defaults to 60.
-#
-# cidaemon.recentCache
-#   Number of recent commit SHA-1s per repository to cache and
-#   skip building if they appear again.  This is useful to avoid
-#   rebuilding the same commit multiple times just because it was
-#   pushed into more than one branch.  Defaults to 100.
-#
-# cidaemon.tmpdir
-#   Scratch directory to create the builds within.  The daemon
-#   makes a new subdirectory for each build, then deletes it when
-#   the build has finished.  The pid file is also placed here.
-#   Defaults to '/tmp'.
-#
-# cidaemon.queue
-#   Path to the queue file that the post-receive-cinotify hook
-#   appends events to.  This file is polled by the daemon.  It
-#   must not be on an NFS mount (uses flock).  Required.
-#
-# cidaemon.nocc
-#   Perl regex patterns to match against author and committer
-#   lines.  If a pattern matches, that author or committer will
-#   not be notified of a build failure.
-#
-# Per Repository Config
-# ----------------------
-# Read from the source repository's config file.
-#
-# builder.command
-#   Shell command to execute the build.  This command must
-#   return 0 on "success" and non-zero on failure.  If you
-#   also want to run a test suite, make sure your command
-#   does that too.  Required.
-#
-# builder.queue
-#   Queue file to notify the cidaemon through.  Should match
-#   cidaemon.queue.  If not set the hook will not notify the
-#   cidaemon.
-#
-# builder.skip
-#   Perl regex patterns of refs that should not be sent to
-#   cidaemon.  Updates of these refs will be ignored.
-#
-# builder.newBranchBase
-#   Glob patterns of refs that should be used to form the
-#   'old' revions of a newly created ref.  This should set
-#   to be globs that match your 'mainline' branches.  This
-#   way a build failure of a brand new topic branch does not
-#   attempt to email everyone since the beginning of time;
-#   instead it only emails those authors of commits not in
-#   these 'mainline' branches.
-
-local $ENV{PATH} = join ':', qw(
-	/opt/git/bin
-	/usr/bin
-	/bin
-	);
-
-use strict;
-use warnings;
-use FindBin qw($RealBin);
-use File::Spec;
-use lib File::Spec->catfile($RealBin, '..', 'perl5');
-use Storable qw(retrieve nstore);
-use Fcntl ':flock';
-use POSIX qw(strftime);
-use Getopt::Long qw(:config no_auto_abbrev auto_help);
-
-sub git_config ($;$)
-{
-	my $var = shift;
-	my $required = shift || 0;
-	local *GIT;
-	open GIT, '-|','git','config','--get',$var;
-	my $r = <GIT>;
-	chop $r if $r;
-	close GIT;
-	die "error: $var not set.\n" if ($required && !$r);
-	return $r;
-}
-
-package EXCHANGE_NET_SMTP;
-
-# Microsoft Exchange Server requires an 'AUTH LOGIN'
-# style of authentication.  This is different from
-# the default supported by Net::SMTP so we subclass
-# and override the auth method to support that.
-
-use Net::SMTP;
-use Net::Cmd;
-use MIME::Base64 qw(encode_base64);
-our @ISA = qw(Net::SMTP);
-our $auth_type = ::git_config 'cidaemon.smtpAuth';
-
-sub new
-{
-	my $self = shift;
-	my $type = ref($self) || $self;
-	$type->SUPER::new(@_);
-}
-
-sub auth
-{
-	my $self = shift;
-	return $self->SUPER::auth(@_) unless $auth_type eq 'login';
-
-	my $user = encode_base64 shift, '';
-	my $pass = encode_base64 shift, '';
-	return 0 unless CMD_MORE == $self->command("AUTH LOGIN")->response;
-	return 0 unless CMD_MORE == $self->command($user)->response;
-	CMD_OK == $self->command($pass)->response;
-}
-
-package main;
-
-my ($debug_flag, %recent);
-
-my $ex_host = git_config('cidaemon.smtpHost') || 'localhost';
-my $ex_user = git_config('cidaemon.smtpUser');
-my $ex_pass = git_config('cidaemon.smtpPassword');
-
-my $ex_from_addr = git_config('cidaemon.email', 1);
-my $ex_from_name = git_config('cidaemon.name') || 'cidaemon';
-
-my $scan_delay = git_config('cidaemon.scanDelay') || 60;
-my $recent_size = git_config('cidaemon.recentCache') || 100;
-my $tmpdir = git_config('cidaemon.tmpdir') || '/tmp';
-my $queue_name = git_config('cidaemon.queue', 1);
-my $queue_lock = "$queue_name.lock";
-
-my @nocc_list;
-open GIT,'git config --get-all cidaemon.nocc|';
-while (<GIT>) {
-	chop;
-	push @nocc_list, $_;
-}
-close GIT;
-
-sub nocc_author ($)
-{
-	local $_ = shift;
-	foreach my $pat (@nocc_list) {
-		return 1 if /$pat/;
-	}
-	0;
-}
-
-sub input_echo ($)
-{
-	my $prompt = shift;
-
-	local $| = 1;
-	print $prompt;
-	my $input = <STDIN>;
-	chop $input;
-	return $input;
-}
-
-sub input_noecho ($)
-{
-	my $prompt = shift;
-
-	my $end = sub {system('stty','echo');print "\n";exit};
-	local $SIG{TERM} = $end;
-	local $SIG{INT} = $end;
-	system('stty','-echo');
-
-	local $| = 1;
-	print $prompt;
-	my $input = <STDIN>;
-	system('stty','echo');
-	print "\n";
-	chop $input;
-	return $input;
-}
-
-sub rfc2822_date ()
-{
-	 strftime("%a, %d %b %Y %H:%M:%S %Z", localtime);
-}
-
-sub send_email ($$$)
-{
-	my ($subj, $body, $to) = @_;
-	my $now = rfc2822_date;
-	my $to_str = '';
-	my @rcpt_to;
-	foreach (@$to) {
-		my $s = $_;
-		$s =~ s/^/"/;
-		$s =~ s/(\s+<)/"$1/;
-		$to_str .= ', ' if $to_str;
-		$to_str .= $s;
-		push @rcpt_to, $1 if $s =~ /<(.*)>/;
-	}
-	die "Nobody to send to.\n" unless @rcpt_to;
-	my $msg = <<EOF;
-From: "$ex_from_name" <$ex_from_addr>
-To: $to_str
-Date: $now
-Subject: $subj
-
-$body
-EOF
-
-	my $smtp = EXCHANGE_NET_SMTP->new(Host => $ex_host)
-		or die "Cannot connect to $ex_host: $!\n";
-	if ($ex_user && $ex_pass) {
-		$smtp->auth($ex_user,$ex_pass)
-			or die "$ex_host rejected $ex_user\n";
-	}
-	$smtp->mail($ex_from_addr)
-		or die "$ex_host rejected $ex_from_addr\n";
-	scalar($smtp->recipient(@rcpt_to, { SkipBad => 1 }))
-		or die "$ex_host did not accept any addresses.\n";
-	$smtp->data($msg)
-		or die "$ex_host rejected message data\n";
-	$smtp->quit;
-}
-
-sub pop_queue ()
-{
-	open LOCK, ">$queue_lock" or die "Can't open $queue_lock: $!";
-	flock LOCK, LOCK_EX;
-
-	my $queue = -f $queue_name ? retrieve $queue_name : [];
-	my $ent = shift @$queue;
-	nstore $queue, $queue_name;
-
-	flock LOCK, LOCK_UN;
-	close LOCK;
-	$ent;
-}
-
-sub git_exec (@)
-{
-	system('git',@_) == 0 or die "Cannot git " . join(' ', @_) . "\n";
-}
-
-sub git_val (@)
-{
-	open(C, '-|','git',@_);
-	my $r = <C>;
-	chop $r if $r;
-	close C;
-	$r;
-}
-
-sub do_build ($$)
-{
-	my ($git_dir, $new) = @_;
-
-	my $tmp = File::Spec->catfile($tmpdir, "builder$$");
-	system('rm','-rf',$tmp) == 0 or die "Cannot clear $tmp\n";
-	die "Cannot clear $tmp.\n" if -e $tmp;
-
-	my $result = 1;
-	eval {
-		my $command;
-		{
-			local $ENV{GIT_DIR} = $git_dir;
-			$command = git_val 'config','builder.command';
-		}
-		die "No builder.command for $git_dir.\n" unless $command;
-
-		git_exec 'clone','-n','-l','-s',$git_dir,$tmp;
-		chmod 0700, $tmp or die "Cannot lock $tmp\n";
-		chdir $tmp or die "Cannot enter $tmp\n";
-
-		git_exec 'update-ref','HEAD',$new;
-		git_exec 'read-tree','-m','-u','HEAD','HEAD';
-		system $command;
-		if ($? == -1) {
-			print STDERR "failed to execute '$command': $!\n";
-			$result = 1;
-		} elsif ($? & 127) {
-			my $sig = $? & 127;
-			print STDERR "'$command' died from signal $sig\n";
-			$result = 1;
-		} else {
-			my $r = $? >> 8;
-			print STDERR "'$command' exited with $r\n" if $r;
-			$result = $r;
-		}
-	};
-	if ($@) {
-		$result = 2;
-		print STDERR "$@\n";
-	}
-
-	chdir '/';
-	system('rm','-rf',$tmp);
-	rmdir $tmp;
-	$result;
-}
-
-sub build_failed ($$$$$)
-{
-	my ($git_dir, $ref, $old, $new, $msg) = @_;
-
-	$git_dir =~ m,/([^/]+)$,;
-	my $repo_name = $1;
-	$ref =~ s,^refs/(heads|tags)/,,;
-
-	my %authors;
-	my $shortlog;
-	my $revstr;
-	{
-		local $ENV{GIT_DIR} = $git_dir;
-		my @revs = ($new);
-		push @revs, '--not', @$old if @$old;
-		open LOG,'-|','git','rev-list','--pretty=raw',@revs;
-		while (<LOG>) {
-			if (s/^(author|committer) //) {
-				chomp;
-				s/>.*$/>/;
-				$authors{$_} = 1 unless nocc_author $_;
-			}
-		}
-		close LOG;
-		open LOG,'-|','git','shortlog',@revs;
-		$shortlog .= $_ while <LOG>;
-		close LOG;
-		$revstr = join(' ', @revs);
-	}
-
-	my @to = sort keys %authors;
-	unless (@to) {
-		print STDERR "error: No authors in $revstr\n";
-		return;
-	}
-
-	my $subject = "[$repo_name] $ref : Build Failed";
-	my $body = <<EOF;
-Project: $git_dir
-Branch:  $ref
-Commits: $revstr
-
-$shortlog
-Build Output:
---------------------------------------------------------------
-$msg
-EOF
-	send_email($subject, $body, \@to);
-}
-
-sub run_build ($$$$)
-{
-	my ($git_dir, $ref, $old, $new) = @_;
-
-	if ($debug_flag) {
-		my @revs = ($new);
-		push @revs, '--not', @$old if @$old;
-		print "BUILDING $git_dir\n";
-		print "  BRANCH: $ref\n";
-		print "  COMMITS: ", join(' ', @revs), "\n";
-	}
-
-	local(*R, *W);
-	pipe R, W or die "cannot pipe builder: $!";
-
-	my $builder = fork();
-	if (!defined $builder) {
-		die "cannot fork builder: $!";
-	} elsif (0 == $builder) {
-		close R;
-		close STDIN;open(STDIN, '/dev/null');
-		open(STDOUT, '>&W');
-		open(STDERR, '>&W');
-		exit do_build $git_dir, $new;
-	} else {
-		close W;
-		my $out = '';
-		$out .= $_ while <R>;
-		close R;
-		waitpid $builder, 0;
-		build_failed $git_dir, $ref, $old, $new, $out if $?;
-	}
-
-	print "DONE\n\n" if $debug_flag;
-}
-
-sub daemon_loop ()
-{
-	my $run = 1;
-	my $stop_sub = sub {$run = 0};
-	$SIG{HUP} = $stop_sub;
-	$SIG{INT} = $stop_sub;
-	$SIG{TERM} = $stop_sub;
-
-	mkdir $tmpdir, 0755;
-	my $pidfile = File::Spec->catfile($tmpdir, "cidaemon.pid");
-	open(O, ">$pidfile"); print O "$$\n"; close O;
-
-	while ($run) {
-		my $ent = pop_queue;
-		if ($ent) {
-			my ($git_dir, $ref, $old, $new) = @$ent;
-
-			$ent = $recent{$git_dir};
-			$recent{$git_dir} = $ent = [[], {}] unless $ent;
-			my ($rec_arr, $rec_hash) = @$ent;
-			next if $rec_hash->{$new}++;
-			while (@$rec_arr >= $recent_size) {
-				my $to_kill = shift @$rec_arr;
-				delete $rec_hash->{$to_kill};
-			}
-			push @$rec_arr, $new;
-
-			run_build $git_dir, $ref, $old, $new;
-		} else {
-			sleep $scan_delay;
-		}
-	}
-
-	unlink $pidfile;
-}
-
-$debug_flag = 0;
-GetOptions(
-	'debug|d' => \$debug_flag,
-	'smtp-user=s' => \$ex_user,
-) or die "usage: $0 [--debug] [--smtp-user=user]\n";
-
-$ex_pass = input_noecho("$ex_user SMTP password: ")
-	if ($ex_user && !$ex_pass);
-
-if ($debug_flag) {
-	daemon_loop;
-	exit 0;
-}
-
-my $daemon = fork();
-if (!defined $daemon) {
-	die "cannot fork daemon: $!";
-} elsif (0 == $daemon) {
-	close STDIN;open(STDIN, '/dev/null');
-	close STDOUT;open(STDOUT, '>/dev/null');
-	close STDERR;open(STDERR, '>/dev/null');
-	daemon_loop;
-	exit 0;
-} else {
-	print "Daemon $daemon running in the background.\n";
-}
diff --git a/contrib/continuous/post-receive-cinotify b/contrib/continuous/post-receive-cinotify
deleted file mode 100644
index b8f5a60..0000000
--- a/contrib/continuous/post-receive-cinotify
+++ /dev/null
@@ -1,104 +0,0 @@
-#!/usr/bin/perl
-#
-# A hook that notifies its companion cidaemon through a simple
-# queue file that a ref has been updated via a push (actually
-# by a receive-pack running on the server).
-#
-# See cidaemon for per-repository configuration details.
-#
-# To use this hook, add it as the post-receive hook, make it
-# executable, and set its configuration options.
-#
-
-local $ENV{PATH} = '/opt/git/bin';
-
-use strict;
-use warnings;
-use File::Spec;
-use Storable qw(retrieve nstore);
-use Fcntl ':flock';
-
-my $git_dir = File::Spec->rel2abs($ENV{GIT_DIR});
-my $queue_name = `git config --get builder.queue`;chop $queue_name;
-$queue_name =~ m,^([^\s]+)$,; $queue_name = $1; # untaint
-unless ($queue_name) {
-	1 while <STDIN>;
-	print STDERR "\nerror: builder.queue not set.  Not enqueing.\n\n";
-	exit;
-}
-my $queue_lock = "$queue_name.lock";
-
-my @skip;
-open S, "git config --get-all builder.skip|";
-while (<S>) {
-	chop;
-	push @skip, $_;
-}
-close S;
-
-my @new_branch_base;
-open S, "git config --get-all builder.newBranchBase|";
-while (<S>) {
-	chop;
-	push @new_branch_base, $_;
-}
-close S;
-
-sub skip ($)
-{
-	local $_ = shift;
-	foreach my $p (@skip) {
-		return 1 if /^$p/;
-	}
-	0;
-}
-
-open LOCK, ">$queue_lock" or die "Can't open $queue_lock: $!";
-flock LOCK, LOCK_EX;
-
-my $queue = -f $queue_name ? retrieve $queue_name : [];
-my %existing;
-foreach my $r (@$queue) {
-	my ($gd, $ref) = @$r;
-	$existing{$gd}{$ref} = $r;
-}
-
-my @new_branch_commits;
-my $loaded_new_branch_commits = 0;
-
-while (<STDIN>) {
-	chop;
-	my ($old, $new, $ref) = split / /, $_, 3;
-
-	next if $old eq $new;
-	next if $new =~ /^0{40}$/;
-	next if skip $ref;
-
-	my $r = $existing{$git_dir}{$ref};
-	if ($r) {
-		$r->[3] = $new;
-	} else {
-		if ($old =~ /^0{40}$/) {
-			if (!$loaded_new_branch_commits && @new_branch_base) {
-				open M,'-|','git','show-ref',@new_branch_base;
-				while (<M>) {
-					($_) = split / /, $_;
-					push @new_branch_commits, $_;
-				}
-				close M;
-				$loaded_new_branch_commits = 1;
-			}
-			$old = [@new_branch_commits];
-		} else {
-			$old = [$old];
-		}
-
-		$r = [$git_dir, $ref, $old, $new];
-		$existing{$git_dir}{$ref} = $r;
-		push @$queue, $r;
-	}
-}
-nstore $queue, $queue_name;
-
-flock LOCK, LOCK_UN;
-close LOCK;
diff --git a/contrib/credential/osxkeychain/git-credential-osxkeychain.c b/contrib/credential/osxkeychain/git-credential-osxkeychain.c
index 3940202..bcd3f57 100644
--- a/contrib/credential/osxkeychain/git-credential-osxkeychain.c
+++ b/contrib/credential/osxkeychain/git-credential-osxkeychain.c
@@ -127,10 +127,20 @@
 		*v++ = '\0';
 
 		if (!strcmp(buf, "protocol")) {
-			if (!strcmp(v, "https"))
+			if (!strcmp(v, "imap"))
+				protocol = kSecProtocolTypeIMAP;
+			else if (!strcmp(v, "imaps"))
+				protocol = kSecProtocolTypeIMAPS;
+			else if (!strcmp(v, "ftp"))
+				protocol = kSecProtocolTypeFTP;
+			else if (!strcmp(v, "ftps"))
+				protocol = kSecProtocolTypeFTPS;
+			else if (!strcmp(v, "https"))
 				protocol = kSecProtocolTypeHTTPS;
 			else if (!strcmp(v, "http"))
 				protocol = kSecProtocolTypeHTTP;
+			else if (!strcmp(v, "smtp"))
+				protocol = kSecProtocolTypeSMTP;
 			else /* we don't yet handle other protocols */
 				exit(0);
 		}
diff --git a/contrib/hg-to-git/hg-to-git.py b/contrib/hg-to-git/hg-to-git.py
index 232625a..60dec86 100755
--- a/contrib/hg-to-git/hg-to-git.py
+++ b/contrib/hg-to-git/hg-to-git.py
@@ -225,7 +225,7 @@
     os.system('git ls-files -x .hg --deleted | git update-index --remove --stdin')
 
     # commit
-    os.system(getgitenv(user, date) + 'git commit --allow-empty -a -F %s' % filecomment)
+    os.system(getgitenv(user, date) + 'git commit --allow-empty --allow-empty-message -a -F %s' % filecomment)
     os.unlink(filecomment)
 
     # tag
diff --git a/contrib/hooks/multimail/README b/contrib/hooks/multimail/README
new file mode 100644
index 0000000..9904396
--- /dev/null
+++ b/contrib/hooks/multimail/README
@@ -0,0 +1,486 @@
+			   git-multimail
+			   =============
+
+git-multimail is a tool for sending notification emails on pushes to a
+Git repository.  It includes a Python module called git_multimail.py,
+which can either be used as a hook script directly or can be imported
+as a Python module into another script.
+
+git-multimail is derived from the Git project's old
+contrib/hooks/post-receive-email, and is mostly compatible with that
+script.  See README.migrate-from-post-receive-email for details about
+the differences and for how to migrate from post-receive-email to
+git-multimail.
+
+git-multimail, like the rest of the Git project, is licensed under
+GPLv2 (see the COPYING file for details).
+
+Please note: although, as a convenience, git-multimail may be
+distributed along with the main Git project, development of
+git-multimail takes place in its own, separate project.  See section
+"Getting involved" below for more information.
+
+
+By default, for each push received by the repository, git-multimail:
+
+1. Outputs one email summarizing each reference that was changed.
+   These "reference change" (called "refchange" below) emails describe
+   the nature of the change (e.g., was the reference created, deleted,
+   fast-forwarded, etc.) and include a one-line summary of each commit
+   that was added to the reference.
+
+2. Outputs one email for each new commit that was introduced by the
+   reference change.  These "commit" emails include a list of the
+   files changed by the commit, followed by the diffs of files
+   modified by the commit.  The commit emails are threaded to the
+   corresponding reference change email via "In-Reply-To".  This style
+   (similar to the "git format-patch" style used on the Git mailing
+   list) makes it easy to scan through the emails, jump to patches
+   that need further attention, and write comments about specific
+   commits.  Commits are handled in reverse topological order (i.e.,
+   parents shown before children).  For example,
+
+   [git] branch master updated
+   + [git] 01/08: doc: fix xref link from api docs to manual pages
+   + [git] 02/08: api-credentials.txt: show the big picture first
+   + [git] 03/08: api-credentials.txt: mention credential.helper explicitly
+   + [git] 04/08: api-credentials.txt: add "see also" section
+   + [git] 05/08: t3510 (cherry-pick-sequence): add missing '&&'
+   + [git] 06/08: Merge branch 'rr/maint-t3510-cascade-fix'
+   + [git] 07/08: Merge branch 'mm/api-credentials-doc'
+   + [git] 08/08: Git 1.7.11-rc2
+
+   Each commit appears in exactly one commit email, the first time
+   that it is pushed to the repository.  If a commit is later merged
+   into another branch, then a one-line summary of the commit is
+   included in the reference change email (as usual), but no
+   additional commit email is generated.
+
+   By default, reference change emails have their "Reply-To" field set
+   to the person who pushed the change, and commit emails have their
+   "Reply-To" field set to the author of the commit.
+
+3. Output one "announce" mail for each new annotated tag, including
+   information about the tag and optionally a shortlog describing the
+   changes since the previous tag.  Such emails might be useful if you
+   use annotated tags to mark releases of your project.
+
+
+Requirements
+------------
+
+* Python 2.x, version 2.4 or later.  No non-standard Python modules
+  are required.  git-multimail does *not* currently work with Python
+  3.x.
+
+  The example scripts invoke Python using the following shebang line
+  (following PEP 394 [1]):
+
+      #! /usr/bin/env python2
+
+  If your system's Python2 interpreter is not in your PATH or is not
+  called "python2", you can change the lines accordingly.  Or you can
+  invoke the Python interpreter explicitly, for example via a tiny
+  shell script like
+
+      #! /bin/sh
+      /usr/local/bin/python /path/to/git_multimail.py "$@"
+
+* The "git" command must be in your PATH.  git-multimail is known to
+  work with Git versions back to 1.7.1.  (Earlier versions have not
+  been tested; if you do so, please report your results.)
+
+* To send emails using the default configuration, a standard sendmail
+  program must be located at '/usr/sbin/sendmail' and configured
+  correctly to send emails.  If this is not the case, see the
+  multimailhook.mailer configuration variable below for how to
+  configure git-multimail to send emails via an SMTP server.
+
+
+Invocation
+----------
+
+git_multimail.py is designed to be used as a "post-receive" hook in a
+Git repository (see githooks(5)).  Link or copy it to
+$GIT_DIR/hooks/post-receive within the repository for which email
+notifications are desired.  Usually it should be installed on the
+central repository for a project, to which all commits are eventually
+pushed.
+
+For use on pre-v1.5.1 Git servers, git_multimail.py can also work as
+an "update" hook, taking its arguments on the command line.  To use
+this script in this manner, link or copy it to $GIT_DIR/hooks/update.
+Please note that the script is not completely reliable in this mode
+[2].
+
+Alternatively, git_multimail.py can be imported as a Python module
+into your own Python post-receive script.  This method is a bit more
+work, but allows the behavior of the hook to be customized using
+arbitrary Python code.  For example, you can use a custom environment
+(perhaps inheriting from GenericEnvironment or GitoliteEnvironment) to
+
+* change how the user who did the push is determined
+
+* read users' email addresses from an LDAP server or from a database
+
+* decide which users should be notified about which commits based on
+  the contents of the commits (e.g., for users who want to be notified
+  only about changes affecting particular files or subdirectories)
+
+Or you can change how emails are sent by writing your own Mailer
+class.  The "post-receive" script in this directory demonstrates how
+to use git_multimail.py as a Python module.  (If you make interesting
+changes of this type, please consider sharing them with the
+community.)
+
+
+Configuration
+-------------
+
+By default, git-multimail mostly takes its configuration from the
+following "git config" settings:
+
+multimailhook.environment
+
+    This describes the general environment of the repository.
+    Currently supported values:
+
+    "generic" -- the username of the pusher is read from $USER and the
+        repository name is derived from the repository's path.
+
+    "gitolite" -- the username of the pusher is read from $GL_USER and
+        the repository name from $GL_REPO.
+
+    If neither of these environments is suitable for your setup, then
+    you can implement a Python class that inherits from Environment
+    and instantiate it via a script that looks like the example
+    post-receive script.
+
+    The environment value can be specified on the command line using
+    the --environment option.  If it is not specified on the command
+    line or by multimailhook.environment, then it defaults to
+    "gitolite" if the environment contains variables $GL_USER and
+    $GL_REPO; otherwise "generic".
+
+multimailhook.repoName
+
+    A short name of this Git repository, to be used in various places
+    in the notification email text.  The default is to use $GL_REPO
+    for gitolite repositories, or otherwise to derive this value from
+    the repository path name.
+
+multimailhook.mailinglist
+
+    The list of email addresses to which notification emails should be
+    sent, as RFC 2822 email addresses separated by commas.  This
+    configuration option can be multivalued.  Leave it unset or set it
+    to the empty string to not send emails by default.  The next few
+    settings can be used to configure specific address lists for
+    specific types of notification email.
+
+multimailhook.refchangeList
+
+    The list of email addresses to which summary emails about
+    reference changes should be sent, as RFC 2822 email addresses
+    separated by commas.  This configuration option can be
+    multivalued.  The default is the value in
+    multimailhook.mailinglist.  Set this value to the empty string to
+    prevent reference change emails from being sent.
+
+multimailhook.announceList
+
+    The list of email addresses to which emails about new annotated
+    tags should be sent, as RFC 2822 email addresses separated by
+    commas.  This configuration option can be multivalued.  The
+    default is the value in multimailhook.refchangelist or
+    multimailhook.mailinglist.  Set this value to the empty string to
+    prevent annotated tag announcement emails from being sent.
+
+multimailhook.commitList
+
+    The list of email addresses to which emails about individual new
+    commits should be sent, as RFC 2822 email addresses separated by
+    commas.  This configuration option can be multivalued.  The
+    default is the value in multimailhook.mailinglist.  Set this value
+    to the empty string to prevent notification emails about
+    individual commits from being sent.
+
+multimailhook.announceShortlog
+
+    If this option is set to true, then emails about changes to
+    annotated tags include a shortlog of changes since the previous
+    tag.  This can be useful if the annotated tags represent releases;
+    then the shortlog will be a kind of rough summary of what has
+    happened since the last release.  But if your tagging policy is
+    not so straightforward, then the shortlog might be confusing
+    rather than useful.  Default is false.
+
+multimailhook.refchangeShowLog
+
+    If this option is set to true, then summary emails about reference
+    changes will include a detailed log of the added commits in
+    addition to the one line summary.  The log is generated by running
+    "git log" with the options specified in multimailhook.logOpts.
+    Default is false.
+
+multimailhook.mailer
+
+    This option changes the way emails are sent.  Accepted values are:
+
+    - sendmail (the default): use the command /usr/sbin/sendmail or
+      /usr/lib/sendmail (or sendmailCommand, if configured).  This
+      mode can be further customized via the following options:
+
+       multimailhook.sendmailCommand
+
+           The command used by mailer "sendmail" to send emails.  Shell
+           quoting is allowed in the value of this setting, but remember that
+           Git requires double-quotes to be escaped; e.g.,
+
+             git config multimailhook.sendmailcommand '/usr/sbin/sendmail -t -F \"Git Repo\"'
+
+           Default is '/usr/sbin/sendmail -t' or '/usr/lib/sendmail
+           -t' (depending on which file is present and executable).
+
+       multimailhook.envelopeSender
+
+           If set then pass this value to sendmail via the -f option to set
+           the envelope sender address.
+
+    - smtp: use Python's smtplib.  This is useful when the sendmail
+      command is not available on the system.  This mode can be
+      further customized via the following options:
+
+       multimailhook.smtpServer
+
+           The name of the SMTP server to connect to.  The value can
+           also include a colon and a port number; e.g.,
+           "mail.example.com:25".  Default is 'localhost' using port
+           25.
+
+       multimailhook.envelopeSender
+
+           The sender address to be passed to the SMTP server.  If
+           unset, then the value of multimailhook.from is used.
+
+multimailhook.from
+
+    If set then use this value in the From: field of generated emails.
+    If unset, then use the repository's user configuration (user.name
+    and user.email).  If user.email is also unset, then use
+    multimailhook.envelopeSender.
+
+multimailhook.administrator
+
+    The name and/or email address of the administrator of the Git
+    repository; used in FOOTER_TEMPLATE.  Default is
+    multimailhook.envelopesender if it is set; otherwise a generic
+    string is used.
+
+multimailhook.emailPrefix
+
+    All emails have this string prepended to their subjects, to aid
+    email filtering (though filtering based on the X-Git-* email
+    headers is probably more robust).  Default is the short name of
+    the repository in square brackets; e.g., "[myrepo]".
+
+multimailhook.emailMaxLines
+
+    The maximum number of lines that should be included in the body of
+    a generated email.  If not specified, there is no limit.  Lines
+    beyond the limit are suppressed and counted, and a final line is
+    added indicating the number of suppressed lines.
+
+multimailhook.emailMaxLineLength
+
+    The maximum length of a line in the email body.  Lines longer than
+    this limit are truncated to this length with a trailing " [...]"
+    added to indicate the missing text.  The default is 500, because
+    (a) diffs with longer lines are probably from binary files, for
+    which a diff is useless, and (b) even if a text file has such long
+    lines, the diffs are probably unreadable anyway.  To disable line
+    truncation, set this option to 0.
+
+multimailhook.maxCommitEmails
+
+    The maximum number of commit emails to send for a given change.
+    When the number of patches is larger that this value, only the
+    summary refchange email is sent.  This can avoid accidental
+    mailbombing, for example on an initial push.  To disable commit
+    emails limit, set this option to 0.  The default is 500.
+
+multimailhook.emailStrictUTF8
+
+    If this boolean option is set to "true", then the main part of the
+    email body is forced to be valid UTF-8.  Any characters that are
+    not valid UTF-8 are converted to the Unicode replacement
+    character, U+FFFD.  The default is "true".
+
+multimailhook.diffOpts
+
+    Options passed to "git diff-tree" when generating the summary
+    information for ReferenceChange emails.  Default is "--stat
+    --summary --find-copies-harder".  Add -p to those options to
+    include a unified diff of changes in addition to the usual summary
+    output.  Shell quoting is allowed; see multimailhook.logOpts for
+    details.
+
+multimailhook.logOpts
+
+    Options passed to "git log" to generate additional info for
+    reference change emails (used only if refchangeShowLog is set).
+    For example, adding --graph will show the graph of revisions, -p
+    will show the complete diff, etc.  The default is empty.
+
+    Shell quoting is allowed; for example, a log format that contains
+    spaces can be specified using something like:
+
+      git config multimailhook.logopts '--pretty=format:"%h %aN <%aE>%n%s%n%n%b%n"'
+
+    If you want to set this by editing your configuration file
+    directly, remember that Git requires double-quotes to be escaped
+    (see git-config(1) for more information):
+
+      [multimailhook]
+              logopts = --pretty=format:\"%h %aN <%aE>%n%s%n%n%b%n\"
+
+multimailhook.emailDomain
+
+    Domain name appended to the username of the person doing the push
+    to convert it into an email address (via "%s@%s" % (username,
+    emaildomain)).  More complicated schemes can be implemented by
+    overriding Environment and overriding its get_pusher_email()
+    method.
+
+multimailhook.replyTo
+multimailhook.replyToCommit
+multimailhook.replyToRefchange
+
+    Addresses to use in the Reply-To: field for commit emails
+    (replyToCommit) and refchange emails (replyToRefchange).
+    multimailhook.replyTo is used as default when replyToCommit or
+    replyToRefchange is not set.  The value for these variables can be
+    either:
+
+    - An email address, which will be used directly.
+
+    - The value "pusher", in which case the pusher's address (if
+      available) will be used.  This is the default for refchange
+      emails.
+
+    - The value "author" (meaningful only for replyToCommit), in which
+      case the commit author's address will be used.  This is the
+      default for commit emails.
+
+    - The value "none", in which case the Reply-To: field will be
+      omitted.
+
+
+Email filtering aids
+--------------------
+
+All emails include extra headers to enable fine tuned filtering and
+give information for debugging.  All emails include the headers
+"X-Git-Repo", "X-Git-Refname", and "X-Git-Reftype".  ReferenceChange
+emails also include headers "X-Git-Oldrev" and "X-Git-Newrev";
+Revision emails also include header "X-Git-Rev".
+
+
+Customizing email contents
+--------------------------
+
+git-multimail mostly generates emails by expanding templates.  The
+templates can be customized.  To avoid the need to edit
+git_multimail.py directly, the preferred way to change the templates
+is to write a separate Python script that imports git_multimail.py as
+a module, then replaces the templates in place.  See the provided
+post-receive script for an example of how this is done.
+
+
+Customizing git-multimail for your environment
+----------------------------------------------
+
+git-multimail is mostly customized via an "environment" that describes
+the local environment in which Git is running.  Two types of
+environment are built in:
+
+* GenericEnvironment: a stand-alone Git repository.
+
+* GitoliteEnvironment: a Git repository that is managed by gitolite
+  [3].  For such repositories, the identity of the pusher is read from
+  environment variable $GL_USER, and the name of the repository is
+  read from $GL_REPO (if it is not overridden by
+  multimailhook.reponame).
+
+By default, git-multimail assumes GitoliteEnvironment if $GL_USER and
+$GL_REPO are set, and otherwise assumes GenericEnvironment.
+Alternatively, you can choose one of these two environments explicitly
+by setting a "multimailhook.environment" config setting (which can
+have the value "generic" or "gitolite") or by passing an --environment
+option to the script.
+
+If you need to customize the script in ways that are not supported by
+the existing environments, you can define your own environment class
+class using arbitrary Python code.  To do so, you need to import
+git_multimail.py as a Python module, as demonstrated by the example
+post-receive script.  Then implement your environment class; it should
+usually inherit from one of the existing Environment classes and
+possibly one or more of the EnvironmentMixin classes.  Then set the
+"environment" variable to an instance of your own environment class
+and pass it to run_as_post_receive_hook().
+
+The standard environment classes, GenericEnvironment and
+GitoliteEnvironment, are in fact themselves put together out of a
+number of mixin classes, each of which handles one aspect of the
+customization.  For the finest control over your configuration, you
+can specify exactly which mixin classes your own environment class
+should inherit from, and override individual methods (or even add your
+own mixin classes) to implement entirely new behaviors.  If you
+implement any mixins that might be useful to other people, please
+consider sharing them with the community!
+
+
+Getting involved
+----------------
+
+git-multimail is an open-source project, built by volunteers.  We
+would welcome your help!
+
+The current maintainer is Michael Haggerty <mhagger@alum.mit.edu>.
+
+General discussion of git-multimail takes place on the main Git
+mailing list,
+
+    git@vger.kernel.org
+
+Please CC emails regarding git-multimail to me so that I don't
+overlook them.
+
+The git-multimail project itself is currently hosted on GitHub:
+
+    https://github.com/mhagger/git-multimail
+
+We use the GitHub issue tracker to keep track of bugs and feature
+requests, and GitHub pull requests to exchange patches (though, if you
+prefer, you can send patches via the Git mailing list with cc to me).
+
+Please note that although a copy of git-multimail will probably be
+distributed in the "contrib" section of the main Git project,
+development takes place in the separate git-multimail repository on
+GitHub!  (Whenever enough changes to git-multimail have accumulated, a
+new code-drop of git-multimail will be submitted for inclusion in the
+Git project.)
+
+
+Footnotes
+---------
+
+[1] http://www.python.org/dev/peps/pep-0394/
+
+[2] Because of the way information is passed to update hooks, the
+    script's method of determining whether a commit has already been
+    seen does not work when it is used as an "update" script.  In
+    particular, no notification email will be generated for a new
+    commit that is added to multiple references in the same push.
+
+[3] https://github.com/sitaramc/gitolite
diff --git a/contrib/hooks/multimail/README.Git b/contrib/hooks/multimail/README.Git
new file mode 100644
index 0000000..9c2e66a
--- /dev/null
+++ b/contrib/hooks/multimail/README.Git
@@ -0,0 +1,15 @@
+This copy of git-multimail is distributed as part of the "contrib"
+section of the Git project as a convenience to Git users.
+git-multimail is developed as an independent project at the following
+website:
+
+    https://github.com/mhagger/git-multimail
+
+The version in this directory was obtained from the upstream project
+on 2013-07-14 and consists of the "git-multimail" subdirectory from
+revision
+
+    1a5cb09c698a74d15a715a86b09ead5f56bf4b06
+
+Please see the README file in this directory for information about how
+to report bugs or contribute to git-multimail.
diff --git a/contrib/hooks/multimail/README.migrate-from-post-receive-email b/contrib/hooks/multimail/README.migrate-from-post-receive-email
new file mode 100644
index 0000000..1e6a976
--- /dev/null
+++ b/contrib/hooks/multimail/README.migrate-from-post-receive-email
@@ -0,0 +1,145 @@
+git-multimail is close to, but not exactly, a plug-in replacement for
+the old Git project script contrib/hooks/post-receive-email.  This
+document describes the differences and explains how to configure
+git-multimail to get behavior closest to that of post-receive-email.
+
+If you are in a hurry
+=====================
+
+A script called migrate-mailhook-config is included with
+git-multimail.  If you run this script within a Git repository that is
+configured to use post-receive-email, it will convert the
+configuration settings into the approximate equivalent settings for
+git-multimail.  For more information, run
+
+    migrate-mailhook-config --help
+
+
+Configuration differences
+=========================
+
+* The names of the config options for git-multimail are in namespace
+  "multimailhook.*" instead of "hooks.*".  (Editorial comment:
+  post-receive-email should never have used such a generic top-level
+  namespace.)
+
+* In emails about new annotated tags, post-receive-email includes a
+  shortlog of all changes since the previous annotated tag.  To get
+  this behavior with git-multimail, you need to set
+  multimailhook.announceshortlog to true:
+
+      git config multimailhook.announceshortlog true
+
+* multimailhook.commitlist -- This is a new configuration variable.
+  Recipients listed here will receive a separate email for each new
+  commit.  However, if this variable is *not* set, it defaults to the
+  value of multimailhook.mailinglist.  Therefore, if you *don't* want
+  the members of multimailhook.mailinglist to receive one email per
+  commit, then set this value to the empty string:
+
+      git config multimailhook.commitlist ''
+
+* multimailhook.emailprefix -- If this value is not set, then the
+  subjects of generated emails are prefixed with the short name of the
+  repository enclosed in square brackets; e.g., "[myrepo]".
+  post-receive-email defaults to prefix "[SCM]" if this option is not
+  set.  So if you were using the old default and want to retain it
+  (for example, to avoid having to change your email filters), set
+  this variable explicitly to the old value:
+
+      git config multimailhook.emailprefix "[SCM]"
+
+* The "multimailhook.showrev" configuration option is not supported.
+  Its main use is obsoleted by the one-email-per-commit feature of
+  git-multimail.
+
+
+Other differences
+=================
+
+This section describes other differences in the behavior of
+git-multimail vs. post-receive-email.  For full details, please refer
+to the main README file:
+
+* One email per commit.  For each reference change, the script first
+  outputs one email summarizing the reference change (including
+  one-line summaries of the new commits), then it outputs a separate
+  email for each new commit that was introduced, including patches.
+  These one-email-per-commit emails go to the addresses listed in
+  multimailhook.commitlist.  post-receive-email sends only one email
+  for each *reference* that is changed, no matter how many commits
+  were added to the reference.
+
+* Better algorithm for detecting new commits.  post-receive-email
+  processes one reference change at a time, which causes it to fail to
+  describe new commits that were included in multiple branches.  For
+  example, if a single push adds the "*" commits in the diagram below,
+  then post-receive-email would never include the details of the two
+  commits that are common to "master" and "branch" in its
+  notifications.
+
+      o---o---o---*---*---*    <-- master
+                       \
+                        *---*  <-- branch
+
+  git-multimail analyzes all reference modifications to determine
+  which commits were not present before the change, therefore avoiding
+  that error.
+
+* In reference change emails, git-multimail tells which commits have
+  been added to the reference vs. are entirely new to the repository,
+  and which commits that have been omitted from the reference
+  vs. entirely discarded from the repository.
+
+* The environment in which Git is running can be configured via an
+  "Environment" abstraction.
+
+* Built-in support for Gitolite-managed repositories.
+
+* Instead of using full SHA1 object names in emails, git-multimail
+  mostly uses abbreviated SHA1s, plus one-line log message summaries
+  where appropriate.
+
+* In the schematic diagrams that explain non-fast-forward commits,
+  git-multimail shows the names of the branches involved.
+
+* The emails generated by git-multimail include the name of the Git
+  repository that was modified; this is convenient for recipients who
+  are monitoring multiple repositories.
+
+* git-multimail allows the email "From" addresses to be configured.
+
+* The recipients lists (multimailhook.mailinglist,
+  multimailhook.refchangelist, multimailhook.announcelist, and
+  multimailhook.commitlist) can be comma-separated values and/or
+  multivalued settings in the config file; e.g.,
+
+      [multimailhook]
+              mailinglist = mr.brown@example.com, mr.black@example.com
+              announcelist = Him <him@example.com>
+              announcelist = Jim <jim@example.com>
+              announcelist = pop@example.com
+
+  This might make it easier to maintain short recipients lists without
+  requiring full-fledged mailing list software.
+
+* By default, git-multimail sets email "Reply-To" headers to reply to
+  the pusher (for reference updates) and to the author (for commit
+  notifications).  By default, the pusher's email address is
+  constructed by appending "multimailhook.emaildomain" to the pusher's
+  username.
+
+* The generated emails contain a configurable footer.  By default, it
+  lists the name of the administrator who should be contacted to
+  unsubscribe from notification emails.
+
+* New option multimailhook.emailmaxlinelength to limit the length of
+  lines in the main part of the email body.  The default limit is 500
+  characters.
+
+* New option multimailhook.emailstrictutf8 to ensure that the main
+  part of the email body is valid UTF-8.  Invalid characters are
+  turned into the Unicode replacement character, U+FFFD.  By default
+  this option is turned on.
+
+* Written in Python.  Easier to add new features.
diff --git a/contrib/hooks/multimail/git_multimail.py b/contrib/hooks/multimail/git_multimail.py
new file mode 100755
index 0000000..81c6a51
--- /dev/null
+++ b/contrib/hooks/multimail/git_multimail.py
@@ -0,0 +1,2393 @@
+#! /usr/bin/env python2
+
+# Copyright (c) 2012,2013 Michael Haggerty
+# Derived from contrib/hooks/post-receive-email, which is
+# Copyright (c) 2007 Andy Parkins
+# and also includes contributions by other authors.
+#
+# This file is part of git-multimail.
+#
+# git-multimail is free software: you can redistribute it and/or
+# modify it under the terms of the GNU General Public License version
+# 2 as published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 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, see
+# <http://www.gnu.org/licenses/>.
+
+"""Generate notification emails for pushes to a git repository.
+
+This hook sends emails describing changes introduced by pushes to a
+git repository.  For each reference that was changed, it emits one
+ReferenceChange email summarizing how the reference was changed,
+followed by one Revision email for each new commit that was introduced
+by the reference change.
+
+Each commit is announced in exactly one Revision email.  If the same
+commit is merged into another branch in the same or a later push, then
+the ReferenceChange email will list the commit's SHA1 and its one-line
+summary, but no new Revision email will be generated.
+
+This script is designed to be used as a "post-receive" hook in a git
+repository (see githooks(5)).  It can also be used as an "update"
+script, but this usage is not completely reliable and is deprecated.
+
+To help with debugging, this script accepts a --stdout option, which
+causes the emails to be written to standard output rather than sent
+using sendmail.
+
+See the accompanying README file for the complete documentation.
+
+"""
+
+import sys
+import os
+import re
+import bisect
+import subprocess
+import shlex
+import optparse
+import smtplib
+
+try:
+    from email.utils import make_msgid
+    from email.utils import getaddresses
+    from email.utils import formataddr
+    from email.header import Header
+except ImportError:
+    # Prior to Python 2.5, the email module used different names:
+    from email.Utils import make_msgid
+    from email.Utils import getaddresses
+    from email.Utils import formataddr
+    from email.Header import Header
+
+
+DEBUG = False
+
+ZEROS = '0' * 40
+LOGBEGIN = '- Log -----------------------------------------------------------------\n'
+LOGEND = '-----------------------------------------------------------------------\n'
+
+
+# It is assumed in many places that the encoding is uniformly UTF-8,
+# so changing these constants is unsupported.  But define them here
+# anyway, to make it easier to find (at least most of) the places
+# where the encoding is important.
+(ENCODING, CHARSET) = ('UTF-8', 'utf-8')
+
+
+REF_CREATED_SUBJECT_TEMPLATE = (
+    '%(emailprefix)s%(refname_type)s %(short_refname)s created'
+    ' (now %(newrev_short)s)'
+    )
+REF_UPDATED_SUBJECT_TEMPLATE = (
+    '%(emailprefix)s%(refname_type)s %(short_refname)s updated'
+    ' (%(oldrev_short)s -> %(newrev_short)s)'
+    )
+REF_DELETED_SUBJECT_TEMPLATE = (
+    '%(emailprefix)s%(refname_type)s %(short_refname)s deleted'
+    ' (was %(oldrev_short)s)'
+    )
+
+REFCHANGE_HEADER_TEMPLATE = """\
+To: %(recipients)s
+Subject: %(subject)s
+MIME-Version: 1.0
+Content-Type: text/plain; charset=%(charset)s
+Content-Transfer-Encoding: 8bit
+Message-ID: %(msgid)s
+From: %(fromaddr)s
+Reply-To: %(reply_to)s
+X-Git-Repo: %(repo_shortname)s
+X-Git-Refname: %(refname)s
+X-Git-Reftype: %(refname_type)s
+X-Git-Oldrev: %(oldrev)s
+X-Git-Newrev: %(newrev)s
+Auto-Submitted: auto-generated
+"""
+
+REFCHANGE_INTRO_TEMPLATE = """\
+This is an automated email from the git hooks/post-receive script.
+
+%(pusher)s pushed a change to %(refname_type)s %(short_refname)s
+in repository %(repo_shortname)s.
+
+"""
+
+
+FOOTER_TEMPLATE = """\
+
+-- \n\
+To stop receiving notification emails like this one, please contact
+%(administrator)s.
+"""
+
+
+REWIND_ONLY_TEMPLATE = """\
+This update removed existing revisions from the reference, leaving the
+reference pointing at a previous point in the repository history.
+
+ * -- * -- N   %(refname)s (%(newrev_short)s)
+            \\
+             O -- O -- O   (%(oldrev_short)s)
+
+Any revisions marked "omits" are not gone; other references still
+refer to them.  Any revisions marked "discards" are gone forever.
+"""
+
+
+NON_FF_TEMPLATE = """\
+This update added new revisions after undoing existing revisions.
+That is to say, some revisions that were in the old version of the
+%(refname_type)s are not in the new version.  This situation occurs
+when a user --force pushes a change and generates a repository
+containing something like this:
+
+ * -- * -- B -- O -- O -- O   (%(oldrev_short)s)
+            \\
+             N -- N -- N   %(refname)s (%(newrev_short)s)
+
+You should already have received notification emails for all of the O
+revisions, and so the following emails describe only the N revisions
+from the common base, B.
+
+Any revisions marked "omits" are not gone; other references still
+refer to them.  Any revisions marked "discards" are gone forever.
+"""
+
+
+NO_NEW_REVISIONS_TEMPLATE = """\
+No new revisions were added by this update.
+"""
+
+
+DISCARDED_REVISIONS_TEMPLATE = """\
+This change permanently discards the following revisions:
+"""
+
+
+NO_DISCARDED_REVISIONS_TEMPLATE = """\
+The revisions that were on this %(refname_type)s are still contained in
+other references; therefore, this change does not discard any commits
+from the repository.
+"""
+
+
+NEW_REVISIONS_TEMPLATE = """\
+The %(tot)s revisions listed above as "new" are entirely new to this
+repository and will be described in separate emails.  The revisions
+listed as "adds" were already present in the repository and have only
+been added to this reference.
+
+"""
+
+
+TAG_CREATED_TEMPLATE = """\
+        at  %(newrev_short)-9s (%(newrev_type)s)
+"""
+
+
+TAG_UPDATED_TEMPLATE = """\
+*** WARNING: tag %(short_refname)s was modified! ***
+
+      from  %(oldrev_short)-9s (%(oldrev_type)s)
+        to  %(newrev_short)-9s (%(newrev_type)s)
+"""
+
+
+TAG_DELETED_TEMPLATE = """\
+*** WARNING: tag %(short_refname)s was deleted! ***
+
+"""
+
+
+# The template used in summary tables.  It looks best if this uses the
+# same alignment as TAG_CREATED_TEMPLATE and TAG_UPDATED_TEMPLATE.
+BRIEF_SUMMARY_TEMPLATE = """\
+%(action)10s  %(rev_short)-9s %(text)s
+"""
+
+
+NON_COMMIT_UPDATE_TEMPLATE = """\
+This is an unusual reference change because the reference did not
+refer to a commit either before or after the change.  We do not know
+how to provide full information about this reference change.
+"""
+
+
+REVISION_HEADER_TEMPLATE = """\
+To: %(recipients)s
+Subject: %(emailprefix)s%(num)02d/%(tot)02d: %(oneline)s
+MIME-Version: 1.0
+Content-Type: text/plain; charset=%(charset)s
+Content-Transfer-Encoding: 8bit
+From: %(fromaddr)s
+Reply-To: %(reply_to)s
+In-Reply-To: %(reply_to_msgid)s
+References: %(reply_to_msgid)s
+X-Git-Repo: %(repo_shortname)s
+X-Git-Refname: %(refname)s
+X-Git-Reftype: %(refname_type)s
+X-Git-Rev: %(rev)s
+Auto-Submitted: auto-generated
+"""
+
+REVISION_INTRO_TEMPLATE = """\
+This is an automated email from the git hooks/post-receive script.
+
+%(pusher)s pushed a commit to %(refname_type)s %(short_refname)s
+in repository %(repo_shortname)s.
+
+"""
+
+
+REVISION_FOOTER_TEMPLATE = FOOTER_TEMPLATE
+
+
+class CommandError(Exception):
+    def __init__(self, cmd, retcode):
+        self.cmd = cmd
+        self.retcode = retcode
+        Exception.__init__(
+            self,
+            'Command "%s" failed with retcode %s' % (' '.join(cmd), retcode,)
+            )
+
+
+class ConfigurationException(Exception):
+    pass
+
+
+def read_git_output(args, input=None, keepends=False, **kw):
+    """Read the output of a Git command."""
+
+    return read_output(
+        ['git', '-c', 'i18n.logoutputencoding=%s' % (ENCODING,)] + args,
+        input=input, keepends=keepends, **kw
+        )
+
+
+def read_output(cmd, input=None, keepends=False, **kw):
+    if input:
+        stdin = subprocess.PIPE
+    else:
+        stdin = None
+    p = subprocess.Popen(
+        cmd, stdin=stdin, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kw
+        )
+    (out, err) = p.communicate(input)
+    retcode = p.wait()
+    if retcode:
+        raise CommandError(cmd, retcode)
+    if not keepends:
+        out = out.rstrip('\n\r')
+    return out
+
+
+def read_git_lines(args, keepends=False, **kw):
+    """Return the lines output by Git command.
+
+    Return as single lines, with newlines stripped off."""
+
+    return read_git_output(args, keepends=True, **kw).splitlines(keepends)
+
+
+class Config(object):
+    def __init__(self, section, git_config=None):
+        """Represent a section of the git configuration.
+
+        If git_config is specified, it is passed to "git config" in
+        the GIT_CONFIG environment variable, meaning that "git config"
+        will read the specified path rather than the Git default
+        config paths."""
+
+        self.section = section
+        if git_config:
+            self.env = os.environ.copy()
+            self.env['GIT_CONFIG'] = git_config
+        else:
+            self.env = None
+
+    @staticmethod
+    def _split(s):
+        """Split NUL-terminated values."""
+
+        words = s.split('\0')
+        assert words[-1] == ''
+        return words[:-1]
+
+    def get(self, name, default=None):
+        try:
+            values = self._split(read_git_output(
+                    ['config', '--get', '--null', '%s.%s' % (self.section, name)],
+                    env=self.env, keepends=True,
+                    ))
+            assert len(values) == 1
+            return values[0]
+        except CommandError:
+            return default
+
+    def get_bool(self, name, default=None):
+        try:
+            value = read_git_output(
+                ['config', '--get', '--bool', '%s.%s' % (self.section, name)],
+                env=self.env,
+                )
+        except CommandError:
+            return default
+        return value == 'true'
+
+    def get_all(self, name, default=None):
+        """Read a (possibly multivalued) setting from the configuration.
+
+        Return the result as a list of values, or default if the name
+        is unset."""
+
+        try:
+            return self._split(read_git_output(
+                ['config', '--get-all', '--null', '%s.%s' % (self.section, name)],
+                env=self.env, keepends=True,
+                ))
+        except CommandError, e:
+            if e.retcode == 1:
+                # "the section or key is invalid"; i.e., there is no
+                # value for the specified key.
+                return default
+            else:
+                raise
+
+    def get_recipients(self, name, default=None):
+        """Read a recipients list from the configuration.
+
+        Return the result as a comma-separated list of email
+        addresses, or default if the option is unset.  If the setting
+        has multiple values, concatenate them with comma separators."""
+
+        lines = self.get_all(name, default=None)
+        if lines is None:
+            return default
+        return ', '.join(line.strip() for line in lines)
+
+    def set(self, name, value):
+        read_git_output(
+            ['config', '%s.%s' % (self.section, name), value],
+            env=self.env,
+            )
+
+    def add(self, name, value):
+        read_git_output(
+            ['config', '--add', '%s.%s' % (self.section, name), value],
+            env=self.env,
+            )
+
+    def has_key(self, name):
+        return self.get_all(name, default=None) is not None
+
+    def unset_all(self, name):
+        try:
+            read_git_output(
+                ['config', '--unset-all', '%s.%s' % (self.section, name)],
+                env=self.env,
+                )
+        except CommandError, e:
+            if e.retcode == 5:
+                # The name doesn't exist, which is what we wanted anyway...
+                pass
+            else:
+                raise
+
+    def set_recipients(self, name, value):
+        self.unset_all(name)
+        for pair in getaddresses([value]):
+            self.add(name, formataddr(pair))
+
+
+def generate_summaries(*log_args):
+    """Generate a brief summary for each revision requested.
+
+    log_args are strings that will be passed directly to "git log" as
+    revision selectors.  Iterate over (sha1_short, subject) for each
+    commit specified by log_args (subject is the first line of the
+    commit message as a string without EOLs)."""
+
+    cmd = [
+        'log', '--abbrev', '--format=%h %s',
+        ] + list(log_args) + ['--']
+    for line in read_git_lines(cmd):
+        yield tuple(line.split(' ', 1))
+
+
+def limit_lines(lines, max_lines):
+    for (index, line) in enumerate(lines):
+        if index < max_lines:
+            yield line
+
+    if index >= max_lines:
+        yield '... %d lines suppressed ...\n' % (index + 1 - max_lines,)
+
+
+def limit_linelength(lines, max_linelength):
+    for line in lines:
+        # Don't forget that lines always include a trailing newline.
+        if len(line) > max_linelength + 1:
+            line = line[:max_linelength - 7] + ' [...]\n'
+        yield line
+
+
+class CommitSet(object):
+    """A (constant) set of object names.
+
+    The set should be initialized with full SHA1 object names.  The
+    __contains__() method returns True iff its argument is an
+    abbreviation of any the names in the set."""
+
+    def __init__(self, names):
+        self._names = sorted(names)
+
+    def __len__(self):
+        return len(self._names)
+
+    def __contains__(self, sha1_abbrev):
+        """Return True iff this set contains sha1_abbrev (which might be abbreviated)."""
+
+        i = bisect.bisect_left(self._names, sha1_abbrev)
+        return i < len(self) and self._names[i].startswith(sha1_abbrev)
+
+
+class GitObject(object):
+    def __init__(self, sha1, type=None):
+        if sha1 == ZEROS:
+            self.sha1 = self.type = self.commit_sha1 = None
+        else:
+            self.sha1 = sha1
+            self.type = type or read_git_output(['cat-file', '-t', self.sha1])
+
+            if self.type == 'commit':
+                self.commit_sha1 = self.sha1
+            elif self.type == 'tag':
+                try:
+                    self.commit_sha1 = read_git_output(
+                        ['rev-parse', '--verify', '%s^0' % (self.sha1,)]
+                        )
+                except CommandError:
+                    # Cannot deref tag to determine commit_sha1
+                    self.commit_sha1 = None
+            else:
+                self.commit_sha1 = None
+
+        self.short = read_git_output(['rev-parse', '--short', sha1])
+
+    def get_summary(self):
+        """Return (sha1_short, subject) for this commit."""
+
+        if not self.sha1:
+            raise ValueError('Empty commit has no summary')
+
+        return iter(generate_summaries('--no-walk', self.sha1)).next()
+
+    def __eq__(self, other):
+        return isinstance(other, GitObject) and self.sha1 == other.sha1
+
+    def __hash__(self):
+        return hash(self.sha1)
+
+    def __nonzero__(self):
+        return bool(self.sha1)
+
+    def __str__(self):
+        return self.sha1 or ZEROS
+
+
+class Change(object):
+    """A Change that has been made to the Git repository.
+
+    Abstract class from which both Revisions and ReferenceChanges are
+    derived.  A Change knows how to generate a notification email
+    describing itself."""
+
+    def __init__(self, environment):
+        self.environment = environment
+        self._values = None
+
+    def _compute_values(self):
+        """Return a dictionary {keyword : expansion} for this Change.
+
+        Derived classes overload this method to add more entries to
+        the return value.  This method is used internally by
+        get_values().  The return value should always be a new
+        dictionary."""
+
+        return self.environment.get_values()
+
+    def get_values(self, **extra_values):
+        """Return a dictionary {keyword : expansion} for this Change.
+
+        Return a dictionary mapping keywords to the values that they
+        should be expanded to for this Change (used when interpolating
+        template strings).  If any keyword arguments are supplied, add
+        those to the return value as well.  The return value is always
+        a new dictionary."""
+
+        if self._values is None:
+            self._values = self._compute_values()
+
+        values = self._values.copy()
+        if extra_values:
+            values.update(extra_values)
+        return values
+
+    def expand(self, template, **extra_values):
+        """Expand template.
+
+        Expand the template (which should be a string) using string
+        interpolation of the values for this Change.  If any keyword
+        arguments are provided, also include those in the keywords
+        available for interpolation."""
+
+        return template % self.get_values(**extra_values)
+
+    def expand_lines(self, template, **extra_values):
+        """Break template into lines and expand each line."""
+
+        values = self.get_values(**extra_values)
+        for line in template.splitlines(True):
+            yield line % values
+
+    def expand_header_lines(self, template, **extra_values):
+        """Break template into lines and expand each line as an RFC 2822 header.
+
+        Encode values and split up lines that are too long.  Silently
+        skip lines that contain references to unknown variables."""
+
+        values = self.get_values(**extra_values)
+        for line in template.splitlines():
+            (name, value) = line.split(':', 1)
+
+            try:
+                value = value % values
+            except KeyError, e:
+                if DEBUG:
+                    sys.stderr.write(
+                        'Warning: unknown variable %r in the following line; line skipped:\n'
+                        '    %s\n'
+                        % (e.args[0], line,)
+                        )
+            else:
+                try:
+                    h = Header(value, header_name=name)
+                except UnicodeDecodeError:
+                    h = Header(value, header_name=name, charset=CHARSET, errors='replace')
+                for splitline in ('%s: %s\n' % (name, h.encode(),)).splitlines(True):
+                    yield splitline
+
+    def generate_email_header(self):
+        """Generate the RFC 2822 email headers for this Change, a line at a time.
+
+        The output should not include the trailing blank line."""
+
+        raise NotImplementedError()
+
+    def generate_email_intro(self):
+        """Generate the email intro for this Change, a line at a time.
+
+        The output will be used as the standard boilerplate at the top
+        of the email body."""
+
+        raise NotImplementedError()
+
+    def generate_email_body(self):
+        """Generate the main part of the email body, a line at a time.
+
+        The text in the body might be truncated after a specified
+        number of lines (see multimailhook.emailmaxlines)."""
+
+        raise NotImplementedError()
+
+    def generate_email_footer(self):
+        """Generate the footer of the email, a line at a time.
+
+        The footer is always included, irrespective of
+        multimailhook.emailmaxlines."""
+
+        raise NotImplementedError()
+
+    def generate_email(self, push, body_filter=None):
+        """Generate an email describing this change.
+
+        Iterate over the lines (including the header lines) of an
+        email describing this change.  If body_filter is not None,
+        then use it to filter the lines that are intended for the
+        email body."""
+
+        for line in self.generate_email_header():
+            yield line
+        yield '\n'
+        for line in self.generate_email_intro():
+            yield line
+
+        body = self.generate_email_body(push)
+        if body_filter is not None:
+            body = body_filter(body)
+        for line in body:
+            yield line
+
+        for line in self.generate_email_footer():
+            yield line
+
+
+class Revision(Change):
+    """A Change consisting of a single git commit."""
+
+    def __init__(self, reference_change, rev, num, tot):
+        Change.__init__(self, reference_change.environment)
+        self.reference_change = reference_change
+        self.rev = rev
+        self.change_type = self.reference_change.change_type
+        self.refname = self.reference_change.refname
+        self.num = num
+        self.tot = tot
+        self.author = read_git_output(['log', '--no-walk', '--format=%aN <%aE>', self.rev.sha1])
+        self.recipients = self.environment.get_revision_recipients(self)
+
+    def _compute_values(self):
+        values = Change._compute_values(self)
+
+        oneline = read_git_output(
+            ['log', '--format=%s', '--no-walk', self.rev.sha1]
+            )
+
+        values['rev'] = self.rev.sha1
+        values['rev_short'] = self.rev.short
+        values['change_type'] = self.change_type
+        values['refname'] = self.refname
+        values['short_refname'] = self.reference_change.short_refname
+        values['refname_type'] = self.reference_change.refname_type
+        values['reply_to_msgid'] = self.reference_change.msgid
+        values['num'] = self.num
+        values['tot'] = self.tot
+        values['recipients'] = self.recipients
+        values['oneline'] = oneline
+        values['author'] = self.author
+
+        reply_to = self.environment.get_reply_to_commit(self)
+        if reply_to:
+            values['reply_to'] = reply_to
+
+        return values
+
+    def generate_email_header(self):
+        for line in self.expand_header_lines(REVISION_HEADER_TEMPLATE):
+            yield line
+
+    def generate_email_intro(self):
+        for line in self.expand_lines(REVISION_INTRO_TEMPLATE):
+            yield line
+
+    def generate_email_body(self, push):
+        """Show this revision."""
+
+        return read_git_lines(
+            [
+                'log', '-C',
+                 '--stat', '-p', '--cc',
+                '-1', self.rev.sha1,
+                ],
+            keepends=True,
+            )
+
+    def generate_email_footer(self):
+        return self.expand_lines(REVISION_FOOTER_TEMPLATE)
+
+
+class ReferenceChange(Change):
+    """A Change to a Git reference.
+
+    An abstract class representing a create, update, or delete of a
+    Git reference.  Derived classes handle specific types of reference
+    (e.g., tags vs. branches).  These classes generate the main
+    reference change email summarizing the reference change and
+    whether it caused any any commits to be added or removed.
+
+    ReferenceChange objects are usually created using the static
+    create() method, which has the logic to decide which derived class
+    to instantiate."""
+
+    REF_RE = re.compile(r'^refs\/(?P<area>[^\/]+)\/(?P<shortname>.*)$')
+
+    @staticmethod
+    def create(environment, oldrev, newrev, refname):
+        """Return a ReferenceChange object representing the change.
+
+        Return an object that represents the type of change that is being
+        made. oldrev and newrev should be SHA1s or ZEROS."""
+
+        old = GitObject(oldrev)
+        new = GitObject(newrev)
+        rev = new or old
+
+        # The revision type tells us what type the commit is, combined with
+        # the location of the ref we can decide between
+        #  - working branch
+        #  - tracking branch
+        #  - unannotated tag
+        #  - annotated tag
+        m = ReferenceChange.REF_RE.match(refname)
+        if m:
+            area = m.group('area')
+            short_refname = m.group('shortname')
+        else:
+            area = ''
+            short_refname = refname
+
+        if rev.type == 'tag':
+            # Annotated tag:
+            klass = AnnotatedTagChange
+        elif rev.type == 'commit':
+            if area == 'tags':
+                # Non-annotated tag:
+                klass = NonAnnotatedTagChange
+            elif area == 'heads':
+                # Branch:
+                klass = BranchChange
+            elif area == 'remotes':
+                # Tracking branch:
+                sys.stderr.write(
+                    '*** Push-update of tracking branch %r\n'
+                    '***  - incomplete email generated.\n'
+                     % (refname,)
+                    )
+                klass = OtherReferenceChange
+            else:
+                # Some other reference namespace:
+                sys.stderr.write(
+                    '*** Push-update of strange reference %r\n'
+                    '***  - incomplete email generated.\n'
+                     % (refname,)
+                    )
+                klass = OtherReferenceChange
+        else:
+            # Anything else (is there anything else?)
+            sys.stderr.write(
+                '*** Unknown type of update to %r (%s)\n'
+                '***  - incomplete email generated.\n'
+                 % (refname, rev.type,)
+                )
+            klass = OtherReferenceChange
+
+        return klass(
+            environment,
+            refname=refname, short_refname=short_refname,
+            old=old, new=new, rev=rev,
+            )
+
+    def __init__(self, environment, refname, short_refname, old, new, rev):
+        Change.__init__(self, environment)
+        self.change_type = {
+            (False, True) : 'create',
+            (True, True) : 'update',
+            (True, False) : 'delete',
+            }[bool(old), bool(new)]
+        self.refname = refname
+        self.short_refname = short_refname
+        self.old = old
+        self.new = new
+        self.rev = rev
+        self.msgid = make_msgid()
+        self.diffopts = environment.diffopts
+        self.logopts = environment.logopts
+        self.showlog = environment.refchange_showlog
+
+    def _compute_values(self):
+        values = Change._compute_values(self)
+
+        values['change_type'] = self.change_type
+        values['refname_type'] = self.refname_type
+        values['refname'] = self.refname
+        values['short_refname'] = self.short_refname
+        values['msgid'] = self.msgid
+        values['recipients'] = self.recipients
+        values['oldrev'] = str(self.old)
+        values['oldrev_short'] = self.old.short
+        values['newrev'] = str(self.new)
+        values['newrev_short'] = self.new.short
+
+        if self.old:
+            values['oldrev_type'] = self.old.type
+        if self.new:
+            values['newrev_type'] = self.new.type
+
+        reply_to = self.environment.get_reply_to_refchange(self)
+        if reply_to:
+            values['reply_to'] = reply_to
+
+        return values
+
+    def get_subject(self):
+        template = {
+            'create' : REF_CREATED_SUBJECT_TEMPLATE,
+            'update' : REF_UPDATED_SUBJECT_TEMPLATE,
+            'delete' : REF_DELETED_SUBJECT_TEMPLATE,
+            }[self.change_type]
+        return self.expand(template)
+
+    def generate_email_header(self):
+        for line in self.expand_header_lines(
+            REFCHANGE_HEADER_TEMPLATE, subject=self.get_subject(),
+            ):
+            yield line
+
+    def generate_email_intro(self):
+        for line in self.expand_lines(REFCHANGE_INTRO_TEMPLATE):
+            yield line
+
+    def generate_email_body(self, push):
+        """Call the appropriate body-generation routine.
+
+        Call one of generate_create_summary() /
+        generate_update_summary() / generate_delete_summary()."""
+
+        change_summary = {
+            'create' : self.generate_create_summary,
+            'delete' : self.generate_delete_summary,
+            'update' : self.generate_update_summary,
+            }[self.change_type](push)
+        for line in change_summary:
+            yield line
+
+        for line in self.generate_revision_change_summary(push):
+            yield line
+
+    def generate_email_footer(self):
+        return self.expand_lines(FOOTER_TEMPLATE)
+
+    def generate_revision_change_log(self, new_commits_list):
+        if self.showlog:
+            yield '\n'
+            yield 'Detailed log of new commits:\n\n'
+            for line in read_git_lines(
+                    ['log', '--no-walk']
+                    + self.logopts
+                    + new_commits_list
+                    + ['--'],
+                    keepends=True,
+                ):
+                yield line
+
+    def generate_revision_change_summary(self, push):
+        """Generate a summary of the revisions added/removed by this change."""
+
+        if self.new.commit_sha1 and not self.old.commit_sha1:
+            # A new reference was created.  List the new revisions
+            # brought by the new reference (i.e., those revisions that
+            # were not in the repository before this reference
+            # change).
+            sha1s = list(push.get_new_commits(self))
+            sha1s.reverse()
+            tot = len(sha1s)
+            new_revisions = [
+                Revision(self, GitObject(sha1), num=i+1, tot=tot)
+                for (i, sha1) in enumerate(sha1s)
+                ]
+
+            if new_revisions:
+                yield self.expand('This %(refname_type)s includes the following new commits:\n')
+                yield '\n'
+                for r in new_revisions:
+                    (sha1, subject) = r.rev.get_summary()
+                    yield r.expand(
+                        BRIEF_SUMMARY_TEMPLATE, action='new', text=subject,
+                        )
+                yield '\n'
+                for line in self.expand_lines(NEW_REVISIONS_TEMPLATE, tot=tot):
+                    yield line
+                for line in self.generate_revision_change_log([r.rev.sha1 for r in new_revisions]):
+                    yield line
+            else:
+                for line in self.expand_lines(NO_NEW_REVISIONS_TEMPLATE):
+                    yield line
+
+        elif self.new.commit_sha1 and self.old.commit_sha1:
+            # A reference was changed to point at a different commit.
+            # List the revisions that were removed and/or added *from
+            # that reference* by this reference change, along with a
+            # diff between the trees for its old and new values.
+
+            # List of the revisions that were added to the branch by
+            # this update.  Note this list can include revisions that
+            # have already had notification emails; we want such
+            # revisions in the summary even though we will not send
+            # new notification emails for them.
+            adds = list(generate_summaries(
+                    '--topo-order', '--reverse', '%s..%s'
+                    % (self.old.commit_sha1, self.new.commit_sha1,)
+                    ))
+
+            # List of the revisions that were removed from the branch
+            # by this update.  This will be empty except for
+            # non-fast-forward updates.
+            discards = list(generate_summaries(
+                    '%s..%s' % (self.new.commit_sha1, self.old.commit_sha1,)
+                    ))
+
+            if adds:
+                new_commits_list = push.get_new_commits(self)
+            else:
+                new_commits_list = []
+            new_commits = CommitSet(new_commits_list)
+
+            if discards:
+                discarded_commits = CommitSet(push.get_discarded_commits(self))
+            else:
+                discarded_commits = CommitSet([])
+
+            if discards and adds:
+                for (sha1, subject) in discards:
+                    if sha1 in discarded_commits:
+                        action = 'discards'
+                    else:
+                        action = 'omits'
+                    yield self.expand(
+                        BRIEF_SUMMARY_TEMPLATE, action=action,
+                        rev_short=sha1, text=subject,
+                        )
+                for (sha1, subject) in adds:
+                    if sha1 in new_commits:
+                        action = 'new'
+                    else:
+                        action = 'adds'
+                    yield self.expand(
+                        BRIEF_SUMMARY_TEMPLATE, action=action,
+                        rev_short=sha1, text=subject,
+                        )
+                yield '\n'
+                for line in self.expand_lines(NON_FF_TEMPLATE):
+                    yield line
+
+            elif discards:
+                for (sha1, subject) in discards:
+                    if sha1 in discarded_commits:
+                        action = 'discards'
+                    else:
+                        action = 'omits'
+                    yield self.expand(
+                        BRIEF_SUMMARY_TEMPLATE, action=action,
+                        rev_short=sha1, text=subject,
+                        )
+                yield '\n'
+                for line in self.expand_lines(REWIND_ONLY_TEMPLATE):
+                    yield line
+
+            elif adds:
+                (sha1, subject) = self.old.get_summary()
+                yield self.expand(
+                    BRIEF_SUMMARY_TEMPLATE, action='from',
+                    rev_short=sha1, text=subject,
+                    )
+                for (sha1, subject) in adds:
+                    if sha1 in new_commits:
+                        action = 'new'
+                    else:
+                        action = 'adds'
+                    yield self.expand(
+                        BRIEF_SUMMARY_TEMPLATE, action=action,
+                        rev_short=sha1, text=subject,
+                        )
+
+            yield '\n'
+
+            if new_commits:
+                for line in self.expand_lines(NEW_REVISIONS_TEMPLATE, tot=len(new_commits)):
+                    yield line
+                for line in self.generate_revision_change_log(new_commits_list):
+                    yield line
+            else:
+                for line in self.expand_lines(NO_NEW_REVISIONS_TEMPLATE):
+                    yield line
+
+            # The diffstat is shown from the old revision to the new
+            # revision.  This is to show the truth of what happened in
+            # this change.  There's no point showing the stat from the
+            # base to the new revision because the base is effectively a
+            # random revision at this point - the user will be interested
+            # in what this revision changed - including the undoing of
+            # previous revisions in the case of non-fast-forward updates.
+            yield '\n'
+            yield 'Summary of changes:\n'
+            for line in read_git_lines(
+                ['diff-tree']
+                + self.diffopts
+                + ['%s..%s' % (self.old.commit_sha1, self.new.commit_sha1,)],
+                keepends=True,
+                ):
+                yield line
+
+        elif self.old.commit_sha1 and not self.new.commit_sha1:
+            # A reference was deleted.  List the revisions that were
+            # removed from the repository by this reference change.
+
+            sha1s = list(push.get_discarded_commits(self))
+            tot = len(sha1s)
+            discarded_revisions = [
+                Revision(self, GitObject(sha1), num=i+1, tot=tot)
+                for (i, sha1) in enumerate(sha1s)
+                ]
+
+            if discarded_revisions:
+                for line in self.expand_lines(DISCARDED_REVISIONS_TEMPLATE):
+                    yield line
+                yield '\n'
+                for r in discarded_revisions:
+                    (sha1, subject) = r.rev.get_summary()
+                    yield r.expand(
+                        BRIEF_SUMMARY_TEMPLATE, action='discards', text=subject,
+                        )
+            else:
+                for line in self.expand_lines(NO_DISCARDED_REVISIONS_TEMPLATE):
+                    yield line
+
+        elif not self.old.commit_sha1 and not self.new.commit_sha1:
+            for line in self.expand_lines(NON_COMMIT_UPDATE_TEMPLATE):
+                yield line
+
+    def generate_create_summary(self, push):
+        """Called for the creation of a reference."""
+
+        # This is a new reference and so oldrev is not valid
+        (sha1, subject) = self.new.get_summary()
+        yield self.expand(
+            BRIEF_SUMMARY_TEMPLATE, action='at',
+            rev_short=sha1, text=subject,
+            )
+        yield '\n'
+
+    def generate_update_summary(self, push):
+        """Called for the change of a pre-existing branch."""
+
+        return iter([])
+
+    def generate_delete_summary(self, push):
+        """Called for the deletion of any type of reference."""
+
+        (sha1, subject) = self.old.get_summary()
+        yield self.expand(
+            BRIEF_SUMMARY_TEMPLATE, action='was',
+            rev_short=sha1, text=subject,
+            )
+        yield '\n'
+
+
+class BranchChange(ReferenceChange):
+    refname_type = 'branch'
+
+    def __init__(self, environment, refname, short_refname, old, new, rev):
+        ReferenceChange.__init__(
+            self, environment,
+            refname=refname, short_refname=short_refname,
+            old=old, new=new, rev=rev,
+            )
+        self.recipients = environment.get_refchange_recipients(self)
+
+
+class AnnotatedTagChange(ReferenceChange):
+    refname_type = 'annotated tag'
+
+    def __init__(self, environment, refname, short_refname, old, new, rev):
+        ReferenceChange.__init__(
+            self, environment,
+            refname=refname, short_refname=short_refname,
+            old=old, new=new, rev=rev,
+            )
+        self.recipients = environment.get_announce_recipients(self)
+        self.show_shortlog = environment.announce_show_shortlog
+
+    ANNOTATED_TAG_FORMAT = (
+        '%(*objectname)\n'
+        '%(*objecttype)\n'
+        '%(taggername)\n'
+        '%(taggerdate)'
+        )
+
+    def describe_tag(self, push):
+        """Describe the new value of an annotated tag."""
+
+        # Use git for-each-ref to pull out the individual fields from
+        # the tag
+        [tagobject, tagtype, tagger, tagged] = read_git_lines(
+            ['for-each-ref', '--format=%s' % (self.ANNOTATED_TAG_FORMAT,), self.refname],
+            )
+
+        yield self.expand(
+            BRIEF_SUMMARY_TEMPLATE, action='tagging',
+            rev_short=tagobject, text='(%s)' % (tagtype,),
+            )
+        if tagtype == 'commit':
+            # If the tagged object is a commit, then we assume this is a
+            # release, and so we calculate which tag this tag is
+            # replacing
+            try:
+                prevtag = read_git_output(['describe', '--abbrev=0', '%s^' % (self.new,)])
+            except CommandError:
+                prevtag = None
+            if prevtag:
+                yield '  replaces  %s\n' % (prevtag,)
+        else:
+            prevtag = None
+            yield '    length  %s bytes\n' % (read_git_output(['cat-file', '-s', tagobject]),)
+
+        yield ' tagged by  %s\n' % (tagger,)
+        yield '        on  %s\n' % (tagged,)
+        yield '\n'
+
+        # Show the content of the tag message; this might contain a
+        # change log or release notes so is worth displaying.
+        yield LOGBEGIN
+        contents = list(read_git_lines(['cat-file', 'tag', self.new.sha1], keepends=True))
+        contents = contents[contents.index('\n') + 1:]
+        if contents and contents[-1][-1:] != '\n':
+            contents.append('\n')
+        for line in contents:
+            yield line
+
+        if self.show_shortlog and tagtype == 'commit':
+            # Only commit tags make sense to have rev-list operations
+            # performed on them
+            yield '\n'
+            if prevtag:
+                # Show changes since the previous release
+                revlist = read_git_output(
+                    ['rev-list', '--pretty=short', '%s..%s' % (prevtag, self.new,)],
+                    keepends=True,
+                    )
+            else:
+                # No previous tag, show all the changes since time
+                # began
+                revlist = read_git_output(
+                    ['rev-list', '--pretty=short', '%s' % (self.new,)],
+                    keepends=True,
+                    )
+            for line in read_git_lines(['shortlog'], input=revlist, keepends=True):
+                yield line
+
+        yield LOGEND
+        yield '\n'
+
+    def generate_create_summary(self, push):
+        """Called for the creation of an annotated tag."""
+
+        for line in self.expand_lines(TAG_CREATED_TEMPLATE):
+            yield line
+
+        for line in self.describe_tag(push):
+            yield line
+
+    def generate_update_summary(self, push):
+        """Called for the update of an annotated tag.
+
+        This is probably a rare event and may not even be allowed."""
+
+        for line in self.expand_lines(TAG_UPDATED_TEMPLATE):
+            yield line
+
+        for line in self.describe_tag(push):
+            yield line
+
+    def generate_delete_summary(self, push):
+        """Called when a non-annotated reference is updated."""
+
+        for line in self.expand_lines(TAG_DELETED_TEMPLATE):
+            yield line
+
+        yield self.expand('   tag was  %(oldrev_short)s\n')
+        yield '\n'
+
+
+class NonAnnotatedTagChange(ReferenceChange):
+    refname_type = 'tag'
+
+    def __init__(self, environment, refname, short_refname, old, new, rev):
+        ReferenceChange.__init__(
+            self, environment,
+            refname=refname, short_refname=short_refname,
+            old=old, new=new, rev=rev,
+            )
+        self.recipients = environment.get_refchange_recipients(self)
+
+    def generate_create_summary(self, push):
+        """Called for the creation of an annotated tag."""
+
+        for line in self.expand_lines(TAG_CREATED_TEMPLATE):
+            yield line
+
+    def generate_update_summary(self, push):
+        """Called when a non-annotated reference is updated."""
+
+        for line in self.expand_lines(TAG_UPDATED_TEMPLATE):
+            yield line
+
+    def generate_delete_summary(self, push):
+        """Called when a non-annotated reference is updated."""
+
+        for line in self.expand_lines(TAG_DELETED_TEMPLATE):
+            yield line
+
+        for line in ReferenceChange.generate_delete_summary(self, push):
+            yield line
+
+
+class OtherReferenceChange(ReferenceChange):
+    refname_type = 'reference'
+
+    def __init__(self, environment, refname, short_refname, old, new, rev):
+        # We use the full refname as short_refname, because otherwise
+        # the full name of the reference would not be obvious from the
+        # text of the email.
+        ReferenceChange.__init__(
+            self, environment,
+            refname=refname, short_refname=refname,
+            old=old, new=new, rev=rev,
+            )
+        self.recipients = environment.get_refchange_recipients(self)
+
+
+class Mailer(object):
+    """An object that can send emails."""
+
+    def send(self, lines, to_addrs):
+        """Send an email consisting of lines.
+
+        lines must be an iterable over the lines constituting the
+        header and body of the email.  to_addrs is a list of recipient
+        addresses (can be needed even if lines already contains a
+        "To:" field).  It can be either a string (comma-separated list
+        of email addresses) or a Python list of individual email
+        addresses.
+
+        """
+
+        raise NotImplementedError()
+
+
+class SendMailer(Mailer):
+    """Send emails using 'sendmail -t'."""
+
+    SENDMAIL_CANDIDATES = [
+        '/usr/sbin/sendmail',
+        '/usr/lib/sendmail',
+        ]
+
+    @staticmethod
+    def find_sendmail():
+        for path in SendMailer.SENDMAIL_CANDIDATES:
+            if os.access(path, os.X_OK):
+                return path
+        else:
+            raise ConfigurationException(
+                'No sendmail executable found.  '
+                'Try setting multimailhook.sendmailCommand.'
+                )
+
+    def __init__(self, command=None, envelopesender=None):
+        """Construct a SendMailer instance.
+
+        command should be the command and arguments used to invoke
+        sendmail, as a list of strings.  If an envelopesender is
+        provided, it will also be passed to the command, via '-f
+        envelopesender'."""
+
+        if command:
+            self.command = command[:]
+        else:
+            self.command = [self.find_sendmail(), '-t']
+
+        if envelopesender:
+            self.command.extend(['-f', envelopesender])
+
+    def send(self, lines, to_addrs):
+        try:
+            p = subprocess.Popen(self.command, stdin=subprocess.PIPE)
+        except OSError, e:
+            sys.stderr.write(
+                '*** Cannot execute command: %s\n' % ' '.join(self.command)
+                + '*** %s\n' % str(e)
+                + '*** Try setting multimailhook.mailer to "smtp"\n'
+                '*** to send emails without using the sendmail command.\n'
+                )
+            sys.exit(1)
+        try:
+            p.stdin.writelines(lines)
+        except:
+            sys.stderr.write(
+                '*** Error while generating commit email\n'
+                '***  - mail sending aborted.\n'
+                )
+            p.terminate()
+            raise
+        else:
+            p.stdin.close()
+            retcode = p.wait()
+            if retcode:
+                raise CommandError(self.command, retcode)
+
+
+class SMTPMailer(Mailer):
+    """Send emails using Python's smtplib."""
+
+    def __init__(self, envelopesender, smtpserver):
+        if not envelopesender:
+            sys.stderr.write(
+                'fatal: git_multimail: cannot use SMTPMailer without a sender address.\n'
+                'please set either multimailhook.envelopeSender or user.email\n'
+                )
+            sys.exit(1)
+        self.envelopesender = envelopesender
+        self.smtpserver = smtpserver
+        try:
+            self.smtp = smtplib.SMTP(self.smtpserver)
+        except Exception, e:
+            sys.stderr.write('*** Error establishing SMTP connection to %s***\n' % self.smtpserver)
+            sys.stderr.write('*** %s\n' % str(e))
+            sys.exit(1)
+
+    def __del__(self):
+        self.smtp.quit()
+
+    def send(self, lines, to_addrs):
+        try:
+            msg = ''.join(lines)
+            # turn comma-separated list into Python list if needed.
+            if isinstance(to_addrs, basestring):
+                to_addrs = [email for (name, email) in getaddresses([to_addrs])]
+            self.smtp.sendmail(self.envelopesender, to_addrs, msg)
+        except Exception, e:
+            sys.stderr.write('*** Error sending email***\n')
+            sys.stderr.write('*** %s\n' % str(e))
+            self.smtp.quit()
+            sys.exit(1)
+
+
+class OutputMailer(Mailer):
+    """Write emails to an output stream, bracketed by lines of '=' characters.
+
+    This is intended for debugging purposes."""
+
+    SEPARATOR = '=' * 75 + '\n'
+
+    def __init__(self, f):
+        self.f = f
+
+    def send(self, lines, to_addrs):
+        self.f.write(self.SEPARATOR)
+        self.f.writelines(lines)
+        self.f.write(self.SEPARATOR)
+
+
+def get_git_dir():
+    """Determine GIT_DIR.
+
+    Determine GIT_DIR either from the GIT_DIR environment variable or
+    from the working directory, using Git's usual rules."""
+
+    try:
+        return read_git_output(['rev-parse', '--git-dir'])
+    except CommandError:
+        sys.stderr.write('fatal: git_multimail: not in a git directory\n')
+        sys.exit(1)
+
+
+class Environment(object):
+    """Describes the environment in which the push is occurring.
+
+    An Environment object encapsulates information about the local
+    environment.  For example, it knows how to determine:
+
+    * the name of the repository to which the push occurred
+
+    * what user did the push
+
+    * what users want to be informed about various types of changes.
+
+    An Environment object is expected to have the following methods:
+
+        get_repo_shortname()
+
+            Return a short name for the repository, for display
+            purposes.
+
+        get_repo_path()
+
+            Return the absolute path to the Git repository.
+
+        get_emailprefix()
+
+            Return a string that will be prefixed to every email's
+            subject.
+
+        get_pusher()
+
+            Return the username of the person who pushed the changes.
+            This value is used in the email body to indicate who
+            pushed the change.
+
+        get_pusher_email() (may return None)
+
+            Return the email address of the person who pushed the
+            changes.  The value should be a single RFC 2822 email
+            address as a string; e.g., "Joe User <user@example.com>"
+            if available, otherwise "user@example.com".  If set, the
+            value is used as the Reply-To address for refchange
+            emails.  If it is impossible to determine the pusher's
+            email, this attribute should be set to None (in which case
+            no Reply-To header will be output).
+
+        get_sender()
+
+            Return the address to be used as the 'From' email address
+            in the email envelope.
+
+        get_fromaddr()
+
+            Return the 'From' email address used in the email 'From:'
+            headers.  (May be a full RFC 2822 email address like 'Joe
+            User <user@example.com>'.)
+
+        get_administrator()
+
+            Return the name and/or email of the repository
+            administrator.  This value is used in the footer as the
+            person to whom requests to be removed from the
+            notification list should be sent.  Ideally, it should
+            include a valid email address.
+
+        get_reply_to_refchange()
+        get_reply_to_commit()
+
+            Return the address to use in the email "Reply-To" header,
+            as a string.  These can be an RFC 2822 email address, or
+            None to omit the "Reply-To" header.
+            get_reply_to_refchange() is used for refchange emails;
+            get_reply_to_commit() is used for individual commit
+            emails.
+
+    They should also define the following attributes:
+
+        announce_show_shortlog (bool)
+
+            True iff announce emails should include a shortlog.
+
+        refchange_showlog (bool)
+
+            True iff refchanges emails should include a detailed log.
+
+        diffopts (list of strings)
+
+            The options that should be passed to 'git diff' for the
+            summary email.  The value should be a list of strings
+            representing words to be passed to the command.
+
+        logopts (list of strings)
+
+            Analogous to diffopts, but contains options passed to
+            'git log' when generating the detailed log for a set of
+            commits (see refchange_showlog)
+
+    """
+
+    REPO_NAME_RE = re.compile(r'^(?P<name>.+?)(?:\.git)$')
+
+    def __init__(self, osenv=None):
+        self.osenv = osenv or os.environ
+        self.announce_show_shortlog = False
+        self.maxcommitemails = 500
+        self.diffopts = ['--stat', '--summary', '--find-copies-harder']
+        self.logopts = []
+        self.refchange_showlog = False
+
+        self.COMPUTED_KEYS = [
+            'administrator',
+            'charset',
+            'emailprefix',
+            'fromaddr',
+            'pusher',
+            'pusher_email',
+            'repo_path',
+            'repo_shortname',
+            'sender',
+            ]
+
+        self._values = None
+
+    def get_repo_shortname(self):
+        """Use the last part of the repo path, with ".git" stripped off if present."""
+
+        basename = os.path.basename(os.path.abspath(self.get_repo_path()))
+        m = self.REPO_NAME_RE.match(basename)
+        if m:
+            return m.group('name')
+        else:
+            return basename
+
+    def get_pusher(self):
+        raise NotImplementedError()
+
+    def get_pusher_email(self):
+        return None
+
+    def get_administrator(self):
+        return 'the administrator of this repository'
+
+    def get_emailprefix(self):
+        return ''
+
+    def get_repo_path(self):
+        if read_git_output(['rev-parse', '--is-bare-repository']) == 'true':
+            path = get_git_dir()
+        else:
+            path = read_git_output(['rev-parse', '--show-toplevel'])
+        return os.path.abspath(path)
+
+    def get_charset(self):
+        return CHARSET
+
+    def get_values(self):
+        """Return a dictionary {keyword : expansion} for this Environment.
+
+        This method is called by Change._compute_values().  The keys
+        in the returned dictionary are available to be used in any of
+        the templates.  The dictionary is created by calling
+        self.get_NAME() for each of the attributes named in
+        COMPUTED_KEYS and recording those that do not return None.
+        The return value is always a new dictionary."""
+
+        if self._values is None:
+            values = {}
+
+            for key in self.COMPUTED_KEYS:
+                value = getattr(self, 'get_%s' % (key,))()
+                if value is not None:
+                    values[key] = value
+
+            self._values = values
+
+        return self._values.copy()
+
+    def get_refchange_recipients(self, refchange):
+        """Return the recipients for notifications about refchange.
+
+        Return the list of email addresses to which notifications
+        about the specified ReferenceChange should be sent."""
+
+        raise NotImplementedError()
+
+    def get_announce_recipients(self, annotated_tag_change):
+        """Return the recipients for notifications about annotated_tag_change.
+
+        Return the list of email addresses to which notifications
+        about the specified AnnotatedTagChange should be sent."""
+
+        raise NotImplementedError()
+
+    def get_reply_to_refchange(self, refchange):
+        return self.get_pusher_email()
+
+    def get_revision_recipients(self, revision):
+        """Return the recipients for messages about revision.
+
+        Return the list of email addresses to which notifications
+        about the specified Revision should be sent.  This method
+        could be overridden, for example, to take into account the
+        contents of the revision when deciding whom to notify about
+        it.  For example, there could be a scheme for users to express
+        interest in particular files or subdirectories, and only
+        receive notification emails for revisions that affecting those
+        files."""
+
+        raise NotImplementedError()
+
+    def get_reply_to_commit(self, revision):
+        return revision.author
+
+    def filter_body(self, lines):
+        """Filter the lines intended for an email body.
+
+        lines is an iterable over the lines that would go into the
+        email body.  Filter it (e.g., limit the number of lines, the
+        line length, character set, etc.), returning another iterable.
+        See FilterLinesEnvironmentMixin and MaxlinesEnvironmentMixin
+        for classes implementing this functionality."""
+
+        return lines
+
+
+class ConfigEnvironmentMixin(Environment):
+    """A mixin that sets self.config to its constructor's config argument.
+
+    This class's constructor consumes the "config" argument.
+
+    Mixins that need to inspect the config should inherit from this
+    class (1) to make sure that "config" is still in the constructor
+    arguments with its own constructor runs and/or (2) to be sure that
+    self.config is set after construction."""
+
+    def __init__(self, config, **kw):
+        super(ConfigEnvironmentMixin, self).__init__(**kw)
+        self.config = config
+
+
+class ConfigOptionsEnvironmentMixin(ConfigEnvironmentMixin):
+    """An Environment that reads most of its information from "git config"."""
+
+    def __init__(self, config, **kw):
+        super(ConfigOptionsEnvironmentMixin, self).__init__(
+            config=config, **kw
+            )
+
+        self.announce_show_shortlog = config.get_bool(
+            'announceshortlog', default=self.announce_show_shortlog
+            )
+
+        self.refchange_showlog = config.get_bool(
+            'refchangeshowlog', default=self.refchange_showlog
+            )
+
+        maxcommitemails = config.get('maxcommitemails')
+        if maxcommitemails is not None:
+            try:
+                self.maxcommitemails = int(maxcommitemails)
+            except ValueError:
+                sys.stderr.write(
+                    '*** Malformed value for multimailhook.maxCommitEmails: %s\n' % maxcommitemails
+                    + '*** Expected a number.  Ignoring.\n'
+                    )
+
+        diffopts = config.get('diffopts')
+        if diffopts is not None:
+            self.diffopts = shlex.split(diffopts)
+
+        logopts = config.get('logopts')
+        if logopts is not None:
+            self.logopts = shlex.split(logopts)
+
+        reply_to = config.get('replyTo')
+        self.__reply_to_refchange = config.get('replyToRefchange', default=reply_to)
+        if (
+            self.__reply_to_refchange is not None
+            and self.__reply_to_refchange.lower() == 'author'
+            ):
+            raise ConfigurationException(
+                '"author" is not an allowed setting for replyToRefchange'
+                )
+        self.__reply_to_commit = config.get('replyToCommit', default=reply_to)
+
+    def get_administrator(self):
+        return (
+            self.config.get('administrator')
+            or self.get_sender()
+            or super(ConfigOptionsEnvironmentMixin, self).get_administrator()
+            )
+
+    def get_repo_shortname(self):
+        return (
+            self.config.get('reponame')
+            or super(ConfigOptionsEnvironmentMixin, self).get_repo_shortname()
+            )
+
+    def get_emailprefix(self):
+        emailprefix = self.config.get('emailprefix')
+        if emailprefix and emailprefix.strip():
+            return emailprefix.strip() + ' '
+        else:
+            return '[%s] ' % (self.get_repo_shortname(),)
+
+    def get_sender(self):
+        return self.config.get('envelopesender')
+
+    def get_fromaddr(self):
+        fromaddr = self.config.get('from')
+        if fromaddr:
+            return fromaddr
+        else:
+            config = Config('user')
+            fromname = config.get('name', default='')
+            fromemail = config.get('email', default='')
+            if fromemail:
+                return formataddr([fromname, fromemail])
+            else:
+                return self.get_sender()
+
+    def get_reply_to_refchange(self, refchange):
+        if self.__reply_to_refchange is None:
+            return super(ConfigOptionsEnvironmentMixin, self).get_reply_to_refchange(refchange)
+        elif self.__reply_to_refchange.lower() == 'pusher':
+            return self.get_pusher_email()
+        elif self.__reply_to_refchange.lower() == 'none':
+            return None
+        else:
+            return self.__reply_to_refchange
+
+    def get_reply_to_commit(self, revision):
+        if self.__reply_to_commit is None:
+            return super(ConfigOptionsEnvironmentMixin, self).get_reply_to_commit(revision)
+        elif self.__reply_to_commit.lower() == 'author':
+            return revision.get_author()
+        elif self.__reply_to_commit.lower() == 'pusher':
+            return self.get_pusher_email()
+        elif self.__reply_to_commit.lower() == 'none':
+            return None
+        else:
+            return self.__reply_to_commit
+
+
+class FilterLinesEnvironmentMixin(Environment):
+    """Handle encoding and maximum line length of body lines.
+
+        emailmaxlinelength (int or None)
+
+            The maximum length of any single line in the email body.
+            Longer lines are truncated at that length with ' [...]'
+            appended.
+
+        strict_utf8 (bool)
+
+            If this field is set to True, then the email body text is
+            expected to be UTF-8.  Any invalid characters are
+            converted to U+FFFD, the Unicode replacement character
+            (encoded as UTF-8, of course).
+
+    """
+
+    def __init__(self, strict_utf8=True, emailmaxlinelength=500, **kw):
+        super(FilterLinesEnvironmentMixin, self).__init__(**kw)
+        self.__strict_utf8 = strict_utf8
+        self.__emailmaxlinelength = emailmaxlinelength
+
+    def filter_body(self, lines):
+        lines = super(FilterLinesEnvironmentMixin, self).filter_body(lines)
+        if self.__strict_utf8:
+            lines = (line.decode(ENCODING, 'replace') for line in lines)
+            # Limit the line length in Unicode-space to avoid
+            # splitting characters:
+            if self.__emailmaxlinelength:
+                lines = limit_linelength(lines, self.__emailmaxlinelength)
+            lines = (line.encode(ENCODING, 'replace') for line in lines)
+        elif self.__emailmaxlinelength:
+            lines = limit_linelength(lines, self.__emailmaxlinelength)
+
+        return lines
+
+
+class ConfigFilterLinesEnvironmentMixin(
+    ConfigEnvironmentMixin,
+    FilterLinesEnvironmentMixin,
+    ):
+    """Handle encoding and maximum line length based on config."""
+
+    def __init__(self, config, **kw):
+        strict_utf8 = config.get_bool('emailstrictutf8', default=None)
+        if strict_utf8 is not None:
+            kw['strict_utf8'] = strict_utf8
+
+        emailmaxlinelength = config.get('emailmaxlinelength')
+        if emailmaxlinelength is not None:
+            kw['emailmaxlinelength'] = int(emailmaxlinelength)
+
+        super(ConfigFilterLinesEnvironmentMixin, self).__init__(
+            config=config, **kw
+            )
+
+
+class MaxlinesEnvironmentMixin(Environment):
+    """Limit the email body to a specified number of lines."""
+
+    def __init__(self, emailmaxlines, **kw):
+        super(MaxlinesEnvironmentMixin, self).__init__(**kw)
+        self.__emailmaxlines = emailmaxlines
+
+    def filter_body(self, lines):
+        lines = super(MaxlinesEnvironmentMixin, self).filter_body(lines)
+        if self.__emailmaxlines:
+            lines = limit_lines(lines, self.__emailmaxlines)
+        return lines
+
+
+class ConfigMaxlinesEnvironmentMixin(
+    ConfigEnvironmentMixin,
+    MaxlinesEnvironmentMixin,
+    ):
+    """Limit the email body to the number of lines specified in config."""
+
+    def __init__(self, config, **kw):
+        emailmaxlines = int(config.get('emailmaxlines', default='0'))
+        super(ConfigMaxlinesEnvironmentMixin, self).__init__(
+            config=config,
+            emailmaxlines=emailmaxlines,
+            **kw
+            )
+
+
+class PusherDomainEnvironmentMixin(ConfigEnvironmentMixin):
+    """Deduce pusher_email from pusher by appending an emaildomain."""
+
+    def __init__(self, **kw):
+        super(PusherDomainEnvironmentMixin, self).__init__(**kw)
+        self.__emaildomain = self.config.get('emaildomain')
+
+    def get_pusher_email(self):
+        if self.__emaildomain:
+            # Derive the pusher's full email address in the default way:
+            return '%s@%s' % (self.get_pusher(), self.__emaildomain)
+        else:
+            return super(PusherDomainEnvironmentMixin, self).get_pusher_email()
+
+
+class StaticRecipientsEnvironmentMixin(Environment):
+    """Set recipients statically based on constructor parameters."""
+
+    def __init__(
+        self,
+        refchange_recipients, announce_recipients, revision_recipients,
+        **kw
+        ):
+        super(StaticRecipientsEnvironmentMixin, self).__init__(**kw)
+
+        # The recipients for various types of notification emails, as
+        # RFC 2822 email addresses separated by commas (or the empty
+        # string if no recipients are configured).  Although there is
+        # a mechanism to choose the recipient lists based on on the
+        # actual *contents* of the change being reported, we only
+        # choose based on the *type* of the change.  Therefore we can
+        # compute them once and for all:
+        self.__refchange_recipients = refchange_recipients
+        self.__announce_recipients = announce_recipients
+        self.__revision_recipients = revision_recipients
+
+    def get_refchange_recipients(self, refchange):
+        return self.__refchange_recipients
+
+    def get_announce_recipients(self, annotated_tag_change):
+        return self.__announce_recipients
+
+    def get_revision_recipients(self, revision):
+        return self.__revision_recipients
+
+
+class ConfigRecipientsEnvironmentMixin(
+    ConfigEnvironmentMixin,
+    StaticRecipientsEnvironmentMixin
+    ):
+    """Determine recipients statically based on config."""
+
+    def __init__(self, config, **kw):
+        super(ConfigRecipientsEnvironmentMixin, self).__init__(
+            config=config,
+            refchange_recipients=self._get_recipients(
+                config, 'refchangelist', 'mailinglist',
+                ),
+            announce_recipients=self._get_recipients(
+                config, 'announcelist', 'refchangelist', 'mailinglist',
+                ),
+            revision_recipients=self._get_recipients(
+                config, 'commitlist', 'mailinglist',
+                ),
+            **kw
+            )
+
+    def _get_recipients(self, config, *names):
+        """Return the recipients for a particular type of message.
+
+        Return the list of email addresses to which a particular type
+        of notification email should be sent, by looking at the config
+        value for "multimailhook.$name" for each of names.  Use the
+        value from the first name that is configured.  The return
+        value is a (possibly empty) string containing RFC 2822 email
+        addresses separated by commas.  If no configuration could be
+        found, raise a ConfigurationException."""
+
+        for name in names:
+            retval = config.get_recipients(name)
+            if retval is not None:
+                return retval
+        if len(names) == 1:
+            hint = 'Please set "%s.%s"' % (config.section, name)
+        else:
+            hint = (
+                'Please set one of the following:\n    "%s"'
+                % ('"\n    "'.join('%s.%s' % (config.section, name) for name in names))
+                )
+
+        raise ConfigurationException(
+            'The list of recipients for %s is not configured.\n%s' % (names[0], hint)
+            )
+
+
+class ProjectdescEnvironmentMixin(Environment):
+    """Make a "projectdesc" value available for templates.
+
+    By default, it is set to the first line of $GIT_DIR/description
+    (if that file is present and appears to be set meaningfully)."""
+
+    def __init__(self, **kw):
+        super(ProjectdescEnvironmentMixin, self).__init__(**kw)
+        self.COMPUTED_KEYS += ['projectdesc']
+
+    def get_projectdesc(self):
+        """Return a one-line descripition of the project."""
+
+        git_dir = get_git_dir()
+        try:
+            projectdesc = open(os.path.join(git_dir, 'description')).readline().strip()
+            if projectdesc and not projectdesc.startswith('Unnamed repository'):
+                return projectdesc
+        except IOError:
+            pass
+
+        return 'UNNAMED PROJECT'
+
+
+class GenericEnvironmentMixin(Environment):
+    def get_pusher(self):
+        return self.osenv.get('USER', 'unknown user')
+
+
+class GenericEnvironment(
+    ProjectdescEnvironmentMixin,
+    ConfigMaxlinesEnvironmentMixin,
+    ConfigFilterLinesEnvironmentMixin,
+    ConfigRecipientsEnvironmentMixin,
+    PusherDomainEnvironmentMixin,
+    ConfigOptionsEnvironmentMixin,
+    GenericEnvironmentMixin,
+    Environment,
+    ):
+    pass
+
+
+class GitoliteEnvironmentMixin(Environment):
+    def get_repo_shortname(self):
+        # The gitolite environment variable $GL_REPO is a pretty good
+        # repo_shortname (though it's probably not as good as a value
+        # the user might have explicitly put in his config).
+        return (
+            self.osenv.get('GL_REPO', None)
+            or super(GitoliteEnvironmentMixin, self).get_repo_shortname()
+            )
+
+    def get_pusher(self):
+        return self.osenv.get('GL_USER', 'unknown user')
+
+
+class GitoliteEnvironment(
+    ProjectdescEnvironmentMixin,
+    ConfigMaxlinesEnvironmentMixin,
+    ConfigFilterLinesEnvironmentMixin,
+    ConfigRecipientsEnvironmentMixin,
+    PusherDomainEnvironmentMixin,
+    ConfigOptionsEnvironmentMixin,
+    GitoliteEnvironmentMixin,
+    Environment,
+    ):
+    pass
+
+
+class Push(object):
+    """Represent an entire push (i.e., a group of ReferenceChanges).
+
+    It is easy to figure out what commits were added to a *branch* by
+    a Reference change:
+
+        git rev-list change.old..change.new
+
+    or removed from a *branch*:
+
+        git rev-list change.new..change.old
+
+    But it is not quite so trivial to determine which entirely new
+    commits were added to the *repository* by a push and which old
+    commits were discarded by a push.  A big part of the job of this
+    class is to figure out these things, and to make sure that new
+    commits are only detailed once even if they were added to multiple
+    references.
+
+    The first step is to determine the "other" references--those
+    unaffected by the current push.  They are computed by
+    Push._compute_other_ref_sha1s() by listing all references then
+    removing any affected by this push.
+
+    The commits contained in the repository before this push were
+
+        git rev-list other1 other2 other3 ... change1.old change2.old ...
+
+    Where "changeN.old" is the old value of one of the references
+    affected by this push.
+
+    The commits contained in the repository after this push are
+
+        git rev-list other1 other2 other3 ... change1.new change2.new ...
+
+    The commits added by this push are the difference between these
+    two sets, which can be written
+
+        git rev-list \
+            ^other1 ^other2 ... \
+            ^change1.old ^change2.old ... \
+            change1.new change2.new ...
+
+    The commits removed by this push can be computed by
+
+        git rev-list \
+            ^other1 ^other2 ... \
+            ^change1.new ^change2.new ... \
+            change1.old change2.old ...
+
+    The last point is that it is possible that other pushes are
+    occurring simultaneously to this one, so reference values can
+    change at any time.  It is impossible to eliminate all race
+    conditions, but we reduce the window of time during which problems
+    can occur by translating reference names to SHA1s as soon as
+    possible and working with SHA1s thereafter (because SHA1s are
+    immutable)."""
+
+    # A map {(changeclass, changetype) : integer} specifying the order
+    # that reference changes will be processed if multiple reference
+    # changes are included in a single push.  The order is significant
+    # mostly because new commit notifications are threaded together
+    # with the first reference change that includes the commit.  The
+    # following order thus causes commits to be grouped with branch
+    # changes (as opposed to tag changes) if possible.
+    SORT_ORDER = dict(
+        (value, i) for (i, value) in enumerate([
+            (BranchChange, 'update'),
+            (BranchChange, 'create'),
+            (AnnotatedTagChange, 'update'),
+            (AnnotatedTagChange, 'create'),
+            (NonAnnotatedTagChange, 'update'),
+            (NonAnnotatedTagChange, 'create'),
+            (BranchChange, 'delete'),
+            (AnnotatedTagChange, 'delete'),
+            (NonAnnotatedTagChange, 'delete'),
+            (OtherReferenceChange, 'update'),
+            (OtherReferenceChange, 'create'),
+            (OtherReferenceChange, 'delete'),
+            ])
+        )
+
+    def __init__(self, changes):
+        self.changes = sorted(changes, key=self._sort_key)
+
+        # The SHA-1s of commits referred to by references unaffected
+        # by this push:
+        other_ref_sha1s = self._compute_other_ref_sha1s()
+
+        self._old_rev_exclusion_spec = self._compute_rev_exclusion_spec(
+            other_ref_sha1s.union(
+                change.old.sha1
+                for change in self.changes
+                if change.old.type in ['commit', 'tag']
+                )
+            )
+        self._new_rev_exclusion_spec = self._compute_rev_exclusion_spec(
+            other_ref_sha1s.union(
+                change.new.sha1
+                for change in self.changes
+                if change.new.type in ['commit', 'tag']
+                )
+            )
+
+    @classmethod
+    def _sort_key(klass, change):
+        return (klass.SORT_ORDER[change.__class__, change.change_type], change.refname,)
+
+    def _compute_other_ref_sha1s(self):
+        """Return the GitObjects referred to by references unaffected by this push."""
+
+        # The refnames being changed by this push:
+        updated_refs = set(
+            change.refname
+            for change in self.changes
+            )
+
+        # The SHA-1s of commits referred to by all references in this
+        # repository *except* updated_refs:
+        sha1s = set()
+        fmt = (
+            '%(objectname) %(objecttype) %(refname)\n'
+            '%(*objectname) %(*objecttype) %(refname)'
+            )
+        for line in read_git_lines(['for-each-ref', '--format=%s' % (fmt,)]):
+            (sha1, type, name) = line.split(' ', 2)
+            if sha1 and type == 'commit' and name not in updated_refs:
+                sha1s.add(sha1)
+
+        return sha1s
+
+    def _compute_rev_exclusion_spec(self, sha1s):
+        """Return an exclusion specification for 'git rev-list'.
+
+        git_objects is an iterable over GitObject instances.  Return a
+        string that can be passed to the standard input of 'git
+        rev-list --stdin' to exclude all of the commits referred to by
+        git_objects."""
+
+        return ''.join(
+            ['^%s\n' % (sha1,) for sha1 in sorted(sha1s)]
+            )
+
+    def get_new_commits(self, reference_change=None):
+        """Return a list of commits added by this push.
+
+        Return a list of the object names of commits that were added
+        by the part of this push represented by reference_change.  If
+        reference_change is None, then return a list of *all* commits
+        added by this push."""
+
+        if not reference_change:
+            new_revs = sorted(
+                change.new.sha1
+                for change in self.changes
+                if change.new
+                )
+        elif not reference_change.new.commit_sha1:
+            return []
+        else:
+            new_revs = [reference_change.new.commit_sha1]
+
+        cmd = ['rev-list', '--stdin'] + new_revs
+        return read_git_lines(cmd, input=self._old_rev_exclusion_spec)
+
+    def get_discarded_commits(self, reference_change):
+        """Return a list of commits discarded by this push.
+
+        Return a list of the object names of commits that were
+        entirely discarded from the repository by the part of this
+        push represented by reference_change."""
+
+        if not reference_change.old.commit_sha1:
+            return []
+        else:
+            old_revs = [reference_change.old.commit_sha1]
+
+        cmd = ['rev-list', '--stdin'] + old_revs
+        return read_git_lines(cmd, input=self._new_rev_exclusion_spec)
+
+    def send_emails(self, mailer, body_filter=None):
+        """Use send all of the notification emails needed for this push.
+
+        Use send all of the notification emails (including reference
+        change emails and commit emails) needed for this push.  Send
+        the emails using mailer.  If body_filter is not None, then use
+        it to filter the lines that are intended for the email
+        body."""
+
+        # The sha1s of commits that were introduced by this push.
+        # They will be removed from this set as they are processed, to
+        # guarantee that one (and only one) email is generated for
+        # each new commit.
+        unhandled_sha1s = set(self.get_new_commits())
+        for change in self.changes:
+            # Check if we've got anyone to send to
+            if not change.recipients:
+                sys.stderr.write(
+                    '*** no recipients configured so no email will be sent\n'
+                    '*** for %r update %s->%s\n'
+                    % (change.refname, change.old.sha1, change.new.sha1,)
+                    )
+            else:
+                sys.stderr.write('Sending notification emails to: %s\n' % (change.recipients,))
+                mailer.send(change.generate_email(self, body_filter), change.recipients)
+
+            sha1s = []
+            for sha1 in reversed(list(self.get_new_commits(change))):
+                if sha1 in unhandled_sha1s:
+                    sha1s.append(sha1)
+                    unhandled_sha1s.remove(sha1)
+
+            max_emails = change.environment.maxcommitemails
+            if max_emails and len(sha1s) > max_emails:
+                sys.stderr.write(
+                    '*** Too many new commits (%d), not sending commit emails.\n' % len(sha1s)
+                    + '*** Try setting multimailhook.maxCommitEmails to a greater value\n'
+                    + '*** Currently, multimailhook.maxCommitEmails=%d\n' % max_emails
+                    )
+                return
+
+            for (num, sha1) in enumerate(sha1s):
+                rev = Revision(change, GitObject(sha1), num=num+1, tot=len(sha1s))
+                if rev.recipients:
+                    mailer.send(rev.generate_email(self, body_filter), rev.recipients)
+
+        # Consistency check:
+        if unhandled_sha1s:
+            sys.stderr.write(
+                'ERROR: No emails were sent for the following new commits:\n'
+                '    %s\n'
+                % ('\n    '.join(sorted(unhandled_sha1s)),)
+                )
+
+
+def run_as_post_receive_hook(environment, mailer):
+    changes = []
+    for line in sys.stdin:
+        (oldrev, newrev, refname) = line.strip().split(' ', 2)
+        changes.append(
+            ReferenceChange.create(environment, oldrev, newrev, refname)
+            )
+    push = Push(changes)
+    push.send_emails(mailer, body_filter=environment.filter_body)
+
+
+def run_as_update_hook(environment, mailer, refname, oldrev, newrev):
+    changes = [
+        ReferenceChange.create(
+            environment,
+            read_git_output(['rev-parse', '--verify', oldrev]),
+            read_git_output(['rev-parse', '--verify', newrev]),
+            refname,
+            ),
+        ]
+    push = Push(changes)
+    push.send_emails(mailer, body_filter=environment.filter_body)
+
+
+def choose_mailer(config, environment):
+    mailer = config.get('mailer', default='sendmail')
+
+    if mailer == 'smtp':
+        smtpserver = config.get('smtpserver', default='localhost')
+        mailer = SMTPMailer(
+            envelopesender=(environment.get_sender() or environment.get_fromaddr()),
+            smtpserver=smtpserver,
+            )
+    elif mailer == 'sendmail':
+        command = config.get('sendmailcommand')
+        if command:
+            command = shlex.split(command)
+        mailer = SendMailer(command=command, envelopesender=environment.get_sender())
+    else:
+        sys.stderr.write(
+            'fatal: multimailhook.mailer is set to an incorrect value: "%s"\n' % mailer
+            + 'please use one of "smtp" or "sendmail".\n'
+            )
+        sys.exit(1)
+    return mailer
+
+
+KNOWN_ENVIRONMENTS = {
+    'generic' : GenericEnvironmentMixin,
+    'gitolite' : GitoliteEnvironmentMixin,
+    }
+
+
+def choose_environment(config, osenv=None, env=None, recipients=None):
+    if not osenv:
+        osenv = os.environ
+
+    environment_mixins = [
+        ProjectdescEnvironmentMixin,
+        ConfigMaxlinesEnvironmentMixin,
+        ConfigFilterLinesEnvironmentMixin,
+        PusherDomainEnvironmentMixin,
+        ConfigOptionsEnvironmentMixin,
+        ]
+    environment_kw = {
+        'osenv' : osenv,
+        'config' : config,
+        }
+
+    if not env:
+        env = config.get('environment')
+
+    if not env:
+        if 'GL_USER' in osenv and 'GL_REPO' in osenv:
+            env = 'gitolite'
+        else:
+            env = 'generic'
+
+    environment_mixins.append(KNOWN_ENVIRONMENTS[env])
+
+    if recipients:
+        environment_mixins.insert(0, StaticRecipientsEnvironmentMixin)
+        environment_kw['refchange_recipients'] = recipients
+        environment_kw['announce_recipients'] = recipients
+        environment_kw['revision_recipients'] = recipients
+    else:
+        environment_mixins.insert(0, ConfigRecipientsEnvironmentMixin)
+
+    environment_klass = type(
+        'EffectiveEnvironment',
+        tuple(environment_mixins) + (Environment,),
+        {},
+        )
+    return environment_klass(**environment_kw)
+
+
+def main(args):
+    parser = optparse.OptionParser(
+        description=__doc__,
+        usage='%prog [OPTIONS]\n   or: %prog [OPTIONS] REFNAME OLDREV NEWREV',
+        )
+
+    parser.add_option(
+        '--environment', '--env', action='store', type='choice',
+        choices=['generic', 'gitolite'], default=None,
+        help=(
+            'Choose type of environment is in use.  Default is taken from '
+            'multimailhook.environment if set; otherwise "generic".'
+            ),
+        )
+    parser.add_option(
+        '--stdout', action='store_true', default=False,
+        help='Output emails to stdout rather than sending them.',
+        )
+    parser.add_option(
+        '--recipients', action='store', default=None,
+        help='Set list of email recipients for all types of emails.',
+        )
+    parser.add_option(
+        '--show-env', action='store_true', default=False,
+        help=(
+            'Write to stderr the values determined for the environment '
+            '(intended for debugging purposes).'
+            ),
+        )
+
+    (options, args) = parser.parse_args(args)
+
+    config = Config('multimailhook')
+
+    try:
+        environment = choose_environment(
+            config, osenv=os.environ,
+            env=options.environment,
+            recipients=options.recipients,
+            )
+
+        if options.show_env:
+            sys.stderr.write('Environment values:\n')
+            for (k,v) in sorted(environment.get_values().items()):
+                sys.stderr.write('    %s : %r\n' % (k,v))
+            sys.stderr.write('\n')
+
+        if options.stdout:
+            mailer = OutputMailer(sys.stdout)
+        else:
+            mailer = choose_mailer(config, environment)
+
+        # Dual mode: if arguments were specified on the command line, run
+        # like an update hook; otherwise, run as a post-receive hook.
+        if args:
+            if len(args) != 3:
+                parser.error('Need zero or three non-option arguments')
+            (refname, oldrev, newrev) = args
+            run_as_update_hook(environment, mailer, refname, oldrev, newrev)
+        else:
+            run_as_post_receive_hook(environment, mailer)
+    except ConfigurationException, e:
+        sys.exit(str(e))
+
+
+if __name__ == '__main__':
+    main(sys.argv[1:])
diff --git a/contrib/hooks/multimail/migrate-mailhook-config b/contrib/hooks/multimail/migrate-mailhook-config
new file mode 100755
index 0000000..04eeaac
--- /dev/null
+++ b/contrib/hooks/multimail/migrate-mailhook-config
@@ -0,0 +1,269 @@
+#! /usr/bin/env python2
+
+"""Migrate a post-receive-email configuration to be usable with git_multimail.py.
+
+See README.migrate-from-post-receive-email for more information.
+
+"""
+
+import sys
+import optparse
+
+from git_multimail import CommandError
+from git_multimail import Config
+from git_multimail import read_output
+
+
+OLD_NAMES = [
+    'mailinglist',
+    'announcelist',
+    'envelopesender',
+    'emailprefix',
+    'showrev',
+    'emailmaxlines',
+    'diffopts',
+    ]
+
+NEW_NAMES = [
+    'environment',
+    'reponame',
+    'mailinglist',
+    'refchangelist',
+    'commitlist',
+    'announcelist',
+    'announceshortlog',
+    'envelopesender',
+    'administrator',
+    'emailprefix',
+    'emailmaxlines',
+    'diffopts',
+    'emaildomain',
+    ]
+
+
+INFO = """\
+
+SUCCESS!
+
+Your post-receive-email configuration has been converted to
+git-multimail format.  Please see README and
+README.migrate-from-post-receive-email to learn about other
+git-multimail configuration possibilities.
+
+For example, git-multimail has the following new options with no
+equivalent in post-receive-email.  You might want to read about them
+to see if they would be useful in your situation:
+
+"""
+
+
+def _check_old_config_exists(old):
+    """Check that at least one old configuration value is set."""
+
+    for name in OLD_NAMES:
+        if old.has_key(name):
+            return True
+
+    return False
+
+
+def _check_new_config_clear(new):
+    """Check that none of the new configuration names are set."""
+
+    retval = True
+    for name in NEW_NAMES:
+        if new.has_key(name):
+            if retval:
+                sys.stderr.write('INFO: The following configuration values already exist:\n\n')
+            sys.stderr.write('    "%s.%s"\n' % (new.section, name))
+            retval = False
+
+    return retval
+
+
+def erase_values(config, names):
+    for name in names:
+        if config.has_key(name):
+            try:
+                sys.stderr.write('...unsetting "%s.%s"\n' % (config.section, name))
+                config.unset_all(name)
+            except CommandError:
+                sys.stderr.write(
+                    '\nWARNING: could not unset "%s.%s".  '
+                    'Perhaps it is not set at the --local level?\n\n'
+                    % (config.section, name)
+                    )
+
+
+def is_section_empty(section, local):
+    """Return True iff the specified configuration section is empty.
+
+    Iff local is True, use the --local option when invoking 'git
+    config'."""
+
+    if local:
+        local_option = ['--local']
+    else:
+        local_option = []
+
+    try:
+        read_output(
+            ['git', 'config']
+            + local_option
+            + ['--get-regexp', '^%s\.' % (section,)]
+            )
+    except CommandError, e:
+        if e.retcode == 1:
+            # This means that no settings were found.
+            return True
+        else:
+            raise
+    else:
+        return False
+
+
+def remove_section_if_empty(section):
+    """If the specified configuration section is empty, delete it."""
+
+    try:
+        empty = is_section_empty(section, local=True)
+    except CommandError:
+        # Older versions of git do not support the --local option, so
+        # if the first attempt fails, try without --local.
+        try:
+            empty = is_section_empty(section, local=False)
+        except CommandError:
+            sys.stderr.write(
+                '\nINFO: If configuration section "%s.*" is empty, you might want '
+                'to delete it.\n\n'
+                % (section,)
+                )
+            return
+
+    if empty:
+        sys.stderr.write('...removing section "%s.*"\n' % (section,))
+        read_output(['git', 'config', '--remove-section', section])
+    else:
+        sys.stderr.write(
+            '\nINFO: Configuration section "%s.*" still has contents.  '
+            'It will not be deleted.\n\n'
+            % (section,)
+            )
+
+
+def migrate_config(strict=False, retain=False, overwrite=False):
+    old = Config('hooks')
+    new = Config('multimailhook')
+    if not _check_old_config_exists(old):
+        sys.exit(
+            'Your repository has no post-receive-email configuration.  '
+            'Nothing to do.'
+            )
+    if not _check_new_config_clear(new):
+        if overwrite:
+            sys.stderr.write('\nWARNING: Erasing the above values...\n\n')
+            erase_values(new, NEW_NAMES)
+        else:
+            sys.exit(
+                '\nERROR: Refusing to overwrite existing values.  Use the --overwrite\n'
+                'option to continue anyway.'
+                )
+
+    name = 'showrev'
+    if old.has_key(name):
+        msg = 'git-multimail does not support "%s.%s"' % (old.section, name,)
+        if strict:
+            sys.exit(
+                'ERROR: %s.\n'
+                'Please unset that value then try again, or run without --strict.'
+                % (msg,)
+                )
+        else:
+            sys.stderr.write('\nWARNING: %s (ignoring).\n\n' % (msg,))
+
+    for name in ['mailinglist', 'announcelist']:
+        if old.has_key(name):
+            sys.stderr.write(
+                '...copying "%s.%s" to "%s.%s"\n' % (old.section, name, new.section, name)
+                )
+            new.set_recipients(name, old.get_recipients(name))
+
+    if strict:
+        sys.stderr.write(
+            '...setting "%s.commitlist" to the empty string\n' % (new.section,)
+            )
+        new.set_recipients('commitlist', '')
+        sys.stderr.write(
+            '...setting "%s.announceshortlog" to "true"\n' % (new.section,)
+            )
+        new.set('announceshortlog', 'true')
+
+    for name in ['envelopesender', 'emailmaxlines', 'diffopts']:
+        if old.has_key(name):
+            sys.stderr.write(
+                '...copying "%s.%s" to "%s.%s"\n' % (old.section, name, new.section, name)
+                )
+            new.set(name, old.get(name))
+
+    name = 'emailprefix'
+    if old.has_key(name):
+        sys.stderr.write(
+            '...copying "%s.%s" to "%s.%s"\n' % (old.section, name, new.section, name)
+            )
+        new.set(name, old.get(name))
+    elif strict:
+        sys.stderr.write(
+            '...setting "%s.%s" to "[SCM]" to preserve old subject lines\n'
+            % (new.section, name)
+            )
+        new.set(name, '[SCM]')
+
+    if not retain:
+        erase_values(old, OLD_NAMES)
+        remove_section_if_empty(old.section)
+
+    sys.stderr.write(INFO)
+    for name in NEW_NAMES:
+        if name not in OLD_NAMES:
+            sys.stderr.write('    "%s.%s"\n' % (new.section, name,))
+    sys.stderr.write('\n')
+
+
+def main(args):
+    parser = optparse.OptionParser(
+        description=__doc__,
+        usage='%prog [OPTIONS]',
+        )
+
+    parser.add_option(
+        '--strict', action='store_true', default=False,
+        help=(
+            'Slavishly configure git-multimail as closely as possible to '
+            'the post-receive-email configuration.  Default is to turn '
+            'on some new features that have no equivalent in post-receive-email.'
+            ),
+        )
+    parser.add_option(
+        '--retain', action='store_true', default=False,
+        help=(
+            'Retain the post-receive-email configuration values.  '
+            'Default is to delete them after the new values are set.'
+            ),
+        )
+    parser.add_option(
+        '--overwrite', action='store_true', default=False,
+        help=(
+            'Overwrite any existing git-multimail configuration settings.  '
+            'Default is to abort if such settings already exist.'
+            ),
+        )
+
+    (options, args) = parser.parse_args(args)
+
+    if args:
+        parser.error('Unexpected arguments: %s' % (' '.join(args),))
+
+    migrate_config(strict=options.strict, retain=options.retain, overwrite=options.overwrite)
+
+
+main(sys.argv[1:])
diff --git a/contrib/hooks/multimail/post-receive b/contrib/hooks/multimail/post-receive
new file mode 100755
index 0000000..93ebb43
--- /dev/null
+++ b/contrib/hooks/multimail/post-receive
@@ -0,0 +1,90 @@
+#! /usr/bin/env python2
+
+"""Example post-receive hook based on git-multimail.
+
+This script is a simple example of a post-receive hook implemented
+using git_multimail.py as a Python module.  It is intended to be
+customized before use; see the comments in the script to help you get
+started.
+
+It is possible to use git_multimail.py itself as a post-receive or
+update hook, configured via git config settings and/or command-line
+parameters.  But for more flexibility, it can also be imported as a
+Python module by a custom post-receive script as done here.  The
+latter has the following advantages:
+
+* The tool's behavior can be customized using arbitrary Python code,
+  without having to edit git_multimail.py.
+
+* Configuration settings can be read from other sources; for example,
+  user names and email addresses could be read from LDAP or from a
+  database.  Or the settings can even be hardcoded in the importing
+  Python script, if this is preferred.
+
+This script is a very basic example of how to use git_multimail.py as
+a module.  The comments below explain some of the points at which the
+script's behavior could be changed or customized.
+
+"""
+
+import sys
+import os
+
+# If necessary, add the path to the directory containing
+# git_multimail.py to the Python path as follows.  (This is not
+# necessary if git_multimail.py is in the same directory as this
+# script):
+
+#LIBDIR = 'path/to/directory/containing/module'
+#sys.path.insert(0, LIBDIR)
+
+import git_multimail
+
+
+# It is possible to modify the output templates here; e.g.:
+
+#git_multimail.FOOTER_TEMPLATE = """\
+#
+#-- \n\
+#This email was generated by the wonderful git-multimail tool.
+#"""
+
+
+# Specify which "git config" section contains the configuration for
+# git-multimail:
+config = git_multimail.Config('multimailhook')
+
+
+# Select the type of environment:
+environment = git_multimail.GenericEnvironment(config=config)
+#environment = git_multimail.GitoliteEnvironment(config=config)
+
+
+# Choose the method of sending emails based on the git config:
+mailer = git_multimail.choose_mailer(config, environment)
+
+# Alternatively, you may hardcode the mailer using code like one of
+# the following:
+
+# Use "/usr/sbin/sendmail -t" to send emails.  The envelopesender
+# argument is optional:
+#mailer = git_multimail.SendMailer(
+#    command=['/usr/sbin/sendmail', '-t'],
+#    envelopesender='git-repo@example.com',
+#    )
+
+# Use Python's smtplib to send emails.  Both arguments are required.
+#mailer = git_multimail.SMTPMailer(
+#    envelopesender='git-repo@example.com',
+#    # The smtpserver argument can also include a port number; e.g.,
+#    #     smtpserver='mail.example.com:25'
+#    smtpserver='mail.example.com',
+#    )
+
+# OutputMailer is intended only for testing; it writes the emails to
+# the specified file stream.
+#mailer = git_multimail.OutputMailer(sys.stdout)
+
+
+# Read changes from stdin and send notification emails:
+git_multimail.run_as_post_receive_hook(environment, mailer)
diff --git a/contrib/hooks/post-receive-email b/contrib/hooks/post-receive-email
index 0e5b72d..1531150 100755
--- a/contrib/hooks/post-receive-email
+++ b/contrib/hooks/post-receive-email
@@ -2,10 +2,19 @@
 #
 # Copyright (c) 2007 Andy Parkins
 #
-# An example hook script to mail out commit update information.  This hook
-# sends emails listing new revisions to the repository introduced by the
-# change being reported.  The rule is that (for branch updates) each commit
-# will appear on one email and one email only.
+# An example hook script to mail out commit update information.
+#
+# NOTE: This script is no longer under active development.  There
+# is another script, git-multimail, which is more capable and
+# configurable and is largely backwards-compatible with this script;
+# please see "contrib/hooks/multimail/".  For instructions on how to
+# migrate from post-receive-email to git-multimail, please see
+# "README.migrate-from-post-receive-email" in that directory.
+#
+# This hook sends emails listing new revisions to the repository
+# introduced by the change being reported.  The rule is that (for
+# branch updates) each commit will appear on one email and one email
+# only.
 #
 # This hook is stored in the contrib/hooks directory.  Your distribution
 # will have put this somewhere standard.  You should make this script
diff --git a/contrib/mw-to-git/.gitignore b/contrib/mw-to-git/.gitignore
index b919655..ae545b0 100644
--- a/contrib/mw-to-git/.gitignore
+++ b/contrib/mw-to-git/.gitignore
@@ -1 +1,2 @@
 git-remote-mediawiki
+git-mw
diff --git a/contrib/mw-to-git/.perlcriticrc b/contrib/mw-to-git/.perlcriticrc
new file mode 100644
index 0000000..5a9955d
--- /dev/null
+++ b/contrib/mw-to-git/.perlcriticrc
@@ -0,0 +1,28 @@
+# These 3 rules demand to add the s, m and x flag to *every* regexp. This is
+# overkill and would be harmful for readability.
+[-RegularExpressions::RequireExtendedFormatting]
+[-RegularExpressions::RequireDotMatchAnything]
+[-RegularExpressions::RequireLineBoundaryMatching]
+
+# This rule says that builtin functions should not be called with parentheses
+# e.g.: (taken from CPAN's documentation)
+# open($handle, '>', $filename); #not ok
+# open $handle, '>', $filename;  #ok
+# Applying such a rule would mean modifying a huge number of lines for a
+# question of style.
+[-CodeLayout::ProhibitParensWithBuiltins]
+
+# This rule states that each system call should have its return value checked
+# The problem is that it includes the print call. Checking every print call's
+# return value would be harmful to the code readabilty.
+# This configuration keeps all default function but print.
+[InputOutput::RequireCheckedSyscalls]
+functions = open say close
+
+# This rules demands to add a dependancy for the Readonly module. This is not
+# wished.
+[-ValuesAndExpressions::ProhibitConstantPragma]
+
+# This rule is not really useful (rather a question of style) and produces many
+# warnings among the code.
+[-ValuesAndExpressions::ProhibitNoisyQuotes]
diff --git a/contrib/mw-to-git/Git/Mediawiki.pm b/contrib/mw-to-git/Git/Mediawiki.pm
new file mode 100644
index 0000000..d13c4df
--- /dev/null
+++ b/contrib/mw-to-git/Git/Mediawiki.pm
@@ -0,0 +1,100 @@
+package Git::Mediawiki;
+
+use 5.008;
+use strict;
+use Git;
+
+BEGIN {
+
+our ($VERSION, @ISA, @EXPORT, @EXPORT_OK);
+
+# Totally unstable API.
+$VERSION = '0.01';
+
+require Exporter;
+
+@ISA = qw(Exporter);
+
+@EXPORT = ();
+
+# Methods which can be called as standalone functions as well:
+@EXPORT_OK = qw(clean_filename smudge_filename connect_maybe
+				EMPTY HTTP_CODE_OK HTTP_CODE_PAGE_NOT_FOUND);
+}
+
+# Mediawiki filenames can contain forward slashes. This variable decides by which pattern they should be replaced
+use constant SLASH_REPLACEMENT => '%2F';
+
+# Used to test for empty strings
+use constant EMPTY => q{};
+
+# HTTP codes
+use constant HTTP_CODE_OK => 200;
+use constant HTTP_CODE_PAGE_NOT_FOUND => 404;
+
+sub clean_filename {
+	my $filename = shift;
+	$filename =~ s{@{[SLASH_REPLACEMENT]}}{/}g;
+	# [, ], |, {, and } are forbidden by MediaWiki, even URL-encoded.
+	# Do a variant of URL-encoding, i.e. looks like URL-encoding,
+	# but with _ added to prevent MediaWiki from thinking this is
+	# an actual special character.
+	$filename =~ s/[\[\]\{\}\|]/sprintf("_%%_%x", ord($&))/ge;
+	# If we use the uri escape before
+	# we should unescape here, before anything
+
+	return $filename;
+}
+
+sub smudge_filename {
+	my $filename = shift;
+	$filename =~ s{/}{@{[SLASH_REPLACEMENT]}}g;
+	$filename =~ s/ /_/g;
+	# Decode forbidden characters encoded in clean_filename
+	$filename =~ s/_%_([0-9a-fA-F][0-9a-fA-F])/sprintf('%c', hex($1))/ge;
+	return $filename;
+}
+
+sub connect_maybe {
+	my $wiki = shift;
+	if ($wiki) {
+		return $wiki;
+	}
+
+	my $remote_name = shift;
+	my $remote_url = shift;
+	my ($wiki_login, $wiki_password, $wiki_domain);
+
+	$wiki_login = Git::config("remote.${remote_name}.mwLogin");
+	$wiki_password = Git::config("remote.${remote_name}.mwPassword");
+	$wiki_domain = Git::config("remote.${remote_name}.mwDomain");
+
+	$wiki = MediaWiki::API->new;
+	$wiki->{config}->{api_url} = "${remote_url}/api.php";
+	if ($wiki_login) {
+		my %credential = (
+			'url' => $remote_url,
+			'username' => $wiki_login,
+			'password' => $wiki_password
+		);
+		Git::credential(\%credential);
+		my $request = {lgname => $credential{username},
+			       lgpassword => $credential{password},
+			       lgdomain => $wiki_domain};
+		if ($wiki->login($request)) {
+			Git::credential(\%credential, 'approve');
+			print {*STDERR} qq(Logged in mediawiki user "$credential{username}".\n);
+		} else {
+			print {*STDERR} qq(Failed to log in mediawiki user "$credential{username}" on ${remote_url}\n);
+			print {*STDERR} '  (error ' .
+				$wiki->{error}->{code} . ': ' .
+				$wiki->{error}->{details} . ")\n";
+			Git::credential(\%credential, 'reject');
+			exit 1;
+		}
+	}
+
+	return $wiki;
+}
+
+1; # Famous last words
diff --git a/contrib/mw-to-git/Makefile b/contrib/mw-to-git/Makefile
index f149719..76fcd4d 100644
--- a/contrib/mw-to-git/Makefile
+++ b/contrib/mw-to-git/Makefile
@@ -2,16 +2,43 @@
 # Copyright (C) 2013
 #     Matthieu Moy <Matthieu.Moy@imag.fr>
 #
-## Build git-remote-mediawiki
+# To build and test:
+#
+#   make
+#   bin-wrapper/git mw preview Some_page.mw
+#   bin-wrapper/git clone mediawiki::http://example.com/wiki/
+#
+# To install, run Git's toplevel 'make install' then run:
+#
+#   make install
 
+GIT_MEDIAWIKI_PM=Git/Mediawiki.pm
 SCRIPT_PERL=git-remote-mediawiki.perl
+SCRIPT_PERL+=git-mw.perl
 GIT_ROOT_DIR=../..
 HERE=contrib/mw-to-git/
 
 SCRIPT_PERL_FULL=$(patsubst %,$(HERE)/%,$(SCRIPT_PERL))
+INSTLIBDIR=$(shell $(MAKE) -C $(GIT_ROOT_DIR)/perl \
+                -s --no-print-directory instlibdir)
 
 all: build
 
-build install clean:
-	$(MAKE) -C $(GIT_ROOT_DIR) SCRIPT_PERL=$(SCRIPT_PERL_FULL) \
-                $@-perl-script
+install_pm:
+	install $(GIT_MEDIAWIKI_PM) $(INSTLIBDIR)/$(GIT_MEDIAWIKI_PM)
+
+build:
+	$(MAKE) -C $(GIT_ROOT_DIR) SCRIPT_PERL="$(SCRIPT_PERL_FULL)" \
+                build-perl-script
+
+install: install_pm
+	$(MAKE) -C $(GIT_ROOT_DIR) SCRIPT_PERL="$(SCRIPT_PERL_FULL)" \
+                install-perl-script
+
+clean:
+	$(MAKE) -C $(GIT_ROOT_DIR) SCRIPT_PERL="$(SCRIPT_PERL_FULL)" \
+                clean-perl-script
+	rm $(INSTLIBDIR)/$(GIT_MEDIAWIKI_PM)
+
+perlcritic:
+	perlcritic -2 *.perl
diff --git a/contrib/mw-to-git/bin-wrapper/git b/contrib/mw-to-git/bin-wrapper/git
new file mode 100755
index 0000000..6663ae5
--- /dev/null
+++ b/contrib/mw-to-git/bin-wrapper/git
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+# git executable wrapper script for Git-Mediawiki to run tests without
+# installing all the scripts and perl packages.
+
+GIT_ROOT_DIR=../../..
+GIT_EXEC_PATH=$(cd "$(dirname "$0")" && cd ${GIT_ROOT_DIR} && pwd)
+
+GITPERLLIB="$GIT_EXEC_PATH"'/contrib/mw-to-git'"${GITPERLLIB:+:$GITPERLLIB}"
+PATH="$GIT_EXEC_PATH"'/contrib/mw-to-git:'"$PATH"
+
+export GITPERLLIB PATH
+
+exec "${GIT_EXEC_PATH}/bin-wrappers/git" "$@"
diff --git a/contrib/mw-to-git/git-mw.perl b/contrib/mw-to-git/git-mw.perl
new file mode 100755
index 0000000..28df3ee
--- /dev/null
+++ b/contrib/mw-to-git/git-mw.perl
@@ -0,0 +1,368 @@
+#!/usr/bin/perl
+
+# Copyright (C) 2013
+#     Benoit Person <benoit.person@ensimag.imag.fr>
+#     Celestin Matte <celestin.matte@ensimag.imag.fr>
+# License: GPL v2 or later
+
+# Set of tools for git repo with a mediawiki remote.
+# Documentation & bugtracker: https://github.com/moy/Git-Mediawiki/
+
+use strict;
+use warnings;
+
+use Getopt::Long;
+use URI::URL qw(url);
+use LWP::UserAgent;
+use HTML::TreeBuilder;
+
+use Git;
+use MediaWiki::API;
+use Git::Mediawiki qw(clean_filename connect_maybe
+					EMPTY HTTP_CODE_PAGE_NOT_FOUND);
+
+# By default, use UTF-8 to communicate with Git and the user
+binmode STDERR, ':encoding(UTF-8)';
+binmode STDOUT, ':encoding(UTF-8)';
+
+# Global parameters
+my $verbose = 0;
+sub v_print {
+	if ($verbose) {
+		return print {*STDERR} @_;
+	}
+	return;
+}
+
+# Preview parameters
+my $file_name = EMPTY;
+my $remote_name = EMPTY;
+my $preview_file_name = EMPTY;
+my $autoload = 0;
+sub file {
+	$file_name = shift;
+	return $file_name;
+}
+
+my %commands = (
+	'help' =>
+		[\&help, {}, \&help],
+	'preview' =>
+		[\&preview, {
+			'<>' => \&file,
+			'output|o=s' => \$preview_file_name,
+			'remote|r=s' => \$remote_name,
+			'autoload|a' => \$autoload
+		}, \&preview_help]
+);
+
+# Search for sub-command
+my $cmd = $commands{'help'};
+for (0..@ARGV-1) {
+	if (defined $commands{$ARGV[$_]}) {
+		$cmd = $commands{$ARGV[$_]};
+		splice @ARGV, $_, 1;
+		last;
+	}
+};
+GetOptions( %{$cmd->[1]},
+	'help|h' => \&{$cmd->[2]},
+	'verbose|v'  => \$verbose);
+
+# Launch command
+&{$cmd->[0]};
+
+############################# Preview Functions ################################
+
+sub preview_help {
+	print {*STDOUT} <<'END';
+USAGE: git mw preview [--remote|-r <remote name>] [--autoload|-a]
+                      [--output|-o <output filename>] [--verbose|-v]
+                      <blob> | <filename>
+
+DESCRIPTION:
+Preview is an utiliy to preview local content of a mediawiki repo as if it was
+pushed on the remote.
+
+For that, preview searches for the remote name of the current branch's
+upstream if --remote is not set. If that remote is not found or if it
+is not a mediawiki, it lists all mediawiki remotes configured and asks
+you to replay your command with the --remote option set properly.
+
+Then, it searches for a file named 'filename'. If it's not found in
+the current dir, it will assume it's a blob.
+
+The content retrieved in the file (or in the blob) will then be parsed
+by the remote mediawiki and combined with a template retrieved from
+the mediawiki.
+
+Finally, preview will save the HTML result in a file. and autoload it
+in your default web browser if the option --autoload is present.
+
+OPTIONS:
+    -r <remote name>, --remote <remote name>
+        If the remote is a mediawiki, the template and the parse engine
+        used for the preview will be those of that remote.
+        If not, a list of valid remotes will be shown.
+
+    -a, --autoload
+        Try to load the HTML output in a new tab (or new window) of your
+        default web browser.
+
+    -o <output filename>, --output <output filename>
+        Change the HTML output filename. Default filename is based on the
+        input filename with its extension replaced by '.html'.
+
+    -v, --verbose
+        Show more information on what's going on under the hood.
+END
+	exit;
+}
+
+sub preview {
+	my $wiki;
+	my ($remote_url, $wiki_page_name);
+	my ($new_content, $template);
+	my $file_content;
+
+	if ($file_name eq EMPTY) {
+		die "Missing file argument, see `git mw help`\n";
+	}
+
+	v_print("### Selecting remote\n");
+	if ($remote_name eq EMPTY) {
+		$remote_name = find_upstream_remote_name();
+		if ($remote_name) {
+			$remote_url = mediawiki_remote_url_maybe($remote_name);
+		}
+
+		if (! $remote_url) {
+			my @valid_remotes = find_mediawiki_remotes();
+
+			if ($#valid_remotes == 0) {
+				print {*STDERR} "No mediawiki remote in this repo. \n";
+				exit 1;
+			} else {
+				my $remotes_list = join("\n\t", @valid_remotes);
+				print {*STDERR} <<"MESSAGE";
+There are multiple mediawiki remotes, which of:
+	${remotes_list}
+do you want ? Use the -r option to specify the remote.
+MESSAGE
+			}
+
+			exit 1;
+		}
+	} else {
+		if (!is_valid_remote($remote_name)) {
+			die "${remote_name} is not a remote\n";
+		}
+
+		$remote_url = mediawiki_remote_url_maybe($remote_name);
+		if (! $remote_url) {
+			die "${remote_name} is not a mediawiki remote\n";
+		}
+	}
+	v_print("selected remote:\n\tname: ${remote_name}\n\turl: ${remote_url}\n");
+
+	$wiki = connect_maybe($wiki, $remote_name, $remote_url);
+
+	# Read file content
+	if (! -e $file_name) {
+		$file_content = git_cmd_try {
+			Git::command('cat-file', 'blob', $file_name); }
+			"%s failed w/ code %d";
+
+		if ($file_name =~ /(.+):(.+)/) {
+			$file_name = $2;
+		}
+	} else {
+		open my $read_fh, "<", $file_name
+			or die "could not open ${file_name}: $!\n";
+		$file_content = do { local $/ = undef; <$read_fh> };
+		close $read_fh
+			or die "unable to close: $!\n";
+	}
+
+	v_print("### Retrieving template\n");
+	($wiki_page_name = clean_filename($file_name)) =~ s/\.[^.]+$//;
+	$template = get_template($remote_url, $wiki_page_name);
+
+	v_print("### Parsing local content\n");
+	$new_content = $wiki->api({
+		action => 'parse',
+		text => $file_content,
+		title => $wiki_page_name
+	}, {
+		skip_encoding => 1
+	}) or die "No response from remote mediawiki\n";
+	$new_content = $new_content->{'parse'}->{'text'}->{'*'};
+
+	v_print("### Merging contents\n");
+	if ($preview_file_name eq EMPTY) {
+		($preview_file_name = $file_name) =~ s/\.[^.]+$/.html/;
+	}
+	open(my $save_fh, '>:encoding(UTF-8)', $preview_file_name)
+		or die "Could not open: $!\n";
+	print {$save_fh} merge_contents($template, $new_content, $remote_url);
+	close($save_fh)
+		or die "Could not close: $!\n";
+
+	v_print("### Results\n");
+	if ($autoload) {
+		v_print("Launching browser w/ file: ${preview_file_name}");
+		system('git', 'web--browse', $preview_file_name);
+	} else {
+		print {*STDERR} "Preview file saved as: ${preview_file_name}\n";
+	}
+
+	exit;
+}
+
+# uses global scope variable: $remote_name
+sub merge_contents {
+	my $template = shift;
+	my $content = shift;
+	my $remote_url = shift;
+	my ($content_tree, $html_tree, $mw_content_text);
+	my $template_content_id = 'bodyContent';
+
+	$html_tree = HTML::TreeBuilder->new;
+	$html_tree->parse($template);
+
+	$content_tree = HTML::TreeBuilder->new;
+	$content_tree->parse($content);
+
+	$template_content_id = Git::config("remote.${remote_name}.mwIDcontent")
+		|| $template_content_id;
+	v_print("Using '${template_content_id}' as the content ID\n");
+
+	$mw_content_text = $html_tree->look_down('id', $template_content_id);
+	if (!defined $mw_content_text) {
+		print {*STDERR} <<"CONFIG";
+Could not combine the new content with the template. You might want to
+configure `mediawiki.IDContent` in your config:
+	git config --add remote.${remote_name}.mwIDcontent <id>
+and re-run the command afterward.
+CONFIG
+		exit 1;
+	}
+	$mw_content_text->delete_content();
+	$mw_content_text->push_content($content_tree);
+
+	make_links_absolute($html_tree, $remote_url);
+
+	return $html_tree->as_HTML;
+}
+
+sub make_links_absolute {
+	my $html_tree = shift;
+	my $remote_url = shift;
+	for (@{ $html_tree->extract_links() }) {
+		my ($link, $element, $attr) = @{ $_ };
+		my $url = url($link)->canonical;
+		if ($url !~ /#/) {
+			$element->attr($attr, URI->new_abs($url, $remote_url));
+		}
+	}
+	return $html_tree;
+}
+
+sub is_valid_remote {
+	my $remote = shift;
+	my @remotes = git_cmd_try {
+		Git::command('remote') }
+		"%s failed w/ code %d";
+	my $found_remote = 0;
+	foreach my $remote (@remotes) {
+		if ($remote eq $remote) {
+			$found_remote = 1;
+			last;
+		}
+	}
+	return $found_remote;
+}
+
+sub find_mediawiki_remotes {
+	my @remotes = git_cmd_try {
+		Git::command('remote'); }
+		"%s failed w/ code %d";
+	my $remote_url;
+	my @valid_remotes = ();
+	foreach my $remote (@remotes) {
+		$remote_url = mediawiki_remote_url_maybe($remote);
+		if ($remote_url) {
+			push(@valid_remotes, $remote);
+		}
+	}
+	return @valid_remotes;
+}
+
+sub find_upstream_remote_name {
+	my $current_branch = git_cmd_try {
+		Git::command_oneline('symbolic-ref', '--short', 'HEAD') }
+		"%s failed w/ code %d";
+	return Git::config("branch.${current_branch}.remote");
+}
+
+sub mediawiki_remote_url_maybe {
+	my $remote = shift;
+
+	# Find remote url
+	my $remote_url = Git::config("remote.${remote}.url");
+	if ($remote_url =~ s/mediawiki::(.*)/$1/) {
+		return url($remote_url)->canonical;
+	}
+
+	return;
+}
+
+sub get_template {
+	my $url = shift;
+	my $page_name = shift;
+	my ($req, $res, $code, $url_after);
+
+	$req = LWP::UserAgent->new;
+	if ($verbose) {
+		$req->show_progress(1);
+	}
+
+	$res = $req->get("${url}/index.php?title=${page_name}");
+	if (!$res->is_success) {
+		$code = $res->code;
+		$url_after = $res->request()->uri(); # resolve all redirections
+		if ($code == HTTP_CODE_PAGE_NOT_FOUND) {
+			if ($verbose) {
+				print {*STDERR} <<"WARNING";
+Warning: Failed to retrieve '$page_name'. Create it on the mediawiki if you want
+all the links to work properly.
+Trying to use the mediawiki homepage as a fallback template ...
+WARNING
+			}
+
+			# LWP automatically redirects GET request
+			$res = $req->get("${url}/index.php");
+			if (!$res->is_success) {
+				$url_after = $res->request()->uri(); # resolve all redirections
+				die "Failed to get homepage @ ${url_after} w/ code ${code}\n";
+			}
+		} else {
+			die "Failed to get '${page_name}' @ ${url_after} w/ code ${code}\n";
+		}
+	}
+
+	return $res->decoded_content;
+}
+
+############################## Help Functions ##################################
+
+sub help {
+	print {*STDOUT} <<'END';
+usage: git mw <command> <args>
+
+git mw commands are:
+    help        Display help information about git mw
+    preview     Parse and render local file into HTML
+END
+	exit;
+}
diff --git a/contrib/mw-to-git/git-remote-mediawiki.perl b/contrib/mw-to-git/git-remote-mediawiki.perl
index 9c14c1f..85d0c42 100755
--- a/contrib/mw-to-git/git-remote-mediawiki.perl
+++ b/contrib/mw-to-git/git-remote-mediawiki.perl
@@ -13,19 +13,17 @@
 
 use strict;
 use MediaWiki::API;
+use Git;
+use Git::Mediawiki qw(clean_filename smudge_filename connect_maybe
+					EMPTY HTTP_CODE_OK);
 use DateTime::Format::ISO8601;
-
-# By default, use UTF-8 to communicate with Git and the user
-binmode STDERR, ":utf8";
-binmode STDOUT, ":utf8";
-
-use URI::Escape;
-use IPC::Open2;
-
 use warnings;
 
-# Mediawiki filenames can contain forward slashes. This variable decides by which pattern they should be replaced
-use constant SLASH_REPLACEMENT => "%2F";
+# By default, use UTF-8 to communicate with Git and the user
+binmode STDERR, ':encoding(UTF-8)';
+binmode STDOUT, ':encoding(UTF-8)';
+
+use URI::Escape;
 
 # It's not always possible to delete pages (may require some
 # privileges). Deleted pages are replaced with this content.
@@ -36,45 +34,57 @@
 use constant EMPTY_CONTENT => "<!-- empty page -->\n";
 
 # used to reflect file creation or deletion in diff.
-use constant NULL_SHA1 => "0000000000000000000000000000000000000000";
+use constant NULL_SHA1 => '0000000000000000000000000000000000000000';
 
 # Used on Git's side to reflect empty edit messages on the wiki
 use constant EMPTY_MESSAGE => '*Empty MediaWiki Message*';
 
+# Number of pages taken into account at once in submodule get_mw_page_list
+use constant SLICE_SIZE => 50;
+
+# Number of linked mediafile to get at once in get_linked_mediafiles
+# The query is split in small batches because of the MW API limit of
+# the number of links to be returned (500 links max).
+use constant BATCH_SIZE => 10;
+
+if (@ARGV != 2) {
+	exit_error_usage();
+}
+
 my $remotename = $ARGV[0];
 my $url = $ARGV[1];
 
 # Accept both space-separated and multiple keys in config file.
 # Spaces should be written as _ anyway because we'll use chomp.
-my @tracked_pages = split(/[ \n]/, run_git("config --get-all remote.". $remotename .".pages"));
+my @tracked_pages = split(/[ \n]/, run_git("config --get-all remote.${remotename}.pages"));
 chomp(@tracked_pages);
 
 # Just like @tracked_pages, but for MediaWiki categories.
-my @tracked_categories = split(/[ \n]/, run_git("config --get-all remote.". $remotename .".categories"));
+my @tracked_categories = split(/[ \n]/, run_git("config --get-all remote.${remotename}.categories"));
 chomp(@tracked_categories);
 
 # Import media files on pull
-my $import_media = run_git("config --get --bool remote.". $remotename .".mediaimport");
+my $import_media = run_git("config --get --bool remote.${remotename}.mediaimport");
 chomp($import_media);
-$import_media = ($import_media eq "true");
+$import_media = ($import_media eq 'true');
 
 # Export media files on push
-my $export_media = run_git("config --get --bool remote.". $remotename .".mediaexport");
+my $export_media = run_git("config --get --bool remote.${remotename}.mediaexport");
 chomp($export_media);
-$export_media = !($export_media eq "false");
+$export_media = !($export_media eq 'false');
 
-my $wiki_login = run_git("config --get remote.". $remotename .".mwLogin");
+my $wiki_login = run_git("config --get remote.${remotename}.mwLogin");
 # Note: mwPassword is discourraged. Use the credential system instead.
-my $wiki_passwd = run_git("config --get remote.". $remotename .".mwPassword");
-my $wiki_domain = run_git("config --get remote.". $remotename .".mwDomain");
+my $wiki_passwd = run_git("config --get remote.${remotename}.mwPassword");
+my $wiki_domain = run_git("config --get remote.${remotename}.mwDomain");
 chomp($wiki_login);
 chomp($wiki_passwd);
 chomp($wiki_domain);
 
 # Import only last revisions (both for clone and fetch)
-my $shallow_import = run_git("config --get --bool remote.". $remotename .".shallow");
+my $shallow_import = run_git("config --get --bool remote.${remotename}.shallow");
 chomp($shallow_import);
-$shallow_import = ($shallow_import eq "true");
+$shallow_import = ($shallow_import eq 'true');
 
 # Fetch (clone and pull) by revisions instead of by pages. This behavior
 # is more efficient when we have a wiki with lots of pages and we fetch
@@ -82,15 +92,18 @@
 # Possible values:
 # - by_rev: perform one query per new revision on the remote wiki
 # - by_page: query each tracked page for new revision
-my $fetch_strategy = run_git("config --get remote.$remotename.fetchStrategy");
-unless ($fetch_strategy) {
-	$fetch_strategy = run_git("config --get mediawiki.fetchStrategy");
+my $fetch_strategy = run_git("config --get remote.${remotename}.fetchStrategy");
+if (!$fetch_strategy) {
+	$fetch_strategy = run_git('config --get mediawiki.fetchStrategy');
 }
 chomp($fetch_strategy);
-unless ($fetch_strategy) {
-	$fetch_strategy = "by_page";
+if (!$fetch_strategy) {
+	$fetch_strategy = 'by_page';
 }
 
+# Remember the timestamp corresponding to a revision id.
+my %basetimestamps;
+
 # Dumb push: don't update notes and mediawiki ref to reflect the last push.
 #
 # Configurable with mediawiki.dumbPush, or per-remote with
@@ -105,48 +118,25 @@
 # will get the history with information lost). If the import is
 # deterministic, this means everybody gets the same sha1 for each
 # MediaWiki revision.
-my $dumb_push = run_git("config --get --bool remote.$remotename.dumbPush");
-unless ($dumb_push) {
-	$dumb_push = run_git("config --get --bool mediawiki.dumbPush");
+my $dumb_push = run_git("config --get --bool remote.${remotename}.dumbPush");
+if (!$dumb_push) {
+	$dumb_push = run_git('config --get --bool mediawiki.dumbPush');
 }
 chomp($dumb_push);
-$dumb_push = ($dumb_push eq "true");
+$dumb_push = ($dumb_push eq 'true');
 
 my $wiki_name = $url;
-$wiki_name =~ s/[^\/]*:\/\///;
+$wiki_name =~ s{[^/]*://}{};
 # If URL is like http://user:password@example.com/, we clearly don't
 # want the password in $wiki_name. While we're there, also remove user
 # and '@' sign, to avoid author like MWUser@HTTPUser@host.com
 $wiki_name =~ s/^.*@//;
 
 # Commands parser
-my $entry;
-my @cmd;
 while (<STDIN>) {
 	chomp;
-	@cmd = split(/ /);
-	if (defined($cmd[0])) {
-		# Line not blank
-		if ($cmd[0] eq "capabilities") {
-			die("Too many arguments for capabilities") unless (!defined($cmd[1]));
-			mw_capabilities();
-		} elsif ($cmd[0] eq "list") {
-			die("Too many arguments for list") unless (!defined($cmd[2]));
-			mw_list($cmd[1]);
-		} elsif ($cmd[0] eq "import") {
-			die("Invalid arguments for import") unless ($cmd[1] ne "" && !defined($cmd[2]));
-			mw_import($cmd[1]);
-		} elsif ($cmd[0] eq "option") {
-			die("Too many arguments for option") unless ($cmd[1] ne "" && $cmd[2] ne "" && !defined($cmd[3]));
-			mw_option($cmd[1],$cmd[2]);
-		} elsif ($cmd[0] eq "push") {
-			mw_push($cmd[1]);
-		} else {
-			print STDERR "Unknown command. Aborting...\n";
-			last;
-		}
-	} else {
-		# blank line: we should terminate
+
+	if (!parse_command($_)) {
 		last;
 	}
 
@@ -156,107 +146,91 @@
 
 ########################## Functions ##############################
 
-## credential API management (generic functions)
-
-sub credential_read {
-	my %credential;
-	my $reader = shift;
-	my $op = shift;
-	while (<$reader>) {
-		my ($key, $value) = /([^=]*)=(.*)/;
-		if (not defined $key) {
-			die "ERROR receiving response from git credential $op:\n$_\n";
-		}
-		$credential{$key} = $value;
-	}
-	return %credential;
+## error handling
+sub exit_error_usage {
+	die "ERROR: git-remote-mediawiki module was not called with a correct number of\n" .
+	    "parameters\n" .
+	    "You may obtain this error because you attempted to run the git-remote-mediawiki\n" .
+            "module directly.\n" .
+	    "This module can be used the following way:\n" .
+	    "\tgit clone mediawiki://<address of a mediawiki>\n" .
+	    "Then, use git commit, push and pull as with every normal git repository.\n";
 }
 
-sub credential_write {
-	my $credential = shift;
-	my $writer = shift;
-	# url overwrites other fields, so it must come first
-	print $writer "url=$credential->{url}\n" if exists $credential->{url};
-	while (my ($key, $value) = each(%$credential) ) {
-		if (length $value && $key ne 'url') {
-			print $writer "$key=$value\n";
-		}
+sub parse_command {
+	my ($line) = @_;
+	my @cmd = split(/ /, $line);
+	if (!defined $cmd[0]) {
+		return 0;
 	}
-}
-
-sub credential_run {
-	my $op = shift;
-	my $credential = shift;
-	my $pid = open2(my $reader, my $writer, "git credential $op");
-	credential_write($credential, $writer);
-	print $writer "\n";
-	close($writer);
-
-	if ($op eq "fill") {
-		%$credential = credential_read($reader, $op);
+	if ($cmd[0] eq 'capabilities') {
+		die("Too many arguments for capabilities\n")
+		    if (defined($cmd[1]));
+		mw_capabilities();
+	} elsif ($cmd[0] eq 'list') {
+		die("Too many arguments for list\n") if (defined($cmd[2]));
+		mw_list($cmd[1]);
+	} elsif ($cmd[0] eq 'import') {
+		die("Invalid argument for import\n")
+		    if ($cmd[1] eq EMPTY);
+		die("Too many arguments for import\n")
+		    if (defined($cmd[2]));
+		mw_import($cmd[1]);
+	} elsif ($cmd[0] eq 'option') {
+		die("Invalid arguments for option\n")
+		    if ($cmd[1] eq EMPTY || $cmd[2] eq EMPTY);
+		die("Too many arguments for option\n")
+		    if (defined($cmd[3]));
+		mw_option($cmd[1],$cmd[2]);
+	} elsif ($cmd[0] eq 'push') {
+		mw_push($cmd[1]);
 	} else {
-		if (<$reader>) {
-			die "ERROR while running git credential $op:\n$_";
-		}
+		print {*STDERR} "Unknown command. Aborting...\n";
+		return 0;
 	}
-	close($reader);
-	waitpid($pid, 0);
-	my $child_exit_status = $? >> 8;
-	if ($child_exit_status != 0) {
-		die "'git credential $op' failed with code $child_exit_status.";
-	}
+	return 1;
 }
 
 # MediaWiki API instance, created lazily.
 my $mediawiki;
 
-sub mw_connect_maybe {
-	if ($mediawiki) {
-		return;
+sub fatal_mw_error {
+	my $action = shift;
+	print STDERR "fatal: could not $action.\n";
+	print STDERR "fatal: '$url' does not appear to be a mediawiki\n";
+	if ($url =~ /^https/) {
+		print STDERR "fatal: make sure '$url/api.php' is a valid page\n";
+		print STDERR "fatal: and the SSL certificate is correct.\n";
+	} else {
+		print STDERR "fatal: make sure '$url/api.php' is a valid page.\n";
 	}
-	$mediawiki = MediaWiki::API->new;
-	$mediawiki->{config}->{api_url} = "$url/api.php";
-	if ($wiki_login) {
-		my %credential = (url => $url);
-		$credential{username} = $wiki_login;
-		$credential{password} = $wiki_passwd;
-		credential_run("fill", \%credential);
-		my $request = {lgname => $credential{username},
-			       lgpassword => $credential{password},
-			       lgdomain => $wiki_domain};
-		if ($mediawiki->login($request)) {
-			credential_run("approve", \%credential);
-			print STDERR "Logged in mediawiki user \"$credential{username}\".\n";
-		} else {
-			print STDERR "Failed to log in mediawiki user \"$credential{username}\" on $url\n";
-			print STDERR "  (error " .
-				$mediawiki->{error}->{code} . ': ' .
-				$mediawiki->{error}->{details} . ")\n";
-			credential_run("reject", \%credential);
-			exit 1;
-		}
-	}
+	print STDERR "fatal: (error " .
+	    $mediawiki->{error}->{code} . ': ' .
+	    $mediawiki->{error}->{details} . ")\n";
+	exit 1;
 }
 
 ## Functions for listing pages on the remote wiki
 sub get_mw_tracked_pages {
 	my $pages = shift;
 	get_mw_page_list(\@tracked_pages, $pages);
+	return;
 }
 
 sub get_mw_page_list {
 	my $page_list = shift;
 	my $pages = shift;
-	my @some_pages = @$page_list;
+	my @some_pages = @{$page_list};
 	while (@some_pages) {
-		my $last = 50;
-		if ($#some_pages < $last) {
-			$last = $#some_pages;
+		my $last_page = SLICE_SIZE;
+		if ($#some_pages < $last_page) {
+			$last_page = $#some_pages;
 		}
-		my @slice = @some_pages[0..$last];
+		my @slice = @some_pages[0..$last_page];
 		get_mw_first_pages(\@slice, $pages);
-		@some_pages = @some_pages[51..$#some_pages];
+		@some_pages = @some_pages[(SLICE_SIZE + 1)..$#some_pages];
 	}
+	return;
 }
 
 sub get_mw_tracked_categories {
@@ -266,7 +240,7 @@
 			# Mediawiki requires the Category
 			# prefix, but let's not force the user
 			# to specify it.
-			$category = "Category:" . $category;
+			$category = "Category:${category}";
 		}
 		my $mw_pages = $mediawiki->list( {
 			action => 'query',
@@ -274,11 +248,12 @@
 			cmtitle => $category,
 			cmlimit => 'max' } )
 			|| die $mediawiki->{error}->{code} . ': '
-				. $mediawiki->{error}->{details};
+				. $mediawiki->{error}->{details} . "\n";
 		foreach my $page (@{$mw_pages}) {
 			$pages->{$page->{title}} = $page;
 		}
 	}
+	return;
 }
 
 sub get_mw_all_pages {
@@ -290,14 +265,12 @@
 		aplimit => 'max'
 	});
 	if (!defined($mw_pages)) {
-		print STDERR "fatal: could not get the list of wiki pages.\n";
-		print STDERR "fatal: '$url' does not appear to be a mediawiki\n";
-		print STDERR "fatal: make sure '$url/api.php' is a valid page.\n";
-		exit 1;
+		fatal_mw_error("get the list of wiki pages");
 	}
 	foreach my $page (@{$mw_pages}) {
 		$pages->{$page->{title}} = $page;
 	}
+	return;
 }
 
 # queries the wiki for a set of pages. Meant to be used within a loop
@@ -316,25 +289,23 @@
 		titles => $titles,
 	});
 	if (!defined($mw_pages)) {
-		print STDERR "fatal: could not query the list of wiki pages.\n";
-		print STDERR "fatal: '$url' does not appear to be a mediawiki\n";
-		print STDERR "fatal: make sure '$url/api.php' is a valid page.\n";
-		exit 1;
+		fatal_mw_error("query the list of wiki pages");
 	}
 	while (my ($id, $page) = each(%{$mw_pages->{query}->{pages}})) {
 		if ($id < 0) {
-			print STDERR "Warning: page $page->{title} not found on wiki\n";
+			print {*STDERR} "Warning: page $page->{title} not found on wiki\n";
 		} else {
 			$pages->{$page->{title}} = $page;
 		}
 	}
+	return;
 }
 
 # Get the list of pages to be fetched according to configuration.
 sub get_mw_pages {
-	mw_connect_maybe();
+	$mediawiki = connect_maybe($mediawiki, $remotename, $url);
 
-	print STDERR "Listing pages on remote wiki...\n";
+	print {*STDERR} "Listing pages on remote wiki...\n";
 
 	my %pages; # hash on page titles to avoid duplicates
 	my $user_defined;
@@ -352,14 +323,14 @@
 		get_mw_all_pages(\%pages);
 	}
 	if ($import_media) {
-		print STDERR "Getting media files for selected pages...\n";
+		print {*STDERR} "Getting media files for selected pages...\n";
 		if ($user_defined) {
 			get_linked_mediafiles(\%pages);
 		} else {
 			get_all_mediafiles(\%pages);
 		}
 	}
-	print STDERR (scalar keys %pages) . " pages found.\n";
+	print {*STDERR} (scalar keys %pages) . " pages found.\n";
 	return %pages;
 }
 
@@ -367,9 +338,13 @@
 #        $out = run_git("command args", "raw"); # don't interpret output as UTF-8.
 sub run_git {
 	my $args = shift;
-	my $encoding = (shift || "encoding(UTF-8)");
-	open(my $git, "-|:$encoding", "git " . $args);
-	my $res = do { local $/; <$git> };
+	my $encoding = (shift || 'encoding(UTF-8)');
+	open(my $git, "-|:${encoding}", "git ${args}")
+	    or die "Unable to fork: $!\n";
+	my $res = do {
+		local $/ = undef;
+		<$git>
+	};
 	close($git);
 
 	return $res;
@@ -384,27 +359,26 @@
 	my $mw_pages = $mediawiki->list({
 		action => 'query',
 		list => 'allpages',
-		apnamespace => get_mw_namespace_id("File"),
+		apnamespace => get_mw_namespace_id('File'),
 		aplimit => 'max'
 	});
 	if (!defined($mw_pages)) {
-		print STDERR "fatal: could not get the list of pages for media files.\n";
-		print STDERR "fatal: '$url' does not appear to be a mediawiki\n";
-		print STDERR "fatal: make sure '$url/api.php' is a valid page.\n";
+		print {*STDERR} "fatal: could not get the list of pages for media files.\n";
+		print {*STDERR} "fatal: '$url' does not appear to be a mediawiki\n";
+		print {*STDERR} "fatal: make sure '$url/api.php' is a valid page.\n";
 		exit 1;
 	}
 	foreach my $page (@{$mw_pages}) {
 		$pages->{$page->{title}} = $page;
 	}
+	return;
 }
 
 sub get_linked_mediafiles {
 	my $pages = shift;
-	my @titles = map $_->{title}, values(%{$pages});
+	my @titles = map { $_->{title} } values(%{$pages});
 
-	# The query is split in small batches because of the MW API limit of
-	# the number of links to be returned (500 links max).
-	my $batch = 10;
+	my $batch = BATCH_SIZE;
 	while (@titles) {
 		if ($#titles < $batch) {
 			$batch = $#titles;
@@ -420,7 +394,7 @@
 			action => 'query',
 			prop => 'links|images',
 			titles => $mw_titles,
-			plnamespace => get_mw_namespace_id("File"),
+			plnamespace => get_mw_namespace_id('File'),
 			pllimit => 'max'
 		};
 		my $result = $mediawiki->api($query);
@@ -428,11 +402,13 @@
 		while (my ($id, $page) = each(%{$result->{query}->{pages}})) {
 			my @media_titles;
 			if (defined($page->{links})) {
-				my @link_titles = map $_->{title}, @{$page->{links}};
+				my @link_titles
+				    = map { $_->{title} } @{$page->{links}};
 				push(@media_titles, @link_titles);
 			}
 			if (defined($page->{images})) {
-				my @image_titles = map $_->{title}, @{$page->{images}};
+				my @image_titles
+				    = map { $_->{title} } @{$page->{images}};
 				push(@media_titles, @image_titles);
 			}
 			if (@media_titles) {
@@ -442,6 +418,7 @@
 
 		@titles = @titles[($batch+1)..$#titles];
 	}
+	return;
 }
 
 sub get_mw_mediafile_for_page_revision {
@@ -455,7 +432,7 @@
 	my $query = {
 		action => 'query',
 		prop => 'imageinfo',
-		titles => "File:" . $filename,
+		titles => "File:${filename}",
 		iistart => $timestamp,
 		iiend => $timestamp,
 		iiprop => 'timestamp|archivename|url',
@@ -473,53 +450,50 @@
 		$mediafile{timestamp} = $fileinfo->{timestamp};
 		# Mediawiki::API's download function doesn't support https URLs
 		# and can't download old versions of files.
-		print STDERR "\tDownloading file $mediafile{title}, version $mediafile{timestamp}\n";
+		print {*STDERR} "\tDownloading file $mediafile{title}, version $mediafile{timestamp}\n";
 		$mediafile{content} = download_mw_mediafile($fileinfo->{url});
 	}
 	return %mediafile;
 }
 
 sub download_mw_mediafile {
-	my $url = shift;
+	my $download_url = shift;
 
-	my $response = $mediawiki->{ua}->get($url);
-	if ($response->code == 200) {
+	my $response = $mediawiki->{ua}->get($download_url);
+	if ($response->code == HTTP_CODE_OK) {
 		return $response->decoded_content;
 	} else {
-		print STDERR "Error downloading mediafile from :\n";
-		print STDERR "URL: $url\n";
-		print STDERR "Server response: " . $response->code . " " . $response->message . "\n";
+		print {*STDERR} "Error downloading mediafile from :\n";
+		print {*STDERR} "URL: ${download_url}\n";
+		print {*STDERR} 'Server response: ' . $response->code . q{ } . $response->message . "\n";
 		exit 1;
 	}
 }
 
 sub get_last_local_revision {
 	# Get note regarding last mediawiki revision
-	my $note = run_git("notes --ref=$remotename/mediawiki show refs/mediawiki/$remotename/master 2>/dev/null");
+	my $note = run_git("notes --ref=${remotename}/mediawiki show refs/mediawiki/${remotename}/master 2>/dev/null");
 	my @note_info = split(/ /, $note);
 
 	my $lastrevision_number;
-	if (!(defined($note_info[0]) && $note_info[0] eq "mediawiki_revision:")) {
-		print STDERR "No previous mediawiki revision found";
+	if (!(defined($note_info[0]) && $note_info[0] eq 'mediawiki_revision:')) {
+		print {*STDERR} 'No previous mediawiki revision found';
 		$lastrevision_number = 0;
 	} else {
 		# Notes are formatted : mediawiki_revision: #number
 		$lastrevision_number = $note_info[1];
 		chomp($lastrevision_number);
-		print STDERR "Last local mediawiki revision found is $lastrevision_number";
+		print {*STDERR} "Last local mediawiki revision found is ${lastrevision_number}";
 	}
 	return $lastrevision_number;
 }
 
-# Remember the timestamp corresponding to a revision id.
-my %basetimestamps;
-
 # Get the last remote revision without taking in account which pages are
 # tracked or not. This function makes a single request to the wiki thus
 # avoid a loop onto all tracked pages. This is useful for the fetch-by-rev
 # option.
 sub get_last_global_remote_rev {
-	mw_connect_maybe();
+	$mediawiki = connect_maybe($mediawiki, $remotename, $url);
 
 	my $query = {
 		action => 'query',
@@ -535,14 +509,14 @@
 # Get the last remote revision concerning the tracked pages and the tracked
 # categories.
 sub get_last_remote_revision {
-	mw_connect_maybe();
+	$mediawiki = connect_maybe($mediawiki, $remotename, $url);
 
 	my %pages_hash = get_mw_pages();
 	my @pages = values(%pages_hash);
 
 	my $max_rev_num = 0;
 
-	print STDERR "Getting last revision id on tracked pages...\n";
+	print {*STDERR} "Getting last revision id on tracked pages...\n";
 
 	foreach my $page (@pages) {
 		my $id = $page->{pageid};
@@ -563,7 +537,7 @@
 		$max_rev_num = ($lastrev->{revid} > $max_rev_num ? $lastrev->{revid} : $max_rev_num);
 	}
 
-	print STDERR "Last remote revision found is $max_rev_num.\n";
+	print {*STDERR} "Last remote revision found is $max_rev_num.\n";
 	return $max_rev_num;
 }
 
@@ -574,7 +548,7 @@
 	# Mediawiki does not allow blank space at the end of a page and ends with a single \n.
 	# This function right trims a string and adds a \n at the end to follow this rule
 	$string =~ s/\s+$//;
-	if ($string eq "" && $page_created) {
+	if ($string eq EMPTY && $page_created) {
 		# Creating empty pages is forbidden.
 		$string = EMPTY_CONTENT;
 	}
@@ -585,38 +559,16 @@
 sub mediawiki_smudge {
 	my $string = shift;
 	if ($string eq EMPTY_CONTENT) {
-		$string = "";
+		$string = EMPTY;
 	}
 	# This \n is important. This is due to mediawiki's way to handle end of files.
-	return $string."\n";
-}
-
-sub mediawiki_clean_filename {
-	my $filename = shift;
-	$filename =~ s/@{[SLASH_REPLACEMENT]}/\//g;
-	# [, ], |, {, and } are forbidden by MediaWiki, even URL-encoded.
-	# Do a variant of URL-encoding, i.e. looks like URL-encoding,
-	# but with _ added to prevent MediaWiki from thinking this is
-	# an actual special character.
-	$filename =~ s/[\[\]\{\}\|]/sprintf("_%%_%x", ord($&))/ge;
-	# If we use the uri escape before
-	# we should unescape here, before anything
-
-	return $filename;
-}
-
-sub mediawiki_smudge_filename {
-	my $filename = shift;
-	$filename =~ s/\//@{[SLASH_REPLACEMENT]}/g;
-	$filename =~ s/ /_/g;
-	# Decode forbidden characters encoded in mediawiki_clean_filename
-	$filename =~ s/_%_([0-9a-fA-F][0-9a-fA-F])/sprintf("%c", hex($1))/ge;
-	return $filename;
+	return "${string}\n";
 }
 
 sub literal_data {
 	my ($content) = @_;
-	print STDOUT "data ", bytes::length($content), "\n", $content;
+	print {*STDOUT} 'data ', bytes::length($content), "\n", $content;
+	return;
 }
 
 sub literal_data_raw {
@@ -624,33 +576,37 @@
 	my ($content) = @_;
 	# Avoid confusion between size in bytes and in characters
 	utf8::downgrade($content);
-	binmode STDOUT, ":raw";
-	print STDOUT "data ", bytes::length($content), "\n", $content;
-	binmode STDOUT, ":utf8";
+	binmode STDOUT, ':raw';
+	print {*STDOUT} 'data ', bytes::length($content), "\n", $content;
+	binmode STDOUT, ':encoding(UTF-8)';
+	return;
 }
 
 sub mw_capabilities {
 	# Revisions are imported to the private namespace
 	# refs/mediawiki/$remotename/ by the helper and fetched into
 	# refs/remotes/$remotename later by fetch.
-	print STDOUT "refspec refs/heads/*:refs/mediawiki/$remotename/*\n";
-	print STDOUT "import\n";
-	print STDOUT "list\n";
-	print STDOUT "push\n";
-	print STDOUT "\n";
+	print {*STDOUT} "refspec refs/heads/*:refs/mediawiki/${remotename}/*\n";
+	print {*STDOUT} "import\n";
+	print {*STDOUT} "list\n";
+	print {*STDOUT} "push\n";
+	print {*STDOUT} "\n";
+	return;
 }
 
 sub mw_list {
 	# MediaWiki do not have branches, we consider one branch arbitrarily
 	# called master, and HEAD pointing to it.
-	print STDOUT "? refs/heads/master\n";
-	print STDOUT "\@refs/heads/master HEAD\n";
-	print STDOUT "\n";
+	print {*STDOUT} "? refs/heads/master\n";
+	print {*STDOUT} "\@refs/heads/master HEAD\n";
+	print {*STDOUT} "\n";
+	return;
 }
 
 sub mw_option {
-	print STDERR "remote-helper command 'option $_[0]' not yet implemented\n";
-	print STDOUT "unsupported\n";
+	print {*STDERR} "remote-helper command 'option $_[0]' not yet implemented\n";
+	print {*STDOUT} "unsupported\n";
+	return;
 }
 
 sub fetch_mw_revisions_for_page {
@@ -666,6 +622,9 @@
 		rvstartid => $fetch_from,
 		rvlimit => 500,
 		pageids => $id,
+
+		# Let MediaWiki know that we support the latest API.
+		continue => '',
 	};
 
 	my $revnum = 0;
@@ -681,15 +640,22 @@
 			push(@page_revs, $page_rev_ids);
 			$revnum++;
 		}
-		last unless $result->{'query-continue'};
-		$query->{rvstartid} = $result->{'query-continue'}->{revisions}->{rvstartid};
+
+		if ($result->{'query-continue'}) { # For legacy APIs
+			$query->{rvstartid} = $result->{'query-continue'}->{revisions}->{rvstartid};
+		} elsif ($result->{continue}) { # For newer APIs
+			$query->{rvstartid} = $result->{continue}->{rvcontinue};
+			$query->{continue} = $result->{continue}->{continue};
+		} else {
+			last;
+		}
 	}
 	if ($shallow_import && @page_revs) {
-		print STDERR "  Found 1 revision (shallow import).\n";
+		print {*STDERR} "  Found 1 revision (shallow import).\n";
 		@page_revs = sort {$b->{revid} <=> $a->{revid}} (@page_revs);
 		return $page_revs[0];
 	}
-	print STDERR "  Found ", $revnum, " revision(s).\n";
+	print {*STDERR} "  Found ${revnum} revision(s).\n";
 	return @page_revs;
 }
 
@@ -701,8 +667,7 @@
 	my $n = 1;
 	foreach my $page (@pages) {
 		my $id = $page->{pageid};
-
-		print STDERR "page $n/", scalar(@pages), ": ". $page->{title} ."\n";
+		print {*STDERR} "page ${n}/", scalar(@pages), ': ', $page->{title}, "\n";
 		$n++;
 		my @page_revs = fetch_mw_revisions_for_page($page, $id, $fetch_from);
 		@revisions = (@page_revs, @revisions);
@@ -716,7 +681,7 @@
     $path =~ s/\\/\\\\/g;
     $path =~ s/"/\\"/g;
     $path =~ s/\n/\\n/g;
-    return '"' . $path . '"';
+    return qq("${path}");
 }
 
 sub import_file_revision {
@@ -736,42 +701,43 @@
 	my $author = $commit{author};
 	my $date = $commit{date};
 
-	print STDOUT "commit refs/mediawiki/$remotename/master\n";
-	print STDOUT "mark :$n\n";
-	print STDOUT "committer $author <$author\@$wiki_name> ", $date->epoch, " +0000\n";
+	print {*STDOUT} "commit refs/mediawiki/${remotename}/master\n";
+	print {*STDOUT} "mark :${n}\n";
+	print {*STDOUT} "committer ${author} <${author}\@${wiki_name}> " . $date->epoch . " +0000\n";
 	literal_data($comment);
 
 	# If it's not a clone, we need to know where to start from
 	if (!$full_import && $n == 1) {
-		print STDOUT "from refs/mediawiki/$remotename/master^0\n";
+		print {*STDOUT} "from refs/mediawiki/${remotename}/master^0\n";
 	}
 	if ($content ne DELETED_CONTENT) {
-		print STDOUT "M 644 inline " .
-		    fe_escape_path($title . ".mw") . "\n";
+		print {*STDOUT} 'M 644 inline ' .
+		    fe_escape_path("${title}.mw") . "\n";
 		literal_data($content);
 		if (%mediafile) {
-			print STDOUT "M 644 inline "
+			print {*STDOUT} 'M 644 inline '
 			    . fe_escape_path($mediafile{title}) . "\n";
 			literal_data_raw($mediafile{content});
 		}
-		print STDOUT "\n\n";
+		print {*STDOUT} "\n\n";
 	} else {
-		print STDOUT "D " . fe_escape_path($title . ".mw") . "\n";
+		print {*STDOUT} 'D ' . fe_escape_path("${title}.mw") . "\n";
 	}
 
 	# mediawiki revision number in the git note
 	if ($full_import && $n == 1) {
-		print STDOUT "reset refs/notes/$remotename/mediawiki\n";
+		print {*STDOUT} "reset refs/notes/${remotename}/mediawiki\n";
 	}
-	print STDOUT "commit refs/notes/$remotename/mediawiki\n";
-	print STDOUT "committer $author <$author\@$wiki_name> ", $date->epoch, " +0000\n";
-	literal_data("Note added by git-mediawiki during import");
+	print {*STDOUT} "commit refs/notes/${remotename}/mediawiki\n";
+	print {*STDOUT} "committer ${author} <${author}\@${wiki_name}> " . $date->epoch . " +0000\n";
+	literal_data('Note added by git-mediawiki during import');
 	if (!$full_import && $n == 1) {
-		print STDOUT "from refs/notes/$remotename/mediawiki^0\n";
+		print {*STDOUT} "from refs/notes/${remotename}/mediawiki^0\n";
 	}
-	print STDOUT "N inline :$n\n";
-	literal_data("mediawiki_revision: " . $commit{mw_revision});
-	print STDOUT "\n\n";
+	print {*STDOUT} "N inline :${n}\n";
+	literal_data("mediawiki_revision: $commit{mw_revision}");
+	print {*STDOUT} "\n\n";
+	return;
 }
 
 # parse a sequence of
@@ -784,23 +750,25 @@
 	my @refs;
 	while (1) {
 		my $line = <STDIN>;
-		if ($line =~ m/^$cmd (.*)$/) {
+		if ($line =~ /^$cmd (.*)$/) {
 			push(@refs, $1);
 		} elsif ($line eq "\n") {
 			return @refs;
 		} else {
-			die("Invalid command in a '$cmd' batch: ". $_);
+			die("Invalid command in a '$cmd' batch: $_\n");
 		}
 	}
+	return;
 }
 
 sub mw_import {
 	# multiple import commands can follow each other.
-	my @refs = (shift, get_more_refs("import"));
+	my @refs = (shift, get_more_refs('import'));
 	foreach my $ref (@refs) {
 		mw_import_ref($ref);
 	}
-	print STDOUT "done\n";
+	print {*STDOUT} "done\n";
+	return;
 }
 
 sub mw_import_ref {
@@ -810,40 +778,41 @@
 	# Since HEAD is a symbolic ref to master (by convention,
 	# followed by the output of the command "list" that we gave),
 	# we don't need to do anything in this case.
-	if ($ref eq "HEAD") {
+	if ($ref eq 'HEAD') {
 		return;
 	}
 
-	mw_connect_maybe();
+	$mediawiki = connect_maybe($mediawiki, $remotename, $url);
 
-	print STDERR "Searching revisions...\n";
+	print {*STDERR} "Searching revisions...\n";
 	my $last_local = get_last_local_revision();
 	my $fetch_from = $last_local + 1;
 	if ($fetch_from == 1) {
-		print STDERR ", fetching from beginning.\n";
+		print {*STDERR} ", fetching from beginning.\n";
 	} else {
-		print STDERR ", fetching from here.\n";
+		print {*STDERR} ", fetching from here.\n";
 	}
 
 	my $n = 0;
-	if ($fetch_strategy eq "by_rev") {
-		print STDERR "Fetching & writing export data by revs...\n";
+	if ($fetch_strategy eq 'by_rev') {
+		print {*STDERR} "Fetching & writing export data by revs...\n";
 		$n = mw_import_ref_by_revs($fetch_from);
-	} elsif ($fetch_strategy eq "by_page") {
-		print STDERR "Fetching & writing export data by pages...\n";
+	} elsif ($fetch_strategy eq 'by_page') {
+		print {*STDERR} "Fetching & writing export data by pages...\n";
 		$n = mw_import_ref_by_pages($fetch_from);
 	} else {
-		print STDERR "fatal: invalid fetch strategy \"$fetch_strategy\".\n";
-		print STDERR "Check your configuration variables remote.$remotename.fetchStrategy and mediawiki.fetchStrategy\n";
+		print {*STDERR} qq(fatal: invalid fetch strategy "${fetch_strategy}".\n);
+		print {*STDERR} "Check your configuration variables remote.${remotename}.fetchStrategy and mediawiki.fetchStrategy\n";
 		exit 1;
 	}
 
 	if ($fetch_from == 1 && $n == 0) {
-		print STDERR "You appear to have cloned an empty MediaWiki.\n";
+		print {*STDERR} "You appear to have cloned an empty MediaWiki.\n";
 		# Something has to be done remote-helper side. If nothing is done, an error is
 		# thrown saying that HEAD is referring to unknown object 0000000000000000000
 		# and the clone fails.
 	}
+	return;
 }
 
 sub mw_import_ref_by_pages {
@@ -855,7 +824,7 @@
 	my ($n, @revisions) = fetch_mw_revisions(\@pages, $fetch_from);
 
 	@revisions = sort {$a->{revid} <=> $b->{revid}} @revisions;
-	my @revision_ids = map $_->{revid}, @revisions;
+	my @revision_ids = map { $_->{revid} } @revisions;
 
 	return mw_import_revids($fetch_from, \@revision_ids, \%pages_hash);
 }
@@ -882,7 +851,7 @@
 	my $n_actual = 0;
 	my $last_timestamp = 0; # Placeholer in case $rev->timestamp is undefined
 
-	foreach my $pagerevid (@$revision_ids) {
+	foreach my $pagerevid (@{$revision_ids}) {
 	        # Count page even if we skip it, since we display
 		# $n/$total and $total includes skipped pages.
 		$n++;
@@ -898,7 +867,7 @@
 		my $result = $mediawiki->api($query);
 
 		if (!$result) {
-			die "Failed to retrieve modified page for revision $pagerevid";
+			die "Failed to retrieve modified page for revision $pagerevid\n";
 		}
 
 		if (defined($result->{query}->{badrevids}->{$pagerevid})) {
@@ -907,7 +876,7 @@
 		}
 
 		if (!defined($result->{query}->{pages})) {
-			die "Invalid revision $pagerevid.";
+			die "Invalid revision ${pagerevid}.\n";
 		}
 
 		my @result_pages = values(%{$result->{query}->{pages}});
@@ -917,8 +886,8 @@
 		my $page_title = $result_page->{title};
 
 		if (!exists($pages->{$page_title})) {
-			print STDERR "$n/", scalar(@$revision_ids),
-				": Skipping revision #$rev->{revid} of $page_title\n";
+			print {*STDERR} "${n}/", scalar(@{$revision_ids}),
+				": Skipping revision #$rev->{revid} of ${page_title}\n";
 			next;
 		}
 
@@ -927,7 +896,7 @@
 		my %commit;
 		$commit{author} = $rev->{user} || 'Anonymous';
 		$commit{comment} = $rev->{comment} || EMPTY_MESSAGE;
-		$commit{title} = mediawiki_smudge_filename($page_title);
+		$commit{title} = smudge_filename($page_title);
 		$commit{mw_revision} = $rev->{revid};
 		$commit{content} = mediawiki_smudge($rev->{'*'});
 
@@ -943,14 +912,14 @@
 		my %mediafile;
 		if ($namespace) {
 			my $id = get_mw_namespace_id($namespace);
-			if ($id && $id == get_mw_namespace_id("File")) {
+			if ($id && $id == get_mw_namespace_id('File')) {
 				%mediafile = get_mw_mediafile_for_page_revision($filename, $rev->{timestamp});
 			}
 		}
 		# If this is a revision of the media page for new version
 		# of a file do one common commit for both file and media page.
 		# Else do commit only for that page.
-		print STDERR "$n/", scalar(@$revision_ids), ": Revision #$rev->{revid} of $commit{title}\n";
+		print {*STDERR} "${n}/", scalar(@{$revision_ids}), ": Revision #$rev->{revid} of $commit{title}\n";
 		import_file_revision(\%commit, ($fetch_from == 1), $n_actual, \%mediafile);
 	}
 
@@ -958,17 +927,17 @@
 }
 
 sub error_non_fast_forward {
-	my $advice = run_git("config --bool advice.pushNonFastForward");
+	my $advice = run_git('config --bool advice.pushNonFastForward');
 	chomp($advice);
-	if ($advice ne "false") {
+	if ($advice ne 'false') {
 		# Native git-push would show this after the summary.
 		# We can't ask it to display it cleanly, so print it
 		# ourselves before.
-		print STDERR "To prevent you from losing history, non-fast-forward updates were rejected\n";
-		print STDERR "Merge the remote changes (e.g. 'git pull') before pushing again. See the\n";
-		print STDERR "'Note about fast-forwards' section of 'git push --help' for details.\n";
+		print {*STDERR} "To prevent you from losing history, non-fast-forward updates were rejected\n";
+		print {*STDERR} "Merge the remote changes (e.g. 'git pull') before pushing again. See the\n";
+		print {*STDERR} "'Note about fast-forwards' section of 'git push --help' for details.\n";
 	}
-	print STDOUT "error $_[0] \"non-fast-forward\"\n";
+	print {*STDOUT} qq(error $_[0] "non-fast-forward"\n);
 	return 0;
 }
 
@@ -979,34 +948,34 @@
 	my $file_deleted = shift;
 	my $summary = shift;
 	my $newrevid;
-	my $path = "File:" . $complete_file_name;
+	my $path = "File:${complete_file_name}";
 	my %hashFiles = get_allowed_file_extensions();
 	if (!exists($hashFiles{$extension})) {
-		print STDERR "$complete_file_name is not a permitted file on this wiki.\n";
-		print STDERR "Check the configuration of file uploads in your mediawiki.\n";
+		print {*STDERR} "${complete_file_name} is not a permitted file on this wiki.\n";
+		print {*STDERR} "Check the configuration of file uploads in your mediawiki.\n";
 		return $newrevid;
 	}
 	# Deleting and uploading a file requires a priviledged user
 	if ($file_deleted) {
-		mw_connect_maybe();
+		$mediawiki = connect_maybe($mediawiki, $remotename, $url);
 		my $query = {
 			action => 'delete',
 			title => $path,
 			reason => $summary
 		};
 		if (!$mediawiki->edit($query)) {
-			print STDERR "Failed to delete file on remote wiki\n";
-			print STDERR "Check your permissions on the remote site. Error code:\n";
-			print STDERR $mediawiki->{error}->{code} . ':' . $mediawiki->{error}->{details};
+			print {*STDERR} "Failed to delete file on remote wiki\n";
+			print {*STDERR} "Check your permissions on the remote site. Error code:\n";
+			print {*STDERR} $mediawiki->{error}->{code} . ':' . $mediawiki->{error}->{details};
 			exit 1;
 		}
 	} else {
 		# Don't let perl try to interpret file content as UTF-8 => use "raw"
-		my $content = run_git("cat-file blob $new_sha1", "raw");
-		if ($content ne "") {
-			mw_connect_maybe();
+		my $content = run_git("cat-file blob ${new_sha1}", 'raw');
+		if ($content ne EMPTY) {
+			$mediawiki = connect_maybe($mediawiki, $remotename, $url);
 			$mediawiki->{config}->{upload_url} =
-				"$url/index.php/Special:Upload";
+				"${url}/index.php/Special:Upload";
 			$mediawiki->edit({
 				action => 'upload',
 				filename => $complete_file_name,
@@ -1018,12 +987,12 @@
 			}, {
 				skip_encoding => 1
 			} ) || die $mediawiki->{error}->{code} . ':'
-				 . $mediawiki->{error}->{details};
+				 . $mediawiki->{error}->{details} . "\n";
 			my $last_file_page = $mediawiki->get_page({title => $path});
 			$newrevid = $last_file_page->{revid};
-			print STDERR "Pushed file: $new_sha1 - $complete_file_name.\n";
+			print {*STDERR} "Pushed file: ${new_sha1} - ${complete_file_name}.\n";
 		} else {
-			print STDERR "Empty file $complete_file_name not pushed.\n";
+			print {*STDERR} "Empty file ${complete_file_name} not pushed.\n";
 		}
 	}
 	return $newrevid;
@@ -1045,24 +1014,24 @@
 	my $newrevid;
 
 	if ($summary eq EMPTY_MESSAGE) {
-		$summary = '';
+		$summary = EMPTY;
 	}
 
 	my $new_sha1 = $diff_info_split[3];
 	my $old_sha1 = $diff_info_split[2];
 	my $page_created = ($old_sha1 eq NULL_SHA1);
 	my $page_deleted = ($new_sha1 eq NULL_SHA1);
-	$complete_file_name = mediawiki_clean_filename($complete_file_name);
+	$complete_file_name = clean_filename($complete_file_name);
 
 	my ($title, $extension) = $complete_file_name =~ /^(.*)\.([^\.]*)$/;
 	if (!defined($extension)) {
-		$extension = "";
+		$extension = EMPTY;
 	}
-	if ($extension eq "mw") {
+	if ($extension eq 'mw') {
 		my $ns = get_mw_namespace_id_for_page($complete_file_name);
-		if ($ns && $ns == get_mw_namespace_id("File") && (!$export_media)) {
-			print STDERR "Ignoring media file related page: $complete_file_name\n";
-			return ($oldrevid, "ok");
+		if ($ns && $ns == get_mw_namespace_id('File') && (!$export_media)) {
+			print {*STDERR} "Ignoring media file related page: ${complete_file_name}\n";
+			return ($oldrevid, 'ok');
 		}
 		my $file_content;
 		if ($page_deleted) {
@@ -1072,10 +1041,10 @@
 			# with this content instead:
 			$file_content = DELETED_CONTENT;
 		} else {
-			$file_content = run_git("cat-file blob $new_sha1");
+			$file_content = run_git("cat-file blob ${new_sha1}");
 		}
 
-		mw_connect_maybe();
+		$mediawiki = connect_maybe($mediawiki, $remotename, $url);
 
 		my $result = $mediawiki->edit( {
 			action => 'edit',
@@ -1089,49 +1058,49 @@
 		if (!$result) {
 			if ($mediawiki->{error}->{code} == 3) {
 				# edit conflicts, considered as non-fast-forward
-				print STDERR 'Warning: Error ' .
+				print {*STDERR} 'Warning: Error ' .
 				    $mediawiki->{error}->{code} .
-				    ' from mediwiki: ' . $mediawiki->{error}->{details} .
+				    ' from mediawiki: ' . $mediawiki->{error}->{details} .
 				    ".\n";
-				return ($oldrevid, "non-fast-forward");
+				return ($oldrevid, 'non-fast-forward');
 			} else {
 				# Other errors. Shouldn't happen => just die()
 				die 'Fatal: Error ' .
 				    $mediawiki->{error}->{code} .
-				    ' from mediwiki: ' . $mediawiki->{error}->{details};
+				    ' from mediawiki: ' . $mediawiki->{error}->{details} . "\n";
 			}
 		}
 		$newrevid = $result->{edit}->{newrevid};
-		print STDERR "Pushed file: $new_sha1 - $title\n";
+		print {*STDERR} "Pushed file: ${new_sha1} - ${title}\n";
 	} elsif ($export_media) {
 		$newrevid = mw_upload_file($complete_file_name, $new_sha1,
 					   $extension, $page_deleted,
 					   $summary);
 	} else {
-		print STDERR "Ignoring media file $title\n";
+		print {*STDERR} "Ignoring media file ${title}\n";
 	}
 	$newrevid = ($newrevid or $oldrevid);
-	return ($newrevid, "ok");
+	return ($newrevid, 'ok');
 }
 
 sub mw_push {
 	# multiple push statements can follow each other
-	my @refsspecs = (shift, get_more_refs("push"));
+	my @refsspecs = (shift, get_more_refs('push'));
 	my $pushed;
 	for my $refspec (@refsspecs) {
 		my ($force, $local, $remote) = $refspec =~ /^(\+)?([^:]*):([^:]*)$/
-		    or die("Invalid refspec for push. Expected <src>:<dst> or +<src>:<dst>");
+		    or die("Invalid refspec for push. Expected <src>:<dst> or +<src>:<dst>\n");
 		if ($force) {
-			print STDERR "Warning: forced push not allowed on a MediaWiki.\n";
+			print {*STDERR} "Warning: forced push not allowed on a MediaWiki.\n";
 		}
-		if ($local eq "") {
-			print STDERR "Cannot delete remote branch on a MediaWiki\n";
-			print STDOUT "error $remote cannot delete\n";
+		if ($local eq EMPTY) {
+			print {*STDERR} "Cannot delete remote branch on a MediaWiki\n";
+			print {*STDOUT} "error ${remote} cannot delete\n";
 			next;
 		}
-		if ($remote ne "refs/heads/master") {
-			print STDERR "Only push to the branch 'master' is supported on a MediaWiki\n";
-			print STDOUT "error $remote only master allowed\n";
+		if ($remote ne 'refs/heads/master') {
+			print {*STDERR} "Only push to the branch 'master' is supported on a MediaWiki\n";
+			print {*STDOUT} "error ${remote} only master allowed\n";
 			next;
 		}
 		if (mw_push_revision($local, $remote)) {
@@ -1140,30 +1109,32 @@
 	}
 
 	# Notify Git that the push is done
-	print STDOUT "\n";
+	print {*STDOUT} "\n";
 
 	if ($pushed && $dumb_push) {
-		print STDERR "Just pushed some revisions to MediaWiki.\n";
-		print STDERR "The pushed revisions now have to be re-imported, and your current branch\n";
-		print STDERR "needs to be updated with these re-imported commits. You can do this with\n";
-		print STDERR "\n";
-		print STDERR "  git pull --rebase\n";
-		print STDERR "\n";
+		print {*STDERR} "Just pushed some revisions to MediaWiki.\n";
+		print {*STDERR} "The pushed revisions now have to be re-imported, and your current branch\n";
+		print {*STDERR} "needs to be updated with these re-imported commits. You can do this with\n";
+		print {*STDERR} "\n";
+		print {*STDERR} "  git pull --rebase\n";
+		print {*STDERR} "\n";
 	}
+	return;
 }
 
 sub mw_push_revision {
 	my $local = shift;
 	my $remote = shift; # actually, this has to be "refs/heads/master" at this point.
 	my $last_local_revid = get_last_local_revision();
-	print STDERR ".\n"; # Finish sentence started by get_last_local_revision()
+	print {*STDERR} ".\n"; # Finish sentence started by get_last_local_revision()
 	my $last_remote_revid = get_last_remote_revision();
 	my $mw_revision = $last_remote_revid;
 
 	# Get sha1 of commit pointed by local HEAD
-	my $HEAD_sha1 = run_git("rev-parse $local 2>/dev/null"); chomp($HEAD_sha1);
+	my $HEAD_sha1 = run_git("rev-parse ${local} 2>/dev/null");
+	chomp($HEAD_sha1);
 	# Get sha1 of commit pointed by remotes/$remotename/master
-	my $remoteorigin_sha1 = run_git("rev-parse refs/remotes/$remotename/master 2>/dev/null");
+	my $remoteorigin_sha1 = run_git("rev-parse refs/remotes/${remotename}/master 2>/dev/null");
 	chomp($remoteorigin_sha1);
 
 	if ($last_local_revid > 0 &&
@@ -1182,22 +1153,22 @@
 	if ($last_local_revid > 0) {
 		my $parsed_sha1 = $remoteorigin_sha1;
 		# Find a path from last MediaWiki commit to pushed commit
-		print STDERR "Computing path from local to remote ...\n";
-		my @local_ancestry = split(/\n/, run_git("rev-list --boundary --parents $local ^$parsed_sha1"));
+		print {*STDERR} "Computing path from local to remote ...\n";
+		my @local_ancestry = split(/\n/, run_git("rev-list --boundary --parents ${local} ^${parsed_sha1}"));
 		my %local_ancestry;
 		foreach my $line (@local_ancestry) {
-			if (my ($child, $parents) = $line =~ m/^-?([a-f0-9]+) ([a-f0-9 ]+)/) {
-				foreach my $parent (split(' ', $parents)) {
+			if (my ($child, $parents) = $line =~ /^-?([a-f0-9]+) ([a-f0-9 ]+)/) {
+				foreach my $parent (split(/ /, $parents)) {
 					$local_ancestry{$parent} = $child;
 				}
-			} elsif (!$line =~ m/^([a-f0-9]+)/) {
-				die "Unexpected output from git rev-list: $line";
+			} elsif (!$line =~ /^([a-f0-9]+)/) {
+				die "Unexpected output from git rev-list: ${line}\n";
 			}
 		}
 		while ($parsed_sha1 ne $HEAD_sha1) {
 			my $child = $local_ancestry{$parsed_sha1};
 			if (!$child) {
-				printf STDERR "Cannot find a path in history from remote commit to last commit\n";
+				print {*STDERR} "Cannot find a path in history from remote commit to last commit\n";
 				return error_non_fast_forward($remote);
 			}
 			push(@commit_pairs, [$parsed_sha1, $child]);
@@ -1206,12 +1177,12 @@
 	} else {
 		# No remote mediawiki revision. Export the whole
 		# history (linearized with --first-parent)
-		print STDERR "Warning: no common ancestor, pushing complete history\n";
-		my $history = run_git("rev-list --first-parent --children $local");
-		my @history = split('\n', $history);
+		print {*STDERR} "Warning: no common ancestor, pushing complete history\n";
+		my $history = run_git("rev-list --first-parent --children ${local}");
+		my @history = split(/\n/, $history);
 		@history = @history[1..$#history];
 		foreach my $line (reverse @history) {
-			my @commit_info_split = split(/ |\n/, $line);
+			my @commit_info_split = split(/[ \n]/, $line);
 			push(@commit_pairs, \@commit_info_split);
 		}
 	}
@@ -1219,12 +1190,12 @@
 	foreach my $commit_info_split (@commit_pairs) {
 		my $sha1_child = @{$commit_info_split}[0];
 		my $sha1_commit = @{$commit_info_split}[1];
-		my $diff_infos = run_git("diff-tree -r --raw -z $sha1_child $sha1_commit");
+		my $diff_infos = run_git("diff-tree -r --raw -z ${sha1_child} ${sha1_commit}");
 		# TODO: we could detect rename, and encode them with a #redirect on the wiki.
 		# TODO: for now, it's just a delete+add
 		my @diff_info_list = split(/\0/, $diff_infos);
 		# Keep the subject line of the commit message as mediawiki comment for the revision
-		my $commit_msg = run_git("log --no-walk --format=\"%s\" $sha1_commit");
+		my $commit_msg = run_git(qq(log --no-walk --format="%s" ${sha1_commit}));
 		chomp($commit_msg);
 		# Push every blob
 		while (@diff_info_list) {
@@ -1236,7 +1207,7 @@
 			my $info = shift(@diff_info_list);
 			my $file = shift(@diff_info_list);
 			($mw_revision, $status) = mw_push_file($info, $file, $commit_msg, $mw_revision);
-			if ($status eq "non-fast-forward") {
+			if ($status eq 'non-fast-forward') {
 				# we may already have sent part of the
 				# commit to MediaWiki, but it's too
 				# late to cancel it. Stop the push in
@@ -1244,22 +1215,22 @@
 				# accurate error message.
 				return error_non_fast_forward($remote);
 			}
-			if ($status ne "ok") {
-				die("Unknown error from mw_push_file()");
+			if ($status ne 'ok') {
+				die("Unknown error from mw_push_file()\n");
 			}
 		}
-		unless ($dumb_push) {
-			run_git("notes --ref=$remotename/mediawiki add -f -m \"mediawiki_revision: $mw_revision\" $sha1_commit");
-			run_git("update-ref -m \"Git-MediaWiki push\" refs/mediawiki/$remotename/master $sha1_commit $sha1_child");
+		if (!$dumb_push) {
+			run_git(qq(notes --ref=${remotename}/mediawiki add -f -m "mediawiki_revision: ${mw_revision}" ${sha1_commit}));
+			run_git(qq(update-ref -m "Git-MediaWiki push" refs/mediawiki/${remotename}/master ${sha1_commit} ${sha1_child}));
 		}
 	}
 
-	print STDOUT "ok $remote\n";
+	print {*STDOUT} "ok ${remote}\n";
 	return 1;
 }
 
 sub get_allowed_file_extensions {
-	mw_connect_maybe();
+	$mediawiki = connect_maybe($mediawiki, $remotename, $url);
 
 	my $query = {
 		action => 'query',
@@ -1267,8 +1238,8 @@
 		siprop => 'fileextensions'
 		};
 	my $result = $mediawiki->api($query);
-	my @file_extensions= map $_->{ext},@{$result->{query}->{fileextensions}};
-	my %hashFile = map {$_ => 1}@file_extensions;
+	my @file_extensions = map { $_->{ext}} @{$result->{query}->{fileextensions}};
+	my %hashFile = map { $_ => 1 } @file_extensions;
 
 	return %hashFile;
 }
@@ -1283,15 +1254,15 @@
 # Return MediaWiki id for a canonical namespace name.
 # Ex.: "File", "Project".
 sub get_mw_namespace_id {
-	mw_connect_maybe();
+	$mediawiki = connect_maybe($mediawiki, $remotename, $url);
 	my $name = shift;
 
 	if (!exists $namespace_id{$name}) {
 		# Look at configuration file, if the record for that namespace is
 		# already cached. Namespaces are stored in form:
 		# "Name_of_namespace:Id_namespace", ex.: "File:6".
-		my @temp = split(/[\n]/, run_git("config --get-all remote."
-						. $remotename .".namespaceCache"));
+		my @temp = split(/\n/,
+				 run_git("config --get-all remote.${remotename}.namespaceCache"));
 		chomp(@temp);
 		foreach my $ns (@temp) {
 			my ($n, $id) = split(/:/, $ns);
@@ -1305,7 +1276,7 @@
 	}
 
 	if (!exists $namespace_id{$name}) {
-		print STDERR "Namespace $name not found in cache, querying the wiki ...\n";
+		print {*STDERR} "Namespace ${name} not found in cache, querying the wiki ...\n";
 		# NS not found => get namespace id from MW and store it in
 	        # configuration file.
 	        my $query = {
@@ -1329,8 +1300,8 @@
 	my $ns = $namespace_id{$name};
 	my $id;
 
-	unless (defined $ns) {
-		print STDERR "No such namespace $name on MediaWiki.\n";
+	if (!defined $ns) {
+		print {*STDERR} "No such namespace ${name} on MediaWiki.\n";
 		$ns = {is_namespace => 0};
 		$namespace_id{$name} = $ns;
 	}
@@ -1344,15 +1315,15 @@
 
 	# Store explicitely requested namespaces on disk
 	if (!exists $cached_mw_namespace_id{$name}) {
-		run_git("config --add remote.". $remotename
-			.".namespaceCache \"". $name .":". $store_id ."\"");
+		run_git(qq(config --add remote.${remotename}.namespaceCache "${name}:${store_id}"));
 		$cached_mw_namespace_id{$name} = 1;
 	}
 	return $id;
 }
 
 sub get_mw_namespace_id_for_page {
-	if (my ($namespace) = $_[0] =~ /^([^:]*):/) {
+	my $namespace = shift;
+	if ($namespace =~ /^([^:]*):/) {
 		return get_mw_namespace_id($namespace);
 	} else {
 		return;
diff --git a/contrib/mw-to-git/t/t9365-continuing-queries.sh b/contrib/mw-to-git/t/t9365-continuing-queries.sh
new file mode 100755
index 0000000..27e267f
--- /dev/null
+++ b/contrib/mw-to-git/t/t9365-continuing-queries.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+test_description='Test the Git Mediawiki remote helper: queries w/ more than 500 results'
+
+. ./test-gitmw-lib.sh
+. $TEST_DIRECTORY/test-lib.sh
+
+test_check_precond
+
+test_expect_success 'creating page w/ >500 revisions' '
+	wiki_reset &&
+	for i in `test_seq 501`
+	do
+		echo "creating revision $i" &&
+		wiki_editpage foo "revision $i<br/>" true
+	done
+'
+
+test_expect_success 'cloning page w/ >500 revisions' '
+	git clone mediawiki::'"$WIKI_URL"' mw_dir
+'
+
+test_done
diff --git a/contrib/mw-to-git/t/test-gitmw-lib.sh b/contrib/mw-to-git/t/test-gitmw-lib.sh
index 3b2cfac..ca6860f 100755
--- a/contrib/mw-to-git/t/test-gitmw-lib.sh
+++ b/contrib/mw-to-git/t/test-gitmw-lib.sh
@@ -62,12 +62,8 @@
 		test_done
 	fi
 
-	if [ ! -f "$GIT_BUILD_DIR"/git-remote-mediawiki ];
-	then
-		echo "No remote mediawiki for git found. Copying it in git"
-		echo "cp $GIT_BUILD_DIR/contrib/mw-to-git/git-remote-mediawiki $GIT_BUILD_DIR/"
-		ln -s "$GIT_BUILD_DIR"/contrib/mw-to-git/git-remote-mediawiki "$GIT_BUILD_DIR"
-	fi
+	GIT_EXEC_PATH=$(cd "$(dirname "$0")" && cd "../.." && pwd)
+	PATH="$GIT_EXEC_PATH"'/bin-wrapper:'"$PATH"
 
 	if [ ! -d "$WIKI_DIR_INST/$WIKI_DIR_NAME" ];
 	then
@@ -336,20 +332,21 @@
 	fi
 
 	# Fetch MediaWiki's archive if not already present in the TMP directory
+	MW_FILENAME="mediawiki-$MW_VERSION_MAJOR.$MW_VERSION_MINOR.tar.gz"
 	cd "$TMP"
-	if [ ! -f "$MW_VERSION.tar.gz" ] ; then
-		echo "Downloading $MW_VERSION sources ..."
-		wget "http://download.wikimedia.org/mediawiki/1.19/mediawiki-1.19.0.tar.gz" ||
+	if [ ! -f $MW_FILENAME ] ; then
+		echo "Downloading $MW_VERSION_MAJOR.$MW_VERSION_MINOR sources ..."
+		wget "http://download.wikimedia.org/mediawiki/$MW_VERSION_MAJOR/$MW_FILENAME" ||
 			error "Unable to download "\
-			"http://download.wikimedia.org/mediawiki/1.19/"\
-			"mediawiki-1.19.0.tar.gz. "\
+			"http://download.wikimedia.org/mediawiki/$MW_VERSION_MAJOR/"\
+			"$MW_FILENAME. "\
 			"Please fix your connection and launch the script again."
-		echo "$MW_VERSION.tar.gz downloaded in `pwd`. "\
+		echo "$MW_FILENAME downloaded in `pwd`. "\
 			"You can delete it later if you want."
 	else
-		echo "Reusing existing $MW_VERSION.tar.gz downloaded in `pwd`."
+		echo "Reusing existing $MW_FILENAME downloaded in `pwd`."
 	fi
-	archive_abs_path=$(pwd)/"$MW_VERSION.tar.gz"
+	archive_abs_path=$(pwd)/$MW_FILENAME
 	cd "$WIKI_DIR_INST/$WIKI_DIR_NAME/" ||
 		error "can't cd to $WIKI_DIR_INST/$WIKI_DIR_NAME/"
 	tar xzf "$archive_abs_path" --strip-components=1 ||
@@ -431,5 +428,5 @@
 	# Delete the wiki's SQLite database
 	rm -f "$TMP/$DB_FILE" || error "Database $TMP/$DB_FILE could not be deleted."
 	rm -f "$FILES_FOLDER/$DB_FILE"
-	rm -rf "$TMP/$MW_VERSION"
+	rm -rf "$TMP/mediawiki-$MW_VERSION_MAJOR.$MW_VERSION_MINOR.tar.gz"
 }
diff --git a/contrib/mw-to-git/t/test.config b/contrib/mw-to-git/t/test.config
index 958b37b..4cfebe9 100644
--- a/contrib/mw-to-git/t/test.config
+++ b/contrib/mw-to-git/t/test.config
@@ -30,6 +30,8 @@
 
 # The variables below are used by the script to install a wiki.
 # You should not modify these unless you are modifying the script itself.
-MW_VERSION=mediawiki-1.19.0
+# tested versions: 1.19.X -> 1.21.1
+MW_VERSION_MAJOR=1.21
+MW_VERSION_MINOR=1
 FILES_FOLDER=install-wiki
 DB_INSTALL_SCRIPT=db_install.php
diff --git a/contrib/patches/docbook-xsl-manpages-charmap.patch b/contrib/patches/docbook-xsl-manpages-charmap.patch
deleted file mode 100644
index f2b08b4..0000000
--- a/contrib/patches/docbook-xsl-manpages-charmap.patch
+++ /dev/null
@@ -1,21 +0,0 @@
-From: Ismail Dönmez <ismail@pardus.org.tr>
-
-Trying to build the documentation with docbook-xsl 1.73 may result in
-the following error.  This patch fixes it.
-
-$ xmlto -m callouts.xsl man git-add.xml
-runtime error: file
-file:///usr/share/sgml/docbook/xsl-stylesheets-1.73.0/manpages/other.xsl line
-129 element call-template
-The called template 'read-character-map' was not found.
-
---- docbook-xsl-1.73.0/manpages/docbook.xsl.manpages-charmap	2007-07-23 16:24:23.000000000 +0100
-+++ docbook-xsl-1.73.0/manpages/docbook.xsl	2007-07-23 16:25:16.000000000 +0100
-@@ -37,6 +37,7 @@
-   <xsl:include href="lists.xsl"/>
-   <xsl:include href="endnotes.xsl"/>
-   <xsl:include href="table.xsl"/>
-+  <xsl:include href="../common/charmap.xsl"/>
-
-   <!-- * we rename the following just to avoid using params with "man" -->
-   <!-- * prefixes in the table.xsl stylesheet (because that stylesheet -->
diff --git a/contrib/remote-helpers/git-remote-bzr b/contrib/remote-helpers/git-remote-bzr
index c19ed0e..c3a3cac 100755
--- a/contrib/remote-helpers/git-remote-bzr
+++ b/contrib/remote-helpers/git-remote-bzr
@@ -13,6 +13,9 @@
 # or
 # % git clone bzr::lp:myrepo
 #
+# If you want to specify which branches you want track (per repo):
+# git config remote-bzr.branches 'trunk, devel, test'
+#
 
 import sys
 
@@ -27,6 +30,8 @@
 import bzrlib.transport
 import bzrlib.errors
 import bzrlib.ui
+import bzrlib.urlutils
+import bzrlib.branch
 
 import sys
 import os
@@ -37,6 +42,7 @@
 
 NAME_RE = re.compile('^([^<>]+)')
 AUTHOR_RE = re.compile('^([^<>]+?)? ?<([^<>]*)>$')
+EMAIL_RE = re.compile('^([^<>]+[^ \\\t<>])?\\b(?:[ \\t<>]*?)\\b([^ \\t<>]+@[^ \\t<>]+)')
 RAW_AUTHOR_RE = re.compile('^(\w+) (.+)? <(.*)> (\d+) ([+-]\d+)')
 
 def die(msg, *args):
@@ -49,6 +55,12 @@
 def gittz(tz):
     return '%+03d%02d' % (tz / 3600, tz % 3600 / 60)
 
+def get_config(config):
+    cmd = ['git', 'config', '--get', config]
+    process = subprocess.Popen(cmd, stdout=subprocess.PIPE)
+    output, _ = process.communicate()
+    return output
+
 class Marks:
 
     def __init__(self, path):
@@ -84,7 +96,7 @@
         return self.marks[rev]
 
     def to_rev(self, mark):
-        return self.rev_marks[mark]
+        return str(self.rev_marks[mark])
 
     def next_mark(self):
         self.last_mark += 1
@@ -104,7 +116,10 @@
         self.last_mark = mark
 
     def get_tip(self, branch):
-        return self.tips.get(branch, None)
+        try:
+            return str(self.tips[branch])
+        except KeyError:
+            return None
 
     def set_tip(self, branch, tip):
         self.tips[branch] = tip
@@ -174,9 +189,19 @@
         name = m.group(1)
         mail = m.group(2).strip()
     else:
-        m = NAME_RE.match(user)
+        m = EMAIL_RE.match(user)
         if m:
-            name = m.group(1).strip()
+            name = m.group(1)
+            mail = m.group(2)
+        else:
+            m = NAME_RE.match(user)
+            if m:
+                name = m.group(1).strip()
+
+    if not name:
+        name = 'unknown'
+    if not mail:
+        mail = 'Unknown'
 
     return '%s <%s>' % (name, mail)
 
@@ -250,22 +275,32 @@
 
     return final
 
-def export_branch(branch, name):
+def export_branch(repo, name):
     global prefix
 
     ref = '%s/heads/%s' % (prefix, name)
     tip = marks.get_tip(name)
 
+    branch = get_remote_branch(name)
     repo = branch.repository
-    repo.lock_read()
+
+    branch.lock_read()
     revs = branch.iter_merge_sorted_revisions(None, tip, 'exclude', 'forward')
-    count = 0
+    try:
+        tip_revno = branch.revision_id_to_revno(tip)
+        last_revno, _ = branch.last_revision_info()
+        total = last_revno - tip_revno
+    except bzrlib.errors.NoSuchRevision:
+        tip_revno = 0
+        total = 0
 
-    revs = [revid for revid, _, _, _ in revs if not marks.is_marked(revid)]
+    for revid, _, seq, _ in revs:
 
-    for revid in revs:
+        if marks.is_marked(revid):
+            continue
 
         rev = repo.get_revision(revid)
+        revno = seq[0]
 
         parents = rev.parent_ids
         time = rev.timestamp
@@ -320,12 +355,18 @@
             print "M %s :%u %s" % f
         print
 
-        count += 1
-        if (count % 100 == 0):
-            print "progress revision %s (%d/%d)" % (revid, count, len(revs))
-            print "#############################################################"
+        if len(seq) > 1:
+            # let's skip branch revisions from the progress report
+            continue
 
-    repo.unlock()
+        progress = (revno - tip_revno)
+        if (progress % 100 == 0):
+            if total:
+                print "progress revision %d '%s' (%d/%d)" % (revno, name, progress, total)
+            else:
+                print "progress revision %d '%s' (%d)" % (revno, name, progress)
+
+    branch.unlock()
 
     revid = branch.last_revision()
 
@@ -347,23 +388,24 @@
 def do_import(parser):
     global dirname
 
-    branch = parser.repo
+    repo = parser.repo
     path = os.path.join(dirname, 'marks-git')
 
     print "feature done"
     if os.path.exists(path):
         print "feature import-marks=%s" % path
     print "feature export-marks=%s" % path
+    print "feature force"
     sys.stdout.flush()
 
     while parser.check('import'):
         ref = parser[1]
         if ref.startswith('refs/heads/'):
             name = ref[len('refs/heads/'):]
-            export_branch(branch, name)
+            export_branch(repo, name)
         if ref.startswith('refs/tags/'):
             name = ref[len('refs/tags/'):]
-            export_tag(branch, name)
+            export_tag(repo, name)
         parser.next()
 
     print 'done'
@@ -382,23 +424,21 @@
 
 class CustomTree():
 
-    def __init__(self, repo, revid, parents, files):
+    def __init__(self, branch, revid, parents, files):
         global files_cache
 
-        self.repo = repo
-        self.revid = revid
-        self.parents = parents
         self.updates = {}
+        self.branch = branch
 
         def copy_tree(revid):
             files = files_cache[revid] = {}
-            tree = repo.repository.revision_tree(revid)
-            repo.lock_read()
+            branch.lock_read()
+            tree = branch.repository.revision_tree(revid)
             try:
                 for path, entry in tree.iter_entries_by_dir():
-                    files[path] = entry.file_id
+                    files[path] = [entry.file_id, None]
             finally:
-                repo.unlock()
+                branch.unlock()
             return files
 
         if len(parents) == 0:
@@ -411,12 +451,18 @@
                 self.base_files = copy_tree(self.base_id)
 
         self.files = files_cache[revid] = self.base_files.copy()
+        self.rev_files = {}
+
+        for path, data in self.files.iteritems():
+            fid, mark = data
+            self.rev_files[fid] = [path, mark]
 
         for path, f in files.iteritems():
-            fid = self.files.get(path, None)
+            fid, mark = self.files.get(path, [None, None])
             if not fid:
                 fid = bzrlib.generate_ids.gen_file_id(path)
             f['path'] = path
+            self.rev_files[fid] = [path, mark]
             self.updates[fid] = f
 
     def last_revision(self):
@@ -426,16 +472,16 @@
         changes = []
 
         def get_parent(dirname, basename):
-            parent_fid = self.base_files.get(dirname, None)
+            parent_fid, mark = self.base_files.get(dirname, [None, None])
             if parent_fid:
                 return parent_fid
-            parent_fid = self.files.get(dirname, None)
+            parent_fid, mark = self.files.get(dirname, [None, None])
             if parent_fid:
                 return parent_fid
             if basename == '':
                 return None
             fid = bzrlib.generate_ids.gen_file_id(path)
-            d = add_entry(fid, dirname, 'directory')
+            add_entry(fid, dirname, 'directory')
             return fid
 
         def add_entry(fid, path, kind, mode = None):
@@ -456,9 +502,8 @@
                     (None, basename),
                     (None, kind),
                     (None, executable))
-            self.files[path] = change[0]
+            self.files[path] = [change[0], None]
             changes.append(change)
-            return change
 
         def update_entry(fid, path, kind, mode = None):
             dirname, basename = os.path.split(path)
@@ -478,9 +523,8 @@
                     (None, basename),
                     (None, kind),
                     (None, executable))
-            self.files[path] = change[0]
+            self.files[path] = [change[0], None]
             changes.append(change)
-            return change
 
         def remove_entry(fid, path, kind):
             dirname, basename = os.path.split(path)
@@ -495,7 +539,6 @@
                     (None, None))
             del self.files[path]
             changes.append(change)
-            return change
 
         for fid, f in self.updates.iteritems():
             path = f['path']
@@ -509,13 +552,30 @@
             else:
                 add_entry(fid, path, 'file', f['mode'])
 
+            self.files[path][1] = f['mark']
+            self.rev_files[fid][1] = f['mark']
+
         return changes
 
+    def get_content(self, file_id):
+        path, mark = self.rev_files[file_id]
+        if mark:
+            return blob_marks[mark]
+
+        # last resort
+        tree = self.branch.repository.revision_tree(self.base_id)
+        return tree.get_file_text(file_id)
+
     def get_file_with_stat(self, file_id, path=None):
-        return (StringIO.StringIO(self.updates[file_id]['data']), None)
+        content = self.get_content(file_id)
+        return (StringIO.StringIO(content), None)
 
     def get_symlink_target(self, file_id):
-        return self.updates[file_id]['data']
+        return self.get_content(file_id)
+
+    def id2path(self, file_id):
+        path, mark = self.rev_files[file_id]
+        return path
 
 def c_style_unescape(string):
     if string[0] == string[-1] == '"':
@@ -531,8 +591,11 @@
     ref = parser[1]
     parser.next()
 
-    if ref != 'refs/heads/master':
-        die("bzr doesn't support multiple branches; use 'master'")
+    if ref.startswith('refs/heads/'):
+        name = ref[len('refs/heads/'):]
+        branch = get_remote_branch(name)
+    else:
+        die('unknown ref')
 
     commit_mark = parser.get_mark()
     parser.next()
@@ -559,29 +622,27 @@
         if parser.check('M'):
             t, m, mark_ref, path = line.split(' ', 3)
             mark = int(mark_ref[1:])
-            f = { 'mode' : m, 'data' : blob_marks[mark] }
+            f = { 'mode' : m, 'mark' : mark }
         elif parser.check('D'):
-            t, path = line.split(' ')
+            t, path = line.split(' ', 1)
             f = { 'deleted' : True }
         else:
             die('Unknown file command: %s' % line)
         path = c_style_unescape(path).decode('utf-8')
         files[path] = f
 
-    repo = parser.repo
-
     committer, date, tz = committer
-    parents = [str(mark_to_rev(p)) for p in parents]
+    parents = [mark_to_rev(p) for p in parents]
     revid = bzrlib.generate_ids.gen_revision_id(committer, date)
     props = {}
-    props['branch-nick'] = repo.nick
+    props['branch-nick'] = branch.nick
 
-    mtree = CustomTree(repo, revid, parents, files)
+    mtree = CustomTree(branch, revid, parents, files)
     changes = mtree.iter_changes()
 
-    repo.lock_write()
+    branch.lock_write()
     try:
-        builder = repo.get_commit_builder(parents, None, date, tz, committer, props, revid)
+        builder = branch.get_commit_builder(parents, None, date, tz, committer, props, revid)
         try:
             list(builder.record_iter_changes(mtree, mtree.last_revision(), changes))
             builder.finish_inventory()
@@ -590,7 +651,7 @@
             builder.abort()
             raise
     finally:
-        repo.unlock()
+        branch.unlock()
 
     parsed_refs[ref] = revid
     marks.new_mark(revid, commit_mark)
@@ -601,9 +662,6 @@
     ref = parser[1]
     parser.next()
 
-    if ref != 'refs/heads/master':
-        die("bzr doesn't support multiple branches; use 'master'")
-
     # ugh
     if parser.check('commit'):
         parse_commit(parser)
@@ -616,7 +674,7 @@
     parsed_refs[ref] = mark_to_rev(from_mark)
 
 def do_export(parser):
-    global parsed_refs, dirname, peer
+    global parsed_refs, dirname
 
     parser.next()
 
@@ -634,20 +692,33 @@
         else:
             die('unhandled export command: %s' % line)
 
-    repo = parser.repo
-
     for ref, revid in parsed_refs.iteritems():
-        if ref == 'refs/heads/master':
-            repo.generate_revision_history(revid, marks.get_tip('master'))
-            if peer:
+        if ref.startswith('refs/heads/'):
+            name = ref[len('refs/heads/'):]
+            branch = get_remote_branch(name)
+            branch.generate_revision_history(revid, marks.get_tip(name))
+
+            if name in peers:
+                peer = bzrlib.branch.Branch.open(peers[name])
                 try:
-                    repo.push(peer, stop_revision=revid)
+                    peer.bzrdir.push_branch(branch, revision_id=revid)
                 except bzrlib.errors.DivergedBranches:
                     print "error %s non-fast forward" % ref
                     continue
-            else:
-                wt = repo.bzrdir.open_workingtree()
+
+            try:
+                wt = branch.bzrdir.open_workingtree()
                 wt.update()
+            except bzrlib.errors.NoWorkingTree:
+                pass
+        elif ref.startswith('refs/tags/'):
+            # TODO: implement tag push
+            print "error %s pushing tags not supported" % ref
+            continue
+        else:
+            # transport-helper/fast-export bugs
+            continue
+
         print "ok %s" % ref
 
     print
@@ -673,9 +744,15 @@
 
 def do_list(parser):
     global tags
-    print "? refs/heads/%s" % 'master'
 
-    branch = parser.repo
+    master_branch = None
+
+    for name in branches:
+        if not master_branch:
+            master_branch = name
+        print "? refs/heads/%s" % name
+
+    branch = get_remote_branch(master_branch)
     branch.lock_read()
     for tag, revid in branch.tags.get_tag_dict().items():
         try:
@@ -687,37 +764,123 @@
         print "? refs/tags/%s" % tag
         tags[tag] = revid
     branch.unlock()
-    print "@refs/heads/%s HEAD" % 'master'
+
+    print "@refs/heads/%s HEAD" % master_branch
     print
 
-def get_repo(url, alias):
-    global dirname, peer
+def clone(path, remote_branch):
+    try:
+        bdir = bzrlib.bzrdir.BzrDir.create(path)
+    except bzrlib.errors.AlreadyControlDirError:
+        bdir = bzrlib.bzrdir.BzrDir.open(path)
+    repo = bdir.find_repository()
+    repo.fetch(remote_branch.repository)
+    return remote_branch.sprout(bdir, repository=repo)
 
-    origin = bzrlib.bzrdir.BzrDir.open(url)
-    branch = origin.open_branch()
+def get_remote_branch(name):
+    global dirname, branches
 
-    if not isinstance(origin.transport, bzrlib.transport.local.LocalTransport):
-        clone_path = os.path.join(dirname, 'clone')
-        remote_branch = branch
-        if os.path.exists(clone_path):
-            # pull
-            d = bzrlib.bzrdir.BzrDir.open(clone_path)
-            branch = d.open_branch()
-            result = branch.pull(remote_branch, [], None, False)
-        else:
-            # clone
-            d = origin.sprout(clone_path, None,
-                    hardlink=True, create_tree_if_local=False,
-                    source_branch=remote_branch)
-            branch = d.open_branch()
-            branch.bind(remote_branch)
+    remote_branch = bzrlib.branch.Branch.open(branches[name])
+    if isinstance(remote_branch.user_transport, bzrlib.transport.local.LocalTransport):
+        return remote_branch
 
-        peer = remote_branch
+    branch_path = os.path.join(dirname, 'clone', name)
+
+    try:
+        branch = bzrlib.branch.Branch.open(branch_path)
+    except bzrlib.errors.NotBranchError:
+        # clone
+        branch = clone(branch_path, remote_branch)
     else:
-        peer = None
+        # pull
+        try:
+            branch.pull(remote_branch, overwrite=True)
+        except bzrlib.errors.DivergedBranches:
+            # use remote branch for now
+            return remote_branch
 
     return branch
 
+def find_branches(repo):
+    transport = repo.bzrdir.root_transport
+
+    for fn in transport.iter_files_recursive():
+        if not fn.endswith('.bzr/branch-format'):
+            continue
+
+        name = subdir = fn[:-len('/.bzr/branch-format')]
+        name = name if name != '' else 'master'
+        name = name.replace('/', '+')
+
+        try:
+            cur = transport.clone(subdir)
+            branch = bzrlib.branch.Branch.open_from_transport(cur)
+        except bzrlib.errors.NotBranchError:
+            continue
+        else:
+            yield name, branch.base
+
+def get_repo(url, alias):
+    global dirname, peer, branches
+
+    normal_url = bzrlib.urlutils.normalize_url(url)
+    origin = bzrlib.bzrdir.BzrDir.open(url)
+    is_local = isinstance(origin.transport, bzrlib.transport.local.LocalTransport)
+
+    shared_path = os.path.join(gitdir, 'bzr')
+    try:
+        shared_dir = bzrlib.bzrdir.BzrDir.open(shared_path)
+    except bzrlib.errors.NotBranchError:
+        shared_dir = bzrlib.bzrdir.BzrDir.create(shared_path)
+    try:
+        shared_repo = shared_dir.open_repository()
+    except bzrlib.errors.NoRepositoryPresent:
+        shared_repo = shared_dir.create_repository(shared=True)
+
+    if not is_local:
+        clone_path = os.path.join(dirname, 'clone')
+        if not os.path.exists(clone_path):
+            os.mkdir(clone_path)
+        else:
+            # check and remove old organization
+            try:
+                bdir = bzrlib.bzrdir.BzrDir.open(clone_path)
+                bdir.destroy_repository()
+            except bzrlib.errors.NotBranchError:
+                pass
+            except bzrlib.errors.NoRepositoryPresent:
+                pass
+
+    wanted = get_config('remote-bzr.branches').rstrip().split(', ')
+    # stupid python
+    wanted = [e for e in wanted if e]
+
+    if not wanted:
+        try:
+            repo = origin.open_repository()
+            if not repo.user_transport.listable():
+                # this repository is not usable for us
+                raise bzrlib.errors.NoRepositoryPresent(repo.bzrdir)
+        except bzrlib.errors.NoRepositoryPresent:
+            wanted = ['master']
+
+    if wanted:
+        def list_wanted(url, wanted):
+            for name in wanted:
+                subdir = name if name != 'master' else ''
+                yield name, bzrlib.urlutils.join(url, subdir)
+
+        branch_list = list_wanted(url, wanted)
+    else:
+        branch_list = find_branches(repo)
+
+    for name, url in branch_list:
+        if not is_local:
+            peers[name] = url
+        branches[name] = url
+
+    return origin
+
 def fix_path(alias, orig_url):
     url = urlparse.urlparse(orig_url, 'file')
     if url.scheme != 'file' or os.path.isabs(url.path):
@@ -727,12 +890,13 @@
     subprocess.call(cmd)
 
 def main(args):
-    global marks, prefix, dirname
+    global marks, prefix, gitdir, dirname
     global tags, filenodes
     global blob_marks
     global parsed_refs
     global files_cache
     global is_tmp
+    global branches, peers
 
     alias = args[1]
     url = args[2]
@@ -743,6 +907,8 @@
     parsed_refs = {}
     files_cache = {}
     marks = None
+    branches = {}
+    peers = {}
 
     if alias[5:] == url:
         is_tmp = True
@@ -760,7 +926,8 @@
     if not os.path.exists(dirname):
         os.makedirs(dirname)
 
-    bzrlib.ui.ui_factory.be_quiet(True)
+    if hasattr(bzrlib.ui.ui_factory, 'be_quiet'):
+        bzrlib.ui.ui_factory.be_quiet(True)
 
     repo = get_repo(url, alias)
 
diff --git a/contrib/remote-helpers/git-remote-hg b/contrib/remote-helpers/git-remote-hg
index 06920f2..0194c67 100755
--- a/contrib/remote-helpers/git-remote-hg
+++ b/contrib/remote-helpers/git-remote-hg
@@ -12,7 +12,7 @@
 # For remote repositories a local clone is stored in
 # "$GIT_DIR/hg/origin/clone/.hg/".
 
-from mercurial import hg, ui, bookmarks, context, encoding, node, error, extensions
+from mercurial import hg, ui, bookmarks, context, encoding, node, error, extensions, discovery, util
 
 import re
 import sys
@@ -25,18 +25,15 @@
 import urlparse, hashlib
 
 #
-# If you want to switch to hg-git compatibility mode:
-# git config --global remote-hg.hg-git-compat true
-#
 # If you are not in hg-git-compat mode and want to disable the tracking of
 # named branches:
 # git config --global remote-hg.track-branches false
 #
-# If you don't want to force pushes (and thus risk creating new remote heads):
-# git config --global remote-hg.force-push false
-#
 # If you want the equivalent of hg's clone/pull--insecure option:
-# git config remote-hg.insecure true
+# git config --global remote-hg.insecure true
+#
+# If you want to switch to hg-git compatibility mode:
+# git config --global remote-hg.hg-git-compat true
 #
 # git:
 # Sensible defaults for git.
@@ -55,6 +52,8 @@
 AUTHOR_HG_RE = re.compile('^(.*?) ?<(.*?)(?:>(.+)?)?$')
 RAW_AUTHOR_RE = re.compile('^(\w+) (?:(.+)? )?<(.*)> (\d+) ([+-]\d+)')
 
+VERSION = 2
+
 def die(msg, *args):
     sys.stderr.write('ERROR: %s\n' % (msg % args))
     sys.exit(1)
@@ -72,8 +71,11 @@
     m = { '100755': 'x', '120000': 'l' }
     return m.get(mode, '')
 
-def hghex(node):
-    return hg.node.hex(node)
+def hghex(n):
+    return node.hex(n)
+
+def hgbin(n):
+    return node.bin(n)
 
 def hgref(ref):
     return ref.replace('___', ' ')
@@ -81,22 +83,49 @@
 def gitref(ref):
     return ref.replace(' ', '___')
 
+def check_version(*check):
+    if not hg_version:
+        return True
+    return hg_version >= check
+
 def get_config(config):
     cmd = ['git', 'config', '--get', config]
     process = subprocess.Popen(cmd, stdout=subprocess.PIPE)
     output, _ = process.communicate()
     return output
 
+def get_config_bool(config, default=False):
+    value = get_config(config).rstrip('\n')
+    if value == "true":
+        return True
+    elif value == "false":
+        return False
+    else:
+        return default
+
 class Marks:
 
-    def __init__(self, path):
+    def __init__(self, path, repo):
         self.path = path
+        self.repo = repo
+        self.clear()
+        self.load()
+
+        if self.version < VERSION:
+            if self.version == 1:
+                self.upgrade_one()
+
+            # upgraded?
+            if self.version < VERSION:
+                self.clear()
+                self.version = VERSION
+
+    def clear(self):
         self.tips = {}
         self.marks = {}
         self.rev_marks = {}
         self.last_mark = 0
-
-        self.load()
+        self.version = 0
 
     def load(self):
         if not os.path.exists(self.path):
@@ -107,12 +136,21 @@
         self.tips = tmp['tips']
         self.marks = tmp['marks']
         self.last_mark = tmp['last-mark']
+        self.version = tmp.get('version', 1)
 
         for rev, mark in self.marks.iteritems():
-            self.rev_marks[mark] = int(rev)
+            self.rev_marks[mark] = rev
+
+    def upgrade_one(self):
+        def get_id(rev):
+            return hghex(self.repo.changelog.node(int(rev)))
+        self.tips = dict((name, get_id(rev)) for name, rev in self.tips.iteritems())
+        self.marks = dict((get_id(rev), mark) for rev, mark in self.marks.iteritems())
+        self.rev_marks = dict((mark, get_id(rev)) for mark, rev in self.rev_marks.iteritems())
+        self.version = 2
 
     def dict(self):
-        return { 'tips': self.tips, 'marks': self.marks, 'last-mark' : self.last_mark }
+        return { 'tips': self.tips, 'marks': self.marks, 'last-mark' : self.last_mark, 'version' : self.version }
 
     def store(self):
         json.dump(self.dict(), open(self.path, 'w'))
@@ -121,10 +159,10 @@
         return str(self.dict())
 
     def from_rev(self, rev):
-        return self.marks[str(rev)]
+        return self.marks[rev]
 
     def to_rev(self, mark):
-        return self.rev_marks[mark]
+        return str(self.rev_marks[mark])
 
     def next_mark(self):
         self.last_mark += 1
@@ -132,19 +170,19 @@
 
     def get_mark(self, rev):
         self.last_mark += 1
-        self.marks[str(rev)] = self.last_mark
+        self.marks[rev] = self.last_mark
         return self.last_mark
 
     def new_mark(self, rev, mark):
-        self.marks[str(rev)] = mark
+        self.marks[rev] = mark
         self.rev_marks[mark] = rev
         self.last_mark = mark
 
     def is_marked(self, rev):
-        return str(rev) in self.marks
+        return rev in self.marks
 
     def get_tip(self, branch):
-        return self.tips.get(branch, 0)
+        return str(self.tips[branch])
 
     def set_tip(self, branch, tip):
         self.tips[branch] = tip
@@ -252,7 +290,7 @@
     removed = set()
 
     # load earliest manifest first for caching reasons
-    prev = repo[parent].manifest().copy()
+    prev = parent.manifest().copy()
     cur = ctx.manifest()
 
     for fn in cur:
@@ -320,6 +358,21 @@
 
     return '%s <%s>' % (name, mail)
 
+def updatebookmarks(repo, peer):
+    remotemarks = peer.listkeys('bookmarks')
+    localmarks = repo._bookmarks
+
+    if not remotemarks:
+        return
+
+    for k, v in remotemarks.iteritems():
+        localmarks[k] = hgbin(v)
+
+    if hasattr(localmarks, 'write'):
+        localmarks.write()
+    else:
+        bookmarks.write(repo)
+
 def get_repo(url, alias):
     global dirname, peer
 
@@ -327,41 +380,44 @@
     myui.setconfig('ui', 'interactive', 'off')
     myui.fout = sys.stderr
 
-    try:
-        if get_config('remote-hg.insecure') == 'true\n':
-            myui.setconfig('web', 'cacerts', '')
-    except subprocess.CalledProcessError:
-        pass
+    if get_config_bool('remote-hg.insecure'):
+        myui.setconfig('web', 'cacerts', '')
 
-    try:
-        mod = extensions.load(myui, 'hgext.schemes', None)
-        mod.extsetup(myui)
-    except ImportError:
-        pass
+    extensions.loadall(myui)
 
-    if hg.islocal(url):
+    if hg.islocal(url) and not os.environ.get('GIT_REMOTE_HG_TEST_REMOTE'):
         repo = hg.repository(myui, url)
+        if not os.path.exists(dirname):
+            os.makedirs(dirname)
     else:
+        shared_path = os.path.join(gitdir, 'hg')
+        if not os.path.exists(shared_path):
+            try:
+                hg.clone(myui, {}, url, shared_path, update=False, pull=True)
+            except:
+                die('Repository error')
+
+        if not os.path.exists(dirname):
+            os.makedirs(dirname)
+
         local_path = os.path.join(dirname, 'clone')
         if not os.path.exists(local_path):
-            try:
-                peer, dstpeer = hg.clone(myui, {}, url, local_path, update=True, pull=True)
-            except:
-                die('Repository error')
-            repo = dstpeer.local()
-        else:
-            repo = hg.repository(myui, local_path)
-            try:
-                peer = hg.peer(myui, {}, url)
-            except:
-                die('Repository error')
-            repo.pull(peer, heads=None, force=True)
+            hg.share(myui, shared_path, local_path, update=False)
+
+        repo = hg.repository(myui, local_path)
+        try:
+            peer = hg.peer(myui, {}, url)
+        except:
+            die('Repository error')
+        repo.pull(peer, heads=None, force=True)
+
+        updatebookmarks(repo, peer)
 
     return repo
 
 def rev_to_mark(rev):
     global marks
-    return marks.from_rev(rev)
+    return marks.from_rev(rev.hex())
 
 def mark_to_rev(mark):
     global marks
@@ -371,17 +427,24 @@
     global prefix, marks, mode
 
     ename = '%s/%s' % (kind, name)
-    tip = marks.get_tip(ename)
+    try:
+        tip = marks.get_tip(ename)
+        tip = repo[tip].rev()
+    except:
+        tip = 0
 
     revs = xrange(tip, head.rev() + 1)
-    count = 0
-
-    revs = [rev for rev in revs if not marks.is_marked(rev)]
+    total = len(revs)
 
     for rev in revs:
 
         c = repo[rev]
-        (manifest, user, (time, tz), files, desc, extra) = repo.changelog.read(c.node())
+        node = c.node()
+
+        if marks.is_marked(c.hex()):
+            continue
+
+        (manifest, user, (time, tz), files, desc, extra) = repo.changelog.read(node)
         rev_branch = extra['branch']
 
         author = "%s %d %s" % (fixup_user(user), time, gittz(tz))
@@ -391,7 +454,7 @@
         else:
             committer = author
 
-        parents = [p for p in repo.changelog.parentrevs(rev) if p >= 0]
+        parents = [repo[p] for p in repo.changelog.parentrevs(rev) if p >= 0]
 
         if len(parents) == 0:
             modified = c.manifest().keys()
@@ -433,7 +496,7 @@
         modified_final = export_files(c.filectx(f) for f in modified)
 
         print "commit %s/%s" % (prefix, ename)
-        print "mark :%d" % (marks.get_mark(rev))
+        print "mark :%d" % (marks.get_mark(c.hex()))
         print "author %s" % (author)
         print "committer %s" % (committer)
         print "data %d" % (len(desc))
@@ -444,23 +507,22 @@
             if len(parents) > 1:
                 print "merge :%s" % (rev_to_mark(parents[1]))
 
-        for f in modified_final:
-            print "M %s :%u %s" % f
         for f in removed:
             print "D %s" % (fix_file_path(f))
+        for f in modified_final:
+            print "M %s :%u %s" % f
         print
 
-        count += 1
-        if (count % 100 == 0):
-            print "progress revision %d '%s' (%d/%d)" % (rev, name, count, len(revs))
-            print "#############################################################"
+        progress = (rev - tip)
+        if (progress % 100 == 0):
+            print "progress revision %d '%s' (%d/%d)" % (rev, name, progress, total)
 
     # make sure the ref is updated
     print "reset %s/%s" % (prefix, ename)
-    print "from :%u" % rev_to_mark(rev)
+    print "from :%u" % rev_to_mark(head)
     print
 
-    marks.set_tip(ename, rev)
+    marks.set_tip(ename, head.hex())
 
 def export_tag(repo, tag):
     export_ref(repo, tag, 'tags', repo[hgref(tag)])
@@ -492,15 +554,12 @@
     if os.path.exists(path):
         print "*import-marks %s" % path
     print "*export-marks %s" % path
+    print "option"
 
     print
 
-def branch_tip(repo, branch):
-    # older versions of mercurial don't have this
-    if hasattr(repo, 'branchtip'):
-        return repo.branchtip(branch)
-    else:
-        return repo.branchtags()[branch]
+def branch_tip(branch):
+    return branches[branch][-1]
 
 def get_branch_tip(repo, branch):
     global branches
@@ -512,49 +571,45 @@
     # verify there's only one head
     if (len(heads) > 1):
         warn("Branch '%s' has more than one head, consider merging" % branch)
-        return branch_tip(repo, hgref(branch))
+        return branch_tip(hgref(branch))
 
     return heads[0]
 
 def list_head(repo, cur):
-    global g_head, bmarks
+    global g_head, bmarks, fake_bmark
 
-    head = bookmarks.readcurrent(repo)
-    if head:
-        node = repo[head]
-    else:
-        # fake bookmark from current branch
-        head = cur
-        node = repo['.']
-        if not node:
-            node = repo['tip']
-        if not node:
-            return
-        if head == 'default':
-            head = 'master'
-        bmarks[head] = node
+    if 'default' not in branches:
+        # empty repo
+        return
+
+    node = repo[branch_tip('default')]
+    head = 'master' if not 'master' in bmarks else 'default'
+    fake_bmark = head
+    bmarks[head] = node
 
     head = gitref(head)
     print "@refs/heads/%s HEAD" % head
     g_head = (head, node)
 
 def do_list(parser):
-    global branches, bmarks, mode, track_branches
+    global branches, bmarks, track_branches
 
     repo = parser.repo
     for bmark, node in bookmarks.listbookmarks(repo).iteritems():
         bmarks[bmark] = repo[node]
 
     cur = repo.dirstate.branch()
+    orig = peer if peer else repo
+
+    for branch, heads in orig.branchmap().iteritems():
+        # only open heads
+        heads = [h for h in heads if 'close' not in repo.changelog.read(h)[5]]
+        if heads:
+            branches[branch] = heads
 
     list_head(repo, cur)
 
     if track_branches:
-        for branch in repo.branchmap():
-            heads = repo.branchheads(branch)
-            if len(heads):
-                branches[branch] = heads
-
         for branch in branches:
             print "? refs/heads/branches/%s" % gitref(branch)
 
@@ -577,6 +632,7 @@
     if os.path.exists(path):
         print "feature import-marks=%s" % path
     print "feature export-marks=%s" % path
+    print "feature force"
     sys.stdout.flush()
 
     tmp = encoding.encoding
@@ -666,6 +722,11 @@
             die('Unknown file command: %s' % line)
         files[path] = f
 
+    # only export the commits if we are on an internal proxy repo
+    if dry_run and not peer:
+        parsed_refs[ref] = None
+        return
+
     def getfilectx(repo, memctx, f):
         of = files[f]
         if 'deleted' in of:
@@ -687,14 +748,14 @@
         extra['committer'] = "%s %u %u" % committer
 
     if from_mark:
-        p1 = repo.changelog.node(mark_to_rev(from_mark))
+        p1 = mark_to_rev(from_mark)
     else:
-        p1 = '\0' * 20
+        p1 = '0' * 40
 
     if merge_mark:
-        p2 = repo.changelog.node(mark_to_rev(merge_mark))
+        p2 = mark_to_rev(merge_mark)
     else:
-        p2 = '\0' * 20
+        p2 = '0' * 40
 
     #
     # If files changed from any of the parents, hg wants to know, but in git if
@@ -730,14 +791,12 @@
     tmp = encoding.encoding
     encoding.encoding = 'utf-8'
 
-    node = repo.commitctx(ctx)
+    node = hghex(repo.commitctx(ctx))
 
     encoding.encoding = tmp
 
-    rev = repo[node].rev()
-
     parsed_refs[ref] = node
-    marks.new_mark(rev, commit_mark)
+    marks.new_mark(node, commit_mark)
 
 def parse_reset(parser):
     global parsed_refs
@@ -753,8 +812,11 @@
     from_mark = parser.get_mark()
     parser.next()
 
-    node = parser.repo.changelog.node(mark_to_rev(from_mark))
-    parsed_refs[ref] = node
+    try:
+        rev = mark_to_rev(from_mark)
+    except KeyError:
+        rev = None
+    parsed_refs[ref] = rev
 
 def parse_tag(parser):
     name = parser[1]
@@ -770,7 +832,7 @@
 
 def write_tag(repo, tag, node, msg, author):
     branch = repo[node].branch()
-    tip = branch_tip(repo, branch)
+    tip = branch_tip(branch)
     tip = repo[tip]
 
     def getfilectx(repo, memctx, f):
@@ -779,18 +841,28 @@
             data = fctx.data()
         except error.ManifestLookupError:
             data = ""
-        content = data + "%s %s\n" % (hghex(node), tag)
+        content = data + "%s %s\n" % (node, tag)
         return context.memfilectx(f, content, False, False, None)
 
     p1 = tip.hex()
-    p2 = '\0' * 20
-    if not author:
-        author = (None, 0, 0)
-    user, date, tz = author
+    p2 = '0' * 40
+    if author:
+        user, date, tz = author
+        date_tz = (date, tz)
+    else:
+        cmd = ['git', 'var', 'GIT_COMMITTER_IDENT']
+        process = subprocess.Popen(cmd, stdout=subprocess.PIPE)
+        output, _ = process.communicate()
+        m = re.match('^.* <.*>', output)
+        if m:
+            user = m.group(0)
+        else:
+            user = repo.ui.username()
+        date_tz = None
 
     ctx = context.memctx(repo, (p1, p2), msg,
             ['.hgtags'], getfilectx,
-            user, (date, tz), {'branch' : branch})
+            user, date_tz, {'branch' : branch})
 
     tmp = encoding.encoding
     encoding.encoding = 'utf-8'
@@ -799,12 +871,132 @@
 
     encoding.encoding = tmp
 
-    return tagnode
+    return (tagnode, branch)
+
+def checkheads_bmark(repo, ref, ctx):
+    bmark = ref[len('refs/heads/'):]
+    if not bmark in bmarks:
+        # new bmark
+        return True
+
+    ctx_old = bmarks[bmark]
+    ctx_new = ctx
+    if not repo.changelog.descendant(ctx_old.rev(), ctx_new.rev()):
+        if force_push:
+            print "ok %s forced update" % ref
+        else:
+            print "error %s non-fast forward" % ref
+            return False
+
+    return True
+
+def checkheads(repo, remote, p_revs):
+
+    remotemap = remote.branchmap()
+    if not remotemap:
+        # empty repo
+        return True
+
+    new = {}
+    ret = True
+
+    for node, ref in p_revs.iteritems():
+        ctx = repo[node]
+        branch = ctx.branch()
+        if not branch in remotemap:
+            # new branch
+            continue
+        if not ref.startswith('refs/heads/branches'):
+            if ref.startswith('refs/heads/'):
+                if not checkheads_bmark(repo, ref, ctx):
+                    ret = False
+
+            # only check branches
+            continue
+        new.setdefault(branch, []).append(ctx.rev())
+
+    for branch, heads in new.iteritems():
+        old = [repo.changelog.rev(x) for x in remotemap[branch]]
+        for rev in heads:
+            if check_version(2, 3):
+                ancestors = repo.changelog.ancestors([rev], stoprev=min(old))
+            else:
+                ancestors = repo.changelog.ancestors(rev)
+            found = False
+
+            for x in old:
+                if x in ancestors:
+                    found = True
+                    break
+
+            if found:
+                continue
+
+            node = repo.changelog.node(rev)
+            ref = p_revs[node]
+            if force_push:
+                print "ok %s forced update" % ref
+            else:
+                print "error %s non-fast forward" % ref
+                ret = False
+
+    return ret
+
+def push_unsafe(repo, remote, parsed_refs, p_revs):
+
+    force = force_push
+
+    fci = discovery.findcommonincoming
+    commoninc = fci(repo, remote, force=force)
+    common, _, remoteheads = commoninc
+
+    if not checkheads(repo, remote, p_revs):
+        return None
+
+    cg = repo.getbundle('push', heads=list(p_revs), common=common)
+
+    unbundle = remote.capable('unbundle')
+    if unbundle:
+        if force:
+            remoteheads = ['force']
+        return remote.unbundle(cg, remoteheads, 'push')
+    else:
+        return remote.addchangegroup(cg, 'push', repo.url())
+
+def push(repo, remote, parsed_refs, p_revs):
+    if hasattr(remote, 'canpush') and not remote.canpush():
+        print "error cannot push"
+
+    if not p_revs:
+        # nothing to push
+        return
+
+    lock = None
+    unbundle = remote.capable('unbundle')
+    if not unbundle:
+        lock = remote.lock()
+    try:
+        ret = push_unsafe(repo, remote, parsed_refs, p_revs)
+    finally:
+        if lock is not None:
+            lock.release()
+
+    return ret
+
+def check_tip(ref, kind, name, heads):
+    try:
+        ename = '%s/%s' % (kind, name)
+        tip = marks.get_tip(ename)
+    except KeyError:
+        return True
+    else:
+        return tip in heads
 
 def do_export(parser):
     global parsed_refs, bmarks, peer
 
     p_bmarks = []
+    p_revs = {}
 
     parser.next()
 
@@ -822,71 +1014,114 @@
         else:
             die('unhandled export command: %s' % line)
 
+    need_fetch = False
+
     for ref, node in parsed_refs.iteritems():
+        bnode = hgbin(node) if node else None
         if ref.startswith('refs/heads/branches'):
             branch = ref[len('refs/heads/branches/'):]
-            if branch in branches and node in branches[branch]:
+            if branch in branches and bnode in branches[branch]:
                 # up to date
                 continue
+
+            if peer:
+                remotemap = peer.branchmap()
+                if remotemap and branch in remotemap:
+                    heads = [hghex(e) for e in remotemap[branch]]
+                    if not check_tip(ref, 'branches', branch, heads):
+                        print "error %s fetch first" % ref
+                        need_fetch = True
+                        continue
+
+            p_revs[bnode] = ref
             print "ok %s" % ref
         elif ref.startswith('refs/heads/'):
             bmark = ref[len('refs/heads/'):]
-            p_bmarks.append((bmark, node))
-            continue
+            new = node
+            old = bmarks[bmark].hex() if bmark in bmarks else ''
+
+            if old == new:
+                continue
+
+            print "ok %s" % ref
+            if bmark != fake_bmark and \
+                    not (bmark == 'master' and bmark not in parser.repo._bookmarks):
+                p_bmarks.append((ref, bmark, old, new))
+
+            if peer:
+                remote_old = peer.listkeys('bookmarks').get(bmark)
+                if remote_old:
+                    if not check_tip(ref, 'bookmarks', bmark, remote_old):
+                        print "error %s fetch first" % ref
+                        need_fetch = True
+                        continue
+
+            p_revs[bnode] = ref
         elif ref.startswith('refs/tags/'):
+            if dry_run:
+                print "ok %s" % ref
+                continue
             tag = ref[len('refs/tags/'):]
             tag = hgref(tag)
             author, msg = parsed_tags.get(tag, (None, None))
             if mode == 'git':
                 if not msg:
-                    msg = 'Added tag %s for changeset %s' % (tag, hghex(node[:6]));
-                write_tag(parser.repo, tag, node, msg, author)
+                    msg = 'Added tag %s for changeset %s' % (tag, node[:12]);
+                tagnode, branch = write_tag(parser.repo, tag, node, msg, author)
+                p_revs[tagnode] = 'refs/heads/branches/' + gitref(branch)
             else:
                 fp = parser.repo.opener('localtags', 'a')
-                fp.write('%s %s\n' % (hghex(node), tag))
+                fp.write('%s %s\n' % (node, tag))
                 fp.close()
+            p_revs[bnode] = ref
             print "ok %s" % ref
         else:
             # transport-helper/fast-export bugs
             continue
 
+    if need_fetch:
+        print
+        return
+
+    if dry_run:
+        if peer and not force_push:
+            checkheads(parser.repo, peer, p_revs)
+        print
+        return
+
     if peer:
-        parser.repo.push(peer, force=force_push)
+        if not push(parser.repo, peer, parsed_refs, p_revs):
+            # do not update bookmarks
+            print
+            return
 
-    # handle bookmarks
-    for bmark, node in p_bmarks:
-        ref = 'refs/heads/' + bmark
-        new = hghex(node)
-
-        if bmark in bmarks:
-            old = bmarks[bmark].hex()
-        else:
-            old = ''
-
-        if old == new:
-            continue
-
-        if bmark == 'master' and 'master' not in parser.repo._bookmarks:
-            # fake bookmark
-            pass
-        elif bookmarks.pushbookmark(parser.repo, bmark, old, new):
-            # updated locally
-            pass
-        else:
-            print "error %s" % ref
-            continue
-
-        if peer:
-            rb = peer.listkeys('bookmarks')
-            old = rb.get(bmark, '')
+        # update remote bookmarks
+        remote_bmarks = peer.listkeys('bookmarks')
+        for ref, bmark, old, new in p_bmarks:
+            if force_push:
+                old = remote_bmarks.get(bmark, '')
             if not peer.pushkey('bookmarks', bmark, old, new):
                 print "error %s" % ref
-                continue
-
-        print "ok %s" % ref
+    else:
+        # update local bookmarks
+        for ref, bmark, old, new in p_bmarks:
+            if not bookmarks.pushbookmark(parser.repo, bmark, old, new):
+                print "error %s" % ref
 
     print
 
+def do_option(parser):
+    global dry_run, force_push
+    _, key, value = parser.line.split(' ')
+    if key == 'dry-run':
+        dry_run = (value == 'true')
+        print 'ok'
+    elif key == 'force':
+        force_push = (value == 'true')
+        print 'ok'
+    else:
+        print 'unsupported'
+
 def fix_path(alias, repo, orig_url):
     url = urlparse.urlparse(orig_url, 'file')
     if url.scheme != 'file' or os.path.isabs(url.path):
@@ -896,31 +1131,22 @@
     subprocess.call(cmd)
 
 def main(args):
-    global prefix, dirname, branches, bmarks
+    global prefix, gitdir, dirname, branches, bmarks
     global marks, blob_marks, parsed_refs
     global peer, mode, bad_mail, bad_name
     global track_branches, force_push, is_tmp
     global parsed_tags
     global filenodes
+    global fake_bmark, hg_version
+    global dry_run
 
     alias = args[1]
     url = args[2]
     peer = None
 
-    hg_git_compat = False
-    track_branches = True
-    force_push = True
-
-    try:
-        if get_config('remote-hg.hg-git-compat') == 'true\n':
-            hg_git_compat = True
-            track_branches = False
-        if get_config('remote-hg.track-branches') == 'false\n':
-            track_branches = False
-        if get_config('remote-hg.force-push') == 'false\n':
-            force_push = False
-    except subprocess.CalledProcessError:
-        pass
+    hg_git_compat = get_config_bool('remote-hg.hg-git-compat')
+    track_branches = get_config_bool('remote-hg.track-branches', True)
+    force_push = False
 
     if hg_git_compat:
         mode = 'hg'
@@ -946,6 +1172,12 @@
     marks = None
     parsed_tags = {}
     filenodes = {}
+    fake_bmark = None
+    try:
+        hg_version = tuple(int(e) for e in util.version().split('.'))
+    except:
+        hg_version = None
+    dry_run = False
 
     repo = get_repo(url, alias)
     prefix = 'refs/hg/%s' % alias
@@ -953,11 +1185,12 @@
     if not is_tmp:
         fix_path(alias, peer or repo, url)
 
-    if not os.path.exists(dirname):
-        os.makedirs(dirname)
-
     marks_path = os.path.join(dirname, 'marks-hg')
-    marks = Marks(marks_path)
+    marks = Marks(marks_path, repo)
+
+    if sys.platform == 'win32':
+        import msvcrt
+        msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
 
     parser = Parser(repo)
     for line in parser:
@@ -969,6 +1202,8 @@
             do_import(parser)
         elif parser.check('export'):
             do_export(parser)
+        elif parser.check('option'):
+            do_option(parser)
         else:
             die('unhandled command: %s' % line)
         sys.stdout.flush()
diff --git a/contrib/remote-helpers/test-bzr.sh b/contrib/remote-helpers/test-bzr.sh
index 34666e1..dce281f 100755
--- a/contrib/remote-helpers/test-bzr.sh
+++ b/contrib/remote-helpers/test-bzr.sh
@@ -12,86 +12,90 @@
 	test_done
 fi
 
-if ! "$PYTHON_PATH" -c 'import bzrlib'; then
+if ! python -c 'import bzrlib'; then
 	skip_all='skipping remote-bzr tests; bzr not available'
 	test_done
 fi
 
 check () {
-	(cd $1 &&
-	git log --format='%s' -1 &&
-	git symbolic-ref HEAD) > actual &&
-	(echo $2 &&
-	echo "refs/heads/$3") > expected &&
+	echo $3 > expected &&
+	git --git-dir=$1/.git log --format='%s' -1 $2 > actual
 	test_cmp expected actual
 }
 
 bzr whoami "A U Thor <author@example.com>"
 
 test_expect_success 'cloning' '
-  (bzr init bzrrepo &&
-  cd bzrrepo &&
-  echo one > content &&
-  bzr add content &&
-  bzr commit -m one
-  ) &&
+	(
+	bzr init bzrrepo &&
+	cd bzrrepo &&
+	echo one > content &&
+	bzr add content &&
+	bzr commit -m one
+	) &&
 
-  git clone "bzr::$PWD/bzrrepo" gitrepo &&
-  check gitrepo one master
+	git clone "bzr::bzrrepo" gitrepo &&
+	check gitrepo HEAD one
 '
 
 test_expect_success 'pulling' '
-  (cd bzrrepo &&
-  echo two > content &&
-  bzr commit -m two
-  ) &&
+	(
+	cd bzrrepo &&
+	echo two > content &&
+	bzr commit -m two
+	) &&
 
-  (cd gitrepo && git pull) &&
+	(cd gitrepo && git pull) &&
 
-  check gitrepo two master
+	check gitrepo HEAD two
 '
 
 test_expect_success 'pushing' '
-  (cd gitrepo &&
-  echo three > content &&
-  git commit -a -m three &&
-  git push
-  ) &&
+	(
+	cd gitrepo &&
+	echo three > content &&
+	git commit -a -m three &&
+	git push
+	) &&
 
-  echo three > expected &&
-  cat bzrrepo/content > actual &&
-  test_cmp expected actual
+	echo three > expected &&
+	cat bzrrepo/content > actual &&
+	test_cmp expected actual
 '
 
 test_expect_success 'roundtrip' '
-  (cd gitrepo &&
-  git pull &&
-  git log --format="%s" -1 origin/master > actual) &&
-  echo three > expected &&
-  test_cmp expected actual &&
+	(
+	cd gitrepo &&
+	git pull &&
+	git log --format="%s" -1 origin/master > actual
+	) &&
+	echo three > expected &&
+	test_cmp expected actual &&
 
-  (cd gitrepo && git push && git pull) &&
+	(cd gitrepo && git push && git pull) &&
 
-  (cd bzrrepo &&
-  echo four > content &&
-  bzr commit -m four
-  ) &&
+	(
+	cd bzrrepo &&
+	echo four > content &&
+	bzr commit -m four
+	) &&
 
-  (cd gitrepo && git pull && git push) &&
+	(cd gitrepo && git pull && git push) &&
 
-  check gitrepo four master &&
+	check gitrepo HEAD four &&
 
-  (cd gitrepo &&
-  echo five > content &&
-  git commit -a -m five &&
-  git push && git pull
-  ) &&
+	(
+	cd gitrepo &&
+	echo five > content &&
+	git commit -a -m five &&
+	git push && git pull
+	) &&
 
-  (cd bzrrepo && bzr revert) &&
+	(cd bzrrepo && bzr revert) &&
 
-  echo five > expected &&
-  cat bzrrepo/content > actual &&
-  test_cmp expected actual
+	echo five > expected &&
+	cat bzrrepo/content > actual &&
+	test_cmp expected actual
 '
 
 cat > expected <<EOF
@@ -101,29 +105,35 @@
 EOF
 
 test_expect_success 'special modes' '
-  (cd bzrrepo &&
-  echo exec > executable
-  chmod +x executable &&
-  bzr add executable
-  bzr commit -m exec &&
-  ln -s content link
-  bzr add link
-  bzr commit -m link &&
-  mkdir dir &&
-  bzr add dir &&
-  bzr commit -m dir) &&
+	(
+	cd bzrrepo &&
+	echo exec > executable
+	chmod +x executable &&
+	bzr add executable
+	bzr commit -m exec &&
+	ln -s content link
+	bzr add link
+	bzr commit -m link &&
+	mkdir dir &&
+	bzr add dir &&
+	bzr commit -m dir
+	) &&
 
-  (cd gitrepo &&
-  git pull
-  git ls-tree HEAD > ../actual) &&
+	(
+	cd gitrepo &&
+	git pull
+	git ls-tree HEAD > ../actual
+	) &&
 
-  test_cmp expected actual &&
+	test_cmp expected actual &&
 
-  (cd gitrepo &&
-  git cat-file -p HEAD:link > ../actual) &&
+	(
+	cd gitrepo &&
+	git cat-file -p HEAD:link > ../actual
+	) &&
 
-  printf content > expected &&
-  test_cmp expected actual
+	printf content > expected &&
+	test_cmp expected actual
 '
 
 cat > expected <<EOF
@@ -134,98 +144,218 @@
 EOF
 
 test_expect_success 'moving directory' '
-  (cd bzrrepo &&
-  mkdir movedir &&
-  echo one > movedir/one &&
-  echo two > movedir/two &&
-  bzr add movedir &&
-  bzr commit -m movedir &&
-  bzr mv movedir movedir-new &&
-  bzr commit -m movedir-new) &&
+	(
+	cd bzrrepo &&
+	mkdir movedir &&
+	echo one > movedir/one &&
+	echo two > movedir/two &&
+	bzr add movedir &&
+	bzr commit -m movedir &&
+	bzr mv movedir movedir-new &&
+	bzr commit -m movedir-new
+	) &&
 
-  (cd gitrepo &&
-  git pull &&
-  git ls-tree HEAD > ../actual) &&
+	(
+	cd gitrepo &&
+	git pull &&
+	git ls-tree HEAD > ../actual
+	) &&
 
-  test_cmp expected actual
+	test_cmp expected actual
 '
 
 test_expect_success 'different authors' '
-  (cd bzrrepo &&
-  echo john >> content &&
-  bzr commit -m john \
-    --author "Jane Rey <jrey@example.com>" \
-    --author "John Doe <jdoe@example.com>") &&
+	(
+	cd bzrrepo &&
+	echo john >> content &&
+	bzr commit -m john \
+	  --author "Jane Rey <jrey@example.com>" \
+	  --author "John Doe <jdoe@example.com>"
+	) &&
 
-  (cd gitrepo &&
-  git pull &&
-  git show --format="%an <%ae>, %cn <%ce>" --quiet > ../actual) &&
+	(
+	cd gitrepo &&
+	git pull &&
+	git show --format="%an <%ae>, %cn <%ce>" --quiet > ../actual
+	) &&
 
-  echo "Jane Rey <jrey@example.com>, A U Thor <author@example.com>" > expected &&
-  test_cmp expected actual
+	echo "Jane Rey <jrey@example.com>, A U Thor <author@example.com>" > expected &&
+	test_cmp expected actual
 '
 
+# cleanup previous stuff
+rm -rf bzrrepo gitrepo
+
 test_expect_success 'fetch utf-8 filenames' '
-  mkdir -p tmp && cd tmp &&
-  test_when_finished "cd .. && rm -rf tmp && LC_ALL=C" &&
+	test_when_finished "rm -rf bzrrepo gitrepo && LC_ALL=C" &&
 
-  LC_ALL=en_US.UTF-8
-  export LC_ALL
-  (
-  bzr init bzrrepo &&
-  cd bzrrepo &&
+	LC_ALL=en_US.UTF-8
+	export LC_ALL
 
-  echo test >> "ærø" &&
-  bzr add "ærø" &&
-  echo test >> "ø~?" &&
-  bzr add "ø~?" &&
-  bzr commit -m add-utf-8 &&
-  echo test >> "ærø" &&
-  bzr commit -m test-utf-8 &&
-  bzr rm "ø~?" &&
-  bzr mv "ærø" "ø~?" &&
-  bzr commit -m bzr-mv-utf-8
-  ) &&
+	(
+	bzr init bzrrepo &&
+	cd bzrrepo &&
 
-  (
-  git clone "bzr::$PWD/bzrrepo" gitrepo &&
-  cd gitrepo &&
-  git -c core.quotepath=false ls-files > ../actual
-  ) &&
-  echo "ø~?" > expected &&
-  test_cmp expected actual
+	echo test >> "ærø" &&
+	bzr add "ærø" &&
+	echo test >> "ø~?" &&
+	bzr add "ø~?" &&
+	bzr commit -m add-utf-8 &&
+	echo test >> "ærø" &&
+	bzr commit -m test-utf-8 &&
+	bzr rm "ø~?" &&
+	bzr mv "ærø" "ø~?" &&
+	bzr commit -m bzr-mv-utf-8
+	) &&
+
+	(
+	git clone "bzr::bzrrepo" gitrepo &&
+	cd gitrepo &&
+	git -c core.quotepath=false ls-files > ../actual
+	) &&
+	echo "ø~?" > expected &&
+	test_cmp expected actual
 '
 
 test_expect_success 'push utf-8 filenames' '
-  mkdir -p tmp && cd tmp &&
-  test_when_finished "cd .. && rm -rf tmp && LC_ALL=C" &&
+	test_when_finished "rm -rf bzrrepo gitrepo && LC_ALL=C" &&
 
-  LC_ALL=en_US.UTF-8
-  export LC_ALL
+	mkdir -p tmp && cd tmp &&
 
-  (
-  bzr init bzrrepo &&
-  cd bzrrepo &&
+	LC_ALL=en_US.UTF-8
+	export LC_ALL
 
-  echo one >> content &&
-  bzr add content &&
-  bzr commit -m one
-  ) &&
+	(
+	bzr init bzrrepo &&
+	cd bzrrepo &&
 
-  (
-  git clone "bzr::$PWD/bzrrepo" gitrepo &&
-  cd gitrepo &&
+	echo one >> content &&
+	bzr add content &&
+	bzr commit -m one
+	) &&
 
-  echo test >> "ærø" &&
-  git add "ærø" &&
-  git commit -m utf-8 &&
+	(
+	git clone "bzr::bzrrepo" gitrepo &&
+	cd gitrepo &&
 
-  git push
-  ) &&
+	echo test >> "ærø" &&
+	git add "ærø" &&
+	git commit -m utf-8 &&
 
-  (cd bzrrepo && bzr ls > ../actual) &&
-  printf "content\nærø\n" > expected &&
-  test_cmp expected actual
+	git push
+	) &&
+
+	(cd bzrrepo && bzr ls > ../actual) &&
+	printf "content\nærø\n" > expected &&
+	test_cmp expected actual
+'
+
+test_expect_success 'pushing a merge' '
+	test_when_finished "rm -rf bzrrepo gitrepo" &&
+
+	(
+	bzr init bzrrepo &&
+	cd bzrrepo &&
+	echo one > content &&
+	bzr add content &&
+	bzr commit -m one
+	) &&
+
+	git clone "bzr::bzrrepo" gitrepo &&
+
+	(
+	cd bzrrepo &&
+	echo two > content &&
+	bzr commit -m two
+	) &&
+
+	(
+	cd gitrepo &&
+	echo three > content &&
+	git commit -a -m three &&
+	git fetch &&
+	git merge origin/master || true &&
+	echo three > content &&
+	git commit -a --no-edit &&
+	git push
+	) &&
+
+	echo three > expected &&
+	cat bzrrepo/content > actual &&
+	test_cmp expected actual
+'
+
+cat > expected <<EOF
+origin/HEAD
+origin/branch
+origin/trunk
+EOF
+
+test_expect_success 'proper bzr repo' '
+	test_when_finished "rm -rf bzrrepo gitrepo" &&
+
+	bzr init-repo bzrrepo &&
+
+	(
+	bzr init bzrrepo/trunk &&
+	cd bzrrepo/trunk &&
+	echo one >> content &&
+	bzr add content &&
+	bzr commit -m one
+	) &&
+
+	(
+	bzr branch bzrrepo/trunk bzrrepo/branch &&
+	cd bzrrepo/branch &&
+	echo two >> content &&
+	bzr commit -m one
+	) &&
+
+	(
+	git clone "bzr::bzrrepo" gitrepo &&
+	cd gitrepo &&
+	git for-each-ref --format "%(refname:short)" refs/remotes/origin > ../actual
+	) &&
+
+	test_cmp expected actual
+'
+
+test_expect_success 'strip' '
+	test_when_finished "rm -rf bzrrepo gitrepo" &&
+
+	(
+	bzr init bzrrepo &&
+	cd bzrrepo &&
+
+	echo one >> content &&
+	bzr add content &&
+	bzr commit -m one &&
+
+	echo two >> content &&
+	bzr commit -m two
+	) &&
+
+	git clone "bzr::bzrrepo" gitrepo &&
+
+	(
+	cd bzrrepo &&
+	bzr uncommit --force &&
+
+	echo three >> content &&
+	bzr commit -m three &&
+
+	echo four >> content &&
+	bzr commit -m four &&
+	bzr log --line | sed -e "s/^[0-9][0-9]*: //" > ../expected
+	) &&
+
+	(
+	cd gitrepo &&
+	git fetch &&
+	git log --format="%an %ad %s" --date=short origin/master > ../actual
+	) &&
+
+	test_cmp expected actual
 '
 
 test_done
diff --git a/contrib/remote-helpers/test-hg-bidi.sh b/contrib/remote-helpers/test-hg-bidi.sh
index f569697..f83d67d 100755
--- a/contrib/remote-helpers/test-hg-bidi.sh
+++ b/contrib/remote-helpers/test-hg-bidi.sh
@@ -15,23 +15,22 @@
 	test_done
 fi
 
-if ! "$PYTHON_PATH" -c 'import mercurial'; then
+if ! python -c 'import mercurial'; then
 	skip_all='skipping remote-hg tests; mercurial not available'
 	test_done
 fi
 
 # clone to a git repo
 git_clone () {
-	git clone -q "hg::$PWD/$1" $2
+	git clone -q "hg::$1" $2
 }
 
 # clone to an hg repo
 hg_clone () {
 	(
 	hg init $2 &&
-	hg -R $2 bookmark -i master &&
 	cd $1 &&
-	git push -q "hg::$PWD/../$2" 'refs/tags/*:refs/tags/*' 'refs/heads/*:refs/heads/*'
+	git push -q "hg::../$2" 'refs/tags/*:refs/tags/*' 'refs/heads/*:refs/heads/*'
 	) &&
 
 	(cd $2 && hg -q update)
@@ -41,17 +40,15 @@
 hg_push () {
 	(
 	cd $2
-	old=$(git symbolic-ref --short HEAD)
 	git checkout -q -b tmp &&
-	git fetch -q "hg::$PWD/../$1" 'refs/tags/*:refs/tags/*' 'refs/heads/*:refs/heads/*' &&
-	git checkout -q $old &&
+	git fetch -q "hg::../$1" 'refs/tags/*:refs/tags/*' 'refs/heads/*:refs/heads/*' &&
+	git checkout -q @{-1} &&
 	git branch -q -D tmp 2> /dev/null || true
 	)
 }
 
 hg_log () {
-	hg -R $1 log --graph --debug >log &&
-	grep -v 'tag: *default/' log
+	hg -R $1 log --graph --debug
 }
 
 setup () {
@@ -67,6 +64,7 @@
 	echo "graphlog ="
 	) >> "$HOME"/.hgrc &&
 	git config --global remote-hg.hg-git-compat true
+	git config --global remote-hg.track-branches true
 
 	HGEDITOR=/usr/bin/true
 	GIT_AUTHOR_DATE="2007-01-01 00:00:00 +0230"
@@ -77,8 +75,7 @@
 setup
 
 test_expect_success 'encoding' '
-	mkdir -p tmp && cd tmp &&
-	test_when_finished "cd .. && rm -rf tmp" &&
+	test_when_finished "rm -rf gitrepo* hgrepo*" &&
 
 	(
 	git init -q gitrepo &&
@@ -115,8 +112,7 @@
 '
 
 test_expect_success 'file removal' '
-	mkdir -p tmp && cd tmp &&
-	test_when_finished "cd .. && rm -rf tmp" &&
+	test_when_finished "rm -rf gitrepo* hgrepo*" &&
 
 	(
 	git init -q gitrepo &&
@@ -148,8 +144,7 @@
 '
 
 test_expect_success 'git tags' '
-	mkdir -p tmp && cd tmp &&
-	test_when_finished "cd .. && rm -rf tmp" &&
+	test_when_finished "rm -rf gitrepo* hgrepo*" &&
 
 	(
 	git init -q gitrepo &&
@@ -177,8 +172,7 @@
 '
 
 test_expect_success 'hg branch' '
-	mkdir -p tmp && cd tmp &&
-	test_when_finished "cd .. && rm -rf tmp" &&
+	test_when_finished "rm -rf gitrepo* hgrepo*" &&
 
 	(
 	git init -q gitrepo &&
@@ -194,7 +188,7 @@
 	hg_clone gitrepo hgrepo &&
 
 	cd hgrepo &&
-	hg -q co master &&
+	hg -q co default &&
 	hg mv alpha beta &&
 	hg -q commit -m "rename alpha to beta" &&
 	hg branch gamma | grep -v "permanent and global" &&
@@ -214,8 +208,7 @@
 '
 
 test_expect_success 'hg tags' '
-	mkdir -p tmp && cd tmp &&
-	test_when_finished "cd .. && rm -rf tmp" &&
+	test_when_finished "rm -rf gitrepo* hgrepo*" &&
 
 	(
 	git init -q gitrepo &&
@@ -231,7 +224,7 @@
 	hg_clone gitrepo hgrepo &&
 
 	cd hgrepo &&
-	hg co master &&
+	hg co default &&
 	hg tag alpha
 	) &&
 
diff --git a/contrib/remote-helpers/test-hg-hg-git.sh b/contrib/remote-helpers/test-hg-hg-git.sh
index 8440341..2219284 100755
--- a/contrib/remote-helpers/test-hg-hg-git.sh
+++ b/contrib/remote-helpers/test-hg-hg-git.sh
@@ -15,19 +15,20 @@
 	test_done
 fi
 
-if ! "$PYTHON_PATH" -c 'import mercurial'; then
+if ! python -c 'import mercurial'; then
 	skip_all='skipping remote-hg tests; mercurial not available'
 	test_done
 fi
 
-if ! "$PYTHON_PATH" -c 'import hggit'; then
+if ! python -c 'import hggit'; then
 	skip_all='skipping remote-hg tests; hg-git not available'
 	test_done
 fi
 
 # clone to a git repo with git
 git_clone_git () {
-	git clone -q "hg::$PWD/$1" $2
+	git clone -q "hg::$1" $2 &&
+	(cd $2 && git checkout master && git branch -D default)
 }
 
 # clone to an hg repo with git
@@ -36,7 +37,7 @@
 	hg init $2 &&
 	hg -R $2 bookmark -i master &&
 	cd $1 &&
-	git push -q "hg::$PWD/../$2" 'refs/tags/*:refs/tags/*' 'refs/heads/*:refs/heads/*'
+	git push -q "hg::../$2" 'refs/tags/*:refs/tags/*' 'refs/heads/*:refs/heads/*'
 	) &&
 
 	(cd $2 && hg -q update)
@@ -61,10 +62,10 @@
 hg_push_git () {
 	(
 	cd $2
-	old=$(git symbolic-ref --short HEAD)
 	git checkout -q -b tmp &&
-	git fetch -q "hg::$PWD/../$1" 'refs/tags/*:refs/tags/*' 'refs/heads/*:refs/heads/*' &&
-	git checkout -q $old &&
+	git fetch -q "hg::../$1" 'refs/tags/*:refs/tags/*' 'refs/heads/*:refs/heads/*' &&
+	git branch -D default &&
+	git checkout -q @{-1} &&
 	git branch -q -D tmp 2> /dev/null || true
 	)
 }
@@ -102,19 +103,20 @@
 	) >> "$HOME"/.hgrc &&
 	git config --global receive.denycurrentbranch warn
 	git config --global remote-hg.hg-git-compat true
+	git config --global remote-hg.track-branches false
 
-	HGEDITOR=/usr/bin/true
+	HGEDITOR=true
+	HGMERGE=true
 
 	GIT_AUTHOR_DATE="2007-01-01 00:00:00 +0230"
 	GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE"
-	export HGEDITOR GIT_AUTHOR_DATE GIT_COMMITTER_DATE
+	export HGEDITOR HGMERGE GIT_AUTHOR_DATE GIT_COMMITTER_DATE
 }
 
 setup
 
 test_expect_success 'executable bit' '
-	mkdir -p tmp && cd tmp &&
-	test_when_finished "cd .. && rm -rf tmp" &&
+	test_when_finished "rm -rf gitrepo* hgrepo*" &&
 
 	(
 	git init -q gitrepo &&
@@ -149,8 +151,7 @@
 '
 
 test_expect_success 'symlink' '
-	mkdir -p tmp && cd tmp &&
-	test_when_finished "cd .. && rm -rf tmp" &&
+	test_when_finished "rm -rf gitrepo* hgrepo*" &&
 
 	(
 	git init -q gitrepo &&
@@ -180,8 +181,7 @@
 '
 
 test_expect_success 'merge conflict 1' '
-	mkdir -p tmp && cd tmp &&
-	test_when_finished "cd .. && rm -rf tmp" &&
+	test_when_finished "rm -rf gitrepo* hgrepo*" &&
 
 	(
 	hg init hgrepo1 &&
@@ -197,7 +197,7 @@
 	echo C > afile &&
 	hg ci -m "A->C" &&
 
-	hg merge -r1 || true &&
+	hg merge -r1 &&
 	echo C > afile &&
 	hg resolve -m afile &&
 	hg ci -m "merge to C"
@@ -215,8 +215,7 @@
 '
 
 test_expect_success 'merge conflict 2' '
-	mkdir -p tmp && cd tmp &&
-	test_when_finished "cd .. && rm -rf tmp" &&
+	test_when_finished "rm -rf gitrepo* hgrepo*" &&
 
 	(
 	hg init hgrepo1 &&
@@ -250,8 +249,7 @@
 '
 
 test_expect_success 'converged merge' '
-	mkdir -p tmp && cd tmp &&
-	test_when_finished "cd .. && rm -rf tmp" &&
+	test_when_finished "rm -rf gitrepo* hgrepo*" &&
 
 	(
 	hg init hgrepo1 &&
@@ -286,8 +284,7 @@
 '
 
 test_expect_success 'encoding' '
-	mkdir -p tmp && cd tmp &&
-	test_when_finished "cd .. && rm -rf tmp" &&
+	test_when_finished "rm -rf gitrepo* hgrepo*" &&
 
 	(
 	git init -q gitrepo &&
@@ -326,8 +323,7 @@
 '
 
 test_expect_success 'file removal' '
-	mkdir -p tmp && cd tmp &&
-	test_when_finished "cd .. && rm -rf tmp" &&
+	test_when_finished "rm -rf gitrepo* hgrepo*" &&
 
 	(
 	git init -q gitrepo &&
@@ -366,8 +362,7 @@
 '
 
 test_expect_success 'git tags' '
-	mkdir -p tmp && cd tmp &&
-	test_when_finished "cd .. && rm -rf tmp" &&
+	test_when_finished "rm -rf gitrepo* hgrepo*" &&
 
 	(
 	git init -q gitrepo &&
@@ -393,8 +388,7 @@
 '
 
 test_expect_success 'hg author' '
-	mkdir -p tmp && cd tmp &&
-	test_when_finished "cd .. && rm -rf tmp" &&
+	test_when_finished "rm -rf gitrepo* hgrepo*" &&
 
 	for x in hg git; do
 		(
@@ -455,15 +449,12 @@
 		git_log gitrepo-$x > git-log-$x
 	done &&
 
-	test_cmp git-log-hg git-log-git &&
-
 	test_cmp hg-log-hg hg-log-git &&
 	test_cmp git-log-hg git-log-git
 '
 
 test_expect_success 'hg branch' '
-	mkdir -p tmp && cd tmp &&
-	test_when_finished "cd .. && rm -rf tmp" &&
+	test_when_finished "rm -rf gitrepo* hgrepo*" &&
 
 	for x in hg git; do
 		(
@@ -499,8 +490,7 @@
 '
 
 test_expect_success 'hg tags' '
-	mkdir -p tmp && cd tmp &&
-	test_when_finished "cd .. && rm -rf tmp" &&
+	test_when_finished "rm -rf gitrepo* hgrepo*" &&
 
 	for x in hg git; do
 		(
diff --git a/contrib/remote-helpers/test-hg.sh b/contrib/remote-helpers/test-hg.sh
index 8de2aa7..f7ce8aa 100755
--- a/contrib/remote-helpers/test-hg.sh
+++ b/contrib/remote-helpers/test-hg.sh
@@ -15,143 +15,678 @@
 	test_done
 fi
 
-if ! "$PYTHON_PATH" -c 'import mercurial'; then
+if ! python -c 'import mercurial'; then
 	skip_all='skipping remote-hg tests; mercurial not available'
 	test_done
 fi
 
 check () {
-	(cd $1 &&
-	git log --format='%s' -1 &&
-	git symbolic-ref HEAD) > actual &&
-	(echo $2 &&
-	echo "refs/heads/$3") > expected &&
+	echo $3 > expected &&
+	git --git-dir=$1/.git log --format='%s' -1 $2 > actual
 	test_cmp expected actual
 }
 
+check_branch () {
+	if [ -n "$3" ]; then
+		echo $3 > expected &&
+		hg -R $1 log -r $2 --template '{desc}\n' > actual &&
+		test_cmp expected actual
+	else
+		hg -R $1 branches > out &&
+		! grep $2 out
+	fi
+}
+
+check_bookmark () {
+	if [ -n "$3" ]; then
+		echo $3 > expected &&
+		hg -R $1 log -r "bookmark('$2')" --template '{desc}\n' > actual &&
+		test_cmp expected actual
+	else
+		hg -R $1 bookmarks > out &&
+		! grep $2 out
+	fi
+}
+
+check_push () {
+	local expected_ret=$1 ret=0 ref_ret=0 IFS=':'
+
+	shift
+	git push origin "$@" 2> error
+	ret=$?
+	cat error
+
+	while read branch kind
+	do
+		case "$kind" in
+		'new')
+			grep "^ \* \[new branch\] *${branch} -> ${branch}$" error || ref_ret=1
+			;;
+		'non-fast-forward')
+			grep "^ ! \[rejected\] *${branch} -> ${branch} (non-fast-forward)$" error || ref_ret=1
+			;;
+		'fetch-first')
+			grep "^ ! \[rejected\] *${branch} -> ${branch} (fetch first)$" error || ref_ret=1
+			;;
+		'forced-update')
+			grep "^ + [a-f0-9]*\.\.\.[a-f0-9]* *${branch} -> ${branch} (forced update)$" error || ref_ret=1
+			;;
+		'')
+			grep "^   [a-f0-9]*\.\.[a-f0-9]* *${branch} -> ${branch}$" error || ref_ret=1
+			;;
+		esac
+		let 'ref_ret' && echo "match for '$branch' failed" && break
+	done
+
+	if let 'expected_ret != ret || ref_ret'
+	then
+		return 1
+	fi
+
+	return 0
+}
+
 setup () {
 	(
 	echo "[ui]"
 	echo "username = H G Wells <wells@example.com>"
-	) >> "$HOME"/.hgrc
+	echo "[extensions]"
+	echo "mq ="
+	) >> "$HOME"/.hgrc &&
+
+	GIT_AUTHOR_DATE="2007-01-01 00:00:00 +0230" &&
+	GIT_COMMITTER_DATE="$GIT_AUTHOR_DATE" &&
+	export GIT_COMMITTER_DATE GIT_AUTHOR_DATE
 }
 
 setup
 
 test_expect_success 'cloning' '
-  test_when_finished "rm -rf gitrepo*" &&
+	test_when_finished "rm -rf gitrepo*" &&
 
-  (
-  hg init hgrepo &&
-  cd hgrepo &&
-  echo zero > content &&
-  hg add content &&
-  hg commit -m zero
-  ) &&
+	(
+	hg init hgrepo &&
+	cd hgrepo &&
+	echo zero > content &&
+	hg add content &&
+	hg commit -m zero
+	) &&
 
-  git clone "hg::$PWD/hgrepo" gitrepo &&
-  check gitrepo zero master
+	git clone "hg::hgrepo" gitrepo &&
+	check gitrepo HEAD zero
 '
 
 test_expect_success 'cloning with branches' '
-  test_when_finished "rm -rf gitrepo*" &&
+	test_when_finished "rm -rf gitrepo*" &&
 
-  (
-  cd hgrepo &&
-  hg branch next &&
-  echo next > content &&
-  hg commit -m next
-  ) &&
+	(
+	cd hgrepo &&
+	hg branch next &&
+	echo next > content &&
+	hg commit -m next
+	) &&
 
-  git clone "hg::$PWD/hgrepo" gitrepo &&
-  check gitrepo next next &&
-
-  (cd hgrepo && hg checkout default) &&
-
-  git clone "hg::$PWD/hgrepo" gitrepo2 &&
-  check gitrepo2 zero master
+	git clone "hg::hgrepo" gitrepo &&
+	check gitrepo origin/branches/next next
 '
 
 test_expect_success 'cloning with bookmarks' '
-  test_when_finished "rm -rf gitrepo*" &&
+	test_when_finished "rm -rf gitrepo*" &&
 
-  (
-  cd hgrepo &&
-  hg bookmark feature-a &&
-  echo feature-a > content &&
-  hg commit -m feature-a
-  ) &&
+	(
+	cd hgrepo &&
+	hg checkout default &&
+	hg bookmark feature-a &&
+	echo feature-a > content &&
+	hg commit -m feature-a
+	) &&
 
-  git clone "hg::$PWD/hgrepo" gitrepo &&
-  check gitrepo feature-a feature-a
-'
-
-test_expect_success 'cloning with detached head' '
-  test_when_finished "rm -rf gitrepo*" &&
-
-  (
-  cd hgrepo &&
-  hg update -r 0
-  ) &&
-
-  git clone "hg::$PWD/hgrepo" gitrepo &&
-  check gitrepo zero master
+	git clone "hg::hgrepo" gitrepo &&
+	check gitrepo origin/feature-a feature-a
 '
 
 test_expect_success 'update bookmark' '
-  test_when_finished "rm -rf gitrepo*" &&
+	test_when_finished "rm -rf gitrepo*" &&
 
-  (
-  cd hgrepo &&
-  hg bookmark devel
-  ) &&
+	(
+	cd hgrepo &&
+	hg bookmark devel
+	) &&
 
-  (
-  git clone "hg::$PWD/hgrepo" gitrepo &&
-  cd gitrepo &&
-  git checkout devel &&
-  echo devel > content &&
-  git commit -a -m devel &&
-  git push
-  ) &&
+	(
+	git clone "hg::hgrepo" gitrepo &&
+	cd gitrepo &&
+	git checkout --quiet devel &&
+	echo devel > content &&
+	git commit -a -m devel &&
+	git push --quiet
+	) &&
 
-  hg -R hgrepo bookmarks | egrep "devel[	 ]+3:"
+	check_bookmark hgrepo devel devel
 '
 
+test_expect_success 'new bookmark' '
+	test_when_finished "rm -rf gitrepo*" &&
+
+	(
+	git clone "hg::hgrepo" gitrepo &&
+	cd gitrepo &&
+	git checkout --quiet -b feature-b &&
+	echo feature-b > content &&
+	git commit -a -m feature-b &&
+	git push --quiet origin feature-b
+	) &&
+
+	check_bookmark hgrepo feature-b feature-b
+'
+
+# cleanup previous stuff
+rm -rf hgrepo
+
 author_test () {
-  echo $1 >> content &&
-  hg commit -u "$2" -m "add $1" &&
-  echo "$3" >> ../expected
+	echo $1 >> content &&
+	hg commit -u "$2" -m "add $1" &&
+	echo "$3" >> ../expected
 }
 
 test_expect_success 'authors' '
-  mkdir -p tmp && cd tmp &&
-  test_when_finished "cd .. && rm -rf tmp" &&
+	test_when_finished "rm -rf hgrepo gitrepo" &&
 
-  (
-  hg init hgrepo &&
-  cd hgrepo &&
+	(
+	hg init hgrepo &&
+	cd hgrepo &&
 
-  touch content &&
-  hg add content &&
+	touch content &&
+	hg add content &&
 
-  author_test alpha "" "H G Wells <wells@example.com>" &&
-  author_test beta "test" "test <unknown>" &&
-  author_test beta "test <test@example.com> (comment)" "test <test@example.com>" &&
-  author_test gamma "<test@example.com>" "Unknown <test@example.com>" &&
-  author_test delta "name<test@example.com>" "name <test@example.com>" &&
-  author_test epsilon "name <test@example.com" "name <test@example.com>" &&
-  author_test zeta " test " "test <unknown>" &&
-  author_test eta "test < test@example.com >" "test <test@example.com>" &&
-  author_test theta "test >test@example.com>" "test <test@example.com>" &&
-  author_test iota "test < test <at> example <dot> com>" "test <unknown>" &&
-  author_test kappa "test@example.com" "Unknown <test@example.com>"
-  ) &&
+	> ../expected &&
+	author_test alpha "" "H G Wells <wells@example.com>" &&
+	author_test beta "test" "test <unknown>" &&
+	author_test beta "test <test@example.com> (comment)" "test <test@example.com>" &&
+	author_test gamma "<test@example.com>" "Unknown <test@example.com>" &&
+	author_test delta "name<test@example.com>" "name <test@example.com>" &&
+	author_test epsilon "name <test@example.com" "name <test@example.com>" &&
+	author_test zeta " test " "test <unknown>" &&
+	author_test eta "test < test@example.com >" "test <test@example.com>" &&
+	author_test theta "test >test@example.com>" "test <test@example.com>" &&
+	author_test iota "test < test <at> example <dot> com>" "test <unknown>" &&
+	author_test kappa "test@example.com" "Unknown <test@example.com>"
+	) &&
 
-  git clone "hg::$PWD/hgrepo" gitrepo &&
-  git --git-dir=gitrepo/.git log --reverse --format="%an <%ae>" > actual &&
+	git clone "hg::hgrepo" gitrepo &&
+	git --git-dir=gitrepo/.git log --reverse --format="%an <%ae>" > actual &&
 
-  test_cmp expected actual
+	test_cmp expected actual
+'
+
+test_expect_success 'strip' '
+	test_when_finished "rm -rf hgrepo gitrepo" &&
+
+	(
+	hg init hgrepo &&
+	cd hgrepo &&
+
+	echo one >> content &&
+	hg add content &&
+	hg commit -m one &&
+
+	echo two >> content &&
+	hg commit -m two
+	) &&
+
+	git clone "hg::hgrepo" gitrepo &&
+
+	(
+	cd hgrepo &&
+	hg strip 1 &&
+
+	echo three >> content &&
+	hg commit -m three &&
+
+	echo four >> content &&
+	hg commit -m four
+	) &&
+
+	(
+	cd gitrepo &&
+	git fetch &&
+	git log --format="%s" origin/master > ../actual
+	) &&
+
+	hg -R hgrepo log --template "{desc}\n" > expected &&
+	test_cmp actual expected
+'
+
+test_expect_success 'remote push with master bookmark' '
+	test_when_finished "rm -rf hgrepo gitrepo*" &&
+
+	(
+	hg init hgrepo &&
+	cd hgrepo &&
+	echo zero > content &&
+	hg add content &&
+	hg commit -m zero &&
+	hg bookmark master &&
+	echo one > content &&
+	hg commit -m one
+	) &&
+
+	(
+	git clone "hg::hgrepo" gitrepo &&
+	cd gitrepo &&
+	echo two > content &&
+	git commit -a -m two &&
+	git push
+	) &&
+
+	check_branch hgrepo default two
+'
+
+cat > expected <<EOF
+changeset:   0:6e2126489d3d
+tag:         tip
+user:        A U Thor <author@example.com>
+date:        Mon Jan 01 00:00:00 2007 +0230
+summary:     one
+
+EOF
+
+test_expect_success 'remote push from master branch' '
+	test_when_finished "rm -rf hgrepo gitrepo*" &&
+
+	hg init hgrepo &&
+
+	(
+	git init gitrepo &&
+	cd gitrepo &&
+	git remote add origin "hg::../hgrepo" &&
+	echo one > content &&
+	git add content &&
+	git commit -a -m one &&
+	git push origin master
+	) &&
+
+	hg -R hgrepo log > actual &&
+	cat actual &&
+	test_cmp expected actual &&
+
+	check_branch hgrepo default one
+'
+
+GIT_REMOTE_HG_TEST_REMOTE=1
+export GIT_REMOTE_HG_TEST_REMOTE
+
+test_expect_success 'remote cloning' '
+	test_when_finished "rm -rf gitrepo*" &&
+
+	(
+	hg init hgrepo &&
+	cd hgrepo &&
+	echo zero > content &&
+	hg add content &&
+	hg commit -m zero
+	) &&
+
+	git clone "hg::hgrepo" gitrepo &&
+	check gitrepo HEAD zero
+'
+
+test_expect_success 'remote update bookmark' '
+	test_when_finished "rm -rf gitrepo*" &&
+
+	(
+	cd hgrepo &&
+	hg bookmark devel
+	) &&
+
+	(
+	git clone "hg::hgrepo" gitrepo &&
+	cd gitrepo &&
+	git checkout --quiet devel &&
+	echo devel > content &&
+	git commit -a -m devel &&
+	git push --quiet
+	) &&
+
+	check_bookmark hgrepo devel devel
+'
+
+test_expect_success 'remote new bookmark' '
+	test_when_finished "rm -rf gitrepo*" &&
+
+	(
+	git clone "hg::hgrepo" gitrepo &&
+	cd gitrepo &&
+	git checkout --quiet -b feature-b &&
+	echo feature-b > content &&
+	git commit -a -m feature-b &&
+	git push --quiet origin feature-b
+	) &&
+
+	check_bookmark hgrepo feature-b feature-b
+'
+
+test_expect_success 'remote push diverged' '
+	test_when_finished "rm -rf gitrepo*" &&
+
+	git clone "hg::hgrepo" gitrepo &&
+
+	(
+	cd hgrepo &&
+	hg checkout default &&
+	echo bump > content &&
+	hg commit -m bump
+	) &&
+
+	(
+	cd gitrepo &&
+	echo diverge > content &&
+	git commit -a -m diverged &&
+	check_push 1 <<-EOF
+	master:non-fast-forward
+	EOF
+	) &&
+
+	check_branch hgrepo default bump
+'
+
+test_expect_success 'remote update bookmark diverge' '
+	test_when_finished "rm -rf gitrepo*" &&
+
+	(
+	cd hgrepo &&
+	hg checkout tip^ &&
+	hg bookmark diverge
+	) &&
+
+	git clone "hg::hgrepo" gitrepo &&
+
+	(
+	cd hgrepo &&
+	echo "bump bookmark" > content &&
+	hg commit -m "bump bookmark"
+	) &&
+
+	(
+	cd gitrepo &&
+	git checkout --quiet diverge &&
+	echo diverge > content &&
+	git commit -a -m diverge &&
+	check_push 1 <<-EOF
+	diverge:fetch-first
+	EOF
+	) &&
+
+	check_bookmark hgrepo diverge "bump bookmark"
+'
+
+test_expect_success 'remote new bookmark multiple branch head' '
+	test_when_finished "rm -rf gitrepo*" &&
+
+	(
+	git clone "hg::hgrepo" gitrepo &&
+	cd gitrepo &&
+	git checkout --quiet -b feature-c HEAD^ &&
+	echo feature-c > content &&
+	git commit -a -m feature-c &&
+	git push --quiet origin feature-c
+	) &&
+
+	check_bookmark hgrepo feature-c feature-c
+'
+
+# cleanup previous stuff
+rm -rf hgrepo
+
+setup_big_push () {
+	(
+	hg init hgrepo &&
+	cd hgrepo &&
+	echo zero > content &&
+	hg add content &&
+	hg commit -m zero &&
+	hg bookmark bad_bmark1 &&
+	echo one > content &&
+	hg commit -m one &&
+	hg bookmark bad_bmark2 &&
+	hg bookmark good_bmark &&
+	hg bookmark -i good_bmark &&
+	hg -q branch good_branch &&
+	echo "good branch" > content &&
+	hg commit -m "good branch" &&
+	hg -q branch bad_branch &&
+	echo "bad branch" > content &&
+	hg commit -m "bad branch"
+	) &&
+
+	git clone "hg::hgrepo" gitrepo &&
+
+	(
+	cd gitrepo &&
+	echo two > content &&
+	git commit -q -a -m two &&
+
+	git checkout -q good_bmark &&
+	echo three > content &&
+	git commit -q -a -m three &&
+
+	git checkout -q bad_bmark1 &&
+	git reset --hard HEAD^ &&
+	echo four > content &&
+	git commit -q -a -m four &&
+
+	git checkout -q bad_bmark2 &&
+	git reset --hard HEAD^ &&
+	echo five > content &&
+	git commit -q -a -m five &&
+
+	git checkout -q -b new_bmark master &&
+	echo six > content &&
+	git commit -q -a -m six &&
+
+	git checkout -q branches/good_branch &&
+	echo seven > content &&
+	git commit -q -a -m seven &&
+	echo eight > content &&
+	git commit -q -a -m eight &&
+
+	git checkout -q branches/bad_branch &&
+	git reset --hard HEAD^ &&
+	echo nine > content &&
+	git commit -q -a -m nine &&
+
+	git checkout -q -b branches/new_branch master &&
+	echo ten > content &&
+	git commit -q -a -m ten
+	)
+}
+
+test_expect_success 'remote big push' '
+	test_when_finished "rm -rf hgrepo gitrepo*" &&
+
+	setup_big_push
+
+	(
+	cd gitrepo &&
+
+	check_push 1 --all <<-EOF
+	master
+	good_bmark
+	branches/good_branch
+	new_bmark:new
+	branches/new_branch:new
+	bad_bmark1:non-fast-forward
+	bad_bmark2:non-fast-forward
+	branches/bad_branch:non-fast-forward
+	EOF
+	) &&
+
+	check_branch hgrepo default one &&
+	check_branch hgrepo good_branch "good branch" &&
+	check_branch hgrepo bad_branch "bad branch" &&
+	check_branch hgrepo new_branch '' &&
+	check_bookmark hgrepo good_bmark one &&
+	check_bookmark hgrepo bad_bmark1 one &&
+	check_bookmark hgrepo bad_bmark2 one &&
+	check_bookmark hgrepo new_bmark ''
+'
+
+test_expect_success 'remote big push fetch first' '
+	test_when_finished "rm -rf hgrepo gitrepo*" &&
+
+	(
+	hg init hgrepo &&
+	cd hgrepo &&
+	echo zero > content &&
+	hg add content &&
+	hg commit -m zero &&
+	hg bookmark bad_bmark &&
+	hg bookmark good_bmark &&
+	hg bookmark -i good_bmark &&
+	hg -q branch good_branch &&
+	echo "good branch" > content &&
+	hg commit -m "good branch" &&
+	hg -q branch bad_branch &&
+	echo "bad branch" > content &&
+	hg commit -m "bad branch"
+	) &&
+
+	git clone "hg::hgrepo" gitrepo &&
+
+	(
+	cd hgrepo &&
+	hg bookmark -f bad_bmark &&
+	echo update_bmark > content &&
+	hg commit -m "update bmark"
+	) &&
+
+	(
+	cd gitrepo &&
+	echo two > content &&
+	git commit -q -a -m two &&
+
+	git checkout -q good_bmark &&
+	echo three > content &&
+	git commit -q -a -m three &&
+
+	git checkout -q bad_bmark &&
+	echo four > content &&
+	git commit -q -a -m four &&
+
+	git checkout -q branches/bad_branch &&
+	echo five > content &&
+	git commit -q -a -m five &&
+
+	check_push 1 --all <<-EOF
+	master
+	good_bmark
+	new_bmark:new
+	new_branch:new
+	bad_bmark:fetch-first
+	branches/bad_branch:festch-first
+	EOF
+
+	git fetch &&
+
+	check_push 1 --all <<-EOF
+	master
+	good_bmark
+	bad_bmark:non-fast-forward
+	branches/bad_branch:non-fast-forward
+	EOF
+	)
+'
+
+test_expect_failure 'remote big push force' '
+	test_when_finished "rm -rf hgrepo gitrepo*" &&
+
+	setup_big_push
+
+	(
+	cd gitrepo &&
+
+	check_push 0 --force --all <<-EOF
+	master
+	good_bmark
+	branches/good_branch
+	new_bmark:new
+	branches/new_branch:new
+	bad_bmark1:forced-update
+	bad_bmark2:forced-update
+	branches/bad_branch:forced-update
+	EOF
+	) &&
+
+	check_branch hgrepo default six &&
+	check_branch hgrepo good_branch eight &&
+	check_branch hgrepo bad_branch nine &&
+	check_branch hgrepo new_branch ten &&
+	check_bookmark hgrepo good_bmark three &&
+	check_bookmark hgrepo bad_bmark1 four &&
+	check_bookmark hgrepo bad_bmark2 five &&
+	check_bookmark hgrepo new_bmark six
+'
+
+test_expect_failure 'remote big push dry-run' '
+	test_when_finished "rm -rf hgrepo gitrepo*" &&
+
+	setup_big_push
+
+	(
+	cd gitrepo &&
+
+	check_push 0 --dry-run --all <<-EOF
+	master
+	good_bmark
+	branches/good_branch
+	new_bmark:new
+	branches/new_branch:new
+	bad_bmark1:non-fast-forward
+	bad_bmark2:non-fast-forward
+	branches/bad_branch:non-fast-forward
+	EOF
+
+	check_push 0 --dry-run master good_bmark new_bmark branches/good_branch branches/new_branch <<-EOF
+	master
+	good_bmark
+	branches/good_branch
+	new_bmark:new
+	branches/new_branch:new
+	EOF
+	) &&
+
+	check_branch hgrepo default one &&
+	check_branch hgrepo good_branch "good branch" &&
+	check_branch hgrepo bad_branch "bad branch" &&
+	check_branch hgrepo new_branch '' &&
+	check_bookmark hgrepo good_bmark one &&
+	check_bookmark hgrepo bad_bmark1 one &&
+	check_bookmark hgrepo bad_bmark2 one &&
+	check_bookmark hgrepo new_bmark ''
+'
+
+test_expect_success 'remote double failed push' '
+	test_when_finished "rm -rf hgrepo gitrepo*" &&
+
+	(
+	hg init hgrepo &&
+	cd hgrepo &&
+	echo zero > content &&
+	hg add content &&
+	hg commit -m zero &&
+	echo one > content &&
+	hg commit -m one
+	) &&
+
+	(
+	git clone "hg::hgrepo" gitrepo &&
+	cd gitrepo &&
+	git reset --hard HEAD^ &&
+	echo two > content &&
+	git commit -a -m two &&
+	test_expect_code 1 git push &&
+	test_expect_code 1 git push
+	)
 '
 
 test_done
diff --git a/contrib/subtree/Makefile b/contrib/subtree/Makefile
index b507505..435b2de 100644
--- a/contrib/subtree/Makefile
+++ b/contrib/subtree/Makefile
@@ -30,6 +30,7 @@
 doc: $(GIT_SUBTREE_DOC)
 
 install: $(GIT_SUBTREE)
+	$(INSTALL) -d -m 755 $(DESTDIR)$(libexecdir)
 	$(INSTALL) -m 755 $(GIT_SUBTREE) $(DESTDIR)$(libexecdir)
 
 install-doc: install-man
diff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh
index 8a23f58..7d7af03 100755
--- a/contrib/subtree/git-subtree.sh
+++ b/contrib/subtree/git-subtree.sh
Binary files differ
diff --git a/contrib/subtree/git-subtree.txt b/contrib/subtree/git-subtree.txt
index 7ba853e..e0957ee 100644
--- a/contrib/subtree/git-subtree.txt
+++ b/contrib/subtree/git-subtree.txt
@@ -270,7 +270,7 @@
 name
 
 You can omit the --squash flag, but doing so will increase the number
-of commits that are incldued in your local repository.
+of commits that are included in your local repository.
 
 We now have a ~/git-extensions/git-subtree directory containing code
 from the master branch of git://github.com/apenwarr/git-subtree.git
diff --git a/contrib/subtree/t/t7900-subtree.sh b/contrib/subtree/t/t7900-subtree.sh
index b0f8536..66ce4b0 100755
--- a/contrib/subtree/t/t7900-subtree.sh
+++ b/contrib/subtree/t/t7900-subtree.sh
@@ -182,9 +182,9 @@
 test_expect_success 'Check that prefix argument is required for split' '
         echo "You must provide the --prefix option." > expected &&
         test_must_fail git subtree split > actual 2>&1 &&
-        test_debug "echo -n expected: " &&
+	test_debug "printf '"'"'expected: '"'"'" &&
         test_debug "cat expected" &&
-        test_debug "echo -n actual: " &&
+	test_debug "printf '"'"'actual: '"'"'" &&
         test_debug "cat actual" &&
         test_cmp expected actual &&
         rm -f expected actual
@@ -193,9 +193,9 @@
 test_expect_success 'Check that the <prefix> exists for a split' '
         echo "'"'"'non-existent-directory'"'"'" does not exist\; use "'"'"'git subtree add'"'"'" > expected &&
         test_must_fail git subtree split --prefix=non-existent-directory > actual 2>&1 &&
-        test_debug "echo -n expected: " &&
+	test_debug "printf '"'"'expected: '"'"'" &&
         test_debug "cat expected" &&
-        test_debug "echo -n actual: " &&
+	test_debug "printf '"'"'actual: '"'"'" &&
         test_debug "cat actual" &&
         test_cmp expected actual
 #        rm -f expected actual
diff --git a/convert.c b/convert.c
index 2a2e46c..11a95fc 100644
--- a/convert.c
+++ b/convert.c
@@ -835,7 +835,7 @@
 
 /*****************************************************************
  *
- * Streaming converison support
+ * Streaming conversion support
  *
  *****************************************************************/
 
diff --git a/convert.h b/convert.h
index ec5fd69..0c2143c 100644
--- a/convert.h
+++ b/convert.h
@@ -48,7 +48,7 @@
 
 /*****************************************************************
  *
- * Streaming converison support
+ * Streaming conversion support
  *
  *****************************************************************/
 
diff --git a/credential-store.c b/credential-store.c
index 26f7589..f9146e5 100644
--- a/credential-store.c
+++ b/credential-store.c
@@ -114,7 +114,7 @@
 	return c->username && c->password;
 }
 
-int main(int argc, const char **argv)
+int main(int argc, char **argv)
 {
 	const char * const usage[] = {
 		"git credential-store [options] <action>",
@@ -131,7 +131,7 @@
 
 	umask(077);
 
-	argc = parse_options(argc, argv, NULL, options, usage, 0);
+	argc = parse_options(argc, (const char **)argv, NULL, options, usage, 0);
 	if (argc != 1)
 		usage_with_options(usage, options);
 	op = argv[0];
diff --git a/daemon.c b/daemon.c
index 6aeddcb..34916c5 100644
--- a/daemon.c
+++ b/daemon.c
@@ -760,7 +760,7 @@
 		snprintf(portbuf, sizeof(portbuf), "REMOTE_PORT=%d",
 		    ntohs(sin_addr->sin_port));
 #ifndef NO_IPV6
-	} else if (addr && addr->sa_family == AF_INET6) {
+	} else if (addr->sa_family == AF_INET6) {
 		struct sockaddr_in6 *sin6_addr = (void *) addr;
 
 		char *buf = addrbuf + 12;
@@ -1047,18 +1047,6 @@
 	}
 }
 
-/* if any standard file descriptor is missing open it to /dev/null */
-static void sanitize_stdfds(void)
-{
-	int fd = open("/dev/null", O_RDWR, 0);
-	while (fd != -1 && fd < 2)
-		fd = dup(fd);
-	if (fd == -1)
-		die_errno("open /dev/null or dup failed");
-	if (fd > 2)
-		close(fd);
-}
-
 #ifdef NO_POSIX_GOODIES
 
 struct credentials;
diff --git a/date.c b/date.c
index df20d0b..29f1540 100644
--- a/date.c
+++ b/date.c
@@ -711,6 +711,28 @@
 	return 0; /* success */
 }
 
+int parse_expiry_date(const char *date, unsigned long *timestamp)
+{
+	int errors = 0;
+
+	if (!strcmp(date, "never") || !strcmp(date, "false"))
+		*timestamp = 0;
+	else if (!strcmp(date, "all") || !strcmp(date, "now"))
+		/*
+		 * We take over "now" here, which usually translates
+		 * to the current timestamp.  This is because the user
+		 * really means to expire everything she has done in
+		 * the past, and by definition reflogs are the record
+		 * of the past, and there is nothing from the future
+		 * to be kept.
+		 */
+		*timestamp = ULONG_MAX;
+	else
+		*timestamp = approxidate_careful(date, &errors);
+
+	return errors;
+}
+
 int parse_date(const char *date, char *result, int maxlen)
 {
 	unsigned long timestamp;
diff --git a/decorate.c b/decorate.c
index 2f8a63e..7cb5d29 100644
--- a/decorate.c
+++ b/decorate.c
@@ -49,7 +49,7 @@
 		const struct object *base = old_hash[i].base;
 		void *decoration = old_hash[i].decoration;
 
-		if (!base)
+		if (!decoration)
 			continue;
 		insert_decoration(n, base, decoration);
 	}
diff --git a/diff-lib.c b/diff-lib.c
index f35de0f..b6f4b21 100644
--- a/diff-lib.c
+++ b/diff-lib.c
@@ -64,8 +64,9 @@
  * commits, untracked content and/or modified content).
  */
 static int match_stat_with_submodule(struct diff_options *diffopt,
-				      struct cache_entry *ce, struct stat *st,
-				      unsigned ce_option, unsigned *dirty_submodule)
+				     const struct cache_entry *ce,
+				     struct stat *st, unsigned ce_option,
+				     unsigned *dirty_submodule)
 {
 	int changed = ce_match_stat(ce, st, ce_option);
 	if (S_ISGITLINK(ce->ce_mode)) {
@@ -237,7 +238,7 @@
 /* A file entry went away or appeared */
 static void diff_index_show_file(struct rev_info *revs,
 				 const char *prefix,
-				 struct cache_entry *ce,
+				 const struct cache_entry *ce,
 				 const unsigned char *sha1, int sha1_valid,
 				 unsigned int mode,
 				 unsigned dirty_submodule)
@@ -246,7 +247,7 @@
 		       sha1, sha1_valid, ce->name, dirty_submodule);
 }
 
-static int get_stat_data(struct cache_entry *ce,
+static int get_stat_data(const struct cache_entry *ce,
 			 const unsigned char **sha1p,
 			 unsigned int *modep,
 			 int cached, int match_missing,
@@ -283,7 +284,7 @@
 }
 
 static void show_new_file(struct rev_info *revs,
-			  struct cache_entry *new,
+			  const struct cache_entry *new,
 			  int cached, int match_missing)
 {
 	const unsigned char *sha1;
@@ -302,8 +303,8 @@
 }
 
 static int show_modified(struct rev_info *revs,
-			 struct cache_entry *old,
-			 struct cache_entry *new,
+			 const struct cache_entry *old,
+			 const struct cache_entry *new,
 			 int report_missing,
 			 int cached, int match_missing)
 {
@@ -362,8 +363,8 @@
  * give you the position and number of entries in the index).
  */
 static void do_oneway_diff(struct unpack_trees_options *o,
-	struct cache_entry *idx,
-	struct cache_entry *tree)
+			   const struct cache_entry *idx,
+			   const struct cache_entry *tree)
 {
 	struct rev_info *revs = o->unpack_data;
 	int match_missing, cached;
@@ -423,10 +424,11 @@
  * the fairly complex unpack_trees() semantic requirements, including
  * the skipping, the path matching, the type conflict cases etc.
  */
-static int oneway_diff(struct cache_entry **src, struct unpack_trees_options *o)
+static int oneway_diff(const struct cache_entry * const *src,
+		       struct unpack_trees_options *o)
 {
-	struct cache_entry *idx = src[0];
-	struct cache_entry *tree = src[1];
+	const struct cache_entry *idx = src[0];
+	const struct cache_entry *tree = src[1];
 	struct rev_info *revs = o->unpack_data;
 
 	/*
diff --git a/diff-no-index.c b/diff-no-index.c
index 74da659..e66fdf3 100644
--- a/diff-no-index.c
+++ b/diff-no-index.c
@@ -45,7 +45,7 @@
 
 	if (!path || !strcmp(path, "/dev/null"))
 		*mode = 0;
-#ifdef _WIN32
+#ifdef GIT_WINDOWS_NATIVE
 	else if (!strcasecmp(path, "nul"))
 		*mode = 0;
 #endif
diff --git a/diff.c b/diff.c
index f0b3e7c..266112c 100644
--- a/diff.c
+++ b/diff.c
@@ -1683,9 +1683,7 @@
 		del = deleted;
 
 		if (graph_width <= max_change) {
-			int total = add + del;
-
-			total = scale_linear(add + del, graph_width, max_change);
+			int total = scale_linear(add + del, graph_width, max_change);
 			if (total < 2 && add && del)
 				/* width >= 2 due to the sanity check */
 				total = 2;
@@ -2586,7 +2584,7 @@
  */
 static int reuse_worktree_file(const char *name, const unsigned char *sha1, int want_file)
 {
-	struct cache_entry *ce;
+	const struct cache_entry *ce;
 	struct stat st;
 	int pos, len;
 
@@ -2677,6 +2675,14 @@
 int diff_populate_filespec(struct diff_filespec *s, int size_only)
 {
 	int err = 0;
+	/*
+	 * demote FAIL to WARN to allow inspecting the situation
+	 * instead of refusing.
+	 */
+	enum safe_crlf crlf_warn = (safe_crlf == SAFE_CRLF_FAIL
+				    ? SAFE_CRLF_WARN
+				    : safe_crlf);
+
 	if (!DIFF_FILE_VALID(s))
 		die("internal error: asking to populate invalid file.");
 	if (S_ISDIR(s->mode))
@@ -2732,7 +2738,7 @@
 		/*
 		 * Convert from working tree format to canonical git format
 		 */
-		if (convert_to_git(s->path, s->data, s->size, &buf, safe_crlf)) {
+		if (convert_to_git(s->path, s->data, s->size, &buf, crlf_warn)) {
 			size_t size = 0;
 			munmap(s->data, s->size);
 			s->should_munmap = 0;
@@ -3497,6 +3503,11 @@
 	return 1;
 }
 
+static void enable_patch_output(int *fmt) {
+	*fmt &= ~DIFF_FORMAT_NO_OUTPUT;
+	*fmt |= DIFF_FORMAT_PATCH;
+}
+
 int diff_opt_parse(struct diff_options *options, const char **av, int ac)
 {
 	const char *arg = av[0];
@@ -3504,15 +3515,15 @@
 	int argcount;
 
 	/* Output format options */
-	if (!strcmp(arg, "-p") || !strcmp(arg, "-u") || !strcmp(arg, "--patch"))
-		options->output_format |= DIFF_FORMAT_PATCH;
-	else if (opt_arg(arg, 'U', "unified", &options->context))
-		options->output_format |= DIFF_FORMAT_PATCH;
+	if (!strcmp(arg, "-p") || !strcmp(arg, "-u") || !strcmp(arg, "--patch")
+	    || opt_arg(arg, 'U', "unified", &options->context))
+		enable_patch_output(&options->output_format);
 	else if (!strcmp(arg, "--raw"))
 		options->output_format |= DIFF_FORMAT_RAW;
-	else if (!strcmp(arg, "--patch-with-raw"))
-		options->output_format |= DIFF_FORMAT_PATCH | DIFF_FORMAT_RAW;
-	else if (!strcmp(arg, "--numstat"))
+	else if (!strcmp(arg, "--patch-with-raw")) {
+		enable_patch_output(&options->output_format);
+		options->output_format |= DIFF_FORMAT_RAW;
+	} else if (!strcmp(arg, "--numstat"))
 		options->output_format |= DIFF_FORMAT_NUMSTAT;
 	else if (!strcmp(arg, "--shortstat"))
 		options->output_format |= DIFF_FORMAT_SHORTSTAT;
@@ -3534,13 +3545,14 @@
 		options->output_format |= DIFF_FORMAT_CHECKDIFF;
 	else if (!strcmp(arg, "--summary"))
 		options->output_format |= DIFF_FORMAT_SUMMARY;
-	else if (!strcmp(arg, "--patch-with-stat"))
-		options->output_format |= DIFF_FORMAT_PATCH | DIFF_FORMAT_DIFFSTAT;
-	else if (!strcmp(arg, "--name-only"))
+	else if (!strcmp(arg, "--patch-with-stat")) {
+		enable_patch_output(&options->output_format);
+		options->output_format |= DIFF_FORMAT_DIFFSTAT;
+	} else if (!strcmp(arg, "--name-only"))
 		options->output_format |= DIFF_FORMAT_NAME;
 	else if (!strcmp(arg, "--name-status"))
 		options->output_format |= DIFF_FORMAT_NAME_STATUS;
-	else if (!strcmp(arg, "-s"))
+	else if (!strcmp(arg, "-s") || !strcmp(arg, "--no-patch"))
 		options->output_format |= DIFF_FORMAT_NO_OUTPUT;
 	else if (!prefixcmp(arg, "--stat"))
 		/* --stat, --stat-width, --stat-name-width, or --stat-count */
@@ -3593,6 +3605,8 @@
 		DIFF_XDL_SET(options, IGNORE_WHITESPACE_CHANGE);
 	else if (!strcmp(arg, "--ignore-space-at-eol"))
 		DIFF_XDL_SET(options, IGNORE_WHITESPACE_AT_EOL);
+	else if (!strcmp(arg, "--ignore-blank-lines"))
+		DIFF_XDL_SET(options, IGNORE_BLANK_LINES);
 	else if (!strcmp(arg, "--patience"))
 		options->xdl_opts = DIFF_WITH_ALG(options, PATIENCE_DIFF);
 	else if (!strcmp(arg, "--histogram"))
@@ -3611,7 +3625,7 @@
 
 	/* flags options */
 	else if (!strcmp(arg, "--binary")) {
-		options->output_format |= DIFF_FORMAT_PATCH;
+		enable_patch_output(&options->output_format);
 		DIFF_OPT_SET(options, BINARY);
 	}
 	else if (!strcmp(arg, "--full-index"))
@@ -4450,7 +4464,7 @@
 	    DIFF_OPT_TST(options, DIFF_FROM_CONTENTS)) {
 		/*
 		 * run diff_flush_patch for the exit status. setting
-		 * options->file to /dev/null should be safe, becaue we
+		 * options->file to /dev/null should be safe, because we
 		 * aren't supposed to produce any output anyway.
 		 */
 		if (options->close_file)
diff --git a/diffcore-pickaxe.c b/diffcore-pickaxe.c
index 63722f8..401eb72 100644
--- a/diffcore-pickaxe.c
+++ b/diffcore-pickaxe.c
@@ -122,7 +122,7 @@
 		char errbuf[1024];
 		regerror(err, &regex, errbuf, 1024);
 		regfree(&regex);
-		die("invalid log-grep regex: %s", errbuf);
+		die("invalid regex: %s", errbuf);
 	}
 
 	pickaxe(&diff_queued_diff, o, &regex, NULL, diff_grep);
@@ -131,8 +131,7 @@
 	return;
 }
 
-static unsigned int contains(mmfile_t *mf, struct diff_options *o,
-			     regex_t *regexp, kwset_t kws)
+static unsigned int contains(mmfile_t *mf, regex_t *regexp, kwset_t kws)
 {
 	unsigned int cnt;
 	unsigned long sz;
@@ -176,11 +175,9 @@
 		       struct diff_options *o,
 		       regex_t *regexp, kwset_t kws)
 {
-	if (!one)
-		return contains(two, o, regexp, kws) != 0;
-	if (!two)
-		return contains(one, o, regexp, kws) != 0;
-	return contains(one, o, regexp, kws) != contains(two, o, regexp, kws);
+	unsigned int one_contains = one ? contains(one, regexp, kws) : 0;
+	unsigned int two_contains = two ? contains(two, regexp, kws) : 0;
+	return one_contains != two_contains;
 }
 
 static int pickaxe_match(struct diff_filepair *p, struct diff_options *o,
@@ -246,7 +243,7 @@
 			char errbuf[1024];
 			regerror(err, &regex, errbuf, 1024);
 			regfree(&regex);
-			die("invalid pickaxe regex: %s", errbuf);
+			die("invalid regex: %s", errbuf);
 		}
 		regexp = &regex;
 	} else {
diff --git a/dir.c b/dir.c
index a5926fb..910bfcd 100644
--- a/dir.c
+++ b/dir.c
@@ -821,6 +821,9 @@
 				dir->basebuf, stk->baselen - 1,
 				dir->basebuf + current, &dt);
 			dir->basebuf[stk->baselen - 1] = '/';
+			if (dir->exclude &&
+			    dir->exclude->flags & EXC_FLAG_NEGATIVE)
+				dir->exclude = NULL;
 			if (dir->exclude) {
 				dir->basebuf[stk->baselen] = 0;
 				dir->exclude_stack = stk;
@@ -930,7 +933,7 @@
  */
 static enum exist_status directory_exists_in_index_icase(const char *dirname, int len)
 {
-	struct cache_entry *ce = index_name_exists(&the_index, dirname, len + 1, ignore_case);
+	const struct cache_entry *ce = index_name_exists(&the_index, dirname, len + 1, ignore_case);
 	unsigned char endchar;
 
 	if (!ce)
@@ -974,7 +977,7 @@
 	if (pos < 0)
 		pos = -pos-1;
 	while (pos < active_nr) {
-		struct cache_entry *ce = active_cache[pos++];
+		const struct cache_entry *ce = active_cache[pos++];
 		unsigned char endchar;
 
 		if (strncmp(ce->name, dirname, len))
@@ -1033,9 +1036,7 @@
 		return path_recurse;
 
 	case index_gitdir:
-		if (dir->flags & DIR_SHOW_OTHER_DIRECTORIES)
-			return path_none;
-		return path_untracked;
+		return path_none;
 
 	case index_nonexistent:
 		if (dir->flags & DIR_SHOW_OTHER_DIRECTORIES)
@@ -1112,7 +1113,7 @@
 static int get_index_dtype(const char *path, int len)
 {
 	int pos;
-	struct cache_entry *ce;
+	const struct cache_entry *ce;
 
 	ce = cache_name_exists(path, len, 0);
 	if (ce) {
@@ -1542,9 +1543,9 @@
 		home_config_paths(NULL, &xdg_path, "ignore");
 		excludes_file = xdg_path;
 	}
-	if (!access_or_warn(path, R_OK))
+	if (!access_or_warn(path, R_OK, 0))
 		add_excludes_from_file(dir, path);
-	if (excludes_file && !access_or_warn(excludes_file, R_OK))
+	if (excludes_file && !access_or_warn(excludes_file, R_OK, 0))
 		add_excludes_from_file(dir, excludes_file);
 }
 
diff --git a/entry.c b/entry.c
index d7c131d..acc892f 100644
--- a/entry.c
+++ b/entry.c
@@ -79,7 +79,7 @@
 	return open(path, O_WRONLY | O_CREAT | O_EXCL, mode);
 }
 
-static void *read_blob_entry(struct cache_entry *ce, unsigned long *size)
+static void *read_blob_entry(const struct cache_entry *ce, unsigned long *size)
 {
 	enum object_type type;
 	void *new = read_sha1_file(ce->sha1, &type, size);
@@ -92,7 +92,7 @@
 	return NULL;
 }
 
-static int open_output_fd(char *path, struct cache_entry *ce, int to_tempfile)
+static int open_output_fd(char *path, const struct cache_entry *ce, int to_tempfile)
 {
 	int symlink = (ce->ce_mode & S_IFMT) != S_IFREG;
 	if (to_tempfile) {
@@ -115,7 +115,7 @@
 	return 0;
 }
 
-static int streaming_write_entry(struct cache_entry *ce, char *path,
+static int streaming_write_entry(const struct cache_entry *ce, char *path,
 				 struct stream_filter *filter,
 				 const struct checkout *state, int to_tempfile,
 				 int *fstat_done, struct stat *statbuf)
@@ -136,7 +136,8 @@
 	return result;
 }
 
-static int write_entry(struct cache_entry *ce, char *path, const struct checkout *state, int to_tempfile)
+static int write_entry(struct cache_entry *ce,
+		       char *path, const struct checkout *state, int to_tempfile)
 {
 	unsigned int ce_mode_s_ifmt = ce->ce_mode & S_IFMT;
 	int fd, ret, fstat_done = 0;
@@ -199,9 +200,9 @@
 		break;
 	case S_IFGITLINK:
 		if (to_tempfile)
-			return error("cannot create temporary subproject %s", path);
+			return error("cannot create temporary submodule %s", path);
 		if (mkdir(path, 0777) < 0)
-			return error("cannot create subproject directory %s", path);
+			return error("cannot create submodule directory %s", path);
 		break;
 	default:
 		return error("unknown file mode for %s in index", path);
@@ -233,7 +234,8 @@
 	return lstat(path, st);
 }
 
-int checkout_entry(struct cache_entry *ce, const struct checkout *state, char *topath)
+int checkout_entry(struct cache_entry *ce,
+		   const struct checkout *state, char *topath)
 {
 	static char path[PATH_MAX + 1];
 	struct stat st;
diff --git a/environment.c b/environment.c
index e2e75c1..5398c36 100644
--- a/environment.c
+++ b/environment.c
@@ -22,6 +22,7 @@
 int is_bare_repository_cfg = -1; /* unspecified */
 int log_all_ref_updates = -1; /* unspecified */
 int warn_ambiguous_refs = 1;
+int warn_on_object_refname_ambiguity = 1;
 int repository_format_version;
 const char *git_commit_encoding;
 const char *git_log_output_encoding;
@@ -37,7 +38,6 @@
 size_t packed_git_limit = DEFAULT_PACKED_GIT_LIMIT;
 size_t delta_base_cache_limit = 16 * 1024 * 1024;
 unsigned long big_file_threshold = 512 * 1024 * 1024;
-const char *log_pack_access;
 const char *pager_program;
 int pager_use_color = 1;
 const char *editor_program;
diff --git a/exec_cmd.h b/exec_cmd.h
index e2b546b..e4c9702 100644
--- a/exec_cmd.h
+++ b/exec_cmd.h
@@ -7,6 +7,7 @@
 extern void setup_path(void);
 extern const char **prepare_git_cmd(const char **argv);
 extern int execv_git_cmd(const char **argv); /* NULL terminated */
+LAST_ARG_MUST_BE_NULL
 extern int execl_git_cmd(const char *cmd, ...);
 extern const char *system_path(const char *path);
 
diff --git a/fast-import.c b/fast-import.c
index 5f539d7..23f625f 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -297,7 +297,7 @@
 static FILE *pack_edges;
 static unsigned int show_stats = 1;
 static int global_argc;
-static const char **global_argv;
+static char **global_argv;
 
 /* Memory pools */
 static size_t mem_pool_alloc = 2*1024*1024 - sizeof(struct mem_pool);
@@ -1822,7 +1822,7 @@
 		*end = 0;
 		mark = strtoumax(line + 1, &end, 10);
 		if (!mark || end == line + 1
-			|| *end != ' ' || get_sha1(end + 1, sha1))
+			|| *end != ' ' || get_sha1_hex(end + 1, sha1))
 			die("corrupt mark line: %s", line);
 		e = find_object(sha1);
 		if (!e) {
@@ -3347,7 +3347,7 @@
 		read_marks();
 }
 
-int main(int argc, const char **argv)
+int main(int argc, char **argv)
 {
 	unsigned int i;
 
diff --git a/fetch-pack.c b/fetch-pack.c
index f156dd4..f5d99c1 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -11,6 +11,7 @@
 #include "run-command.h"
 #include "transport.h"
 #include "version.h"
+#include "prio-queue.h"
 
 static int transfer_unpack_limit = -1;
 static int fetch_unpack_limit = -1;
@@ -20,6 +21,8 @@
 static int fetch_fsck_objects = -1;
 static int transfer_fsck_objects = -1;
 static int agent_supported;
+static struct lock_file shallow_lock;
+static const char *alternate_shallow_file;
 
 #define COMPLETE	(1U << 0)
 #define COMMON		(1U << 1)
@@ -35,7 +38,7 @@
  */
 #define MAX_IN_VAIN 256
 
-static struct commit_list *rev_list;
+static struct prio_queue rev_list = { compare_commits_by_commit_date };
 static int non_common_revs, multi_ack, use_sideband, allow_tip_sha1_in_want;
 
 static void rev_list_push(struct commit *commit, int mark)
@@ -47,7 +50,7 @@
 			if (parse_commit(commit))
 				return;
 
-		commit_list_insert_by_date(commit, &rev_list);
+		prio_queue_put(&rev_list, commit);
 
 		if (!(commit->object.flags & COMMON))
 			non_common_revs++;
@@ -120,10 +123,10 @@
 		unsigned int mark;
 		struct commit_list *parents;
 
-		if (rev_list == NULL || non_common_revs == 0)
+		if (rev_list.nr == 0 || non_common_revs == 0)
 			return NULL;
 
-		commit = rev_list->item;
+		commit = prio_queue_get(&rev_list);
 		if (!commit->object.parsed)
 			parse_commit(commit);
 		parents = commit->parents;
@@ -150,8 +153,6 @@
 				mark_common(parents->item, 1, 0);
 			parents = parents->next;
 		}
-
-		rev_list = rev_list->next;
 	}
 
 	return commit->object.sha1;
@@ -440,7 +441,7 @@
 					in_vain = 0;
 					got_continue = 1;
 					if (ack == ACK_ready) {
-						rev_list = NULL;
+						clear_prio_queue(&rev_list);
 						got_ready = 1;
 					}
 					break;
@@ -503,7 +504,7 @@
 		struct commit *commit = (struct commit *)o;
 		if (!(commit->object.flags & COMPLETE)) {
 			commit->object.flags |= COMPLETE;
-			commit_list_insert_by_date(commit, &complete);
+			commit_list_insert(commit, &complete);
 		}
 	}
 	return 0;
@@ -620,6 +621,7 @@
 	if (!args->depth) {
 		for_each_ref(mark_complete, NULL);
 		for_each_alternate_ref(mark_alternate_complete, NULL);
+		commit_list_sort_by_date(&complete);
 		if (cutoff)
 			mark_recent_complete_commits(args, cutoff);
 	}
@@ -683,12 +685,13 @@
 		    int xd[2], char **pack_lockfile)
 {
 	struct async demux;
-	const char *argv[20];
+	const char *argv[22];
 	char keep_arg[256];
 	char hdr_arg[256];
 	const char **av;
 	int do_keep = args->keep_pack;
 	struct child_process cmd;
+	int ret;
 
 	memset(&demux, 0, sizeof(demux));
 	if (use_sideband) {
@@ -724,6 +727,11 @@
 			do_keep = 1;
 	}
 
+	if (alternate_shallow_file) {
+		*av++ = "--shallow-file";
+		*av++ = alternate_shallow_file;
+	}
+
 	if (do_keep) {
 		if (pack_lockfile)
 			cmd.out = -1;
@@ -740,11 +748,14 @@
 				strcpy(keep_arg + s, "localhost");
 			*av++ = keep_arg;
 		}
+		if (args->check_self_contained_and_connected)
+			*av++ = "--check-self-contained-and-connected";
 	}
 	else {
 		*av++ = "unpack-objects";
 		if (args->quiet || args->no_progress)
 			*av++ = "-q";
+		args->check_self_contained_and_connected = 0;
 	}
 	if (*hdr_arg)
 		*av++ = hdr_arg;
@@ -765,7 +776,12 @@
 		close(cmd.out);
 	}
 
-	if (finish_command(&cmd))
+	ret = finish_command(&cmd);
+	if (!ret || (args->check_self_contained_and_connected && ret == 1))
+		args->self_contained_and_connected =
+			args->check_self_contained_and_connected &&
+			ret == 0;
+	else
 		die("%s failed", argv[0]);
 	if (use_sideband && finish_async(&demux))
 		die("error in sideband demultiplexer");
@@ -779,6 +795,27 @@
 	return strcmp(a->name, b->name);
 }
 
+static void setup_alternate_shallow(void)
+{
+	struct strbuf sb = STRBUF_INIT;
+	int fd;
+
+	check_shallow_file_for_update();
+	fd = hold_lock_file_for_update(&shallow_lock, git_path("shallow"),
+				       LOCK_DIE_ON_ERROR);
+	if (write_shallow_commits(&sb, 0)) {
+		if (write_in_full(fd, sb.buf, sb.len) != sb.len)
+			die_errno("failed to write to %s", shallow_lock.filename);
+		alternate_shallow_file = shallow_lock.filename;
+	} else
+		/*
+		 * is_repository_shallow() sees empty string as "no
+		 * shallow file".
+		 */
+		alternate_shallow_file = "";
+	strbuf_release(&sb);
+}
+
 static struct ref *do_fetch_pack(struct fetch_pack_args *args,
 				 int fd[2],
 				 const struct ref *orig_ref,
@@ -858,6 +895,10 @@
 
 	if (args->stateless_rpc)
 		packet_flush(fd[1]);
+	if (args->depth > 0)
+		setup_alternate_shallow();
+	else
+		alternate_shallow_file = NULL;
 	if (get_pack(args, fd, pack_lockfile))
 		die("git fetch-pack: fetch failed.");
 
@@ -936,15 +977,9 @@
 		       struct ref **sought, int nr_sought,
 		       char **pack_lockfile)
 {
-	struct stat st;
 	struct ref *ref_cpy;
 
 	fetch_pack_setup();
-	if (args->depth > 0) {
-		if (stat(git_path("shallow"), &st))
-			st.st_mtime = 0;
-	}
-
 	if (nr_sought)
 		nr_sought = remove_duplicates_in_refs(sought, nr_sought);
 
@@ -954,35 +989,12 @@
 	}
 	ref_cpy = do_fetch_pack(args, fd, ref, sought, nr_sought, pack_lockfile);
 
-	if (args->depth > 0) {
-		static struct lock_file lock;
-		struct cache_time mtime;
-		struct strbuf sb = STRBUF_INIT;
-		char *shallow = git_path("shallow");
-		int fd;
-
-		mtime.sec = st.st_mtime;
-		mtime.nsec = ST_MTIME_NSEC(st);
-		if (stat(shallow, &st)) {
-			if (mtime.sec)
-				die("shallow file was removed during fetch");
-		} else if (st.st_mtime != mtime.sec
-#ifdef USE_NSEC
-				|| ST_MTIME_NSEC(st) != mtime.nsec
-#endif
-			  )
-			die("shallow file was changed during fetch");
-
-		fd = hold_lock_file_for_update(&lock, shallow,
-					       LOCK_DIE_ON_ERROR);
-		if (!write_shallow_commits(&sb, 0)
-		 || write_in_full(fd, sb.buf, sb.len) != sb.len) {
-			unlink_or_warn(shallow);
-			rollback_lock_file(&lock);
-		} else {
-			commit_lock_file(&lock);
-		}
-		strbuf_release(&sb);
+	if (args->depth > 0 && alternate_shallow_file) {
+		if (*alternate_shallow_file == '\0') { /* --unshallow */
+			unlink_or_warn(git_path("shallow"));
+			rollback_lock_file(&shallow_lock);
+		} else
+			commit_lock_file(&shallow_lock);
 	}
 
 	reprepare_packed_git();
diff --git a/fetch-pack.h b/fetch-pack.h
index dc5266c..40f08ba 100644
--- a/fetch-pack.h
+++ b/fetch-pack.h
@@ -16,7 +16,9 @@
 		verbose:1,
 		no_progress:1,
 		include_tag:1,
-		stateless_rpc:1;
+		stateless_rpc:1,
+		check_self_contained_and_connected:1,
+		self_contained_and_connected:1;
 };
 
 /*
diff --git a/fixup-builtins b/fixup-builtins
deleted file mode 100755
index 63dfa4c..0000000
--- a/fixup-builtins
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/bin/sh
-while [ "$1" ]
-do
-	if [ "$1" != "git-sh-setup" -a "$1" != "git-parse-remote" -a "$1" != "git-svn" ]; then
-		old="$1"
-		new=$(echo "$1" | sed 's/git-/git /')
-		echo "Converting '$old' to '$new'"
-		sed -i "s/\\<$old\\>/$new/g" $(git ls-files '*.sh')
-	fi
-	shift
-done
-
-sed -i 's/git merge-one-file/git-merge-one-file/g
-s/git rebase-todo/git-rebase-todo/g' $(git ls-files '*.sh')
-git update-index --refresh >& /dev/null
-exit 0
diff --git a/git-add--interactive.perl b/git-add--interactive.perl
index d2c4ce6..75a991f 100755
--- a/git-add--interactive.perl
+++ b/git-add--interactive.perl
@@ -44,6 +44,8 @@
 
 my $normal_color = $repo->get_color("", "reset");
 
+my $diff_algorithm = $repo->config('diff.algorithm');
+
 my $use_readkey = 0;
 my $use_termcap = 0;
 my %term_escapes;
@@ -731,6 +733,9 @@
 sub parse_diff {
 	my ($path) = @_;
 	my @diff_cmd = split(" ", $patch_mode_flavour{DIFF});
+	if (defined $diff_algorithm) {
+		splice @diff_cmd, 1, 0, "--diff-algorithm=${diff_algorithm}";
+	}
 	if (defined $patch_mode_revision) {
 		push @diff_cmd, $patch_mode_revision;
 	}
diff --git a/git-am.sh b/git-am.sh
index 1cf3d1d..7ea40fe 100755
--- a/git-am.sh
+++ b/git-am.sh
@@ -6,7 +6,7 @@
 OPTIONS_KEEPDASHDASH=
 OPTIONS_SPEC="\
 git am [options] [(<mbox>|<Maildir>)...]
-git am [options] (--resolved | --skip | --abort)
+git am [options] (--continue | --skip | --abort)
 --
 i,interactive   run interactively
 b,binary*       (historical option -- no-op)
@@ -102,7 +102,7 @@
 	    printf '%s\n' "$resolvemsg"
 	    stop_here $1
     fi
-    eval_gettextln "When you have resolved this problem, run \"\$cmdline --resolved\".
+    eval_gettextln "When you have resolved this problem, run \"\$cmdline --continue\".
 If you prefer to skip this patch, run \"\$cmdline --skip\" instead.
 To restore the original branch and stop patching, run \"\$cmdline --abort\"."
 
@@ -506,7 +506,24 @@
 	esac
 	rm -f "$dotest/dirtyindex"
 else
-	# Make sure we are not given --skip, --resolved, nor --abort
+	# Possible stray $dotest directory in the independent-run
+	# case; in the --rebasing case, it is upto the caller
+	# (git-rebase--am) to take care of stray directories.
+	if test -d "$dotest" && test -z "$rebasing"
+	then
+		case "$skip,$resolved,$abort" in
+		,,t)
+			rm -fr "$dotest"
+			exit 0
+			;;
+		*)
+			die "$(eval_gettext "Stray \$dotest directory found.
+Use \"git am --abort\" to remove it.")"
+			;;
+		esac
+	fi
+
+	# Make sure we are not given --skip, --continue, nor --abort
 	test "$skip$resolved$abort" = "" ||
 		die "$(gettext "Resolve operation not in progress, we are not resuming.")"
 
@@ -653,7 +670,7 @@
 	#  - patch is the patch body.
 	#
 	# When we are resuming, these files are either already prepared
-	# by the user, or the user can tell us to do so by --resolved flag.
+	# by the user, or the user can tell us to do so by --continue flag.
 	case "$resume" in
 	'')
 		if test -f "$dotest/rebasing"
diff --git a/git-bisect.sh b/git-bisect.sh
index d7518e9..9f064b6 100755
--- a/git-bisect.sh
+++ b/git-bisect.sh
@@ -320,8 +320,8 @@
 	elif test $res -eq 2
 	then
 		echo "# only skipped commits left to test" >>"$GIT_DIR/BISECT_LOG"
-		good_revs=$(git for-each-ref --format="--not %(objectname)" "refs/bisect/good-*")
-		for skipped in $(git rev-list refs/bisect/bad $good_revs)
+		good_revs=$(git for-each-ref --format="%(objectname)" "refs/bisect/good-*")
+		for skipped in $(git rev-list refs/bisect/bad --not $good_revs)
 		do
 			skipped_commit=$(git show-branch $skipped)
 			echo "# possible first bad commit: $skipped_commit" >>"$GIT_DIR/BISECT_LOG"
diff --git a/git-compat-util.h b/git-compat-util.h
index e955bb5..96d8881 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -85,13 +85,14 @@
 #define _NETBSD_SOURCE 1
 #define _SGI_SOURCE 1
 
-#ifdef WIN32 /* Both MinGW and MSVC */
+#if defined(WIN32) && !defined(__CYGWIN__) /* Both MinGW and MSVC */
 # if defined (_MSC_VER)
 #  define _WIN32_WINNT 0x0502
 # endif
 #define WIN32_LEAN_AND_MEAN  /* stops windows.h including winsock.h */
 #include <winsock2.h>
 #include <windows.h>
+#define GIT_WINDOWS_NATIVE
 #endif
 
 #include <unistd.h>
@@ -127,6 +128,7 @@
 #else
 #include <poll.h>
 #endif
+
 #if defined(__MINGW32__)
 /* pull in Windows compatibility stuff */
 #include "compat/mingw.h"
@@ -163,12 +165,10 @@
 typedef long intptr_t;
 typedef unsigned long uintptr_t;
 #endif
-int get_st_mode_bits(const char *path, int *mode);
 #if defined(__CYGWIN__)
 #undef _XOPEN_SOURCE
 #include <grp.h>
 #define _XOPEN_SOURCE 600
-#include "compat/cygwin.h"
 #else
 #undef _ALL_SOURCE /* AIX 5.3L defines a struct list with _ALL_SOURCE. */
 #include <grp.h>
@@ -295,6 +295,13 @@
 #endif
 #endif
 
+/* The sentinel attribute is valid from gcc version 4.0 */
+#if defined(__GNUC__) && (__GNUC__ >= 4)
+#define LAST_ARG_MUST_BE_NULL __attribute__((sentinel))
+#else
+#define LAST_ARG_MUST_BE_NULL
+#endif
+
 #include "compat/bswap.h"
 
 #ifdef USE_WILDMATCH
@@ -692,8 +699,9 @@
  * Call access(2), but warn for any error except "missing file"
  * (ENOENT or ENOTDIR).
  */
-int access_or_warn(const char *path, int mode);
-int access_or_die(const char *path, int mode);
+#define ACCESS_EACCES_OK (1U << 0)
+int access_or_warn(const char *path, int mode, unsigned flag);
+int access_or_die(const char *path, int mode, unsigned flag);
 
 /* Warn on an inaccessible file that ought to be accessible */
 void warn_on_inaccessible(const char *path);
diff --git a/git-difftool.perl b/git-difftool.perl
index 6780292..e57d3d12 100755
--- a/git-difftool.perl
+++ b/git-difftool.perl
@@ -85,11 +85,13 @@
 
 sub use_wt_file
 {
-	my ($repo, $workdir, $file, $sha1, $symlinks) = @_;
+	my ($repo, $workdir, $file, $sha1) = @_;
 	my $null_sha1 = '0' x 40;
 
-	if ($sha1 ne $null_sha1 and not $symlinks) {
-		return 0;
+	if (! -e "$workdir/$file") {
+		# If the file doesn't exist in the working tree, we cannot
+		# use it.
+		return (0, $null_sha1);
 	}
 
 	my $wt_sha1 = $repo->command_oneline('hash-object', "$workdir/$file");
@@ -207,8 +209,7 @@
 
 		if ($rmode ne $null_mode) {
 			my ($use, $wt_sha1) = use_wt_file($repo, $workdir,
-							  $dst_path, $rsha1,
-							  $symlinks);
+							  $dst_path, $rsha1);
 			if ($use) {
 				push @working_tree, $dst_path;
 				$wtindex .= "$rmode $wt_sha1\t$dst_path\0";
diff --git a/git-gui/GIT-VERSION-GEN b/git-gui/GIT-VERSION-GEN
index 49b62ea..0a1f8d4 100755
--- a/git-gui/GIT-VERSION-GEN
+++ b/git-gui/GIT-VERSION-GEN
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=0.17.GITGUI
+DEF_VER=0.18.GITGUI
 
 LF='
 '
diff --git a/git-gui/Makefile b/git-gui/Makefile
index e22ba5c..e9c2bc3 100644
--- a/git-gui/Makefile
+++ b/git-gui/Makefile
@@ -254,7 +254,7 @@
 	  auto_mkindex lib '*.tcl' \
 	| $(TCL_PATH) $(QUIET_2DEVNULL); then : ok; \
 	else \
-	 echo 1>&2 "    * $(TCL_PATH) failed; using unoptimized loading"; \
+	 echo >&2 "    * $(TCL_PATH) failed; using unoptimized loading"; \
 	 rm -f $@ ; \
 	 echo '# Autogenerated by git-gui Makefile' >$@ && \
 	 echo >>$@ && \
@@ -274,8 +274,8 @@
 GIT-GUI-VARS: FORCE
 	@VARS='$(TRACK_VARS)'; \
 	if test x"$$VARS" != x"`cat $@ 2>/dev/null`" ; then \
-		echo 1>&2 "    * new locations or Tcl/Tk interpreter"; \
-		echo 1>$@ "$$VARS"; \
+		echo >&2 "    * new locations or Tcl/Tk interpreter"; \
+		echo >$@ "$$VARS"; \
 	fi
 
 ifdef GITGUI_MACOSXAPP
diff --git a/git-gui/git-gui.sh b/git-gui/git-gui.sh
index 89f636f..153f85d 100755
--- a/git-gui/git-gui.sh
+++ b/git-gui/git-gui.sh
@@ -137,6 +137,20 @@
 
 ######################################################################
 ##
+## On Mac, bring the current Wish process window to front
+
+if {[tk windowingsystem] eq "aqua"} {
+	catch {
+		exec osascript -e [format {
+			tell application "System Events"
+				set frontmost of processes whose unix id is %d to true
+			end tell
+		} [pid]]
+	}
+}
+
+######################################################################
+##
 ## read only globals
 
 set _appname {Git Gui}
@@ -3003,18 +3017,11 @@
 	set jump_spec {}
 	set is_path 0
 	foreach a $argv {
-		if {[file exists $a]} {
-			if {$path ne {}} usage
-			set path [normalize_relpath $a]
-			break
-		} elseif {[file exists $_prefix$a]} {
-			if {$path ne {}} usage
-			set path [normalize_relpath $_prefix$a]
-			break
-		}
+		set p [file join $_prefix $a]
 
-		if {$is_path} {
+		if {$is_path || [file exists $p]} {
 			if {$path ne {}} usage
+			set path [normalize_relpath $p]
 			break
 		} elseif {$a eq {--}} {
 			if {$path ne {}} {
diff --git a/git-gui/lib/choose_repository.tcl b/git-gui/lib/choose_repository.tcl
index 657f7d5..ee58981 100644
--- a/git-gui/lib/choose_repository.tcl
+++ b/git-gui/lib/choose_repository.tcl
@@ -286,7 +286,9 @@
 	destroy $w_body
 	if {![winfo exists $w_next]} {
 		${NS}::button $w_next -default active
-		pack $w_next -side right -padx 5 -before $w_quit
+		set pos -before
+		if {[tk windowingsystem] eq "win32"} { set pos -after }
+		pack $w_next -side right -padx 5 $pos $w_quit
 	}
 	_do_$action $this
 }
diff --git a/git-gui/lib/diff.tcl b/git-gui/lib/diff.tcl
index ec44055..30d9a79 100644
--- a/git-gui/lib/diff.tcl
+++ b/git-gui/lib/diff.tcl
@@ -764,8 +764,15 @@
 				# context line
 				set ln [$ui_diff get $i_l $next_l]
 				set patch "$patch$pre_context$ln"
-				set n [expr $n+1]
-				set m [expr $m+1]
+				# Skip the "\ No newline at end of
+				# file". Depending on the locale setting
+				# we don't know what this line looks
+				# like exactly. The only thing we do
+				# know is that it starts with "\ "
+				if {![string match {\\ *} $ln]} {
+					set n [expr $n+1]
+					set m [expr $m+1]
+				}
 				set pre_context {}
 			} elseif {$c1 eq $to_context} {
 				# turn change line into context line
diff --git a/git-gui/lib/mergetool.tcl b/git-gui/lib/mergetool.tcl
index 3c8e73b..120bc40 100644
--- a/git-gui/lib/mergetool.tcl
+++ b/git-gui/lib/mergetool.tcl
@@ -189,9 +189,9 @@
 	}
 	bc3 {
 		if {$base_stage ne {}} {
-			set cmdline [list "$merge_tool_path" "$LOCAL" "$REMOTE" "$BASE" -mergeoutput="$MERGED"]
+			set cmdline [list "$merge_tool_path" "$LOCAL" "$REMOTE" "$BASE" "-mergeoutput=$MERGED"]
 		} else {
-			set cmdline [list "$merge_tool_path" "$LOCAL" "$REMOTE" -mergeoutput="$MERGED"]
+			set cmdline [list "$merge_tool_path" "$LOCAL" "$REMOTE" "-mergeoutput=$MERGED"]
 		}
 	}
 	ecmerge {
diff --git a/git-gui/lib/remote.tcl b/git-gui/lib/remote.tcl
index 5e4e7f4..4e5c784 100644
--- a/git-gui/lib/remote.tcl
+++ b/git-gui/lib/remote.tcl
@@ -245,7 +245,8 @@
 	set prune_m $remote_m.prune
 	if {$have_remote > 1} {
 		make_sure_remote_submenues_exist $remote_m
-		if {[$fetch_m entrycget end -label] ne "All"} {
+		if {[$fetch_m type end] eq "command" \
+			&& [$fetch_m entrycget end -label] ne "All"} {
 
 			$fetch_m insert end separator
 			$fetch_m insert end command \
@@ -259,7 +260,8 @@
 		}
 	} else {
 		if {[winfo exists $fetch_m]} {
-			if {[$fetch_m entrycget end -label] eq "All"} {
+			if {[$fetch_m type end] eq "command" \
+				&& [$fetch_m entrycget end -label] eq "All"} {
 
 				delete_from_menu $fetch_m end
 				delete_from_menu $fetch_m end
diff --git a/git-gui/po/fr.po b/git-gui/po/fr.po
index 40441db..0aff186 100644
--- a/git-gui/po/fr.po
+++ b/git-gui/po/fr.po
@@ -1139,7 +1139,7 @@
 
 #: lib/choose_repository.tcl:514
 msgid "Full Copy (Slower, Redundant Backup)"
-msgstr "Copy complète (plus lent, sauvegarde redondante)"
+msgstr "Copie complète (plus lent, sauvegarde redondante)"
 
 #: lib/choose_repository.tcl:520
 msgid "Shared (Fastest, Not Recommended, No Backup)"
diff --git a/git-mergetool--lib.sh b/git-mergetool--lib.sh
index e338be5..feee6a4 100644
--- a/git-mergetool--lib.sh
+++ b/git-mergetool--lib.sh
@@ -114,10 +114,37 @@
 	test -n "$cmd"
 }
 
+setup_user_tool () {
+	merge_tool_cmd=$(get_merge_tool_cmd "$tool")
+	test -n "$merge_tool_cmd" || return 1
+
+	diff_cmd () {
+		( eval $merge_tool_cmd )
+		status=$?
+		return $status
+	}
+
+	merge_cmd () {
+		trust_exit_code=$(git config --bool \
+			"mergetool.$1.trustExitCode" || echo false)
+		if test "$trust_exit_code" = "false"
+		then
+			touch "$BACKUP"
+			( eval $merge_tool_cmd )
+			status=$?
+			check_unchanged
+		else
+			( eval $merge_tool_cmd )
+			status=$?
+		fi
+		return $status
+	}
+}
+
 setup_tool () {
 	tool="$1"
 
-	# Fallback definitions, to be overriden by tools.
+	# Fallback definitions, to be overridden by tools.
 	can_merge () {
 		return 0
 	}
@@ -142,15 +169,15 @@
 
 	if ! test -f "$MERGE_TOOLS_DIR/$tool"
 	then
-		# Use a special return code for this case since we want to
-		# source "defaults" even when an explicit tool path is
-		# configured since the user can use that to override the
-		# default path in the scriptlet.
-		return 2
+		setup_user_tool
+		return $?
 	fi
 
 	# Load the redefined functions
 	. "$MERGE_TOOLS_DIR/$tool"
+	# Now let the user override the default command for the tool.  If
+	# they have not done so then this will return 1 which we ignore.
+	setup_user_tool
 
 	if merge_mode && ! can_merge
 	then
@@ -187,20 +214,7 @@
 	status=0
 
 	# Bring tool-specific functions into scope
-	setup_tool "$1"
-	exitcode=$?
-	case $exitcode in
-	0)
-		:
-		;;
-	2)
-		# The configured tool is not a built-in tool.
-		test -n "$merge_tool_path" || return 1
-		;;
-	*)
-		return $exitcode
-		;;
-	esac
+	setup_tool "$1" || return 1
 
 	if merge_mode
 	then
@@ -213,38 +227,12 @@
 
 # Run a either a configured or built-in diff tool
 run_diff_cmd () {
-	merge_tool_cmd=$(get_merge_tool_cmd "$1")
-	if test -n "$merge_tool_cmd"
-	then
-		( eval $merge_tool_cmd )
-		status=$?
-		return $status
-	else
-		diff_cmd "$1"
-	fi
+	diff_cmd "$1"
 }
 
 # Run a either a configured or built-in merge tool
 run_merge_cmd () {
-	merge_tool_cmd=$(get_merge_tool_cmd "$1")
-	if test -n "$merge_tool_cmd"
-	then
-		trust_exit_code=$(git config --bool \
-			"mergetool.$1.trustExitCode" || echo false)
-		if test "$trust_exit_code" = "false"
-		then
-			touch "$BACKUP"
-			( eval $merge_tool_cmd )
-			status=$?
-			check_unchanged
-		else
-			( eval $merge_tool_cmd )
-			status=$?
-		fi
-		return $status
-	else
-		merge_cmd "$1"
-	fi
+	merge_cmd "$1"
 }
 
 list_merge_tool_candidates () {
diff --git a/git-p4.py b/git-p4.py
index 911bbce..31e71ff 100755
--- a/git-p4.py
+++ b/git-p4.py
@@ -1786,7 +1786,7 @@
             missingGitTags = gitTags - p4Labels
             self.exportGitTags(missingGitTags)
 
-        # exit with error unless everything applied perfecly
+        # exit with error unless everything applied perfectly
         if len(commits) != len(applied):
                 sys.exit(1)
 
@@ -3168,7 +3168,7 @@
         if os.system("git update-index --refresh") != 0:
             die("Some files in your working directory are modified and different than what is in your index. You can use git update-index <filename> to bring the index up-to-date or stash away all your changes with git stash.");
         if len(read_pipe("git diff-index HEAD --")) > 0:
-            die("You have uncommited changes. Please commit them before rebasing or stash them away with git stash.");
+            die("You have uncommitted changes. Please commit them before rebasing or stash them away with git stash.");
 
         [upstream, settings] = findUpstreamBranchPoint()
         if len(upstream) == 0:
diff --git a/git-pull.sh b/git-pull.sh
index 638aabb..f0df41c 100755
--- a/git-pull.sh
+++ b/git-pull.sh
@@ -5,7 +5,7 @@
 # Fetch one or more remote refs and merge it/them into the current HEAD.
 
 USAGE='[-n | --no-stat] [--[no-]commit] [--[no-]squash] [--[no-]ff] [-s strategy]... [<fetch-options>] <repo> <head>...'
-LONG_USAGE='Fetch one or more remote refs and merge it/them into the current HEAD.'
+LONG_USAGE='Fetch one or more remote refs and integrate it/them with the current HEAD.'
 SUBDIRECTORY_OK=Yes
 OPTIONS_SPEC=
 . git-sh-setup
@@ -266,10 +266,17 @@
 	;;
 esac
 
+# Pulling into unborn branch: a shorthand for branching off
+# FETCH_HEAD, for lazy typers.
 if test -z "$orig_head"
 then
-	git update-ref -m "initial pull" HEAD $merge_head "$curr_head" &&
-	git read-tree -m -u HEAD || exit 1
+	# Two-way merge: we claim the index is based on an empty tree,
+	# and try to fast-forward to HEAD.  This ensures we will not
+	# lose index/worktree changes that the user already made on
+	# the unborn branch.
+	empty_tree=4b825dc642cb6eb9a060e54bf8d69288fbee4904
+	git read-tree -m -u $empty_tree $merge_head &&
+	git update-ref -m "initial pull" HEAD $merge_head "$curr_head"
 	exit
 fi
 
diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index f953d8d..83d6d46 100644
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -80,6 +80,18 @@
 rewritten_list="$state_dir"/rewritten-list
 rewritten_pending="$state_dir"/rewritten-pending
 
+strategy_args=
+if test -n "$do_merge"
+then
+	strategy_args=${strategy:+--strategy=$strategy}
+	eval '
+		for strategy_opt in '"$strategy_opts"'
+		do
+			strategy_args="$strategy_args -X$(git rev-parse --sq-quote "${strategy_opt#--}")"
+		done
+	'
+fi
+
 GIT_CHERRY_PICK_HELP="$resolvemsg"
 export GIT_CHERRY_PICK_HELP
 
@@ -239,7 +251,7 @@
 
 	test -d "$rewritten" &&
 		pick_one_preserving_merges "$@" && return
-	output git cherry-pick $empty_args $ff "$@"
+	output eval git cherry-pick "$strategy_args" $empty_args $ff "$@"
 }
 
 pick_one_preserving_merges () {
@@ -340,9 +352,8 @@
 			msg_content="$(commit_message $sha1)"
 			# No point in merging the first parent, that's HEAD
 			new_parents=${new_parents# $first_parent}
-			if ! do_with_author output \
-				git merge --no-ff ${strategy:+-s $strategy} -m \
-					"$msg_content" $new_parents
+			if ! do_with_author output eval \
+			'git merge --no-ff $strategy_args -m "$msg_content" $new_parents'
 			then
 				printf "%s\n" "$msg_content" > "$GIT_DIR"/MERGE_MSG
 				die_with_patch $sha1 "Error redoing merge $sha1"
@@ -350,7 +361,7 @@
 			echo "$sha1 $(git rev-parse HEAD^0)" >> "$rewritten_list"
 			;;
 		*)
-			output git cherry-pick "$@" ||
+			output eval git cherry-pick "$strategy_args" "$@" ||
 				die_with_patch $sha1 "Could not pick $sha1"
 			;;
 		esac
@@ -689,8 +700,22 @@
 		case "$message" in
 		"squash! "*|"fixup! "*)
 			action="${message%%!*}"
-			rest="${message#*! }"
-			echo "$sha1 $action $rest"
+			rest=$message
+			prefix=
+			# skip all squash! or fixup! (but save for later)
+			while :
+			do
+				case "$rest" in
+				"squash! "*|"fixup! "*)
+					prefix="$prefix${rest%%!*},"
+					rest="${rest#*! }"
+					;;
+				*)
+					break
+					;;
+				esac
+			done
+			echo "$sha1 $action $prefix $rest"
 			# if it's a single word, try to resolve to a full sha1 and
 			# emit a second copy. This allows us to match on both message
 			# and on sha1 prefix
@@ -699,7 +724,7 @@
 				if test -n "$fullsha"; then
 					# prefix the action to uniquely identify this line as
 					# intended for full sha1 match
-					echo "$sha1 +$action $fullsha"
+					echo "$sha1 +$action $prefix $fullsha"
 				fi
 			fi
 		esac
@@ -714,7 +739,7 @@
 		esac
 		printf '%s\n' "$pick $sha1 $message"
 		used="$used$sha1 "
-		while read -r squash action msg_content
+		while read -r squash action msg_prefix msg_content
 		do
 			case " $used" in
 			*" $squash "*) continue ;;
@@ -730,7 +755,8 @@
 				case "$message" in "$msg_content"*) emit=1;; esac ;;
 			esac
 			if test $emit = 1; then
-				printf '%s\n' "$action $squash $action! $msg_content"
+				real_prefix=$(echo "$msg_prefix" | sed "s/,/! /g")
+				printf '%s\n' "$action $squash ${real_prefix}$msg_content"
 				used="$used$squash "
 			fi
 		done <"$1.sq"
@@ -838,8 +864,11 @@
 
 if test ! -z "$switch_to"
 then
+	GIT_REFLOG_ACTION="$GIT_REFLOG_ACTION: checkout $switch_to"
 	output git checkout "$switch_to" -- ||
-		die "Could not checkout $switch_to"
+	die "Could not checkout $switch_to"
+
+	comment_for_reflog start
 fi
 
 orig_head=$(git rev-parse --verify HEAD) || die "No HEAD?"
@@ -981,6 +1010,7 @@
 
 test -d "$rewritten" || test -n "$force_rebase" || skip_unnecessary_picks
 
+GIT_REFLOG_ACTION="$GIT_REFLOG_ACTION: checkout $onto_name"
 output git checkout $onto || die_abort "could not detach HEAD"
 git update-ref ORIG_HEAD $orig_head
 do_rest
diff --git a/git-rebase--merge.sh b/git-rebase--merge.sh
index b10f2cf..16d1817 100644
--- a/git-rebase--merge.sh
+++ b/git-rebase--merge.sh
@@ -96,7 +96,6 @@
 			"$GIT_DIR"/hooks/post-rewrite rebase <"$state_dir"/rewritten
 		fi
 	fi
-	rm -r "$state_dir"
 	say All done.
 }
 
@@ -110,7 +109,7 @@
 		continue_merge
 	done
 	finish_rb_merge
-	exit
+	return
 	;;
 skip)
 	read_state
@@ -122,7 +121,7 @@
 		continue_merge
 	done
 	finish_rb_merge
-	exit
+	return
 	;;
 esac
 
diff --git a/git-rebase.sh b/git-rebase.sh
index 7ab6434..226752f 100755
--- a/git-rebase.sh
+++ b/git-rebase.sh
@@ -13,6 +13,7 @@
  Available options are
 v,verbose!         display a diffstat of what changed upstream
 q,quiet!           be quiet. implies --no-stat
+autostash!         automatically stash/stash pop before and after
 onto=!             rebase onto given branch instead of upstream
 p,preserve-merges! try to recreate merges instead of ignoring them
 s,strategy=!       use the given merge strategy
@@ -64,6 +65,7 @@
 verbose=
 diffstat=
 test "$(git config --bool rebase.stat)" = true && diffstat=t
+autostash="$(git config --bool rebase.autostash || echo false)"
 git_am_opt=
 rebase_root=
 force_rebase=
@@ -82,6 +84,8 @@
 test "$(git config --bool rebase.autosquash)" = "true" && autosquash=t
 
 read_basic_state () {
+	test -f "$state_dir/head-name" &&
+	test -f "$state_dir/onto" &&
 	head_name=$(cat "$state_dir"/head-name) &&
 	onto=$(cat "$state_dir"/onto) &&
 	# We always write to orig-head, but interactive rebase used to write to
@@ -143,6 +147,26 @@
 	esac
 }
 
+finish_rebase () {
+	if test -f "$state_dir/autostash"
+	then
+		stash_sha1=$(cat "$state_dir/autostash")
+		if git stash apply $stash_sha1 2>&1 >/dev/null
+		then
+			echo "$(gettext 'Applied autostash.')"
+		else
+			git stash store -m "autostash" -q $stash_sha1 ||
+			die "$(eval_gettext "Cannot store \$stash_sha1")"
+			gettext 'Applying autostash resulted in conflicts.
+Your changes are safe in the stash.
+You can run "git stash pop" or "git stash drop" at any time.
+'
+		fi
+	fi
+	git gc --auto &&
+	rm -rf "$state_dir"
+}
+
 run_specific_rebase_internal () {
 	if [ "$interactive_rebase" = implied ]; then
 		GIT_EDITOR=:
@@ -162,8 +186,7 @@
 	ret=$?
 	if test $ret -eq 0
 	then
-		git gc --auto &&
-		rm -rf "$state_dir"
+		finish_rebase
 	fi
 	exit $ret
 }
@@ -257,6 +280,9 @@
 	--stat)
 		diffstat=t
 		;;
+	--autostash)
+		autostash=true
+		;;
 	-v)
 		verbose=t
 		diffstat=t
@@ -357,7 +383,7 @@
 		;;
 	esac
 	output git reset --hard $orig_head
-	rm -r "$state_dir"
+	finish_rebase
 	exit
 	;;
 edit-todo)
@@ -416,7 +442,7 @@
 		shift
 		;;
 	esac
-	upstream=`git rev-parse --verify "${upstream_name}^0"` ||
+	upstream=$(peel_committish "${upstream_name}") ||
 	die "$(eval_gettext "invalid upstream \$upstream_name")"
 	upstream_arg="$upstream_name"
 else
@@ -452,7 +478,7 @@
 	fi
 	;;
 *)
-	onto=$(git rev-parse --verify "${onto_name}^0") ||
+	onto=$(peel_committish "$onto_name") ||
 	die "$(eval_gettext "Does not point to a valid commit: \$onto_name")"
 	;;
 esac
@@ -496,6 +522,18 @@
 	;;
 esac
 
+if test "$autostash" = true && ! (require_clean_work_tree) 2>/dev/null
+then
+	stash_sha1=$(git stash create "autostash") ||
+	die "$(gettext 'Cannot autostash')"
+
+	mkdir -p "$state_dir" &&
+	echo $stash_sha1 >"$state_dir/autostash" &&
+	stash_abbrev=$(git rev-parse --short $stash_sha1) &&
+	echo "$(eval_gettext 'Created autostash: $stash_abbrev')" &&
+	git reset --hard
+fi
+
 require_clean_work_tree "rebase" "$(gettext "Please commit or stash them.")"
 
 # Now we are rebasing commits $upstream..$orig_head (or with --root,
@@ -513,8 +551,11 @@
 	if test -z "$force_rebase"
 	then
 		# Lazily switch to the target branch if needed...
-		test -z "$switch_to" || git checkout "$switch_to" --
+		test -z "$switch_to" ||
+		GIT_REFLOG_ACTION="$GIT_REFLOG_ACTION: checkout $switch_to" \
+			git checkout "$switch_to" --
 		say "$(eval_gettext "Current branch \$branch_name is up to date.")"
+		finish_rebase
 		exit 0
 	else
 		say "$(eval_gettext "Current branch \$branch_name is up to date, rebase forced.")"
@@ -538,7 +579,9 @@
 
 # Detach HEAD and reset the tree
 say "$(gettext "First, rewinding head to replay your work on top of it...")"
-git checkout -q "$onto^0" || die "could not detach HEAD"
+
+GIT_REFLOG_ACTION="$GIT_REFLOG_ACTION: checkout $onto_name" \
+	git checkout -q "$onto^0" || die "could not detach HEAD"
 git update-ref ORIG_HEAD $orig_head
 
 # If the $onto is a proper descendant of the tip of the branch, then
@@ -547,6 +590,7 @@
 then
 	say "$(eval_gettext "Fast-forwarded \$branch_name to \$onto_name.")"
 	move_to_original_branch
+	finish_rebase
 	exit 0
 fi
 
diff --git a/git-remote-testgit b/git-remote-testgit
deleted file mode 100755
index e7ed3a3..0000000
--- a/git-remote-testgit
+++ /dev/null
@@ -1,91 +0,0 @@
-#!/usr/bin/env bash
-# Copyright (c) 2012 Felipe Contreras
-
-alias=$1
-url=$2
-
-dir="$GIT_DIR/testgit/$alias"
-prefix="refs/testgit/$alias"
-
-default_refspec="refs/heads/*:${prefix}/heads/*"
-
-refspec="${GIT_REMOTE_TESTGIT_REFSPEC-$default_refspec}"
-
-test -z "$refspec" && prefix="refs"
-
-export GIT_DIR="$url/.git"
-
-mkdir -p "$dir"
-
-if test -z "$GIT_REMOTE_TESTGIT_NO_MARKS"
-then
-	gitmarks="$dir/git.marks"
-	testgitmarks="$dir/testgit.marks"
-	test -e "$gitmarks" || >"$gitmarks"
-	test -e "$testgitmarks" || >"$testgitmarks"
-	testgitmarks_args=( "--"{import,export}"-marks=$testgitmarks" )
-fi
-
-while read line
-do
-	case $line in
-	capabilities)
-		echo 'import'
-		echo 'export'
-		test -n "$refspec" && echo "refspec $refspec"
-		if test -n "$gitmarks"
-		then
-			echo "*import-marks $gitmarks"
-			echo "*export-marks $gitmarks"
-		fi
-		test -n "$GIT_REMOTE_TESTGIT_SIGNED_TAGS" && echo "signed-tags"
-		echo
-		;;
-	list)
-		git for-each-ref --format='? %(refname)' 'refs/heads/'
-		head=$(git symbolic-ref HEAD)
-		echo "@$head HEAD"
-		echo
-		;;
-	import*)
-		# read all import lines
-		while true
-		do
-			ref="${line#* }"
-			refs="$refs $ref"
-			read line
-			test "${line%% *}" != "import" && break
-		done
-
-		if test -n "$gitmarks"
-		then
-			echo "feature import-marks=$gitmarks"
-			echo "feature export-marks=$gitmarks"
-		fi
-		echo "feature done"
-		git fast-export "${testgitmarks_args[@]}" $refs |
-		sed -e "s#refs/heads/#${prefix}/heads/#g"
-		echo "done"
-		;;
-	export)
-		before=$(git for-each-ref --format='%(refname) %(objectname)')
-
-		git fast-import "${testgitmarks_args[@]}" --quiet
-
-		after=$(git for-each-ref --format='%(refname) %(objectname)')
-
-		# figure out which refs were updated
-		join -e 0 -o '0 1.2 2.2' -a 2 <(echo "$before") <(echo "$after") |
-		while read ref a b
-		do
-			test $a == $b && continue
-			echo "ok $ref"
-		done
-
-		echo
-		;;
-	'')
-		exit
-		;;
-	esac
-done
diff --git a/git-remote-testgit.sh b/git-remote-testgit.sh
new file mode 100755
index 0000000..2109070
--- /dev/null
+++ b/git-remote-testgit.sh
@@ -0,0 +1,121 @@
+#!/bin/sh
+# Copyright (c) 2012 Felipe Contreras
+
+alias=$1
+url=$2
+
+dir="$GIT_DIR/testgit/$alias"
+prefix="refs/testgit/$alias"
+
+default_refspec="refs/heads/*:${prefix}/heads/*"
+
+refspec="${GIT_REMOTE_TESTGIT_REFSPEC-$default_refspec}"
+
+test -z "$refspec" && prefix="refs"
+
+export GIT_DIR="$url/.git"
+
+mkdir -p "$dir"
+
+if test -z "$GIT_REMOTE_TESTGIT_NO_MARKS"
+then
+	gitmarks="$dir/git.marks"
+	testgitmarks="$dir/testgit.marks"
+	test -e "$gitmarks" || >"$gitmarks"
+	test -e "$testgitmarks" || >"$testgitmarks"
+fi
+
+while read line
+do
+	case $line in
+	capabilities)
+		echo 'import'
+		echo 'export'
+		test -n "$refspec" && echo "refspec $refspec"
+		if test -n "$gitmarks"
+		then
+			echo "*import-marks $gitmarks"
+			echo "*export-marks $gitmarks"
+		fi
+		test -n "$GIT_REMOTE_TESTGIT_SIGNED_TAGS" && echo "signed-tags"
+		echo
+		;;
+	list)
+		git for-each-ref --format='? %(refname)' 'refs/heads/'
+		head=$(git symbolic-ref HEAD)
+		echo "@$head HEAD"
+		echo
+		;;
+	import*)
+		# read all import lines
+		while true
+		do
+			ref="${line#* }"
+			refs="$refs $ref"
+			read line
+			test "${line%% *}" != "import" && break
+		done
+
+		if test -n "$gitmarks"
+		then
+			echo "feature import-marks=$gitmarks"
+			echo "feature export-marks=$gitmarks"
+		fi
+
+		if test -n "$GIT_REMOTE_TESTGIT_FAILURE"
+		then
+			echo "feature done"
+			exit 1
+		fi
+
+		echo "feature done"
+		git fast-export \
+			${testgitmarks:+"--import-marks=$testgitmarks"} \
+			${testgitmarks:+"--export-marks=$testgitmarks"} \
+			$refs |
+		sed -e "s#refs/heads/#${prefix}/heads/#g"
+		echo "done"
+		;;
+	export)
+		if test -n "$GIT_REMOTE_TESTGIT_FAILURE"
+		then
+			# consume input so fast-export doesn't get SIGPIPE;
+			# git would also notice that case, but we want
+			# to make sure we are exercising the later
+			# error checks
+			while read line; do
+				test "done" = "$line" && break
+			done
+			exit 1
+		fi
+
+		before=$(git for-each-ref --format=' %(refname) %(objectname) ')
+
+		git fast-import \
+			${testgitmarks:+"--import-marks=$testgitmarks"} \
+			${testgitmarks:+"--export-marks=$testgitmarks"} \
+			--quiet
+
+		# figure out which refs were updated
+		git for-each-ref --format='%(refname) %(objectname)' |
+		while read ref a
+		do
+			case "$before" in
+			*" $ref $a "*)
+				continue ;;	# unchanged
+			esac
+			if test -z "$GIT_REMOTE_TESTGIT_PUSH_ERROR"
+			then
+				echo "ok $ref"
+			else
+				echo "error $ref $GIT_REMOTE_TESTGIT_PUSH_ERROR"
+			fi
+		done
+
+		echo
+		;;
+	'')
+		exit
+		;;
+	esac
+done
diff --git a/git-request-pull.sh b/git-request-pull.sh
index d566015..ebf1269 100755
--- a/git-request-pull.sh
+++ b/git-request-pull.sh
@@ -51,8 +51,18 @@
 tag_name=$(git describe --exact "$head^0" 2>/dev/null)
 
 test -n "$base" && test -n "$url" || usage
-baserev=$(git rev-parse --verify "$base"^0) &&
-headrev=$(git rev-parse --verify "$head"^0) || exit
+
+baserev=$(git rev-parse --verify --quiet "$base"^0)
+if test -z "$baserev"
+then
+    die "fatal: Not a valid revision: $base"
+fi
+
+headrev=$(git rev-parse --verify --quiet "$head"^0)
+if test -z "$headrev"
+then
+    die "fatal: Not a valid revision: $head"
+fi
 
 merge_base=$(git merge-base $baserev $headrev) ||
 die "fatal: No commits in common between $base and $head"
diff --git a/git-send-email.perl b/git-send-email.perl
index bd13cc8..3782c3b 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -69,6 +69,9 @@
     --smtp-pass             <str>  * Password for SMTP-AUTH; not necessary.
     --smtp-encryption       <str>  * tls or ssl; anything else disables.
     --smtp-ssl                     * Deprecated. Use '--smtp-encryption ssl'.
+    --smtp-ssl-cert-path    <str>  * Path to ca-certificates (either directory or file).
+                                     Pass an empty string to disable certificate
+                                     verification.
     --smtp-domain           <str>  * The domain name sent to HELO/EHLO handshake
     --smtp-debug            <0|1>  * Disable, enable Net::SMTP debug.
 
@@ -194,7 +197,7 @@
 my ($thread, $chain_reply_to, $suppress_from, $signed_off_by_cc);
 my ($to_cmd, $cc_cmd);
 my ($smtp_server, $smtp_server_port, @smtp_server_options);
-my ($smtp_authuser, $smtp_encryption);
+my ($smtp_authuser, $smtp_encryption, $smtp_ssl_cert_path);
 my ($identity, $aliasfiletype, @alias_files, $smtp_domain);
 my ($validate, $confirm);
 my (@suppress_cc);
@@ -203,11 +206,9 @@
 
 my ($debug_net_smtp) = 0;		# Net::SMTP, see send_message()
 
-my $not_set_by_user = "true but not set by the user";
-
 my %config_bool_settings = (
     "thread" => [\$thread, 1],
-    "chainreplyto" => [\$chain_reply_to, $not_set_by_user],
+    "chainreplyto" => [\$chain_reply_to, 0],
     "suppressfrom" => [\$suppress_from, undef],
     "signedoffbycc" => [\$signed_off_by_cc, undef],
     "signedoffcc" => [\$signed_off_by_cc, undef],      # Deprecated
@@ -222,6 +223,7 @@
     "smtpserveroption" => \@smtp_server_options,
     "smtpuser" => \$smtp_authuser,
     "smtppass" => \$smtp_authpass,
+    "smtpsslcertpath" => \$smtp_ssl_cert_path,
     "smtpdomain" => \$smtp_domain,
     "to" => \@initial_to,
     "tocmd" => \$to_cmd,
@@ -241,19 +243,6 @@
     "aliasesfile" => \@alias_files,
 );
 
-# Help users prepare for 1.7.0
-sub chain_reply_to {
-	if (defined $chain_reply_to &&
-	    $chain_reply_to eq $not_set_by_user) {
-		print STDERR
-		    "In git 1.7.0, the default has changed to --no-chain-reply-to\n" .
-		    "Set sendemail.chainreplyto configuration variable to true if\n" .
-		    "you want to keep --chain-reply-to as your default.\n";
-		$chain_reply_to = 0;
-	}
-	return $chain_reply_to;
-}
-
 # Handle Uncouth Termination
 sub signal_handler {
 
@@ -302,6 +291,7 @@
 		    "smtp-pass:s" => \$smtp_authpass,
 		    "smtp-ssl" => sub { $smtp_encryption = 'ssl' },
 		    "smtp-encryption=s" => \$smtp_encryption,
+		    "smtp-ssl-cert-path" => \$smtp_ssl_cert_path,
 		    "smtp-debug:i" => \$debug_net_smtp,
 		    "smtp-domain:s" => \$smtp_domain,
 		    "identity=s" => \$identity,
@@ -760,6 +750,11 @@
 	$sender = $repoauthor || $repocommitter || '';
 }
 
+# $sender could be an already sanitized address
+# (e.g. sendemail.from could be manually sanitized by user).
+# But it's a no-op to run sanitize_address on an already sanitized address.
+$sender = sanitize_address($sender);
+
 my $prompting = 0;
 if (!@initial_to && !defined $to_cmd) {
 	my $to = ask("Who should the emails be sent to (if any)? ",
@@ -1089,6 +1084,34 @@
 	return $auth;
 }
 
+sub ssl_verify_params {
+	eval {
+		require IO::Socket::SSL;
+		IO::Socket::SSL->import(qw/SSL_VERIFY_PEER SSL_VERIFY_NONE/);
+	};
+	if ($@) {
+		print STDERR "Not using SSL_VERIFY_PEER due to out-of-date IO::Socket::SSL.\n";
+		return;
+	}
+
+	if (!defined $smtp_ssl_cert_path) {
+		$smtp_ssl_cert_path = "/etc/ssl/certs";
+	}
+
+	if ($smtp_ssl_cert_path eq "") {
+		return (SSL_verify_mode => SSL_VERIFY_NONE());
+	} elsif (-d $smtp_ssl_cert_path) {
+		return (SSL_verify_mode => SSL_VERIFY_PEER(),
+			SSL_ca_path => $smtp_ssl_cert_path);
+	} elsif (-f $smtp_ssl_cert_path) {
+		return (SSL_verify_mode => SSL_VERIFY_PEER(),
+			SSL_ca_file => $smtp_ssl_cert_path);
+	} else {
+		print STDERR "Not using SSL_VERIFY_PEER because the CA path does not exist.\n";
+		return (SSL_verify_mode => SSL_VERIFY_NONE());
+	}
+}
+
 # Returns 1 if the message was sent, and 0 otherwise.
 # In actuality, the whole program dies when there
 # is an error sending a message.
@@ -1113,10 +1136,9 @@
 	if ($cc ne '') {
 		$ccline = "\nCc: $cc";
 	}
-	my $sanitized_sender = sanitize_address($sender);
 	make_message_id() unless defined($message_id);
 
-	my $header = "From: $sanitized_sender
+	my $header = "From: $sender
 To: $to${ccline}
 Subject: $subject
 Date: $date
@@ -1133,7 +1155,7 @@
 	}
 
 	my @sendmail_parameters = ('-i', @recipients);
-	my $raw_from = $sanitized_sender;
+	my $raw_from = $sender;
 	if (defined $envelope_sender && $envelope_sender ne "auto") {
 		$raw_from = $envelope_sender;
 	}
@@ -1194,21 +1216,25 @@
 			$smtp_domain ||= maildomain();
 			$smtp ||= Net::SMTP::SSL->new($smtp_server,
 						      Hello => $smtp_domain,
-						      Port => $smtp_server_port);
+						      Port => $smtp_server_port,
+						      ssl_verify_params());
 		}
 		else {
 			require Net::SMTP;
 			$smtp_domain ||= maildomain();
-			$smtp ||= Net::SMTP->new(smtp_host_string(),
+			$smtp_server_port ||= 25;
+			$smtp ||= Net::SMTP->new($smtp_server,
 						 Hello => $smtp_domain,
-						 Debug => $debug_net_smtp);
+						 Debug => $debug_net_smtp,
+						 Port => $smtp_server_port);
 			if ($smtp_encryption eq 'tls' && $smtp) {
 				require Net::SMTP::SSL;
 				$smtp->command('STARTTLS');
 				$smtp->response();
 				if ($smtp->code == 220) {
-					$smtp = Net::SMTP::SSL->start_SSL($smtp)
-						or die "STARTTLS failed! ".$smtp->message;
+					$smtp = Net::SMTP::SSL->start_SSL($smtp,
+									  ssl_verify_params())
+						or die "STARTTLS failed! ".IO::Socket::SSL::errstr();
 					$smtp_encryption = '';
 					# Send EHLO again to receive fresh
 					# supported commands
@@ -1270,6 +1296,7 @@
 	open my $fh, "<", $t or die "can't open file $t";
 
 	my $author = undef;
+	my $sauthor = undef;
 	my $author_encoding;
 	my $has_content_type;
 	my $body_encoding;
@@ -1308,8 +1335,9 @@
 			}
 			elsif (/^From:\s+(.*)$/i) {
 				($author, $author_encoding) = unquote_rfc2047($1);
+				$sauthor = sanitize_address($author);
 				next if $suppress_cc{'author'};
-				next if $suppress_cc{'self'} and $author eq $sender;
+				next if $suppress_cc{'self'} and $sauthor eq $sender;
 				printf("(mbox) Adding cc: %s from line '%s'\n",
 					$1, $_) unless $quiet;
 				push @cc, $1;
@@ -1323,7 +1351,9 @@
 			}
 			elsif (/^Cc:\s+(.*)$/i) {
 				foreach my $addr (parse_address_line($1)) {
-					if (unquote_rfc2047($addr) eq $sender) {
+					my $qaddr = unquote_rfc2047($addr);
+					my $saddr = sanitize_address($qaddr);
+					if ($saddr eq $sender) {
 						next if ($suppress_cc{'self'});
 					} else {
 						next if ($suppress_cc{'cc'});
@@ -1370,7 +1400,8 @@
 			chomp;
 			my ($what, $c) = ($1, $2);
 			chomp $c;
-			if ($c eq $sender) {
+			my $sc = sanitize_address($c);
+			if ($sc eq $sender) {
 				next if ($suppress_cc{'self'});
 			} else {
 				next if $suppress_cc{'sob'} and $what =~ /Signed-off-by/i;
@@ -1400,7 +1431,7 @@
 		$subject = quote_subject($subject, $auto_8bit_encoding);
 	}
 
-	if (defined $author and $author ne $sender) {
+	if (defined $sauthor and $sauthor ne $sender) {
 		$message = "From: $author\n\n$message";
 		if (defined $author_encoding) {
 			if ($has_content_type) {
@@ -1437,7 +1468,7 @@
 
 	# set up for the next message
 	if ($thread && $message_was_sent &&
-		(chain_reply_to() || !defined $reply_to || length($reply_to) == 0 ||
+		($chain_reply_to || !defined $reply_to || length($reply_to) == 0 ||
 		$message_num == 1)) {
 		$reply_to = $message_id;
 		if (length $references > 0) {
@@ -1454,7 +1485,6 @@
 sub recipients_cmd {
 	my ($prefix, $what, $cmd, $file) = @_;
 
-	my $sanitized_sender = sanitize_address($sender);
 	my @addresses = ();
 	open my $fh, "-|", "$cmd \Q$file\E"
 	    or die "($prefix) Could not execute '$cmd'";
@@ -1462,7 +1492,7 @@
 		$address =~ s/^\s*//g;
 		$address =~ s/\s*$//g;
 		$address = sanitize_address($address);
-		next if ($address eq $sanitized_sender and $suppress_from);
+		next if ($address eq $sender and $suppress_cc{'self'});
 		push @addresses, $address;
 		printf("($prefix) Adding %s: %s from: '%s'\n",
 		       $what, $address, $cmd) unless $quiet;
diff --git a/git-sh-setup.sh b/git-sh-setup.sh
index 2f78359..e15be51 100644
--- a/git-sh-setup.sh
+++ b/git-sh-setup.sh
@@ -53,7 +53,7 @@
 die_with_status () {
 	status=$1
 	shift
-	echo >&2 "$*"
+	printf >&2 '%s\n' "$*"
 	exit "$status"
 }
 
@@ -313,3 +313,15 @@
 	}
 	: ${GIT_OBJECT_DIRECTORY="$GIT_DIR/objects"}
 fi
+
+peel_committish () {
+	case "$1" in
+	:/*)
+		peeltmp=$(git rev-parse --verify "$1") &&
+		git rev-parse --verify "${peeltmp}^0"
+		;;
+	*)
+		git rev-parse --verify "${1}^0"
+		;;
+	esac
+}
diff --git a/git-stash.sh b/git-stash.sh
index bbefdf6..1e541a2 100755
--- a/git-stash.sh
+++ b/git-stash.sh
@@ -156,6 +156,41 @@
 	die "$(gettext "Cannot record working tree state")"
 }
 
+store_stash () {
+	while test $# != 0
+	do
+		case "$1" in
+		-m|--message)
+			shift
+			stash_msg="$1"
+			;;
+		-q|--quiet)
+			quiet=t
+			;;
+		*)
+			break
+			;;
+		esac
+		shift
+	done
+	test $# = 1 ||
+	die "$(eval_gettext "\"$dashless store\" requires one <commit> argument")"
+
+	w_commit="$1"
+	if test -z "$stash_msg"
+	then
+		stash_msg="Created via \"git stash store\"."
+	fi
+
+	# Make sure the reflog for stash is kept.
+	: >>"$GIT_DIR/logs/$ref_stash"
+	git update-ref -m "$stash_msg" $ref_stash $w_commit
+	ret=$?
+	test $ret != 0 && test -z $quiet &&
+	die "$(eval_gettext "Cannot update \$ref_stash with \$w_commit")"
+	return $ret
+}
+
 save_stash () {
 	keep_index=
 	patch_mode=
@@ -227,12 +262,8 @@
 		clear_stash || die "$(gettext "Cannot initialize stash")"
 
 	create_stash "$stash_msg" $untracked
-
-	# Make sure the reflog for stash is kept.
-	: >>"$GIT_DIR/logs/$ref_stash"
-
-	git update-ref -m "$stash_msg" $ref_stash $w_commit ||
-		die "$(gettext "Cannot save the current status")"
+	store_stash -m "$stash_msg" -q $w_commit ||
+	die "$(gettext "Cannot save the current status")"
 	say Saved working directory and index state "$stash_msg"
 
 	if test -z "$patch_mode"
@@ -546,12 +577,13 @@
 	clear_stash "$@"
 	;;
 create)
-	if test $# -gt 0 && test "$1" = create
-	then
-		shift
-	fi
+	shift
 	create_stash "$*" && echo "$w_commit"
 	;;
+store)
+	shift
+	store_stash "$@"
+	;;
 drop)
 	shift
 	drop_stash "$@"
diff --git a/git-submodule.sh b/git-submodule.sh
index 79bfaac..2979197 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -14,10 +14,13 @@
    or: $dashless [--quiet] foreach [--recursive] <command>
    or: $dashless [--quiet] sync [--recursive] [--] [<path>...]"
 OPTIONS_SPEC=
+SUBDIRECTORY_OK=Yes
 . git-sh-setup
 . git-sh-i18n
 . git-parse-remote
 require_work_tree
+wt_prefix=$(git rev-parse --show-prefix)
+cd_to_toplevel
 
 command=
 branch=
@@ -32,6 +35,7 @@
 update=
 prefix=
 custom_name=
+depth=
 
 # The function takes at most 2 arguments. The first argument is the
 # URL that navigates to the submodule origin repo. When relative, this URL
@@ -106,14 +110,50 @@
 	echo "${is_relative:+${up_path}}${remoteurl#./}"
 }
 
+# Resolve a path to be relative to another path.  This is intended for
+# converting submodule paths when git-submodule is run in a subdirectory
+# and only handles paths where the directory separator is '/'.
+#
+# The output is the first argument as a path relative to the second argument,
+# which defaults to $wt_prefix if it is omitted.
+relative_path ()
+{
+	local target curdir result
+	target=$1
+	curdir=${2-$wt_prefix}
+	curdir=${curdir%/}
+	result=
+
+	while test -n "$curdir"
+	do
+		case "$target" in
+		"$curdir/"*)
+			target=${target#"$curdir"/}
+			break
+			;;
+		esac
+
+		result="${result}../"
+		if test "$curdir" = "${curdir%/*}"
+		then
+			curdir=
+		else
+			curdir="${curdir%/*}"
+		fi
+	done
+
+	echo "$result$target"
+}
+
 #
 # Get submodule info for registered submodules
 # $@ = path to limit submodule list
 #
 module_list()
 {
+	eval "set $(git rev-parse --sq --prefix "$wt_prefix" -- "$@")"
 	(
-		git ls-files --error-unmatch --stage -- "$@" ||
+		git ls-files -z --error-unmatch --stage -- "$@" ||
 		echo "unmatched pathspec exists"
 	) |
 	perl -e '
@@ -121,6 +161,7 @@
 	my ($null_sha1) = ("0" x 40);
 	my @out = ();
 	my $unmatched = 0;
+	$/ = "\0";
 	while (<STDIN>) {
 		if (/^unmatched pathspec/) {
 			$unmatched = 1;
@@ -211,6 +252,7 @@
 	name=$2
 	url=$3
 	reference="$4"
+	depth="$5"
 	quiet=
 	if test -n "$GIT_QUIET"
 	then
@@ -233,7 +275,7 @@
 		mkdir -p "$gitdir_base"
 		(
 			clear_local_git_env
-			git clone $quiet -n ${reference:+"$reference"} \
+			git clone $quiet ${depth:+"$depth"} -n ${reference:+"$reference"} \
 				--separate-git-dir "$gitdir" "$url" "$sm_path"
 		) ||
 		die "$(eval_gettext "Clone of '\$url' into submodule path '\$sm_path' failed")"
@@ -282,6 +324,7 @@
 cmd_add()
 {
 	# parse $args after "submodule ... add".
+	reference_path=
 	while test $# -ne 0
 	do
 		case "$1" in
@@ -298,17 +341,25 @@
 			;;
 		--reference)
 			case "$2" in '') usage ;; esac
-			reference="--reference=$2"
+			reference_path=$2
 			shift
 			;;
 		--reference=*)
-			reference="$1"
+			reference_path="${1#--reference=}"
 			;;
 		--name)
 			case "$2" in '') usage ;; esac
 			custom_name=$2
 			shift
 			;;
+		--depth)
+			case "$2" in '') usage ;; esac
+			depth="--depth=$2"
+			shift
+			;;
+		--depth=*)
+			depth=$1
+			;;
 		--)
 			shift
 			break
@@ -323,6 +374,14 @@
 		shift
 	done
 
+	if test -n "$reference_path"
+	then
+		is_absolute_path "$reference_path" ||
+		reference_path="$wt_prefix$reference_path"
+
+		reference="--reference=$reference_path"
+	fi
+
 	repo=$1
 	sm_path=$2
 
@@ -335,9 +394,14 @@
 		usage
 	fi
 
+	is_absolute_path "$sm_path" || sm_path="$wt_prefix$sm_path"
+
 	# assure repo is absolute or relative to parent
 	case "$repo" in
 	./*|../*)
+		test -z "$wt_prefix" ||
+		die "$(gettext "Relative path can only be used from the toplevel of the working tree")"
+
 		# dereference source url relative to parent's url
 		realrepo=$(resolve_relative_url "$repo") || exit
 		;;
@@ -405,7 +469,7 @@
 				echo "$(eval_gettext "Reactivating local git directory for submodule '\$sm_name'.")"
 			fi
 		fi
-		module_clone "$sm_path" "$sm_name" "$realrepo" "$reference" || exit
+		module_clone "$sm_path" "$sm_name" "$realrepo" "$reference" "$depth" || exit
 		(
 			clear_local_git_env
 			cd "$sm_path" &&
@@ -471,21 +535,23 @@
 		die_if_unmatched "$mode"
 		if test -e "$sm_path"/.git
 		then
-			say "$(eval_gettext "Entering '\$prefix\$sm_path'")"
+			displaypath=$(relative_path "$sm_path")
+			say "$(eval_gettext "Entering '\$prefix\$displaypath'")"
 			name=$(module_name "$sm_path")
 			(
 				prefix="$prefix$sm_path/"
 				clear_local_git_env
-				# we make $path available to scripts ...
-				path=$sm_path
 				cd "$sm_path" &&
+				sm_path=$(relative_path "$sm_path") &&
+				# we make $path available to scripts ...
+				path=$sm_path &&
 				eval "$@" &&
 				if test -n "$recursive"
 				then
 					cmd_foreach "--recursive" "$@"
 				fi
 			) <&3 3<&- ||
-			die "$(eval_gettext "Stopping at '\$sm_path'; script returned non-zero status.")"
+			die "$(eval_gettext "Stopping at '\$prefix\$displaypath'; script returned non-zero status.")"
 		fi
 	done
 }
@@ -524,12 +590,14 @@
 		die_if_unmatched "$mode"
 		name=$(module_name "$sm_path") || exit
 
+		displaypath=$(relative_path "$sm_path")
+
 		# Copy url setting when it is not set yet
 		if test -z "$(git config "submodule.$name.url")"
 		then
 			url=$(git config -f .gitmodules submodule."$name".url)
 			test -z "$url" &&
-			die "$(eval_gettext "No url found for submodule path '\$sm_path' in .gitmodules")"
+			die "$(eval_gettext "No url found for submodule path '\$displaypath' in .gitmodules")"
 
 			# Possibly a url relative to parent
 			case "$url" in
@@ -538,9 +606,9 @@
 				;;
 			esac
 			git config submodule."$name".url "$url" ||
-			die "$(eval_gettext "Failed to register url for submodule path '\$sm_path'")"
+			die "$(eval_gettext "Failed to register url for submodule path '\$displaypath'")"
 
-			say "$(eval_gettext "Submodule '\$name' (\$url) registered for path '\$sm_path'")"
+			say "$(eval_gettext "Submodule '\$name' (\$url) registered for path '\$displaypath'")"
 		fi
 
 		# Copy "update" setting when it is not set yet
@@ -548,7 +616,7 @@
 		test -z "$upd" ||
 		test -n "$(git config submodule."$name".update)" ||
 		git config submodule."$name".update "$upd" ||
-		die "$(eval_gettext "Failed to register update mode for submodule path '\$sm_path'")"
+		die "$(eval_gettext "Failed to register update mode for submodule path '\$displaypath'")"
 	done
 }
 
@@ -594,27 +662,29 @@
 		die_if_unmatched "$mode"
 		name=$(module_name "$sm_path") || exit
 
+		displaypath=$(relative_path "$sm_path")
+
 		# Remove the submodule work tree (unless the user already did it)
 		if test -d "$sm_path"
 		then
 			# Protect submodules containing a .git directory
 			if test -d "$sm_path/.git"
 			then
-				echo >&2 "$(eval_gettext "Submodule work tree '\$sm_path' contains a .git directory")"
+				echo >&2 "$(eval_gettext "Submodule work tree '\$displaypath' contains a .git directory")"
 				die "$(eval_gettext "(use 'rm -rf' if you really want to remove it including all of its history)")"
 			fi
 
 			if test -z "$force"
 			then
 				git rm -qn "$sm_path" ||
-				die "$(eval_gettext "Submodule work tree '\$sm_path' contains local modifications; use '-f' to discard them")"
+				die "$(eval_gettext "Submodule work tree '\$displaypath' contains local modifications; use '-f' to discard them")"
 			fi
 			rm -rf "$sm_path" &&
-			say "$(eval_gettext "Cleared directory '\$sm_path'")" ||
-			say "$(eval_gettext "Could not remove submodule work tree '\$sm_path'")"
+			say "$(eval_gettext "Cleared directory '\$displaypath'")" ||
+			say "$(eval_gettext "Could not remove submodule work tree '\$displaypath'")"
 		fi
 
-		mkdir "$sm_path" || say "$(eval_gettext "Could not create empty submodule directory '\$sm_path'")"
+		mkdir "$sm_path" || say "$(eval_gettext "Could not create empty submodule directory '\$displaypath'")"
 
 		# Remove the .git/config entries (unless the user already did it)
 		if test -n "$(git config --get-regexp submodule."$name\.")"
@@ -623,7 +693,7 @@
 			# the user later decides to init this submodule again
 			url=$(git config submodule."$name".url)
 			git config --remove-section submodule."$name" 2>/dev/null &&
-			say "$(eval_gettext "Submodule '\$name' (\$url) unregistered for path '\$sm_path'")"
+			say "$(eval_gettext "Submodule '\$name' (\$url) unregistered for path '\$displaypath'")"
 		fi
 	done
 }
@@ -676,6 +746,14 @@
 		--checkout)
 			update="checkout"
 			;;
+		--depth)
+			case "$2" in '') usage ;; esac
+			depth="--depth=$2"
+			shift
+			;;
+		--depth=*)
+			depth=$1
+			;;
 		--)
 			shift
 			break
@@ -717,9 +795,11 @@
 			update_module=$(git config submodule."$name".update)
 		fi
 
+		displaypath=$(relative_path "$prefix$sm_path")
+
 		if test "$update_module" = "none"
 		then
-			echo "Skipping submodule '$prefix$sm_path'"
+			echo "Skipping submodule '$displaypath'"
 			continue
 		fi
 
@@ -728,20 +808,20 @@
 			# Only mention uninitialized submodules when its
 			# path have been specified
 			test "$#" != "0" &&
-			say "$(eval_gettext "Submodule path '\$prefix\$sm_path' not initialized
+			say "$(eval_gettext "Submodule path '\$displaypath' not initialized
 Maybe you want to use 'update --init'?")"
 			continue
 		fi
 
 		if ! test -d "$sm_path"/.git -o -f "$sm_path"/.git
 		then
-			module_clone "$sm_path" "$name" "$url" "$reference" || exit
+			module_clone "$sm_path" "$name" "$url" "$reference" "$depth" || exit
 			cloned_modules="$cloned_modules;$name"
 			subsha1=
 		else
 			subsha1=$(clear_local_git_env; cd "$sm_path" &&
 				git rev-parse --verify HEAD) ||
-			die "$(eval_gettext "Unable to find current revision in submodule path '\$prefix\$sm_path'")"
+			die "$(eval_gettext "Unable to find current revision in submodule path '\$displaypath'")"
 		fi
 
 		if test -n "$remote"
@@ -774,7 +854,7 @@
 				(clear_local_git_env; cd "$sm_path" &&
 					( (rev=$(git rev-list -n 1 $sha1 --not --all 2>/dev/null) &&
 					 test -z "$rev") || git-fetch)) ||
-				die "$(eval_gettext "Unable to fetch in submodule path '\$prefix\$sm_path'")"
+				die "$(eval_gettext "Unable to fetch in submodule path '\$displaypath'")"
 			fi
 
 			# Is this something we just cloned?
@@ -788,20 +868,26 @@
 			case "$update_module" in
 			rebase)
 				command="git rebase"
-				die_msg="$(eval_gettext "Unable to rebase '\$sha1' in submodule path '\$prefix\$sm_path'")"
-				say_msg="$(eval_gettext "Submodule path '\$prefix\$sm_path': rebased into '\$sha1'")"
+				die_msg="$(eval_gettext "Unable to rebase '\$sha1' in submodule path '\$displaypath'")"
+				say_msg="$(eval_gettext "Submodule path '\$displaypath': rebased into '\$sha1'")"
 				must_die_on_failure=yes
 				;;
 			merge)
 				command="git merge"
-				die_msg="$(eval_gettext "Unable to merge '\$sha1' in submodule path '\$prefix\$sm_path'")"
-				say_msg="$(eval_gettext "Submodule path '\$prefix\$sm_path': merged in '\$sha1'")"
+				die_msg="$(eval_gettext "Unable to merge '\$sha1' in submodule path '\$displaypath'")"
+				say_msg="$(eval_gettext "Submodule path '\$displaypath': merged in '\$sha1'")"
+				must_die_on_failure=yes
+				;;
+			!*)
+				command="${update_module#!}"
+				die_msg="$(eval_gettext "Execution of '\$command \$sha1' failed in submodule  path '\$prefix\$sm_path'")"
+				say_msg="$(eval_gettext "Submodule path '\$prefix\$sm_path': '\$command \$sha1'")"
 				must_die_on_failure=yes
 				;;
 			*)
 				command="git checkout $subforce -q"
-				die_msg="$(eval_gettext "Unable to checkout '\$sha1' in submodule path '\$prefix\$sm_path'")"
-				say_msg="$(eval_gettext "Submodule path '\$prefix\$sm_path': checked out '\$sha1'")"
+				die_msg="$(eval_gettext "Unable to checkout '\$sha1' in submodule path '\$displaypath'")"
+				say_msg="$(eval_gettext "Submodule path '\$displaypath': checked out '\$sha1'")"
 				;;
 			esac
 
@@ -828,7 +914,7 @@
 			res=$?
 			if test $res -gt 0
 			then
-				die_msg="$(eval_gettext "Failed to recurse into submodule path '\$prefix\$sm_path'")"
+				die_msg="$(eval_gettext "Failed to recurse into submodule path '\$displaypath'")"
 				if test $res -eq 1
 				then
 					err="${err};$die_msg"
@@ -942,6 +1028,7 @@
 	fi
 
 	cd_to_toplevel
+	eval "set $(git rev-parse --sq --prefix "$wt_prefix" -- "$@")"
 	# Get modified modules cared by user
 	modules=$(git $diff_cmd $cached --ignore-submodules=dirty --raw $head -- "$@" |
 		sane_egrep '^:([0-7]* )?160000' |
@@ -991,16 +1078,18 @@
 		! GIT_DIR="$name/.git" git-rev-parse -q --verify $sha1_dst^0 >/dev/null &&
 		missing_dst=t
 
+		display_name=$(relative_path "$name")
+
 		total_commits=
 		case "$missing_src,$missing_dst" in
 		t,)
-			errmsg="$(eval_gettext "  Warn: \$name doesn't contain commit \$sha1_src")"
+			errmsg="$(eval_gettext "  Warn: \$display_name doesn't contain commit \$sha1_src")"
 			;;
 		,t)
-			errmsg="$(eval_gettext "  Warn: \$name doesn't contain commit \$sha1_dst")"
+			errmsg="$(eval_gettext "  Warn: \$display_name doesn't contain commit \$sha1_dst")"
 			;;
 		t,t)
-			errmsg="$(eval_gettext "  Warn: \$name doesn't contain commits \$sha1_src and \$sha1_dst")"
+			errmsg="$(eval_gettext "  Warn: \$display_name doesn't contain commits \$sha1_src and \$sha1_dst")"
 			;;
 		*)
 			errmsg=
@@ -1029,12 +1118,12 @@
 			submodule="$(gettext "submodule")"
 			if test $mod_dst = 160000
 			then
-				echo "* $name $sha1_abbr_src($blob)->$sha1_abbr_dst($submodule)$total_commits:"
+				echo "* $display_name $sha1_abbr_src($blob)->$sha1_abbr_dst($submodule)$total_commits:"
 			else
-				echo "* $name $sha1_abbr_src($submodule)->$sha1_abbr_dst($blob)$total_commits:"
+				echo "* $display_name $sha1_abbr_src($submodule)->$sha1_abbr_dst($blob)$total_commits:"
 			fi
 		else
-			echo "* $name $sha1_abbr_src...$sha1_abbr_dst$total_commits:"
+			echo "* $display_name $sha1_abbr_src...$sha1_abbr_dst$total_commits:"
 		fi
 		if test -n "$errmsg"
 		then
@@ -1118,7 +1207,7 @@
 		die_if_unmatched "$mode"
 		name=$(module_name "$sm_path") || exit
 		url=$(git config submodule."$name".url)
-		displaypath="$prefix$sm_path"
+		displaypath=$(relative_path "$prefix$sm_path")
 		if test "$stage" = U
 		then
 			say "U$sha1 $displaypath"
@@ -1129,16 +1218,16 @@
 			say "-$sha1 $displaypath"
 			continue;
 		fi
-		set_name_rev "$sm_path" "$sha1"
 		if git diff-files --ignore-submodules=dirty --quiet -- "$sm_path"
 		then
+			set_name_rev "$sm_path" "$sha1"
 			say " $sha1 $displaypath$revname"
 		else
 			if test -z "$cached"
 			then
 				sha1=$(clear_local_git_env; cd "$sm_path" && git rev-parse --verify HEAD)
-				set_name_rev "$sm_path" "$sha1"
 			fi
+			set_name_rev "$sm_path" "$sha1"
 			say "+$sha1 $displaypath$revname"
 		fi
 
@@ -1213,7 +1302,8 @@
 
 		if git config "submodule.$name.url" >/dev/null 2>/dev/null
 		then
-			say "$(eval_gettext "Synchronizing submodule url for '\$prefix\$sm_path'")"
+			displaypath=$(relative_path "$prefix$sm_path")
+			say "$(eval_gettext "Synchronizing submodule url for '\$displaypath'")"
 			git config submodule."$name".url "$super_config_url"
 
 			if test -e "$sm_path"/.git
diff --git a/git-svn.perl b/git-svn.perl
index 6c7bd95..ff1ce3d 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -113,7 +113,7 @@
 	$_template, $_shared,
 	$_version, $_fetch_all, $_no_rebase, $_fetch_parent,
 	$_before, $_after,
-	$_merge, $_strategy, $_preserve_merges, $_dry_run, $_local,
+	$_merge, $_strategy, $_preserve_merges, $_dry_run, $_parents, $_local,
 	$_prefix, $_no_checkout, $_url, $_verbose,
 	$_commit_url, $_tag, $_merge_info, $_interactive);
 
@@ -126,6 +126,7 @@
                     'config-dir=s' => \$Git::SVN::Ra::config_dir,
                     'no-auth-cache' => \$Git::SVN::Prompt::_no_auth_cache,
                     'ignore-paths=s' => \$Git::SVN::Fetcher::_ignore_regex,
+                    'include-paths=s' => \$Git::SVN::Fetcher::_include_regex,
                     'ignore-refs=s' => \$Git::SVN::Ra::_ignore_refs_regex );
 my %fc_opts = ( 'follow-parent|follow!' => \$Git::SVN::_follow_parent,
 		'authors-file|A=s' => \$_authors,
@@ -202,6 +203,7 @@
 	            { 'message|m=s' => \$_message,
 	              'destination|d=s' => \$_branch_dest,
 	              'dry-run|n' => \$_dry_run,
+	              'parents' => \$_parents,
 	              'tag|t' => \$_tag,
 	              'username=s' => \$Git::SVN::Prompt::_username,
 	              'commit-url=s' => \$_commit_url } ],
@@ -210,6 +212,7 @@
 	         { 'message|m=s' => \$_message,
 	           'destination|d=s' => \$_branch_dest,
 	           'dry-run|n' => \$_dry_run,
+	           'parents' => \$_parents,
 	           'username=s' => \$Git::SVN::Prompt::_username,
 	           'commit-url=s' => \$_commit_url } ],
 	'set-tree' => [ \&cmd_set_tree,
@@ -470,6 +473,9 @@
 	my $ignore_paths_regex = \$Git::SVN::Fetcher::_ignore_regex;
 	command_noisy('config', "$pfx.ignore-paths", $$ignore_paths_regex)
 		if defined $$ignore_paths_regex;
+	my $include_paths_regex = \$Git::SVN::Fetcher::_include_regex;
+	command_noisy('config', "$pfx.include-paths", $$include_paths_regex)
+		if defined $$include_paths_regex;
 	my $ignore_refs_regex = \$Git::SVN::Ra::_ignore_refs_regex;
 	command_noisy('config', "$pfx.ignore-refs", $$ignore_refs_regex)
 		if defined $$ignore_refs_regex;
@@ -669,12 +675,14 @@
 }
 
 sub merge_merge_info {
-	my ($mergeinfo_one, $mergeinfo_two) = @_;
+	my ($mergeinfo_one, $mergeinfo_two, $ignore_branch) = @_;
 	my %result_hash = ();
 
 	merge_revs_into_hash(\%result_hash, $mergeinfo_one);
 	merge_revs_into_hash(\%result_hash, $mergeinfo_two);
 
+	delete $result_hash{$ignore_branch} if $ignore_branch;
+
 	my $result = '';
 	# Sort below is for consistency's sake
 	for my $branchname (sort keys(%result_hash)) {
@@ -695,6 +703,7 @@
 		my $all_parents_ok = 1;
 		my $aggregate_mergeinfo = '';
 		my $rooturl = $gs->repos_root;
+		my ($target_branch) = $gs->full_pushurl =~ /^\Q$rooturl\E(.*)/;
 
 		if (defined($rewritten_parent)) {
 			# Replace first parent with newly-rewritten version
@@ -726,7 +735,8 @@
 			# Merge previous mergeinfo values
 			$aggregate_mergeinfo =
 				merge_merge_info($aggregate_mergeinfo,
-								 $par_mergeinfo, 0);
+								$par_mergeinfo,
+								$target_branch);
 
 			next if $parent eq $parents[0]; # Skip first parent
 			# Add new changes being placed in tree by merge
@@ -769,7 +779,8 @@
 			my $newmergeinfo = "$branchpath:" . join(',', @revsin);
 			$aggregate_mergeinfo =
 				merge_merge_info($aggregate_mergeinfo,
-								 $newmergeinfo, 1);
+								$newmergeinfo,
+								$target_branch);
 		}
 		if ($all_parents_ok and $aggregate_mergeinfo) {
 			return $aggregate_mergeinfo;
@@ -820,7 +831,7 @@
 sub cmd_dcommit {
 	my $head = shift;
 	command_noisy(qw/update-index --refresh/);
-	git_cmd_try { command_oneline(qw/diff-index --quiet HEAD/) }
+	git_cmd_try { command_oneline(qw/diff-index --quiet HEAD --/) }
 		'Cannot dcommit with a dirty index.  Commit your changes first, '
 		. "or stash them with `git stash'.\n";
 	$head ||= 'HEAD';
@@ -1163,6 +1174,10 @@
 		$ctx->ls($dst, 'HEAD', 0);
 	} and die "branch ${branch_name} already exists\n";
 
+	if ($_parents) {
+		mk_parent_dirs($ctx, $dst);
+	}
+
 	print "Copying ${src} at r${rev} to ${dst}...\n";
 	$ctx->copy($src, $rev, $dst)
 		unless $_dry_run;
@@ -1170,6 +1185,17 @@
 	$gs->fetch_all;
 }
 
+sub mk_parent_dirs {
+	my ($ctx, $parent) = @_;
+	$parent =~ s{/[^/]*$}{};
+
+	if (!eval{$ctx->ls($parent, 'HEAD', 0)}) {
+		mk_parent_dirs($ctx, $parent);
+		print "Creating parent folder ${parent} ...\n";
+		$ctx->mkdir($parent) unless $_dry_run;
+	}
+}
+
 sub cmd_find_rev {
 	my $revision_or_hash = shift or die "SVN or git revision required ",
 	                                    "as a command-line argument\n";
@@ -1220,7 +1246,7 @@
 		return;
 	}
 	if (command(qw/diff-index HEAD --/)) {
-		print STDERR "Cannot rebase with uncommited changes:\n";
+		print STDERR "Cannot rebase with uncommitted changes:\n";
 		command_noisy('status');
 		exit 1;
 	}
@@ -1906,7 +1932,7 @@
 sub working_head_info {
 	my ($head, $refs) = @_;
 	my @args = qw/rev-list --first-parent --pretty=medium/;
-	my ($fh, $ctx) = command_output_pipe(@args, $head);
+	my ($fh, $ctx) = command_output_pipe(@args, $head, "--");
 	my $hash;
 	my %max;
 	while (<$fh>) {
diff --git a/git-web--browse.sh b/git-web--browse.sh
index 9f44679..1d72ec7 100755
--- a/git-web--browse.sh
+++ b/git-web--browse.sh
@@ -32,8 +32,9 @@
 valid_tool() {
 	case "$1" in
 	firefox | iceweasel | seamonkey | iceape | \
-	chrome | google-chrome | chromium | chromium-browser |\
-	konqueror | opera | w3m | elinks | links | lynx | dillo | open | start)
+	chrome | google-chrome | chromium | chromium-browser | \
+	konqueror | opera | w3m | elinks | links | lynx | dillo | open | \
+	start | cygstart)
 		;; # happy
 	*)
 		valid_custom_tool "$1" || return 1
@@ -127,6 +128,10 @@
 	if test -x /bin/start; then
 		browser_candidates="start $browser_candidates"
 	fi
+	# /usr/bin/cygstart indicates Cygwin
+	if test -x /usr/bin/cygstart; then
+		browser_candidates="cygstart $browser_candidates"
+	fi
 
 	for i in $browser_candidates; do
 		init_browser_path $i
@@ -174,7 +179,7 @@
 		;;
 	esac
 	;;
-w3m|elinks|links|lynx|open)
+w3m|elinks|links|lynx|open|cygstart)
 	"$browser_path" "$@"
 	;;
 start)
diff --git a/git.c b/git.c
index 1ada169..2025f77 100644
--- a/git.c
+++ b/git.c
@@ -4,6 +4,7 @@
 #include "help.h"
 #include "quote.h"
 #include "run-command.h"
+#include "commit.h"
 
 const char git_usage_string[] =
 	"git [--version] [--help] [-c name=value]\n"
@@ -146,6 +147,12 @@
 			setenv(GIT_LITERAL_PATHSPECS_ENVIRONMENT, "0", 1);
 			if (envchanged)
 				*envchanged = 1;
+		} else if (!strcmp(cmd, "--shallow-file")) {
+			(*argv)++;
+			(*argc)--;
+			set_alternate_shallow_file((*argv)[0]);
+			if (envchanged)
+				*envchanged = 1;
 		} else {
 			fprintf(stderr, "Unknown option: %s\n", cmd);
 			usage(git_usage_string);
@@ -317,6 +324,7 @@
 		{ "cat-file", cmd_cat_file, RUN_SETUP },
 		{ "check-attr", cmd_check_attr, RUN_SETUP },
 		{ "check-ignore", cmd_check_ignore, RUN_SETUP | NEED_WORK_TREE },
+		{ "check-mailmap", cmd_check_mailmap, RUN_SETUP },
 		{ "check-ref-format", cmd_check_ref_format },
 		{ "checkout", cmd_checkout, RUN_SETUP | NEED_WORK_TREE },
 		{ "checkout-index", cmd_checkout_index,
@@ -507,8 +515,9 @@
 }
 
 
-int main(int argc, const char **argv)
+int main(int argc, char **av)
 {
+	const char **argv = (const char **) av;
 	const char *cmd;
 
 	startup_info = &git_startup_info;
@@ -517,6 +526,13 @@
 	if (!cmd)
 		cmd = "git-help";
 
+	/*
+	 * Always open file descriptors 0/1/2 to avoid clobbering files
+	 * in die().  It also avoids messing up when the pipes are dup'ed
+	 * onto stdin/stdout/stderr in the child processes we spawn.
+	 */
+	sanitize_stdfds();
+
 	git_setup_gettext();
 
 	/*
diff --git a/git.rc b/git.rc
new file mode 100644
index 0000000..bce6db9
--- /dev/null
+++ b/git.rc
@@ -0,0 +1,22 @@
+1 VERSIONINFO
+FILEVERSION     MAJOR,MINOR,PATCH,0
+PRODUCTVERSION  MAJOR,MINOR,PATCH,0
+BEGIN
+  BLOCK "StringFileInfo"
+  BEGIN
+    BLOCK "040904b0"   /* LANG_ENGLISH/SUBLANG_ENGLISH_US, Unicode CP */
+    BEGIN
+      VALUE "CompanyName", "The Git Development Community\0"
+      VALUE "FileDescription", "Git for Windows\0"
+      VALUE "InternalName", "git\0"
+      VALUE "OriginalFilename", "git.exe\0"
+      VALUE "ProductName", "Git\0"
+      VALUE "ProductVersion", GIT_VERSION "\0"
+    END
+  END
+
+  BLOCK "VarFileInfo"
+  BEGIN
+    VALUE "Translation", 0x409, 1200
+  END
+END
diff --git a/gitk-git/gitk b/gitk-git/gitk
index b3706fc..5cd00d8 100755
--- a/gitk-git/gitk
+++ b/gitk-git/gitk
@@ -1998,6 +1998,9 @@
     return [string map {&& & & {}} [mc $str]]
 }
 
+proc cleardropsel {w} {
+    $w selection clear
+}
 proc makedroplist {w varname args} {
     global use_ttk
     if {$use_ttk} {
@@ -2007,7 +2010,9 @@
             if {$cx > $width} {set width $cx}
         }
 	set gm [ttk::combobox $w -width $width -state readonly\
-		    -textvariable $varname -values $args]
+		    -textvariable $varname -values $args \
+		    -exportselection false]
+	bind $gm <<ComboboxSelected>> [list $gm selection clear]
     } else {
 	set gm [eval [linsert $args 0 tk_optionMenu $w $varname]]
     }
@@ -2026,6 +2031,9 @@
     global highlight_files gdttype
     global searchstring sstring
     global bgcolor fgcolor bglist fglist diffcolors selectbgcolor
+    global uifgcolor uifgdisabledcolor
+    global filesepbgcolor filesepfgcolor
+    global mergecolors foundbgcolor currentsearchhitbgcolor
     global headctxmenu progresscanv progressitem progresscoords statusw
     global fprogitem fprogcoord lastprogupdate progupdatepending
     global rprogitem rprogcoord rownumsel numcommits
@@ -2177,10 +2185,10 @@
 	0x00, 0x38, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0x00, 0x38, 0x00, 0x1c,
 	0x00, 0x0e, 0x00, 0x07, 0x80, 0x03, 0xc0, 0x01};
     }
-    image create bitmap bm-left -data $bm_left_data
-    image create bitmap bm-left-gray -data $bm_left_data -foreground "#999"
-    image create bitmap bm-right -data $bm_right_data
-    image create bitmap bm-right-gray -data $bm_right_data -foreground "#999"
+    image create bitmap bm-left -data $bm_left_data -foreground $uifgcolor
+    image create bitmap bm-left-gray -data $bm_left_data -foreground $uifgdisabledcolor
+    image create bitmap bm-right -data $bm_right_data -foreground $uifgcolor
+    image create bitmap bm-right-gray -data $bm_right_data -foreground $uifgdisabledcolor
 
     ${NS}::button .tf.bar.leftbut -command goback -state disabled -width 26
     if {$use_ttk} {
@@ -2245,7 +2253,8 @@
     set gm [makedroplist .tf.lbar.gdttype gdttype \
 		[mc "containing:"] \
 		[mc "touching paths:"] \
-		[mc "adding/removing string:"]]
+		[mc "adding/removing string:"] \
+		[mc "changing lines matching:"]]
     trace add variable gdttype write gdttype_change
     pack .tf.lbar.gdttype -side left -fill y
 
@@ -2349,32 +2358,32 @@
     lappend fglist $ctext
 
     $ctext tag conf comment -wrap $wrapcomment
-    $ctext tag conf filesep -font textfontbold -back "#aaaaaa"
+    $ctext tag conf filesep -font textfontbold -fore $filesepfgcolor -back $filesepbgcolor
     $ctext tag conf hunksep -fore [lindex $diffcolors 2]
     $ctext tag conf d0 -fore [lindex $diffcolors 0]
     $ctext tag conf dresult -fore [lindex $diffcolors 1]
-    $ctext tag conf m0 -fore red
-    $ctext tag conf m1 -fore blue
-    $ctext tag conf m2 -fore green
-    $ctext tag conf m3 -fore purple
-    $ctext tag conf m4 -fore brown
-    $ctext tag conf m5 -fore "#009090"
-    $ctext tag conf m6 -fore magenta
-    $ctext tag conf m7 -fore "#808000"
-    $ctext tag conf m8 -fore "#009000"
-    $ctext tag conf m9 -fore "#ff0080"
-    $ctext tag conf m10 -fore cyan
-    $ctext tag conf m11 -fore "#b07070"
-    $ctext tag conf m12 -fore "#70b0f0"
-    $ctext tag conf m13 -fore "#70f0b0"
-    $ctext tag conf m14 -fore "#f0b070"
-    $ctext tag conf m15 -fore "#ff70b0"
+    $ctext tag conf m0 -fore [lindex $mergecolors 0]
+    $ctext tag conf m1 -fore [lindex $mergecolors 1]
+    $ctext tag conf m2 -fore [lindex $mergecolors 2]
+    $ctext tag conf m3 -fore [lindex $mergecolors 3]
+    $ctext tag conf m4 -fore [lindex $mergecolors 4]
+    $ctext tag conf m5 -fore [lindex $mergecolors 5]
+    $ctext tag conf m6 -fore [lindex $mergecolors 6]
+    $ctext tag conf m7 -fore [lindex $mergecolors 7]
+    $ctext tag conf m8 -fore [lindex $mergecolors 8]
+    $ctext tag conf m9 -fore [lindex $mergecolors 9]
+    $ctext tag conf m10 -fore [lindex $mergecolors 10]
+    $ctext tag conf m11 -fore [lindex $mergecolors 11]
+    $ctext tag conf m12 -fore [lindex $mergecolors 12]
+    $ctext tag conf m13 -fore [lindex $mergecolors 13]
+    $ctext tag conf m14 -fore [lindex $mergecolors 14]
+    $ctext tag conf m15 -fore [lindex $mergecolors 15]
     $ctext tag conf mmax -fore darkgrey
     set mergemax 16
     $ctext tag conf mresult -font textfontbold
     $ctext tag conf msep -font textfontbold
-    $ctext tag conf found -back yellow
-    $ctext tag conf currentsearchhit -back orange
+    $ctext tag conf found -back $foundbgcolor
+    $ctext tag conf currentsearchhit -back $currentsearchhitbgcolor
     $ctext tag conf wwrap -wrap word
 
     .pwbottom add .bleft
@@ -2559,6 +2568,7 @@
 	{mc "Compare with marked commit" command compare_commits}
 	{mc "Diff this -> marked commit" command {diffvsmark 0}}
 	{mc "Diff marked commit -> this" command {diffvsmark 1}}
+	{mc "Revert this commit" command revert}
     }
     $rowctxmenu configure -tearoff 0
 
@@ -2721,6 +2731,14 @@
     global viewname viewfiles viewargs viewargscmd viewperm nextviewnum
     global cmitmode wrapcomment datetimeformat limitdiffs
     global colors uicolor bgcolor fgcolor diffcolors diffcontext selectbgcolor
+    global uifgcolor uifgdisabledcolor
+    global headbgcolor headfgcolor headoutlinecolor remotebgcolor
+    global tagbgcolor tagfgcolor tagoutlinecolor
+    global reflinecolor filesepbgcolor filesepfgcolor
+    global mergecolors foundbgcolor currentsearchhitbgcolor
+    global linehoverbgcolor linehoverfgcolor linehoveroutlinecolor circlecolors
+    global mainheadcirclecolor workingfilescirclecolor indexcirclecolor
+    global linkfgcolor circleoutlinecolor
     global autoselect autosellen extdifftool perfile_attrs markbgcolor use_ttk
     global hideremotes want_ttk maxrefs
 
@@ -2753,13 +2771,37 @@
 	puts $f [list set want_ttk $want_ttk]
 	puts $f [list set bgcolor $bgcolor]
 	puts $f [list set fgcolor $fgcolor]
+	puts $f [list set uifgcolor $uifgcolor]
+	puts $f [list set uifgdisabledcolor $uifgdisabledcolor]
 	puts $f [list set colors $colors]
 	puts $f [list set diffcolors $diffcolors]
+	puts $f [list set mergecolors $mergecolors]
 	puts $f [list set markbgcolor $markbgcolor]
 	puts $f [list set diffcontext $diffcontext]
 	puts $f [list set selectbgcolor $selectbgcolor]
+	puts $f [list set foundbgcolor $foundbgcolor]
+	puts $f [list set currentsearchhitbgcolor $currentsearchhitbgcolor]
 	puts $f [list set extdifftool $extdifftool]
 	puts $f [list set perfile_attrs $perfile_attrs]
+	puts $f [list set headbgcolor $headbgcolor]
+	puts $f [list set headfgcolor $headfgcolor]
+	puts $f [list set headoutlinecolor $headoutlinecolor]
+	puts $f [list set remotebgcolor $remotebgcolor]
+	puts $f [list set tagbgcolor $tagbgcolor]
+	puts $f [list set tagfgcolor $tagfgcolor]
+	puts $f [list set tagoutlinecolor $tagoutlinecolor]
+	puts $f [list set reflinecolor $reflinecolor]
+	puts $f [list set filesepbgcolor $filesepbgcolor]
+	puts $f [list set filesepfgcolor $filesepfgcolor]
+	puts $f [list set linehoverbgcolor $linehoverbgcolor]
+	puts $f [list set linehoverfgcolor $linehoverfgcolor]
+	puts $f [list set linehoveroutlinecolor $linehoveroutlinecolor]
+	puts $f [list set mainheadcirclecolor $mainheadcirclecolor]
+	puts $f [list set workingfilescirclecolor $workingfilescirclecolor]
+	puts $f [list set indexcirclecolor $indexcirclecolor]
+	puts $f [list set circlecolors $circlecolors]
+	puts $f [list set linkfgcolor $linkfgcolor]
+	puts $f [list set circleoutlinecolor $circleoutlinecolor]
 
 	puts $f "set geometry(main) [wm geometry .]"
 	puts $f "set geometry(state) [wm state .]"
@@ -4617,6 +4659,8 @@
 	set gdtargs [concat -- $relative_paths]
     } elseif {$gdttype eq [mc "adding/removing string:"]} {
 	set gdtargs [list "-S$highlight_files"]
+    } elseif {$gdttype eq [mc "changing lines matching:"]} {
+	set gdtargs [list "-G$highlight_files"]
     } else {
 	# must be "containing:", i.e. we're searching commit info
 	return
@@ -5925,15 +5969,17 @@
     global linehtag linentag linedtag selectedline
     global canvxmax boldids boldnameids fgcolor markedid
     global mainheadid nullid nullid2 circleitem circlecolors ctxbut
+    global mainheadcirclecolor workingfilescirclecolor indexcirclecolor
+    global circleoutlinecolor
 
     # listed is 0 for boundary, 1 for normal, 2 for negative, 3 for left, 4 for right
     set listed $cmitlisted($curview,$id)
     if {$id eq $nullid} {
-	set ofill red
+	set ofill $workingfilescirclecolor
     } elseif {$id eq $nullid2} {
-	set ofill green
+	set ofill $indexcirclecolor
     } elseif {$id eq $mainheadid} {
-	set ofill yellow
+	set ofill $mainheadcirclecolor
     } else {
 	set ofill [lindex $circlecolors $listed]
     }
@@ -5943,21 +5989,21 @@
     if {$listed <= 2} {
 	set t [$canv create oval [expr {$x - $orad}] [expr {$y - $orad}] \
 		   [expr {$x + $orad - 1}] [expr {$y + $orad - 1}] \
-		   -fill $ofill -outline $fgcolor -width 1 -tags circle]
+		   -fill $ofill -outline $circleoutlinecolor -width 1 -tags circle]
     } elseif {$listed == 3} {
 	# triangle pointing left for left-side commits
 	set t [$canv create polygon \
 		   [expr {$x - $orad}] $y \
 		   [expr {$x + $orad - 1}] [expr {$y - $orad}] \
 		   [expr {$x + $orad - 1}] [expr {$y + $orad - 1}] \
-		   -fill $ofill -outline $fgcolor -width 1 -tags circle]
+		   -fill $ofill -outline $circleoutlinecolor -width 1 -tags circle]
     } else {
 	# triangle pointing right for right-side commits
 	set t [$canv create polygon \
 		   [expr {$x + $orad - 1}] $y \
 		   [expr {$x - $orad}] [expr {$y - $orad}] \
 		   [expr {$x - $orad}] [expr {$y + $orad - 1}] \
-		   -fill $ofill -outline $fgcolor -width 1 -tags circle]
+		   -fill $ofill -outline $circleoutlinecolor -width 1 -tags circle]
     }
     set circleitem($row) $t
     $canv raise $t
@@ -6345,6 +6391,9 @@
     global idtags idheads idotherrefs mainhead
     global linespc lthickness
     global canv rowtextx curview fgcolor bgcolor ctxbut
+    global headbgcolor headfgcolor headoutlinecolor remotebgcolor
+    global tagbgcolor tagfgcolor tagoutlinecolor
+    global reflinecolor
 
     set marks {}
     set ntags 0
@@ -6382,7 +6431,7 @@
 	set xt [expr {$xt + $delta + $wid + $lthickness + $linespc}]
     }
     set t [$canv create line $x $y1 [lindex $xvals end] $y1 \
-	       -width $lthickness -fill black -tags tag.$id]
+	       -width $lthickness -fill $reflinecolor -tags tag.$id]
     $canv lower $t
     foreach tag $marks x $xvals wid $wvals {
 	set tag_quoted [string map {% %%} $tag]
@@ -6393,13 +6442,14 @@
 	    # draw a tag
 	    set t [$canv create polygon $x [expr {$yt + $delta}] $xl $yt \
 		       $xr $yt $xr $yb $xl $yb $x [expr {$yb - $delta}] \
-		       -width 1 -outline black -fill yellow -tags tag.$id]
+		       -width 1 -outline $tagoutlinecolor -fill $tagbgcolor \
+		       -tags tag.$id]
 	    $canv bind $t <1> [list showtag $tag_quoted 1]
 	    set rowtextx([rowofcommit $id]) [expr {$xr + $linespc}]
 	} else {
 	    # draw a head or other ref
 	    if {[incr nheads -1] >= 0} {
-		set col green
+		set col $headbgcolor
 		if {$tag eq $mainhead} {
 		    set font mainfontbold
 		}
@@ -6415,10 +6465,10 @@
 		set yti [expr {$yt + 1}]
 		set xri [expr {$x + $rwid}]
 		$canv create polygon $xi $yti $xri $yti $xri $yb $xi $yb \
-			-width 0 -fill "#ffddaa" -tags tag.$id
+			-width 0 -fill $remotebgcolor -tags tag.$id
 	    }
 	}
-	set t [$canv create text $xl $y1 -anchor w -text $tag -fill $fgcolor \
+	set t [$canv create text $xl $y1 -anchor w -text $tag -fill $headfgcolor \
 		   -font $font -tags [list tag.$id text]]
 	if {$ntags >= 0} {
 	    $canv bind $t <1> [list showtag $tag_quoted 1]
@@ -6799,6 +6849,7 @@
 
 proc setlink {id lk} {
     global curview ctext pendinglinks
+    global linkfgcolor
 
     if {[string range $id 0 1] eq "-g"} {
       set id [string range $id 2 end]
@@ -6816,7 +6867,7 @@
 	set known [commitinview $id $curview]
     }
     if {$known} {
-	$ctext tag conf $lk -foreground blue -underline 1
+	$ctext tag conf $lk -foreground $linkfgcolor -underline 1
 	$ctext tag bind $lk <1> [list selbyid $id]
 	$ctext tag bind $lk <Enter> {linkcursor %W 1}
 	$ctext tag bind $lk <Leave> {linkcursor %W -1}
@@ -7571,9 +7622,13 @@
 }
 
 proc gettreediffs {ids} {
-    global treediff treepending
+    global treediff treepending limitdiffs vfilelimit curview
 
-    if {[catch {set gdtf [open [diffcmd $ids {--no-commit-id}] r]}]} return
+    set cmd [diffcmd $ids {--no-commit-id}]
+    if {$limitdiffs && $vfilelimit($curview) ne {}} {
+	    set cmd [concat $cmd -- $vfilelimit($curview)]
+    }
+    if {[catch {set gdtf [open $cmd r]}]} return
 
     set treepending $ids
     set treediff {}
@@ -7617,17 +7672,7 @@
 	return [expr {$nr >= $max? 2: 1}]
     }
     close $gdtf
-    if {$limitdiffs && $vfilelimit($curview) ne {}} {
-	set flist {}
-	foreach f $treediff {
-	    if {[path_filter $vfilelimit($curview) $f]} {
-		lappend flist $f
-	    }
-	}
-	set treediffs($ids) $flist
-    } else {
-	set treediffs($ids) $treediff
-    }
+    set treediffs($ids) $treediff
     unset treepending
     if {$cmitmode eq "tree" && [llength $diffids] == 1} {
 	gettree $diffids
@@ -8459,6 +8504,8 @@
 proc linehover {} {
     global hoverx hovery hoverid hovertimer
     global canv linespc lthickness
+    global linehoverbgcolor linehoverfgcolor linehoveroutlinecolor
+
     global commitinfo
 
     set text [lindex $commitinfo($hoverid) 0]
@@ -8472,10 +8519,11 @@
     set x1 [expr {$x + [font measure mainfont $text] + 2 * $lthickness}]
     set y1 [expr {$y + $linespc + 2 * $lthickness}]
     set t [$canv create rectangle $x0 $y0 $x1 $y1 \
-	       -fill \#ffff80 -outline black -width 1 -tags hover]
+	       -fill $linehoverbgcolor -outline $linehoveroutlinecolor \
+	       -width 1 -tags hover]
     $canv raise $t
     set t [$canv create text $x $y -anchor nw -text $text -tags hover \
-	       -font mainfont]
+	       -font mainfont -fill $linehoverfgcolor]
     $canv raise $t
 }
 
@@ -9039,12 +9087,13 @@
 proc redrawtags {id} {
     global canv linehtag idpos currentid curview cmitlisted markedid
     global canvxmax iddrawn circleitem mainheadid circlecolors
+    global mainheadcirclecolor
 
     if {![commitinview $id $curview]} return
     if {![info exists iddrawn($id)]} return
     set row [rowofcommit $id]
     if {$id eq $mainheadid} {
-	set ofill yellow
+	set ofill $mainheadcirclecolor
     } else {
 	set ofill [lindex $circlecolors $cmitlisted($curview,$id)]
     }
@@ -9301,6 +9350,67 @@
     notbusy cherrypick
 }
 
+proc revert {} {
+    global rowmenuid curview
+    global mainhead mainheadid
+    global gitdir
+
+    set oldhead [exec git rev-parse HEAD]
+    set dheads [descheads $rowmenuid]
+    if { $dheads eq {} || [lsearch -exact $dheads $oldhead] == -1 } {
+       set ok [confirm_popup [mc "Commit %s is not\
+           included in branch %s -- really revert it?" \
+                      [string range $rowmenuid 0 7] $mainhead]]
+       if {!$ok} return
+    }
+    nowbusy revert [mc "Reverting"]
+    update
+
+    if [catch {exec git revert --no-edit $rowmenuid} err] {
+        notbusy revert
+        if [regexp {files would be overwritten by merge:(\n(( |\t)+[^\n]+\n)+)}\
+                $err match files] {
+            regsub {\n( |\t)+} $files "\n" files
+            error_popup [mc "Revert failed because of local changes to\
+                the following files:%s Please commit, reset or stash \
+                your changes and try again." $files]
+        } elseif [regexp {error: could not revert} $err] {
+            if [confirm_popup [mc "Revert failed because of merge conflict.\n\
+                Do you wish to run git citool to resolve it?"]] {
+                # Force citool to read MERGE_MSG
+                file delete [file join $gitdir "GITGUI_MSG"]
+                exec_citool {} $rowmenuid
+            }
+        } else { error_popup $err }
+        run updatecommits
+        return
+    }
+
+    set newhead [exec git rev-parse HEAD]
+    if { $newhead eq $oldhead } {
+        notbusy revert
+        error_popup [mc "No changes committed"]
+        return
+    }
+
+    addnewchild $newhead $oldhead
+
+    if [commitinview $oldhead $curview] {
+        # XXX this isn't right if we have a path limit...
+        insertrow $newhead $oldhead $curview
+        if {$mainhead ne {}} {
+            movehead $newhead $mainhead
+            movedhead $newhead $mainhead
+        }
+        set mainheadid $newhead
+        redrawtags $oldhead
+        redrawtags $newhead
+        selbyid $newhead
+    }
+
+    notbusy revert
+}
+
 proc resethead {} {
     global mainhead rowmenuid confirm_ok resettype NS
 
@@ -10780,7 +10890,7 @@
     set linknum 0
     if {![info exists cached_tagcontent($tag)]} {
 	catch {
-           set cached_tagcontent($tag) [exec git cat-file tag $tag]
+           set cached_tagcontent($tag) [exec git cat-file -p $tag]
 	}
     }
     if {[info exists cached_tagcontent($tag)]} {
@@ -11641,6 +11751,15 @@
     exit 1
 }
 
+# on OSX bring the current Wish process window to front
+if {[tk windowingsystem] eq "aqua"} {
+    exec osascript -e [format {
+        tell application "System Events"
+            set frontmost of processes whose unix id is %d to true
+        end tell
+    } [pid] ]
+}
+
 # Unset GIT_TRACE var if set
 if { [info exists ::env(GIT_TRACE)] } {
     unset ::env(GIT_TRACE)
@@ -11728,22 +11847,47 @@
 set colors {green red blue magenta darkgrey brown orange}
 if {[tk windowingsystem] eq "win32"} {
     set uicolor SystemButtonFace
+    set uifgcolor SystemButtonText
+    set uifgdisabledcolor SystemDisabledText
     set bgcolor SystemWindow
-    set fgcolor SystemButtonText
+    set fgcolor SystemWindowText
     set selectbgcolor SystemHighlight
 } else {
     set uicolor grey85
+    set uifgcolor black
+    set uifgdisabledcolor "#999"
     set bgcolor white
     set fgcolor black
     set selectbgcolor gray85
 }
 set diffcolors {red "#00a000" blue}
 set diffcontext 3
+set mergecolors {red blue green purple brown "#009090" magenta "#808000" "#009000" "#ff0080" cyan "#b07070" "#70b0f0" "#70f0b0" "#f0b070" "#ff70b0"}
 set ignorespace 0
 set worddiff ""
 set markbgcolor "#e0e0ff"
 
+set headbgcolor green
+set headfgcolor black
+set headoutlinecolor black
+set remotebgcolor #ffddaa
+set tagbgcolor yellow
+set tagfgcolor black
+set tagoutlinecolor black
+set reflinecolor black
+set filesepbgcolor #aaaaaa
+set filesepfgcolor black
+set linehoverbgcolor #ffff80
+set linehoverfgcolor black
+set linehoveroutlinecolor black
+set mainheadcirclecolor yellow
+set workingfilescirclecolor red
+set indexcirclecolor green
 set circlecolors {white blue gray blue blue}
+set linkfgcolor blue
+set circleoutlinecolor $fgcolor
+set foundbgcolor yellow
+set currentsearchhitbgcolor orange
 
 # button for popping up context menus
 if {[tk windowingsystem] eq "aqua"} {
diff --git a/gitk-git/po/sv.po b/gitk-git/po/sv.po
index 8cc98dc..df95e01 100644
--- a/gitk-git/po/sv.po
+++ b/gitk-git/po/sv.po
@@ -1,16 +1,16 @@
 # Swedish translation for gitk
-# Copyright (C) 2005-2012 Paul Mackerras
+# Copyright (C) 2005-2013 Paul Mackerras
 # This file is distributed under the same license as the gitk package.
 #
 # Mikael Magnusson <mikachu@gmail.com>, 2008.
-# Peter Krefting <peter@softwolves.pp.se>, 2008, 2009, 2010, 2012.
+# Peter Krefting <peter@softwolves.pp.se>, 2008, 2009, 2010, 2012, 2013.
 #
 msgid ""
 msgstr ""
 "Project-Id-Version: sv\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2012-10-03 08:09+0100\n"
-"PO-Revision-Date: 2012-10-03 08:13+0100\n"
+"POT-Creation-Date: 2013-05-16 08:06+0100\n"
+"PO-Revision-Date: 2013-05-16 08:12+0100\n"
 "Last-Translator: Peter Krefting <peter@softwolves.pp.se>\n"
 "Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
 "Language: sv\n"
@@ -22,11 +22,11 @@
 msgid "Couldn't get list of unmerged files:"
 msgstr "Kunde inte hämta lista över ej sammanslagna filer:"
 
-#: gitk:210 gitk:2317
+#: gitk:210 gitk:2334
 msgid "Color words"
 msgstr "Färga ord"
 
-#: gitk:215 gitk:2317 gitk:7888 gitk:7921
+#: gitk:215 gitk:2334 gitk:7977 gitk:8010
 msgid "Markup words"
 msgstr "Märk upp ord"
 
@@ -60,11 +60,11 @@
 msgid "Reading"
 msgstr "Läser"
 
-#: gitk:484 gitk:4353
+#: gitk:484 gitk:4409
 msgid "Reading commits..."
 msgstr "Läser incheckningar..."
 
-#: gitk:487 gitk:1625 gitk:4356
+#: gitk:487 gitk:1625 gitk:4412
 msgid "No commits selected"
 msgstr "Inga incheckningar markerade"
 
@@ -80,278 +80,286 @@
 msgid "mc"
 msgstr "mc"
 
-#: gitk:1911 gitk:4146 gitk:9282 gitk:10824 gitk:11100
+#: gitk:1911 gitk:4202 gitk:9437 gitk:10979 gitk:11258
 msgid "OK"
 msgstr "OK"
 
-#: gitk:1913 gitk:4148 gitk:8871 gitk:8950 gitk:9065 gitk:9114 gitk:9284
-#: gitk:10825 gitk:11101
+#: gitk:1913 gitk:4204 gitk:8964 gitk:9043 gitk:9159 gitk:9208 gitk:9439
+#: gitk:10980 gitk:11259
 msgid "Cancel"
 msgstr "Avbryt"
 
-#: gitk:2040
+#: gitk:2048
 msgid "Update"
 msgstr "Uppdatera"
 
-#: gitk:2041
+#: gitk:2049
 msgid "Reload"
 msgstr "Ladda om"
 
-#: gitk:2042
+#: gitk:2050
 msgid "Reread references"
 msgstr "Läs om referenser"
 
-#: gitk:2043
+#: gitk:2051
 msgid "List references"
 msgstr "Visa referenser"
 
-#: gitk:2045
+#: gitk:2053
 msgid "Start git gui"
 msgstr "Starta git gui"
 
-#: gitk:2047
+#: gitk:2055
 msgid "Quit"
 msgstr "Avsluta"
 
-#: gitk:2039
+#: gitk:2047
 msgid "File"
 msgstr "Arkiv"
 
-#: gitk:2051
+#: gitk:2059
 msgid "Preferences"
 msgstr "Inställningar"
 
-#: gitk:2050
+#: gitk:2058
 msgid "Edit"
 msgstr "Redigera"
 
-#: gitk:2055
+#: gitk:2063
 msgid "New view..."
 msgstr "Ny vy..."
 
-#: gitk:2056
+#: gitk:2064
 msgid "Edit view..."
 msgstr "Ändra vy..."
 
-#: gitk:2057
+#: gitk:2065
 msgid "Delete view"
 msgstr "Ta bort vy"
 
-#: gitk:2059
+#: gitk:2067
 msgid "All files"
 msgstr "Alla filer"
 
-#: gitk:2054 gitk:3899
+#: gitk:2062 gitk:3955
 msgid "View"
 msgstr "Visa"
 
-#: gitk:2064 gitk:2074 gitk:2869
+#: gitk:2072 gitk:2082 gitk:2925
 msgid "About gitk"
 msgstr "Om gitk"
 
-#: gitk:2065 gitk:2079
+#: gitk:2073 gitk:2087
 msgid "Key bindings"
 msgstr "Tangentbordsbindningar"
 
-#: gitk:2063 gitk:2078
+#: gitk:2071 gitk:2086
 msgid "Help"
 msgstr "Hjälp"
 
-#: gitk:2156 gitk:8330
+#: gitk:2164 gitk:8420
 msgid "SHA1 ID:"
 msgstr "SHA1-id:"
 
-#: gitk:2192
+#: gitk:2208
 msgid "Row"
 msgstr "Rad"
 
-#: gitk:2230
+#: gitk:2246
 msgid "Find"
 msgstr "Sök"
 
-#: gitk:2231
+#: gitk:2247
 msgid "next"
 msgstr "nästa"
 
-#: gitk:2232
+#: gitk:2248
 msgid "prev"
 msgstr "föreg"
 
-#: gitk:2233
+#: gitk:2249
 msgid "commit"
 msgstr "incheckning"
 
-#: gitk:2236 gitk:2238 gitk:4514 gitk:4537 gitk:4561 gitk:6528 gitk:6600
-#: gitk:6685
+#: gitk:2252 gitk:2254 gitk:4570 gitk:4593 gitk:4617 gitk:6592 gitk:6664
+#: gitk:6749
 msgid "containing:"
 msgstr "som innehåller:"
 
-#: gitk:2239 gitk:3381 gitk:3386 gitk:4590
+#: gitk:2255 gitk:3437 gitk:3442 gitk:4646
 msgid "touching paths:"
 msgstr "som rör sökväg:"
 
-#: gitk:2240 gitk:4604
+#: gitk:2256 gitk:4660
 msgid "adding/removing string:"
 msgstr "som lägger/till tar bort sträng:"
 
-#: gitk:2249 gitk:2251 gitk:4593
+#: gitk:2257 gitk:4662
+msgid "changing lines matching:"
+msgstr "ändrar rader som matchar:"
+
+#: gitk:2266 gitk:2268 gitk:4649
 msgid "Exact"
 msgstr "Exakt"
 
-#: gitk:2251 gitk:4679 gitk:6496
+#: gitk:2268 gitk:4737 gitk:6560
 msgid "IgnCase"
 msgstr "IgnVersaler"
 
-#: gitk:2251 gitk:4563 gitk:4677 gitk:6492
+#: gitk:2268 gitk:4619 gitk:4735 gitk:6556
 msgid "Regexp"
 msgstr "Reg.uttr."
 
-#: gitk:2253 gitk:2254 gitk:4699 gitk:4729 gitk:4736 gitk:6621 gitk:6689
+#: gitk:2270 gitk:2271 gitk:4757 gitk:4787 gitk:4794 gitk:6685 gitk:6753
 msgid "All fields"
 msgstr "Alla fält"
 
-#: gitk:2254 gitk:4696 gitk:4729 gitk:6559
+#: gitk:2271 gitk:4754 gitk:4787 gitk:6623
 msgid "Headline"
 msgstr "Rubrik"
 
-#: gitk:2255 gitk:4696 gitk:6559 gitk:6689 gitk:7126
+#: gitk:2272 gitk:4754 gitk:6623 gitk:6753 gitk:7221
 msgid "Comments"
 msgstr "Kommentarer"
 
-#: gitk:2255 gitk:4696 gitk:4701 gitk:4736 gitk:6559 gitk:7061 gitk:8505
-#: gitk:8520
+#: gitk:2272 gitk:4754 gitk:4759 gitk:4794 gitk:6623 gitk:7156 gitk:8598
+#: gitk:8613
 msgid "Author"
 msgstr "Författare"
 
-#: gitk:2255 gitk:4696 gitk:6559 gitk:7063
+#: gitk:2272 gitk:4754 gitk:6623 gitk:7158
 msgid "Committer"
 msgstr "Incheckare"
 
-#: gitk:2286
+#: gitk:2303
 msgid "Search"
 msgstr "Sök"
 
-#: gitk:2294
+#: gitk:2311
 msgid "Diff"
 msgstr "Diff"
 
-#: gitk:2296
+#: gitk:2313
 msgid "Old version"
 msgstr "Gammal version"
 
-#: gitk:2298
+#: gitk:2315
 msgid "New version"
 msgstr "Ny version"
 
-#: gitk:2300
+#: gitk:2317
 msgid "Lines of context"
 msgstr "Rader sammanhang"
 
-#: gitk:2310
+#: gitk:2327
 msgid "Ignore space change"
 msgstr "Ignorera ändringar i blanksteg"
 
-#: gitk:2314 gitk:2316 gitk:7646 gitk:7874
+#: gitk:2331 gitk:2333 gitk:7735 gitk:7963
 msgid "Line diff"
 msgstr "Rad-diff"
 
-#: gitk:2379
+#: gitk:2397
 msgid "Patch"
 msgstr "Patch"
 
-#: gitk:2381
+#: gitk:2399
 msgid "Tree"
 msgstr "Träd"
 
-#: gitk:2540 gitk:2559
+#: gitk:2557 gitk:2577
 msgid "Diff this -> selected"
 msgstr "Diff denna -> markerad"
 
-#: gitk:2541 gitk:2560
+#: gitk:2558 gitk:2578
 msgid "Diff selected -> this"
 msgstr "Diff markerad -> denna"
 
-#: gitk:2542 gitk:2561
+#: gitk:2559 gitk:2579
 msgid "Make patch"
 msgstr "Skapa patch"
 
-#: gitk:2543 gitk:8929
+#: gitk:2560 gitk:9022
 msgid "Create tag"
 msgstr "Skapa tagg"
 
-#: gitk:2544 gitk:9045
+#: gitk:2561 gitk:9139
 msgid "Write commit to file"
 msgstr "Skriv incheckning till fil"
 
-#: gitk:2545 gitk:9102
+#: gitk:2562 gitk:9196
 msgid "Create new branch"
 msgstr "Skapa ny gren"
 
-#: gitk:2546
+#: gitk:2563
 msgid "Cherry-pick this commit"
 msgstr "Plocka denna incheckning"
 
-#: gitk:2547
+#: gitk:2564
 msgid "Reset HEAD branch to here"
 msgstr "Återställ HEAD-grenen hit"
 
-#: gitk:2548
+#: gitk:2565
 msgid "Mark this commit"
 msgstr "Markera denna incheckning"
 
-#: gitk:2549
+#: gitk:2566
 msgid "Return to mark"
 msgstr "Återgå till markering"
 
-#: gitk:2550
+#: gitk:2567
 msgid "Find descendant of this and mark"
 msgstr "Hitta efterföljare till denna och markera"
 
-#: gitk:2551
+#: gitk:2568
 msgid "Compare with marked commit"
 msgstr "Jämför med markerad incheckning"
 
-#: gitk:2552 gitk:2562
+#: gitk:2569 gitk:2580
 msgid "Diff this -> marked commit"
 msgstr "Diff denna -> markerad incheckning"
 
-#: gitk:2553 gitk:2563
+#: gitk:2570 gitk:2581
 msgid "Diff marked commit -> this"
 msgstr "Diff markerad incheckning -> denna"
 
-#: gitk:2569
+#: gitk:2571
+msgid "Revert this commit"
+msgstr "Ångra denna incheckning"
+
+#: gitk:2587
 msgid "Check out this branch"
 msgstr "Checka ut denna gren"
 
-#: gitk:2570
+#: gitk:2588
 msgid "Remove this branch"
 msgstr "Ta bort denna gren"
 
-#: gitk:2577
+#: gitk:2595
 msgid "Highlight this too"
 msgstr "Markera även detta"
 
-#: gitk:2578
+#: gitk:2596
 msgid "Highlight this only"
 msgstr "Markera bara detta"
 
-#: gitk:2579
+#: gitk:2597
 msgid "External diff"
 msgstr "Extern diff"
 
-#: gitk:2580
+#: gitk:2598
 msgid "Blame parent commit"
 msgstr "Klandra föräldraincheckning"
 
-#: gitk:2587
+#: gitk:2605
 msgid "Show origin of this line"
 msgstr "Visa ursprunget för den här raden"
 
-#: gitk:2588
+#: gitk:2606
 msgid "Run git gui blame on this line"
 msgstr "Kör git gui blame på den här raden"
 
-#: gitk:2871
+#: gitk:2927
 msgid ""
 "\n"
 "Gitk - a commit viewer for git\n"
@@ -367,302 +375,302 @@
 "\n"
 "Använd och vidareförmedla enligt villkoren i GNU General Public License"
 
-#: gitk:2879 gitk:2944 gitk:9468
+#: gitk:2935 gitk:3000 gitk:9623
 msgid "Close"
 msgstr "Stäng"
 
-#: gitk:2900
+#: gitk:2956
 msgid "Gitk key bindings"
 msgstr "Tangentbordsbindningar för Gitk"
 
-#: gitk:2903
+#: gitk:2959
 msgid "Gitk key bindings:"
 msgstr "Tangentbordsbindningar för Gitk:"
 
-#: gitk:2905
+#: gitk:2961
 #, tcl-format
 msgid "<%s-Q>\t\tQuit"
 msgstr "<%s-Q>\t\tAvsluta"
 
-#: gitk:2906
+#: gitk:2962
 #, tcl-format
 msgid "<%s-W>\t\tClose window"
 msgstr "<%s-W>\t\tStäng fönster"
 
-#: gitk:2907
+#: gitk:2963
 msgid "<Home>\t\tMove to first commit"
 msgstr "<Home>\t\tGå till första incheckning"
 
-#: gitk:2908
+#: gitk:2964
 msgid "<End>\t\tMove to last commit"
 msgstr "<End>\t\tGå till sista incheckning"
 
-#: gitk:2909
+#: gitk:2965
 msgid "<Up>, p, k\tMove up one commit"
 msgstr "<Upp>, p, k\tGå en incheckning upp"
 
-#: gitk:2910
+#: gitk:2966
 msgid "<Down>, n, j\tMove down one commit"
 msgstr "<Ned>, n, j\tGå en incheckning ned"
 
-#: gitk:2911
+#: gitk:2967
 msgid "<Left>, z, h\tGo back in history list"
 msgstr "<Vänster>, z, h\tGå bakåt i historiken"
 
-#: gitk:2912
+#: gitk:2968
 msgid "<Right>, x, l\tGo forward in history list"
 msgstr "<Höger>, x, l\tGå framåt i historiken"
 
-#: gitk:2913
+#: gitk:2969
 msgid "<PageUp>\tMove up one page in commit list"
 msgstr "<PageUp>\tGå upp en sida i incheckningslistan"
 
-#: gitk:2914
+#: gitk:2970
 msgid "<PageDown>\tMove down one page in commit list"
 msgstr "<PageDown>\tGå ned en sida i incheckningslistan"
 
-#: gitk:2915
+#: gitk:2971
 #, tcl-format
 msgid "<%s-Home>\tScroll to top of commit list"
 msgstr "<%s-Home>\tRulla till början av incheckningslistan"
 
-#: gitk:2916
+#: gitk:2972
 #, tcl-format
 msgid "<%s-End>\tScroll to bottom of commit list"
 msgstr "<%s-End>\tRulla till slutet av incheckningslistan"
 
-#: gitk:2917
+#: gitk:2973
 #, tcl-format
 msgid "<%s-Up>\tScroll commit list up one line"
 msgstr "<%s-Upp>\tRulla incheckningslistan upp ett steg"
 
-#: gitk:2918
+#: gitk:2974
 #, tcl-format
 msgid "<%s-Down>\tScroll commit list down one line"
 msgstr "<%s-Ned>\tRulla incheckningslistan ned ett steg"
 
-#: gitk:2919
+#: gitk:2975
 #, tcl-format
 msgid "<%s-PageUp>\tScroll commit list up one page"
 msgstr "<%s-PageUp>\tRulla incheckningslistan upp en sida"
 
-#: gitk:2920
+#: gitk:2976
 #, tcl-format
 msgid "<%s-PageDown>\tScroll commit list down one page"
 msgstr "<%s-PageDown>\tRulla incheckningslistan ned en sida"
 
-#: gitk:2921
+#: gitk:2977
 msgid "<Shift-Up>\tFind backwards (upwards, later commits)"
 msgstr "<Skift-Upp>\tSök bakåt (uppåt, senare incheckningar)"
 
-#: gitk:2922
+#: gitk:2978
 msgid "<Shift-Down>\tFind forwards (downwards, earlier commits)"
 msgstr "<Skift-Ned>\tSök framåt (nedåt, tidigare incheckningar)"
 
-#: gitk:2923
+#: gitk:2979
 msgid "<Delete>, b\tScroll diff view up one page"
 msgstr "<Delete>, b\tRulla diffvisningen upp en sida"
 
-#: gitk:2924
+#: gitk:2980
 msgid "<Backspace>\tScroll diff view up one page"
 msgstr "<Baksteg>\tRulla diffvisningen upp en sida"
 
-#: gitk:2925
+#: gitk:2981
 msgid "<Space>\t\tScroll diff view down one page"
 msgstr "<Blanksteg>\tRulla diffvisningen ned en sida"
 
-#: gitk:2926
+#: gitk:2982
 msgid "u\t\tScroll diff view up 18 lines"
 msgstr "u\t\tRulla diffvisningen upp 18 rader"
 
-#: gitk:2927
+#: gitk:2983
 msgid "d\t\tScroll diff view down 18 lines"
 msgstr "d\t\tRulla diffvisningen ned 18 rader"
 
-#: gitk:2928
+#: gitk:2984
 #, tcl-format
 msgid "<%s-F>\t\tFind"
 msgstr "<%s-F>\t\tSök"
 
-#: gitk:2929
+#: gitk:2985
 #, tcl-format
 msgid "<%s-G>\t\tMove to next find hit"
 msgstr "<%s-G>\t\tGå till nästa sökträff"
 
-#: gitk:2930
+#: gitk:2986
 msgid "<Return>\tMove to next find hit"
 msgstr "<Return>\t\tGå till nästa sökträff"
 
-#: gitk:2931
+#: gitk:2987
 msgid "/\t\tFocus the search box"
 msgstr "/\t\tFokusera sökrutan"
 
-#: gitk:2932
+#: gitk:2988
 msgid "?\t\tMove to previous find hit"
 msgstr "?\t\tGå till föregående sökträff"
 
-#: gitk:2933
+#: gitk:2989
 msgid "f\t\tScroll diff view to next file"
 msgstr "f\t\tRulla diffvisningen till nästa fil"
 
-#: gitk:2934
+#: gitk:2990
 #, tcl-format
 msgid "<%s-S>\t\tSearch for next hit in diff view"
 msgstr "<%s-S>\t\tGå till nästa sökträff i diffvisningen"
 
-#: gitk:2935
+#: gitk:2991
 #, tcl-format
 msgid "<%s-R>\t\tSearch for previous hit in diff view"
 msgstr "<%s-R>\t\tGå till föregående sökträff i diffvisningen"
 
-#: gitk:2936
+#: gitk:2992
 #, tcl-format
 msgid "<%s-KP+>\tIncrease font size"
 msgstr "<%s-Num+>\tÖka teckenstorlek"
 
-#: gitk:2937
+#: gitk:2993
 #, tcl-format
 msgid "<%s-plus>\tIncrease font size"
 msgstr "<%s-plus>\tÖka teckenstorlek"
 
-#: gitk:2938
+#: gitk:2994
 #, tcl-format
 msgid "<%s-KP->\tDecrease font size"
 msgstr "<%s-Num->\tMinska teckenstorlek"
 
-#: gitk:2939
+#: gitk:2995
 #, tcl-format
 msgid "<%s-minus>\tDecrease font size"
 msgstr "<%s-minus>\tMinska teckenstorlek"
 
-#: gitk:2940
+#: gitk:2996
 msgid "<F5>\t\tUpdate"
 msgstr "<F5>\t\tUppdatera"
 
-#: gitk:3395 gitk:3404
+#: gitk:3451 gitk:3460
 #, tcl-format
 msgid "Error creating temporary directory %s:"
 msgstr "Fel vid skapande av temporär katalog %s:"
 
-#: gitk:3417
+#: gitk:3473
 #, tcl-format
 msgid "Error getting \"%s\" from %s:"
 msgstr "Fel vid hämtning av  \"%s\" från %s:"
 
-#: gitk:3480
+#: gitk:3536
 msgid "command failed:"
 msgstr "kommando misslyckades:"
 
-#: gitk:3629
+#: gitk:3685
 msgid "No such commit"
 msgstr "Incheckning saknas"
 
-#: gitk:3643
+#: gitk:3699
 msgid "git gui blame: command failed:"
 msgstr "git gui blame: kommando misslyckades:"
 
-#: gitk:3674
+#: gitk:3730
 #, tcl-format
 msgid "Couldn't read merge head: %s"
 msgstr "Kunde inte läsa sammanslagningshuvud: %s"
 
-#: gitk:3682
+#: gitk:3738
 #, tcl-format
 msgid "Error reading index: %s"
 msgstr "Fel vid läsning av index: %s"
 
-#: gitk:3707
+#: gitk:3763
 #, tcl-format
 msgid "Couldn't start git blame: %s"
 msgstr "Kunde inte starta git blame: %s"
 
-#: gitk:3710 gitk:6527
+#: gitk:3766 gitk:6591
 msgid "Searching"
 msgstr "Söker"
 
-#: gitk:3742
+#: gitk:3798
 #, tcl-format
 msgid "Error running git blame: %s"
 msgstr "Fel vid körning av git blame: %s"
 
-#: gitk:3770
+#: gitk:3826
 #, tcl-format
 msgid "That line comes from commit %s,  which is not in this view"
 msgstr "Raden kommer från incheckningen %s, som inte finns i denna vy"
 
-#: gitk:3784
+#: gitk:3840
 msgid "External diff viewer failed:"
 msgstr "Externt diff-verktyg misslyckades:"
 
-#: gitk:3902
+#: gitk:3958
 msgid "Gitk view definition"
 msgstr "Definition av Gitk-vy"
 
-#: gitk:3906
+#: gitk:3962
 msgid "Remember this view"
 msgstr "Spara denna vy"
 
-#: gitk:3907
+#: gitk:3963
 msgid "References (space separated list):"
 msgstr "Referenser (blankstegsavdelad lista):"
 
-#: gitk:3908
+#: gitk:3964
 msgid "Branches & tags:"
 msgstr "Grenar & taggar:"
 
-#: gitk:3909
+#: gitk:3965
 msgid "All refs"
 msgstr "Alla referenser"
 
-#: gitk:3910
+#: gitk:3966
 msgid "All (local) branches"
 msgstr "Alla (lokala) grenar"
 
-#: gitk:3911
+#: gitk:3967
 msgid "All tags"
 msgstr "Alla taggar"
 
-#: gitk:3912
+#: gitk:3968
 msgid "All remote-tracking branches"
 msgstr "Alla fjärrspårande grenar"
 
-#: gitk:3913
+#: gitk:3969
 msgid "Commit Info (regular expressions):"
 msgstr "Incheckningsinfo (reguljära uttryck):"
 
-#: gitk:3914
+#: gitk:3970
 msgid "Author:"
 msgstr "Författare:"
 
-#: gitk:3915
+#: gitk:3971
 msgid "Committer:"
 msgstr "Incheckare:"
 
-#: gitk:3916
+#: gitk:3972
 msgid "Commit Message:"
 msgstr "Incheckningsmeddelande:"
 
-#: gitk:3917
+#: gitk:3973
 msgid "Matches all Commit Info criteria"
 msgstr "Motsvarar alla kriterier för incheckningsinfo"
 
-#: gitk:3918
+#: gitk:3974
 msgid "Changes to Files:"
 msgstr "Ändringar av filer:"
 
-#: gitk:3919
+#: gitk:3975
 msgid "Fixed String"
 msgstr "Fast sträng"
 
-#: gitk:3920
+#: gitk:3976
 msgid "Regular Expression"
 msgstr "Reguljärt uttryck"
 
-#: gitk:3921
+#: gitk:3977
 msgid "Search string:"
 msgstr "Söksträng:"
 
-#: gitk:3922
+#: gitk:3978
 msgid ""
 "Commit Dates (\"2 weeks ago\", \"2009-03-17 15:27:38\", \"March 17, 2009 "
 "15:27:38\"):"
@@ -670,197 +678,201 @@
 "Incheckingsdatum (\"2 weeks ago\", \"2009-03-17 15:27:38\", \"March 17, 2009 "
 "15:27:38\"):"
 
-#: gitk:3923
+#: gitk:3979
 msgid "Since:"
 msgstr "Från:"
 
-#: gitk:3924
+#: gitk:3980
 msgid "Until:"
 msgstr "Till:"
 
-#: gitk:3925
+#: gitk:3981
 msgid "Limit and/or skip a number of revisions (positive integer):"
 msgstr "Begränsa och/eller hoppa över ett antal revisioner (positivt heltal):"
 
-#: gitk:3926
+#: gitk:3982
 msgid "Number to show:"
 msgstr "Antal att visa:"
 
-#: gitk:3927
+#: gitk:3983
 msgid "Number to skip:"
 msgstr "Antal att hoppa över:"
 
-#: gitk:3928
+#: gitk:3984
 msgid "Miscellaneous options:"
 msgstr "Diverse alternativ:"
 
-#: gitk:3929
+#: gitk:3985
 msgid "Strictly sort by date"
 msgstr "Strikt datumsortering"
 
-#: gitk:3930
+#: gitk:3986
 msgid "Mark branch sides"
 msgstr "Markera sidogrenar"
 
-#: gitk:3931
+#: gitk:3987
 msgid "Limit to first parent"
 msgstr "Begränsa till första förälder"
 
-#: gitk:3932
+#: gitk:3988
 msgid "Simple history"
 msgstr "Enkel historik"
 
-#: gitk:3933
+#: gitk:3989
 msgid "Additional arguments to git log:"
 msgstr "Ytterligare argument till git log:"
 
-#: gitk:3934
+#: gitk:3990
 msgid "Enter files and directories to include, one per line:"
 msgstr "Ange filer och kataloger att ta med, en per rad:"
 
-#: gitk:3935
+#: gitk:3991
 msgid "Command to generate more commits to include:"
 msgstr "Kommando för att generera fler incheckningar att ta med:"
 
-#: gitk:4059
+#: gitk:4115
 msgid "Gitk: edit view"
 msgstr "Gitk: redigera vy"
 
-#: gitk:4067
+#: gitk:4123
 msgid "-- criteria for selecting revisions"
 msgstr " - kriterier för val av revisioner"
 
-#: gitk:4072
+#: gitk:4128
 msgid "View Name"
 msgstr "Namn på vy"
 
-#: gitk:4147
+#: gitk:4203
 msgid "Apply (F5)"
 msgstr "Använd (F5)"
 
-#: gitk:4185
+#: gitk:4241
 msgid "Error in commit selection arguments:"
 msgstr "Fel i argument för val av incheckningar:"
 
-#: gitk:4238 gitk:4290 gitk:4749 gitk:4763 gitk:6027 gitk:11849 gitk:11850
+#: gitk:4294 gitk:4346 gitk:4807 gitk:4821 gitk:6087 gitk:12041 gitk:12042
 msgid "None"
 msgstr "Inget"
 
-#: gitk:4846 gitk:4851
+#: gitk:4904 gitk:4909
 msgid "Descendant"
 msgstr "Avkomling"
 
-#: gitk:4847
+#: gitk:4905
 msgid "Not descendant"
 msgstr "Inte avkomling"
 
-#: gitk:4854 gitk:4859
+#: gitk:4912 gitk:4917
 msgid "Ancestor"
 msgstr "Förfader"
 
-#: gitk:4855
+#: gitk:4913
 msgid "Not ancestor"
 msgstr "Inte förfader"
 
-#: gitk:5145
+#: gitk:5203
 msgid "Local changes checked in to index but not committed"
 msgstr "Lokala ändringar sparade i indexet men inte incheckade"
 
-#: gitk:5181
+#: gitk:5239
 msgid "Local uncommitted changes, not checked in to index"
 msgstr "Lokala ändringar, ej sparade i indexet"
 
-#: gitk:6882
+#: gitk:6971
+msgid "and many more"
+msgstr "med många flera"
+
+#: gitk:6974
 msgid "many"
 msgstr "många"
 
-#: gitk:7065
+#: gitk:7160
 msgid "Tags:"
 msgstr "Taggar:"
 
-#: gitk:7082 gitk:7088 gitk:8500
+#: gitk:7177 gitk:7183 gitk:8593
 msgid "Parent"
 msgstr "Förälder"
 
-#: gitk:7093
+#: gitk:7188
 msgid "Child"
 msgstr "Barn"
 
-#: gitk:7102
+#: gitk:7197
 msgid "Branch"
 msgstr "Gren"
 
-#: gitk:7105
+#: gitk:7200
 msgid "Follows"
 msgstr "Följer"
 
-#: gitk:7108
+#: gitk:7203
 msgid "Precedes"
 msgstr "Föregår"
 
-#: gitk:7653
+#: gitk:7742
 #, tcl-format
 msgid "Error getting diffs: %s"
 msgstr "Fel vid hämtning av diff: %s"
 
-#: gitk:8328
+#: gitk:8418
 msgid "Goto:"
 msgstr "Gå till:"
 
-#: gitk:8349
+#: gitk:8439
 #, tcl-format
 msgid "Short SHA1 id %s is ambiguous"
 msgstr "Förkortat SHA1-id %s är tvetydigt"
 
-#: gitk:8356
+#: gitk:8446
 #, tcl-format
 msgid "Revision %s is not known"
 msgstr "Revisionen %s är inte känd"
 
-#: gitk:8366
+#: gitk:8456
 #, tcl-format
 msgid "SHA1 id %s is not known"
 msgstr "SHA-id:t %s är inte känt"
 
-#: gitk:8368
+#: gitk:8458
 #, tcl-format
 msgid "Revision %s is not in the current view"
 msgstr "Revisionen %s finns inte i den nuvarande vyn"
 
-#: gitk:8507 gitk:8522
+#: gitk:8600 gitk:8615
 msgid "Date"
 msgstr "Datum"
 
-#: gitk:8510
+#: gitk:8603
 msgid "Children"
 msgstr "Barn"
 
-#: gitk:8573
+#: gitk:8666
 #, tcl-format
 msgid "Reset %s branch to here"
 msgstr "Återställ grenen %s hit"
 
-#: gitk:8575
+#: gitk:8668
 msgid "Detached head: can't reset"
 msgstr "Frånkopplad head: kan inte återställa"
 
-#: gitk:8680 gitk:8686
+#: gitk:8773 gitk:8779
 msgid "Skipping merge commit "
 msgstr "Hoppar över sammanslagningsincheckning "
 
-#: gitk:8695 gitk:8700
+#: gitk:8788 gitk:8793
 msgid "Error getting patch ID for "
 msgstr "Fel vid hämtning av patch-id för "
 
-#: gitk:8696 gitk:8701
+#: gitk:8789 gitk:8794
 msgid " - stopping\n"
 msgstr " - stannar\n"
 
-#: gitk:8706 gitk:8709 gitk:8717 gitk:8731 gitk:8740
+#: gitk:8799 gitk:8802 gitk:8810 gitk:8824 gitk:8833
 msgid "Commit "
 msgstr "Incheckning "
 
-#: gitk:8710
+#: gitk:8803
 msgid ""
 " is the same patch as\n"
 "       "
@@ -868,7 +880,7 @@
 " är samma patch som\n"
 "       "
 
-#: gitk:8718
+#: gitk:8811
 msgid ""
 " differs from\n"
 "       "
@@ -876,7 +888,7 @@
 " skiljer sig från\n"
 "       "
 
-#: gitk:8720
+#: gitk:8813
 msgid ""
 "Diff of commits:\n"
 "\n"
@@ -884,131 +896,131 @@
 "Skillnad mellan incheckningar:\n"
 "\n"
 
-#: gitk:8732 gitk:8741
+#: gitk:8825 gitk:8834
 #, tcl-format
 msgid " has %s children - stopping\n"
 msgstr " har %s barn - stannar\n"
 
-#: gitk:8760
+#: gitk:8853
 #, tcl-format
 msgid "Error writing commit to file: %s"
 msgstr "Fel vid skrivning av incheckning till fil: %s"
 
-#: gitk:8766
+#: gitk:8859
 #, tcl-format
 msgid "Error diffing commits: %s"
 msgstr "Fel vid jämförelse av incheckningar: %s"
 
-#: gitk:8812
+#: gitk:8905
 msgid "Top"
 msgstr "Topp"
 
-#: gitk:8813
+#: gitk:8906
 msgid "From"
 msgstr "Från"
 
-#: gitk:8818
+#: gitk:8911
 msgid "To"
 msgstr "Till"
 
-#: gitk:8842
+#: gitk:8935
 msgid "Generate patch"
 msgstr "Generera patch"
 
-#: gitk:8844
+#: gitk:8937
 msgid "From:"
 msgstr "Från:"
 
-#: gitk:8853
+#: gitk:8946
 msgid "To:"
 msgstr "Till:"
 
-#: gitk:8862
+#: gitk:8955
 msgid "Reverse"
 msgstr "Vänd"
 
-#: gitk:8864 gitk:9059
+#: gitk:8957 gitk:9153
 msgid "Output file:"
 msgstr "Utdatafil:"
 
-#: gitk:8870
+#: gitk:8963
 msgid "Generate"
 msgstr "Generera"
 
-#: gitk:8908
+#: gitk:9001
 msgid "Error creating patch:"
 msgstr "Fel vid generering av patch:"
 
-#: gitk:8931 gitk:9047 gitk:9104
+#: gitk:9024 gitk:9141 gitk:9198
 msgid "ID:"
 msgstr "Id:"
 
-#: gitk:8940
+#: gitk:9033
 msgid "Tag name:"
 msgstr "Taggnamn:"
 
-#: gitk:8943
+#: gitk:9036
 msgid "Tag message is optional"
 msgstr "Taggmeddelandet är valfritt"
 
-#: gitk:8945
+#: gitk:9038
 msgid "Tag message:"
 msgstr "Taggmeddelande:"
 
-#: gitk:8949 gitk:9113
+#: gitk:9042 gitk:9207
 msgid "Create"
 msgstr "Skapa"
 
-#: gitk:8967
+#: gitk:9060
 msgid "No tag name specified"
 msgstr "Inget taggnamn angavs"
 
-#: gitk:8971
+#: gitk:9064
 #, tcl-format
 msgid "Tag \"%s\" already exists"
 msgstr "Taggen \"%s\" finns redan"
 
-#: gitk:8981
+#: gitk:9074
 msgid "Error creating tag:"
 msgstr "Fel vid skapande av tagg:"
 
-#: gitk:9056
+#: gitk:9150
 msgid "Command:"
 msgstr "Kommando:"
 
-#: gitk:9064
+#: gitk:9158
 msgid "Write"
 msgstr "Skriv"
 
-#: gitk:9082
+#: gitk:9176
 msgid "Error writing commit:"
 msgstr "Fel vid skrivning av incheckning:"
 
-#: gitk:9109
+#: gitk:9203
 msgid "Name:"
 msgstr "Namn:"
 
-#: gitk:9132
+#: gitk:9226
 msgid "Please specify a name for the new branch"
 msgstr "Ange ett namn för den nya grenen"
 
-#: gitk:9137
+#: gitk:9231
 #, tcl-format
 msgid "Branch '%s' already exists. Overwrite?"
 msgstr "Grenen \"%s\" finns redan. Skriva över?"
 
-#: gitk:9204
+#: gitk:9298
 #, tcl-format
 msgid "Commit %s is already included in branch %s -- really re-apply it?"
 msgstr ""
 "Incheckningen %s finns redan på grenen %s -- skall den verkligen appliceras "
 "på nytt?"
 
-#: gitk:9209
+#: gitk:9303
 msgid "Cherry-picking"
 msgstr "Plockar"
 
-#: gitk:9218
+#: gitk:9312
 #, tcl-format
 msgid ""
 "Cherry-pick failed because of local changes to file '%s'.\n"
@@ -1018,7 +1030,7 @@
 "Checka in, återställ eller spara undan (stash) dina ändringar och försök "
 "igen."
 
-#: gitk:9224
+#: gitk:9318
 msgid ""
 "Cherry-pick failed because of merge conflict.\n"
 "Do you wish to run git citool to resolve it?"
@@ -1026,32 +1038,59 @@
 "Cherry-pick misslyckades på grund av en sammanslagningskonflikt.\n"
 "Vill du köra git citool för att lösa den?"
 
-#: gitk:9240
+#: gitk:9334 gitk:9392
 msgid "No changes committed"
 msgstr "Inga ändringar incheckade"
 
-#: gitk:9266
+#: gitk:9361
+#, tcl-format
+msgid "Commit %s is not included in branch %s -- really revert it?"
+msgstr "Incheckningen %s finns inte på grenen %s -- vill du verkligen ångra?"
+
+#: gitk:9366
+msgid "Reverting"
+msgstr "Ångrar"
+
+#: gitk:9374
+#, tcl-format
+msgid ""
+"Revert failed because of local changes to the following files:%s Please "
+"commit, reset or stash  your changes and try again."
+msgstr ""
+"Misslyckades med att ångra på grund av lokala ändringar i följande filer:%s. "
+"Checka in, återställ eller spara undan (stash) dina ändringar och försök "
+"igen."
+
+#: gitk:9378
+msgid ""
+"Revert failed because of merge conflict.\n"
+" Do you wish to run git citool to resolve it?"
+msgstr ""
+"Misslyckades med att ångra på grund av en sammanslagningskonflikt.\n"
+" Vill du köra git citool för att lösa den?"
+
+#: gitk:9421
 msgid "Confirm reset"
 msgstr "Bekräfta återställning"
 
-#: gitk:9268
+#: gitk:9423
 #, tcl-format
 msgid "Reset branch %s to %s?"
 msgstr "Återställa grenen %s till %s?"
 
-#: gitk:9270
+#: gitk:9425
 msgid "Reset type:"
 msgstr "Typ av återställning:"
 
-#: gitk:9273
+#: gitk:9428
 msgid "Soft: Leave working tree and index untouched"
 msgstr "Mjuk: Rör inte utcheckning och index"
 
-#: gitk:9276
+#: gitk:9431
 msgid "Mixed: Leave working tree untouched, reset index"
 msgstr "Blandad: Rör inte utcheckning, återställ index"
 
-#: gitk:9279
+#: gitk:9434
 msgid ""
 "Hard: Reset working tree and index\n"
 "(discard ALL local changes)"
@@ -1059,19 +1098,19 @@
 "Hård: Återställ utcheckning och index\n"
 "(förkastar ALLA lokala ändringar)"
 
-#: gitk:9296
+#: gitk:9451
 msgid "Resetting"
 msgstr "Återställer"
 
-#: gitk:9356
+#: gitk:9511
 msgid "Checking out"
 msgstr "Checkar ut"
 
-#: gitk:9409
+#: gitk:9564
 msgid "Cannot delete the currently checked-out branch"
 msgstr "Kan inte ta bort den just nu utcheckade grenen"
 
-#: gitk:9415
+#: gitk:9570
 #, tcl-format
 msgid ""
 "The commits on branch %s aren't on any other branch.\n"
@@ -1080,16 +1119,16 @@
 "Incheckningarna på grenen %s existerar inte på någon annan gren.\n"
 "Vill du verkligen ta bort grenen %s?"
 
-#: gitk:9446
+#: gitk:9601
 #, tcl-format
 msgid "Tags and heads: %s"
 msgstr "Taggar och huvuden: %s"
 
-#: gitk:9461
+#: gitk:9616
 msgid "Filter"
 msgstr "Filter"
 
-#: gitk:9757
+#: gitk:9912
 msgid ""
 "Error reading commit topology information; branch and preceding/following "
 "tag information will be incomplete."
@@ -1097,210 +1136,214 @@
 "Fel vid läsning av information om incheckningstopologi; information om "
 "grenar och föregående/senare taggar kommer inte vara komplett."
 
-#: gitk:10744
+#: gitk:10899
 msgid "Tag"
 msgstr "Tagg"
 
-#: gitk:10744
+#: gitk:10899
 msgid "Id"
 msgstr "Id"
 
-#: gitk:10793
+#: gitk:10948
 msgid "Gitk font chooser"
 msgstr "Teckensnittsväljare för Gitk"
 
-#: gitk:10810
+#: gitk:10965
 msgid "B"
 msgstr "F"
 
-#: gitk:10813
+#: gitk:10968
 msgid "I"
 msgstr "K"
 
-#: gitk:10931
+#: gitk:11086
 msgid "Commit list display options"
 msgstr "Alternativ för incheckningslistvy"
 
-#: gitk:10934
+#: gitk:11089
 msgid "Maximum graph width (lines)"
 msgstr "Maximal grafbredd (rader)"
 
-#: gitk:10937
+#: gitk:11092
 #, tcl-format
 msgid "Maximum graph width (% of pane)"
 msgstr "Maximal grafbredd (% av ruta)"
 
-#: gitk:10940
+#: gitk:11095
 msgid "Show local changes"
 msgstr "Visa lokala ändringar"
 
-#: gitk:10943
+#: gitk:11098
 msgid "Auto-select SHA1 (length)"
 msgstr "Välj SHA1 (längd) automatiskt"
 
-#: gitk:10947
+#: gitk:11102
 msgid "Hide remote refs"
 msgstr "Dölj fjärr-referenser"
 
-#: gitk:10951
+#: gitk:11106
 msgid "Diff display options"
 msgstr "Alternativ för diffvy"
 
-#: gitk:10953
+#: gitk:11108
 msgid "Tab spacing"
 msgstr "Blanksteg för tabulatortecken"
 
-#: gitk:10956
-msgid "Display nearby tags"
-msgstr "Visa närliggande taggar"
+#: gitk:11111
+msgid "Display nearby tags/heads"
+msgstr "Visa närliggande taggar/huvuden"
 
-#: gitk:10959
+#: gitk:11114
+msgid "Maximum # tags/heads to show"
+msgstr "Maximalt antal taggar/huvuden att visa"
+
+#: gitk:11117
 msgid "Limit diffs to listed paths"
 msgstr "Begränsa diff till listade sökvägar"
 
-#: gitk:10962
+#: gitk:11120
 msgid "Support per-file encodings"
 msgstr "Stöd för filspecifika teckenkodningar"
 
-#: gitk:10968 gitk:11115
+#: gitk:11126 gitk:11273
 msgid "External diff tool"
 msgstr "Externt diff-verktyg"
 
-#: gitk:10969
+#: gitk:11127
 msgid "Choose..."
 msgstr "Välj..."
 
-#: gitk:10974
+#: gitk:11132
 msgid "General options"
 msgstr "Allmänna inställningar"
 
-#: gitk:10977
+#: gitk:11135
 msgid "Use themed widgets"
 msgstr "Använd tema på fönsterelement"
 
-#: gitk:10979
+#: gitk:11137
 msgid "(change requires restart)"
 msgstr "(ändringen kräver omstart)"
 
-#: gitk:10981
+#: gitk:11139
 msgid "(currently unavailable)"
 msgstr "(för närvarande inte tillgängligt)"
 
-#: gitk:10992
+#: gitk:11150
 msgid "Colors: press to choose"
 msgstr "Färger: tryck för att välja"
 
-#: gitk:10995
+#: gitk:11153
 msgid "Interface"
 msgstr "Gränssnitt"
 
-#: gitk:10996
+#: gitk:11154
 msgid "interface"
 msgstr "gränssnitt"
 
-#: gitk:10999
+#: gitk:11157
 msgid "Background"
 msgstr "Bakgrund"
 
-#: gitk:11000 gitk:11030
+#: gitk:11158 gitk:11188
 msgid "background"
 msgstr "bakgrund"
 
-#: gitk:11003
+#: gitk:11161
 msgid "Foreground"
 msgstr "Förgrund"
 
-#: gitk:11004
+#: gitk:11162
 msgid "foreground"
 msgstr "förgrund"
 
-#: gitk:11007
+#: gitk:11165
 msgid "Diff: old lines"
 msgstr "Diff: gamla rader"
 
-#: gitk:11008
+#: gitk:11166
 msgid "diff old lines"
 msgstr "diff gamla rader"
 
-#: gitk:11012
+#: gitk:11170
 msgid "Diff: new lines"
 msgstr "Diff: nya rader"
 
-#: gitk:11013
+#: gitk:11171
 msgid "diff new lines"
 msgstr "diff nya rader"
 
-#: gitk:11017
+#: gitk:11175
 msgid "Diff: hunk header"
 msgstr "Diff: delhuvud"
 
-#: gitk:11019
+#: gitk:11177
 msgid "diff hunk header"
 msgstr "diff delhuvud"
 
-#: gitk:11023
+#: gitk:11181
 msgid "Marked line bg"
 msgstr "Markerad rad bakgrund"
 
-#: gitk:11025
+#: gitk:11183
 msgid "marked line background"
 msgstr "markerad rad bakgrund"
 
-#: gitk:11029
+#: gitk:11187
 msgid "Select bg"
 msgstr "Markerad bakgrund"
 
-#: gitk:11038
+#: gitk:11196
 msgid "Fonts: press to choose"
 msgstr "Teckensnitt: tryck för att välja"
 
-#: gitk:11040
+#: gitk:11198
 msgid "Main font"
 msgstr "Huvudteckensnitt"
 
-#: gitk:11041
+#: gitk:11199
 msgid "Diff display font"
 msgstr "Teckensnitt för diffvisning"
 
-#: gitk:11042
+#: gitk:11200
 msgid "User interface font"
 msgstr "Teckensnitt för användargränssnitt"
 
-#: gitk:11064
+#: gitk:11222
 msgid "Gitk preferences"
 msgstr "Inställningar för Gitk"
 
-#: gitk:11073
+#: gitk:11231
 msgid "General"
 msgstr "Allmänt"
 
-#: gitk:11074
+#: gitk:11232
 msgid "Colors"
 msgstr "Färger"
 
-#: gitk:11075
+#: gitk:11233
 msgid "Fonts"
 msgstr "Teckensnitt"
 
-#: gitk:11125
+#: gitk:11283
 #, tcl-format
 msgid "Gitk: choose color for %s"
 msgstr "Gitk: välj färg för %s"
 
-#: gitk:11745
+#: gitk:11937
 msgid "Cannot find a git repository here."
 msgstr "Hittar inget git-arkiv här."
 
-#: gitk:11792
+#: gitk:11984
 #, tcl-format
 msgid "Ambiguous argument '%s': both revision and filename"
 msgstr "Tvetydigt argument \"%s\": både revision och filnamn"
 
-#: gitk:11804
+#: gitk:11996
 msgid "Bad arguments to gitk:"
 msgstr "Felaktiga argument till gitk:"
 
-#: gitk:11907
+#: gitk:12099
 msgid "Command line"
 msgstr "Kommandorad"
 
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index 80950c0..f429f75 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -85,6 +85,9 @@
 # string of the home link on top of all pages
 our $home_link_str = "++GITWEB_HOME_LINK_STR++";
 
+# extra breadcrumbs preceding the home link
+our @extra_breadcrumbs = ();
+
 # name of your site or organization to appear in page titles
 # replace this with something more descriptive for clearer bookmarks
 our $site_name = "++GITWEB_SITENAME++"
@@ -1086,7 +1089,7 @@
 	our $search_use_regexp = $input_params{'search_use_regexp'};
 
 	our $searchtext = $input_params{'searchtext'};
-	our $search_regexp;
+	our $search_regexp = undef;
 	if (defined $searchtext) {
 		if (length($searchtext) < 2) {
 			die_error(403, "At least two characters are required for search parameter");
@@ -3982,7 +3985,9 @@
 sub print_nav_breadcrumbs {
 	my %opts = @_;
 
-	print $cgi->a({-href => esc_url($home_link)}, $home_link_str) . " / ";
+	for my $crumb (@extra_breadcrumbs, [ $home_link_str => $home_link ]) {
+		print $cgi->a({-href => esc_url($crumb->[1])}, $crumb->[0]) . " / ";
+	}
 	if (defined $project) {
 		my @dirname = split '/', $project;
 		my $projectbasename = pop @dirname;
diff --git a/help.c b/help.c
index 02ba043..f068925 100644
--- a/help.c
+++ b/help.c
@@ -7,6 +7,7 @@
 #include "string-list.h"
 #include "column.h"
 #include "version.h"
+#include "refs.h"
 
 void add_cmdname(struct cmdnames *cmds, const char *name, int len)
 {
@@ -106,10 +107,7 @@
 	    !S_ISREG(st.st_mode))
 		return 0;
 
-#if defined(WIN32) || defined(__CYGWIN__)
-#if defined(__CYGWIN__)
-if ((st.st_mode & S_IXUSR) == 0)
-#endif
+#if defined(GIT_WINDOWS_NATIVE)
 {	/* cannot trust the executable bit, peek into the file instead */
 	char buf[3] = { 0 };
 	int n;
@@ -404,3 +402,52 @@
 	printf("git version %s\n", git_version_string);
 	return 0;
 }
+
+struct similar_ref_cb {
+	const char *base_ref;
+	struct string_list *similar_refs;
+};
+
+static int append_similar_ref(const char *refname, const unsigned char *sha1,
+			      int flags, void *cb_data)
+{
+	struct similar_ref_cb *cb = (struct similar_ref_cb *)(cb_data);
+	char *branch = strrchr(refname, '/') + 1;
+	/* A remote branch of the same name is deemed similar */
+	if (!prefixcmp(refname, "refs/remotes/") &&
+	    !strcmp(branch, cb->base_ref))
+		string_list_append(cb->similar_refs,
+				   refname + strlen("refs/remotes/"));
+	return 0;
+}
+
+static struct string_list guess_refs(const char *ref)
+{
+	struct similar_ref_cb ref_cb;
+	struct string_list similar_refs = STRING_LIST_INIT_NODUP;
+
+	ref_cb.base_ref = ref;
+	ref_cb.similar_refs = &similar_refs;
+	for_each_ref(append_similar_ref, &ref_cb);
+	return similar_refs;
+}
+
+void help_unknown_ref(const char *ref, const char *cmd, const char *error)
+{
+	int i;
+	struct string_list suggested_refs = guess_refs(ref);
+
+	fprintf_ln(stderr, _("%s: %s - %s"), cmd, ref, error);
+
+	if (suggested_refs.nr > 0) {
+		fprintf_ln(stderr,
+			   Q_("\nDid you mean this?",
+			      "\nDid you mean one of these?",
+			      suggested_refs.nr));
+		for (i = 0; i < suggested_refs.nr; i++)
+			fprintf(stderr, "\t%s\n", suggested_refs.items[i].string);
+	}
+
+	string_list_clear(&suggested_refs, 0);
+	exit(1);
+}
diff --git a/help.h b/help.h
index 0ae5a12..b21d7c9 100644
--- a/help.h
+++ b/help.h
@@ -27,4 +27,9 @@
 extern int is_in_cmdlist(struct cmdnames *cmds, const char *name);
 extern void list_commands(unsigned int colopts, struct cmdnames *main_cmds, struct cmdnames *other_cmds);
 
+/*
+ * call this to die(), when it is suspected that the user mistyped a
+ * ref to the command, to give suggested "correct" refs.
+ */
+extern void help_unknown_ref(const char *ref, const char *cmd, const char *error);
 #endif /* HELP_H */
diff --git a/http-backend.c b/http-backend.c
index 6b85ffa..0324417 100644
--- a/http-backend.c
+++ b/http-backend.c
@@ -410,14 +410,14 @@
 	strbuf_release(&buf);
 }
 
-static int show_head_ref(const char *name, const unsigned char *sha1,
+static int show_head_ref(const char *refname, const unsigned char *sha1,
 	int flag, void *cb_data)
 {
 	struct strbuf *buf = cb_data;
 
 	if (flag & REF_ISSYMREF) {
-		unsigned char sha1[20];
-		const char *target = resolve_ref_unsafe(name, sha1, 1, NULL);
+		unsigned char unused[20];
+		const char *target = resolve_ref_unsafe(refname, unused, 1, NULL);
 		const char *target_nons = strip_namespace(target);
 
 		strbuf_addf(buf, "ref: %s\n", target_nons);
diff --git a/http-push.c b/http-push.c
index 395a8cf..6dad188 100644
--- a/http-push.c
+++ b/http-push.c
@@ -663,7 +663,7 @@
 
 static int add_send_request(struct object *obj, struct remote_lock *lock)
 {
-	struct transfer_request *request = request_queue_head;
+	struct transfer_request *request;
 	struct packed_git *target;
 
 	/* Keep locks active */
diff --git a/http.c b/http.c
index 92aba59..2d086ae 100644
--- a/http.c
+++ b/http.c
@@ -228,9 +228,15 @@
 #else
 	{
 		static struct strbuf up = STRBUF_INIT;
-		strbuf_reset(&up);
-		strbuf_addf(&up, "%s:%s",
-			    http_auth.username, http_auth.password);
+		/*
+		 * Note that we assume we only ever have a single set of
+		 * credentials in a given program run, so we do not have
+		 * to worry about updating this buffer, only setting its
+		 * initial value.
+		 */
+		if (!up.len)
+			strbuf_addf(&up, "%s:%s",
+				http_auth.username, http_auth.password);
 		curl_easy_setopt(result, CURLOPT_USERPWD, up.buf);
 	}
 #endif
diff --git a/imap-send.c b/imap-send.c
index d9bcfb4..d6b65e2 100644
--- a/imap-send.c
+++ b/imap-send.c
@@ -29,8 +29,18 @@
 #ifdef NO_OPENSSL
 typedef void *SSL;
 #else
+#ifdef APPLE_COMMON_CRYPTO
+#include <CommonCrypto/CommonHMAC.h>
+#define HMAC_CTX CCHmacContext
+#define HMAC_Init(hmac, key, len, algo) CCHmacInit(hmac, algo, key, len)
+#define HMAC_Update CCHmacUpdate
+#define HMAC_Final(hmac, hash, ptr) CCHmacFinal(hmac, hash)
+#define HMAC_CTX_cleanup(ignore)
+#define EVP_md5() kCCHmacAlgMD5
+#else
 #include <openssl/evp.h>
 #include <openssl/hmac.h>
+#endif
 #include <openssl/x509v3.h>
 #endif
 
diff --git a/kwset.c b/kwset.c
index 5800999..a0f49b3 100644
--- a/kwset.c
+++ b/kwset.c
@@ -65,7 +65,7 @@
   struct trie *fail;		/* Aho-Corasick failure function. */
   int depth;			/* Depth of this node from the root. */
   int shift;			/* Shift function for search failures. */
-  int maxshift;			/* Max shift of self and descendents. */
+  int maxshift;			/* Max shift of self and descendants. */
 };
 
 /* Structure returned opaquely to the caller, containing everything. */
@@ -308,7 +308,7 @@
   treefails(tree->rlink, fail, recourse);
 
   /* Find, in the chain of fails going back to the root, the first
-     node that has a descendent on the current label. */
+     node that has a descendant on the current label. */
   while (fail)
     {
       link = fail->links;
@@ -426,13 +426,13 @@
 	 computing the delta table, failure function, and shift function. */
       for (curr = last = kwset->trie; curr; curr = curr->next)
 	{
-	  /* Enqueue the immediate descendents in the level order queue. */
+	  /* Enqueue the immediate descendants in the level order queue. */
 	  enqueue(curr->links, &last);
 
 	  curr->shift = kwset->mind;
 	  curr->maxshift = kwset->mind;
 
-	  /* Update the delta table for the descendents of this node. */
+	  /* Update the delta table for the descendants of this node. */
 	  treedelta(curr->links, curr->depth, delta);
 
 	  /* Compute the failure function for the descendants of this node. */
@@ -450,7 +450,7 @@
 		  fail->shift = curr->depth - fail->depth;
 
 	      /* If the current node is accepting then the shift at the
-		 fail and its descendents should be no larger than the
+		 fail and its descendants should be no larger than the
 		 difference of their depths. */
 	      if (curr->accepting && fail->maxshift > curr->depth - fail->depth)
 		fail->maxshift = curr->depth - fail->depth;
diff --git a/line-log.c b/line-log.c
new file mode 100644
index 0000000..c2d01dc
--- /dev/null
+++ b/line-log.c
@@ -0,0 +1,1277 @@
+#include "git-compat-util.h"
+#include "line-range.h"
+#include "cache.h"
+#include "tag.h"
+#include "blob.h"
+#include "tree.h"
+#include "diff.h"
+#include "commit.h"
+#include "decorate.h"
+#include "revision.h"
+#include "xdiff-interface.h"
+#include "strbuf.h"
+#include "log-tree.h"
+#include "graph.h"
+#include "userdiff.h"
+#include "line-log.h"
+
+static void range_set_grow(struct range_set *rs, size_t extra)
+{
+	ALLOC_GROW(rs->ranges, rs->nr + extra, rs->alloc);
+}
+
+/* Either initialization would be fine */
+#define RANGE_SET_INIT {0}
+
+static void range_set_init(struct range_set *rs, size_t prealloc)
+{
+	rs->alloc = rs->nr = 0;
+	rs->ranges = NULL;
+	if (prealloc)
+		range_set_grow(rs, prealloc);
+}
+
+static void range_set_release(struct range_set *rs)
+{
+	free(rs->ranges);
+	rs->alloc = rs->nr = 0;
+	rs->ranges = NULL;
+}
+
+/* dst must be uninitialized! */
+static void range_set_copy(struct range_set *dst, struct range_set *src)
+{
+	range_set_init(dst, src->nr);
+	memcpy(dst->ranges, src->ranges, src->nr*sizeof(struct range_set));
+	dst->nr = src->nr;
+}
+static void range_set_move(struct range_set *dst, struct range_set *src)
+{
+	range_set_release(dst);
+	dst->ranges = src->ranges;
+	dst->nr = src->nr;
+	dst->alloc = src->alloc;
+	src->ranges = NULL;
+	src->alloc = src->nr = 0;
+}
+
+/* tack on a _new_ range _at the end_ */
+static void range_set_append_unsafe(struct range_set *rs, long a, long b)
+{
+	assert(a <= b);
+	range_set_grow(rs, 1);
+	rs->ranges[rs->nr].start = a;
+	rs->ranges[rs->nr].end = b;
+	rs->nr++;
+}
+
+static void range_set_append(struct range_set *rs, long a, long b)
+{
+	assert(rs->nr == 0 || rs->ranges[rs->nr-1].end <= a);
+	range_set_append_unsafe(rs, a, b);
+}
+
+static int range_cmp(const void *_r, const void *_s)
+{
+	const struct range *r = _r;
+	const struct range *s = _s;
+
+	/* this could be simply 'return r.start-s.start', but for the types */
+	if (r->start == s->start)
+		return 0;
+	if (r->start < s->start)
+		return -1;
+	return 1;
+}
+
+/*
+ * Check that the ranges are non-empty, sorted and non-overlapping
+ */
+static void range_set_check_invariants(struct range_set *rs)
+{
+	int i;
+
+	if (!rs)
+		return;
+
+	if (rs->nr)
+		assert(rs->ranges[0].start < rs->ranges[0].end);
+
+	for (i = 1; i < rs->nr; i++) {
+		assert(rs->ranges[i-1].end < rs->ranges[i].start);
+		assert(rs->ranges[i].start < rs->ranges[i].end);
+	}
+}
+
+/*
+ * In-place pass of sorting and merging the ranges in the range set,
+ * to establish the invariants when we get the ranges from the user
+ */
+static void sort_and_merge_range_set(struct range_set *rs)
+{
+	int i;
+	int o = 0; /* output cursor */
+
+	qsort(rs->ranges, rs->nr, sizeof(struct range), range_cmp);
+
+	for (i = 0; i < rs->nr; i++) {
+		if (rs->ranges[i].start == rs->ranges[i].end)
+			continue;
+		if (o > 0 && rs->ranges[i].start <= rs->ranges[o-1].end) {
+			if (rs->ranges[o-1].end < rs->ranges[i].end)
+				rs->ranges[o-1].end = rs->ranges[i].end;
+		} else {
+			rs->ranges[o].start = rs->ranges[i].start;
+			rs->ranges[o].end = rs->ranges[i].end;
+			o++;
+		}
+	}
+	assert(o <= rs->nr);
+	rs->nr = o;
+
+	range_set_check_invariants(rs);
+}
+
+/*
+ * Union of range sets (i.e., sets of line numbers).  Used to merge
+ * them when searches meet at a common ancestor.
+ *
+ * This is also where the ranges are consolidated into canonical form:
+ * overlapping and adjacent ranges are merged, and empty ranges are
+ * removed.
+ */
+static void range_set_union(struct range_set *out,
+			     struct range_set *a, struct range_set *b)
+{
+	int i = 0, j = 0, o = 0;
+	struct range *ra = a->ranges;
+	struct range *rb = b->ranges;
+	/* cannot make an alias of out->ranges: it may change during grow */
+
+	assert(out->nr == 0);
+	while (i < a->nr || j < b->nr) {
+		struct range *new;
+		if (i < a->nr && j < b->nr) {
+			if (ra[i].start < rb[j].start)
+				new = &ra[i++];
+			else if (ra[i].start > rb[j].start)
+				new = &rb[j++];
+			else if (ra[i].end < rb[j].end)
+				new = &ra[i++];
+			else
+				new = &rb[j++];
+		} else if (i < a->nr)      /* b exhausted */
+			new = &ra[i++];
+		else                       /* a exhausted */
+			new = &rb[j++];
+		if (new->start == new->end)
+			; /* empty range */
+		else if (!o || out->ranges[o-1].end < new->start) {
+			range_set_grow(out, 1);
+			out->ranges[o].start = new->start;
+			out->ranges[o].end = new->end;
+			o++;
+		} else if (out->ranges[o-1].end < new->end) {
+			out->ranges[o-1].end = new->end;
+		}
+	}
+	out->nr = o;
+}
+
+/*
+ * Difference of range sets (out = a \ b).  Pass the "interesting"
+ * ranges as 'a' and the target side of the diff as 'b': it removes
+ * the ranges for which the commit is responsible.
+ */
+static void range_set_difference(struct range_set *out,
+				  struct range_set *a, struct range_set *b)
+{
+	int i, j =  0;
+	for (i = 0; i < a->nr; i++) {
+		long start = a->ranges[i].start;
+		long end = a->ranges[i].end;
+		while (start < end) {
+			while (j < b->nr && start >= b->ranges[j].end)
+				/*
+				 * a:         |-------
+				 * b: ------|
+				 */
+				j++;
+			if (j >= b->nr || end < b->ranges[j].start) {
+				/*
+				 * b exhausted, or
+				 * a:  ----|
+				 * b:         |----
+				 */
+				range_set_append(out, start, end);
+				break;
+			}
+			if (start >= b->ranges[j].start) {
+				/*
+				 * a:     |--????
+				 * b: |------|
+				 */
+				start = b->ranges[j].end;
+			} else if (end > b->ranges[j].start) {
+				/*
+				 * a: |-----|
+				 * b:    |--?????
+				 */
+				if (start < b->ranges[j].start)
+					range_set_append(out, start, b->ranges[j].start);
+				start = b->ranges[j].end;
+			}
+		}
+	}
+}
+
+static void diff_ranges_init(struct diff_ranges *diff)
+{
+	range_set_init(&diff->parent, 0);
+	range_set_init(&diff->target, 0);
+}
+
+static void diff_ranges_release(struct diff_ranges *diff)
+{
+	range_set_release(&diff->parent);
+	range_set_release(&diff->target);
+}
+
+void line_log_data_init(struct line_log_data *r)
+{
+	memset(r, 0, sizeof(struct line_log_data));
+	range_set_init(&r->ranges, 0);
+}
+
+static void line_log_data_clear(struct line_log_data *r)
+{
+	range_set_release(&r->ranges);
+	if (r->pair)
+		diff_free_filepair(r->pair);
+}
+
+static void free_line_log_data(struct line_log_data *r)
+{
+	while (r) {
+		struct line_log_data *next = r->next;
+		line_log_data_clear(r);
+		free(r);
+		r = next;
+	}
+}
+
+static struct line_log_data *
+search_line_log_data(struct line_log_data *list, const char *path,
+		     struct line_log_data **insertion_point)
+{
+	struct line_log_data *p = list;
+	if (insertion_point)
+		*insertion_point = NULL;
+	while (p) {
+		int cmp = strcmp(p->path, path);
+		if (!cmp)
+			return p;
+		if (insertion_point && cmp < 0)
+			*insertion_point = p;
+		p = p->next;
+	}
+	return NULL;
+}
+
+/*
+ * Note: takes ownership of 'path', which happens to be what the only
+ * caller needs.
+ */
+static void line_log_data_insert(struct line_log_data **list,
+				 char *path,
+				 long begin, long end)
+{
+	struct line_log_data *ip;
+	struct line_log_data *p = search_line_log_data(*list, path, &ip);
+
+	if (p) {
+		range_set_append_unsafe(&p->ranges, begin, end);
+		sort_and_merge_range_set(&p->ranges);
+		free(path);
+		return;
+	}
+
+	p = xcalloc(1, sizeof(struct line_log_data));
+	p->path = path;
+	range_set_append(&p->ranges, begin, end);
+	sort_and_merge_range_set(&p->ranges);
+	if (ip) {
+		p->next = ip->next;
+		ip->next = p;
+	} else {
+		p->next = *list;
+		*list = p;
+	}
+}
+
+struct collect_diff_cbdata {
+	struct diff_ranges *diff;
+};
+
+static int collect_diff_cb(long start_a, long count_a,
+			   long start_b, long count_b,
+			   void *data)
+{
+	struct collect_diff_cbdata *d = data;
+
+	if (count_a >= 0)
+		range_set_append(&d->diff->parent, start_a, start_a + count_a);
+	if (count_b >= 0)
+		range_set_append(&d->diff->target, start_b, start_b + count_b);
+
+	return 0;
+}
+
+static void collect_diff(mmfile_t *parent, mmfile_t *target, struct diff_ranges *out)
+{
+	struct collect_diff_cbdata cbdata = {NULL};
+	xpparam_t xpp;
+	xdemitconf_t xecfg;
+	xdemitcb_t ecb;
+
+	memset(&xpp, 0, sizeof(xpp));
+	memset(&xecfg, 0, sizeof(xecfg));
+	xecfg.ctxlen = xecfg.interhunkctxlen = 0;
+
+	cbdata.diff = out;
+	xecfg.hunk_func = collect_diff_cb;
+	memset(&ecb, 0, sizeof(ecb));
+	ecb.priv = &cbdata;
+	xdi_diff(parent, target, &xpp, &xecfg, &ecb);
+}
+
+/*
+ * These are handy for debugging.  Removing them with #if 0 silences
+ * the "unused function" warning.
+ */
+#if 0
+static void dump_range_set(struct range_set *rs, const char *desc)
+{
+	int i;
+	printf("range set %s (%d items):\n", desc, rs->nr);
+	for (i = 0; i < rs->nr; i++)
+		printf("\t[%ld,%ld]\n", rs->ranges[i].start, rs->ranges[i].end);
+}
+
+static void dump_line_log_data(struct line_log_data *r)
+{
+	char buf[4096];
+	while (r) {
+		snprintf(buf, 4096, "file %s\n", r->path);
+		dump_range_set(&r->ranges, buf);
+		r = r->next;
+	}
+}
+
+static void dump_diff_ranges(struct diff_ranges *diff, const char *desc)
+{
+	int i;
+	assert(diff->parent.nr == diff->target.nr);
+	printf("diff ranges %s (%d items):\n", desc, diff->parent.nr);
+	printf("\tparent\ttarget\n");
+	for (i = 0; i < diff->parent.nr; i++) {
+		printf("\t[%ld,%ld]\t[%ld,%ld]\n",
+		       diff->parent.ranges[i].start,
+		       diff->parent.ranges[i].end,
+		       diff->target.ranges[i].start,
+		       diff->target.ranges[i].end);
+	}
+}
+#endif
+
+
+static int ranges_overlap(struct range *a, struct range *b)
+{
+	return !(a->end <= b->start || b->end <= a->start);
+}
+
+/*
+ * Given a diff and the set of interesting ranges, determine all hunks
+ * of the diff which touch (overlap) at least one of the interesting
+ * ranges in the target.
+ */
+static void diff_ranges_filter_touched(struct diff_ranges *out,
+				       struct diff_ranges *diff,
+				       struct range_set *rs)
+{
+	int i, j = 0;
+
+	assert(out->target.nr == 0);
+
+	for (i = 0; i < diff->target.nr; i++) {
+		while (diff->target.ranges[i].start > rs->ranges[j].end) {
+			j++;
+			if (j == rs->nr)
+				return;
+		}
+		if (ranges_overlap(&diff->target.ranges[i], &rs->ranges[j])) {
+			range_set_append(&out->parent,
+					 diff->parent.ranges[i].start,
+					 diff->parent.ranges[i].end);
+			range_set_append(&out->target,
+					 diff->target.ranges[i].start,
+					 diff->target.ranges[i].end);
+		}
+	}
+}
+
+/*
+ * Adjust the line counts in 'rs' to account for the lines
+ * added/removed in the diff.
+ */
+static void range_set_shift_diff(struct range_set *out,
+				 struct range_set *rs,
+				 struct diff_ranges *diff)
+{
+	int i, j = 0;
+	long offset = 0;
+	struct range *src = rs->ranges;
+	struct range *target = diff->target.ranges;
+	struct range *parent = diff->parent.ranges;
+
+	for (i = 0; i < rs->nr; i++) {
+		while (j < diff->target.nr && src[i].start >= target[j].start) {
+			offset += (parent[j].end-parent[j].start)
+				- (target[j].end-target[j].start);
+			j++;
+		}
+		range_set_append(out, src[i].start+offset, src[i].end+offset);
+	}
+}
+
+/*
+ * Given a diff and the set of interesting ranges, map the ranges
+ * across the diff.  That is: observe that the target commit takes
+ * blame for all the + (target-side) ranges.  So for every pair of
+ * ranges in the diff that was touched, we remove the latter and add
+ * its parent side.
+ */
+static void range_set_map_across_diff(struct range_set *out,
+				      struct range_set *rs,
+				      struct diff_ranges *diff,
+				      struct diff_ranges **touched_out)
+{
+	struct diff_ranges *touched = xmalloc(sizeof(*touched));
+	struct range_set tmp1 = RANGE_SET_INIT;
+	struct range_set tmp2 = RANGE_SET_INIT;
+
+	diff_ranges_init(touched);
+	diff_ranges_filter_touched(touched, diff, rs);
+	range_set_difference(&tmp1, rs, &touched->target);
+	range_set_shift_diff(&tmp2, &tmp1, diff);
+	range_set_union(out, &tmp2, &touched->parent);
+	range_set_release(&tmp1);
+	range_set_release(&tmp2);
+
+	*touched_out = touched;
+}
+
+static struct commit *check_single_commit(struct rev_info *revs)
+{
+	struct object *commit = NULL;
+	int found = -1;
+	int i;
+
+	for (i = 0; i < revs->pending.nr; i++) {
+		struct object *obj = revs->pending.objects[i].item;
+		if (obj->flags & UNINTERESTING)
+			continue;
+		while (obj->type == OBJ_TAG)
+			obj = deref_tag(obj, NULL, 0);
+		if (obj->type != OBJ_COMMIT)
+			die("Non commit %s?", revs->pending.objects[i].name);
+		if (commit)
+			die("More than one commit to dig from: %s and %s?",
+			    revs->pending.objects[i].name,
+			    revs->pending.objects[found].name);
+		commit = obj;
+		found = i;
+	}
+
+	if (!commit)
+		die("No commit specified?");
+
+	return (struct commit *) commit;
+}
+
+static void fill_blob_sha1(struct commit *commit, struct diff_filespec *spec)
+{
+	unsigned mode;
+	unsigned char sha1[20];
+
+	if (get_tree_entry(commit->object.sha1, spec->path,
+			   sha1, &mode))
+		die("There is no path %s in the commit", spec->path);
+	fill_filespec(spec, sha1, 1, mode);
+
+	return;
+}
+
+static void fill_line_ends(struct diff_filespec *spec, long *lines,
+			   unsigned long **line_ends)
+{
+	int num = 0, size = 50;
+	long cur = 0;
+	unsigned long *ends = NULL;
+	char *data = NULL;
+
+	if (diff_populate_filespec(spec, 0))
+		die("Cannot read blob %s", sha1_to_hex(spec->sha1));
+
+	ends = xmalloc(size * sizeof(*ends));
+	ends[cur++] = 0;
+	data = spec->data;
+	while (num < spec->size) {
+		if (data[num] == '\n' || num == spec->size - 1) {
+			ALLOC_GROW(ends, (cur + 1), size);
+			ends[cur++] = num;
+		}
+		num++;
+	}
+
+	/* shrink the array to fit the elements */
+	ends = xrealloc(ends, cur * sizeof(*ends));
+	*lines = cur-1;
+	*line_ends = ends;
+}
+
+struct nth_line_cb {
+	struct diff_filespec *spec;
+	long lines;
+	unsigned long *line_ends;
+};
+
+static const char *nth_line(void *data, long line)
+{
+	struct nth_line_cb *d = data;
+	assert(d && line <= d->lines);
+	assert(d->spec && d->spec->data);
+
+	if (line == 0)
+		return (char *)d->spec->data;
+	else
+		return (char *)d->spec->data + d->line_ends[line] + 1;
+}
+
+static struct line_log_data *
+parse_lines(struct commit *commit, const char *prefix, struct string_list *args)
+{
+	long lines = 0;
+	unsigned long *ends = NULL;
+	struct nth_line_cb cb_data;
+	struct string_list_item *item;
+	struct line_log_data *ranges = NULL;
+
+	for_each_string_list_item(item, args) {
+		const char *name_part, *range_part;
+		char *full_name;
+		struct diff_filespec *spec;
+		long begin = 0, end = 0;
+
+		name_part = skip_range_arg(item->string);
+		if (!name_part || *name_part != ':' || !name_part[1])
+			die("-L argument '%s' not of the form start,end:file",
+			    item->string);
+		range_part = xstrndup(item->string, name_part - item->string);
+		name_part++;
+
+		full_name = prefix_path(prefix, prefix ? strlen(prefix) : 0,
+					name_part);
+
+		spec = alloc_filespec(full_name);
+		fill_blob_sha1(commit, spec);
+		fill_line_ends(spec, &lines, &ends);
+		cb_data.spec = spec;
+		cb_data.lines = lines;
+		cb_data.line_ends = ends;
+
+		if (parse_range_arg(range_part, nth_line, &cb_data,
+				    lines, &begin, &end,
+				    full_name))
+			die("malformed -L argument '%s'", range_part);
+		if (begin < 1)
+			begin = 1;
+		if (end < 1)
+			end = lines;
+		begin--;
+		if (lines < end || lines < begin)
+			die("file %s has only %ld lines", name_part, lines);
+		line_log_data_insert(&ranges, full_name, begin, end);
+
+		free_filespec(spec);
+		free(ends);
+		ends = NULL;
+	}
+
+	return ranges;
+}
+
+static struct line_log_data *line_log_data_copy_one(struct line_log_data *r)
+{
+	struct line_log_data *ret = xmalloc(sizeof(*ret));
+
+	assert(r);
+	line_log_data_init(ret);
+	range_set_copy(&ret->ranges, &r->ranges);
+
+	ret->path = xstrdup(r->path);
+
+	return ret;
+}
+
+static struct line_log_data *
+line_log_data_copy(struct line_log_data *r)
+{
+	struct line_log_data *ret = NULL;
+	struct line_log_data *tmp = NULL, *prev = NULL;
+
+	assert(r);
+	ret = tmp = prev = line_log_data_copy_one(r);
+	r = r->next;
+	while (r) {
+		tmp = line_log_data_copy_one(r);
+		prev->next = tmp;
+		prev = tmp;
+		r = r->next;
+	}
+
+	return ret;
+}
+
+/* merge two range sets across files */
+static struct line_log_data *line_log_data_merge(struct line_log_data *a,
+						 struct line_log_data *b)
+{
+	struct line_log_data *head = NULL, **pp = &head;
+
+	while (a || b) {
+		struct line_log_data *src;
+		struct line_log_data *src2 = NULL;
+		struct line_log_data *d;
+		int cmp;
+		if (!a)
+			cmp = 1;
+		else if (!b)
+			cmp = -1;
+		else
+			cmp = strcmp(a->path, b->path);
+		if (cmp < 0) {
+			src = a;
+			a = a->next;
+		} else if (cmp == 0) {
+			src = a;
+			a = a->next;
+			src2 = b;
+			b = b->next;
+		} else {
+			src = b;
+			b = b->next;
+		}
+		d = xmalloc(sizeof(struct line_log_data));
+		line_log_data_init(d);
+		d->path = xstrdup(src->path);
+		*pp = d;
+		pp = &d->next;
+		if (src2)
+			range_set_union(&d->ranges, &src->ranges, &src2->ranges);
+		else
+			range_set_copy(&d->ranges, &src->ranges);
+	}
+
+	return head;
+}
+
+static void add_line_range(struct rev_info *revs, struct commit *commit,
+			   struct line_log_data *range)
+{
+	struct line_log_data *old = NULL;
+	struct line_log_data *new = NULL;
+
+	old = lookup_decoration(&revs->line_log_data, &commit->object);
+	if (old && range) {
+		new = line_log_data_merge(old, range);
+		free_line_log_data(old);
+	} else if (range)
+		new = line_log_data_copy(range);
+
+	if (new)
+		add_decoration(&revs->line_log_data, &commit->object, new);
+}
+
+static void clear_commit_line_range(struct rev_info *revs, struct commit *commit)
+{
+	struct line_log_data *r;
+	r = lookup_decoration(&revs->line_log_data, &commit->object);
+	if (!r)
+		return;
+	free_line_log_data(r);
+	add_decoration(&revs->line_log_data, &commit->object, NULL);
+}
+
+static struct line_log_data *lookup_line_range(struct rev_info *revs,
+					       struct commit *commit)
+{
+	struct line_log_data *ret = NULL;
+	struct line_log_data *d;
+
+	ret = lookup_decoration(&revs->line_log_data, &commit->object);
+
+	for (d = ret; d; d = d->next)
+		range_set_check_invariants(&d->ranges);
+
+	return ret;
+}
+
+void line_log_init(struct rev_info *rev, const char *prefix, struct string_list *args)
+{
+	struct commit *commit = NULL;
+	struct line_log_data *range;
+
+	commit = check_single_commit(rev);
+	range = parse_lines(commit, prefix, args);
+	add_line_range(rev, commit, range);
+
+	if (!rev->diffopt.detect_rename) {
+		int i, count = 0;
+		struct line_log_data *r = range;
+		const char **paths;
+		while (r) {
+			count++;
+			r = r->next;
+		}
+		paths = xmalloc((count+1)*sizeof(char *));
+		r = range;
+		for (i = 0; i < count; i++) {
+			paths[i] = xstrdup(r->path);
+			r = r->next;
+		}
+		paths[count] = NULL;
+		init_pathspec(&rev->diffopt.pathspec, paths);
+		free(paths);
+	}
+}
+
+static void load_tree_desc(struct tree_desc *desc, void **tree,
+			   const unsigned char *sha1)
+{
+	unsigned long size;
+	*tree = read_object_with_reference(sha1, tree_type, &size, NULL);
+	if (!*tree)
+		die("Unable to read tree (%s)", sha1_to_hex(sha1));
+	init_tree_desc(desc, *tree, size);
+}
+
+static int count_parents(struct commit *commit)
+{
+	struct commit_list *parents = commit->parents;
+	int count = 0;
+	while (parents) {
+		count++;
+		parents = parents->next;
+	}
+	return count;
+}
+
+static void move_diff_queue(struct diff_queue_struct *dst,
+			    struct diff_queue_struct *src)
+{
+	assert(src != dst);
+	memcpy(dst, src, sizeof(struct diff_queue_struct));
+	DIFF_QUEUE_CLEAR(src);
+}
+
+static void filter_diffs_for_paths(struct line_log_data *range, int keep_deletions)
+{
+	int i;
+	struct diff_queue_struct outq;
+	DIFF_QUEUE_CLEAR(&outq);
+
+	for (i = 0; i < diff_queued_diff.nr; i++) {
+		struct diff_filepair *p = diff_queued_diff.queue[i];
+		struct line_log_data *rg = NULL;
+
+		if (!DIFF_FILE_VALID(p->two)) {
+			if (keep_deletions)
+				diff_q(&outq, p);
+			else
+				diff_free_filepair(p);
+			continue;
+		}
+		for (rg = range; rg; rg = rg->next) {
+			if (!strcmp(rg->path, p->two->path))
+				break;
+		}
+		if (rg)
+			diff_q(&outq, p);
+		else
+			diff_free_filepair(p);
+	}
+	free(diff_queued_diff.queue);
+	diff_queued_diff = outq;
+}
+
+static inline int diff_might_be_rename(void)
+{
+	int i;
+	for (i = 0; i < diff_queued_diff.nr; i++)
+		if (!DIFF_FILE_VALID(diff_queued_diff.queue[i]->one)) {
+			/* fprintf(stderr, "diff_might_be_rename found creation of: %s\n", */
+			/* 	diff_queued_diff.queue[i]->two->path); */
+			return 1;
+		}
+	return 0;
+}
+
+static void queue_diffs(struct line_log_data *range,
+			struct diff_options *opt,
+			struct diff_queue_struct *queue,
+			struct commit *commit, struct commit *parent)
+{
+	void *tree1 = NULL, *tree2 = NULL;
+	struct tree_desc desc1, desc2;
+
+	assert(commit);
+	load_tree_desc(&desc2, &tree2, commit->tree->object.sha1);
+	if (parent)
+		load_tree_desc(&desc1, &tree1, parent->tree->object.sha1);
+	else
+		init_tree_desc(&desc1, "", 0);
+
+	DIFF_QUEUE_CLEAR(&diff_queued_diff);
+	diff_tree(&desc1, &desc2, "", opt);
+	if (opt->detect_rename) {
+		filter_diffs_for_paths(range, 1);
+		if (diff_might_be_rename())
+			diffcore_std(opt);
+		filter_diffs_for_paths(range, 0);
+	}
+	move_diff_queue(queue, &diff_queued_diff);
+
+	if (tree1)
+		free(tree1);
+	if (tree2)
+		free(tree2);
+}
+
+static char *get_nth_line(long line, unsigned long *ends, void *data)
+{
+	if (line == 0)
+		return (char *)data;
+	else
+		return (char *)data + ends[line] + 1;
+}
+
+static void print_line(const char *prefix, char first,
+		       long line, unsigned long *ends, void *data,
+		       const char *color, const char *reset)
+{
+	char *begin = get_nth_line(line, ends, data);
+	char *end = get_nth_line(line+1, ends, data);
+	int had_nl = 0;
+
+	if (end > begin && end[-1] == '\n') {
+		end--;
+		had_nl = 1;
+	}
+
+	fputs(prefix, stdout);
+	fputs(color, stdout);
+	putchar(first);
+	fwrite(begin, 1, end-begin, stdout);
+	fputs(reset, stdout);
+	putchar('\n');
+	if (!had_nl)
+		fputs("\\ No newline at end of file\n", stdout);
+}
+
+static char *output_prefix(struct diff_options *opt)
+{
+	char *prefix = "";
+
+	if (opt->output_prefix) {
+		struct strbuf *sb = opt->output_prefix(opt, opt->output_prefix_data);
+		prefix = sb->buf;
+	}
+
+	return prefix;
+}
+
+static void dump_diff_hacky_one(struct rev_info *rev, struct line_log_data *range)
+{
+	int i, j = 0;
+	long p_lines, t_lines;
+	unsigned long *p_ends = NULL, *t_ends = NULL;
+	struct diff_filepair *pair = range->pair;
+	struct diff_ranges *diff = &range->diff;
+
+	struct diff_options *opt = &rev->diffopt;
+	char *prefix = output_prefix(opt);
+	const char *c_reset = diff_get_color(opt->use_color, DIFF_RESET);
+	const char *c_frag = diff_get_color(opt->use_color, DIFF_FRAGINFO);
+	const char *c_meta = diff_get_color(opt->use_color, DIFF_METAINFO);
+	const char *c_old = diff_get_color(opt->use_color, DIFF_FILE_OLD);
+	const char *c_new = diff_get_color(opt->use_color, DIFF_FILE_NEW);
+	const char *c_plain = diff_get_color(opt->use_color, DIFF_PLAIN);
+
+	if (!pair || !diff)
+		return;
+
+	if (pair->one->sha1_valid)
+		fill_line_ends(pair->one, &p_lines, &p_ends);
+	fill_line_ends(pair->two, &t_lines, &t_ends);
+
+	printf("%s%sdiff --git a/%s b/%s%s\n", prefix, c_meta, pair->one->path, pair->two->path, c_reset);
+	printf("%s%s--- %s%s%s\n", prefix, c_meta,
+	       pair->one->sha1_valid ? "a/" : "",
+	       pair->one->sha1_valid ? pair->one->path : "/dev/null",
+	       c_reset);
+	printf("%s%s+++ b/%s%s\n", prefix, c_meta, pair->two->path, c_reset);
+	for (i = 0; i < range->ranges.nr; i++) {
+		long p_start, p_end;
+		long t_start = range->ranges.ranges[i].start;
+		long t_end = range->ranges.ranges[i].end;
+		long t_cur = t_start;
+		int j_last;
+
+		while (j < diff->target.nr && diff->target.ranges[j].end < t_start)
+			j++;
+		if (j == diff->target.nr || diff->target.ranges[j].start > t_end)
+			continue;
+
+		/* Scan ahead to determine the last diff that falls in this range */
+		j_last = j;
+		while (j_last < diff->target.nr && diff->target.ranges[j_last].start < t_end)
+			j_last++;
+		if (j_last > j)
+			j_last--;
+
+		/*
+		 * Compute parent hunk headers: we know that the diff
+		 * has the correct line numbers (but not all hunks).
+		 * So it suffices to shift the start/end according to
+		 * the line numbers of the first/last hunk(s) that
+		 * fall in this range.
+		 */
+		if (t_start < diff->target.ranges[j].start)
+			p_start = diff->parent.ranges[j].start - (diff->target.ranges[j].start-t_start);
+		else
+			p_start = diff->parent.ranges[j].start;
+		if (t_end > diff->target.ranges[j_last].end)
+			p_end = diff->parent.ranges[j_last].end + (t_end-diff->target.ranges[j_last].end);
+		else
+			p_end = diff->parent.ranges[j_last].end;
+
+		if (!p_start && !p_end) {
+			p_start = -1;
+			p_end = -1;
+		}
+
+		/* Now output a diff hunk for this range */
+		printf("%s%s@@ -%ld,%ld +%ld,%ld @@%s\n",
+		       prefix, c_frag,
+		       p_start+1, p_end-p_start, t_start+1, t_end-t_start,
+		       c_reset);
+		while (j < diff->target.nr && diff->target.ranges[j].start < t_end) {
+			int k;
+			for (; t_cur < diff->target.ranges[j].start; t_cur++)
+				print_line(prefix, ' ', t_cur, t_ends, pair->two->data,
+					   c_plain, c_reset);
+			for (k = diff->parent.ranges[j].start; k < diff->parent.ranges[j].end; k++)
+				print_line(prefix, '-', k, p_ends, pair->one->data,
+					   c_old, c_reset);
+			for (; t_cur < diff->target.ranges[j].end && t_cur < t_end; t_cur++)
+				print_line(prefix, '+', t_cur, t_ends, pair->two->data,
+					   c_new, c_reset);
+			j++;
+		}
+		for (; t_cur < t_end; t_cur++)
+			print_line(prefix, ' ', t_cur, t_ends, pair->two->data,
+				   c_plain, c_reset);
+	}
+
+	free(p_ends);
+	free(t_ends);
+}
+
+/*
+ * NEEDSWORK: manually building a diff here is not the Right
+ * Thing(tm).  log -L should be built into the diff pipeline.
+ */
+static void dump_diff_hacky(struct rev_info *rev, struct line_log_data *range)
+{
+	puts(output_prefix(&rev->diffopt));
+	while (range) {
+		dump_diff_hacky_one(rev, range);
+		range = range->next;
+	}
+}
+
+/*
+ * Unlike most other functions, this destructively operates on
+ * 'range'.
+ */
+static int process_diff_filepair(struct rev_info *rev,
+				 struct diff_filepair *pair,
+				 struct line_log_data *range,
+				 struct diff_ranges **diff_out)
+{
+	struct line_log_data *rg = range;
+	struct range_set tmp;
+	struct diff_ranges diff;
+	mmfile_t file_parent, file_target;
+
+	assert(pair->two->path);
+	while (rg) {
+		assert(rg->path);
+		if (!strcmp(rg->path, pair->two->path))
+			break;
+		rg = rg->next;
+	}
+
+	if (!rg)
+		return 0;
+	if (rg->ranges.nr == 0)
+		return 0;
+
+	assert(pair->two->sha1_valid);
+	diff_populate_filespec(pair->two, 0);
+	file_target.ptr = pair->two->data;
+	file_target.size = pair->two->size;
+
+	if (pair->one->sha1_valid) {
+		diff_populate_filespec(pair->one, 0);
+		file_parent.ptr = pair->one->data;
+		file_parent.size = pair->one->size;
+	} else {
+		file_parent.ptr = "";
+		file_parent.size = 0;
+	}
+
+	diff_ranges_init(&diff);
+	collect_diff(&file_parent, &file_target, &diff);
+
+	/* NEEDSWORK should apply some heuristics to prevent mismatches */
+	free(rg->path);
+	rg->path = xstrdup(pair->one->path);
+
+	range_set_init(&tmp, 0);
+	range_set_map_across_diff(&tmp, &rg->ranges, &diff, diff_out);
+	range_set_release(&rg->ranges);
+	range_set_move(&rg->ranges, &tmp);
+
+	diff_ranges_release(&diff);
+
+	return ((*diff_out)->parent.nr > 0);
+}
+
+static struct diff_filepair *diff_filepair_dup(struct diff_filepair *pair)
+{
+	struct diff_filepair *new = xmalloc(sizeof(struct diff_filepair));
+	new->one = pair->one;
+	new->two = pair->two;
+	new->one->count++;
+	new->two->count++;
+	return new;
+}
+
+static void free_diffqueues(int n, struct diff_queue_struct *dq)
+{
+	int i, j;
+	for (i = 0; i < n; i++)
+		for (j = 0; j < dq[i].nr; j++)
+			diff_free_filepair(dq[i].queue[j]);
+	free(dq);
+}
+
+static int process_all_files(struct line_log_data **range_out,
+			     struct rev_info *rev,
+			     struct diff_queue_struct *queue,
+			     struct line_log_data *range)
+{
+	int i, changed = 0;
+
+	*range_out = line_log_data_copy(range);
+
+	for (i = 0; i < queue->nr; i++) {
+		struct diff_ranges *pairdiff = NULL;
+		struct diff_filepair *pair = queue->queue[i];
+		if (process_diff_filepair(rev, pair, *range_out, &pairdiff)) {
+			/*
+			 * Store away the diff for later output.  We
+			 * tuck it in the ranges we got as _input_,
+			 * since that's the commit that caused the
+			 * diff.
+			 *
+			 * NEEDSWORK not enough when we get around to
+			 * doing something interesting with merges;
+			 * currently each invocation on a merge parent
+			 * trashes the previous one's diff.
+			 *
+			 * NEEDSWORK tramples over data structures not owned here
+			 */
+			struct line_log_data *rg = range;
+			changed++;
+			while (rg && strcmp(rg->path, pair->two->path))
+				rg = rg->next;
+			assert(rg);
+			rg->pair = diff_filepair_dup(queue->queue[i]);
+			memcpy(&rg->diff, pairdiff, sizeof(struct diff_ranges));
+		}
+	}
+
+	return changed;
+}
+
+int line_log_print(struct rev_info *rev, struct commit *commit)
+{
+	struct line_log_data *range = lookup_line_range(rev, commit);
+
+	show_log(rev);
+	dump_diff_hacky(rev, range);
+	return 1;
+}
+
+static int process_ranges_ordinary_commit(struct rev_info *rev, struct commit *commit,
+					  struct line_log_data *range)
+{
+	struct commit *parent = NULL;
+	struct diff_queue_struct queue;
+	struct line_log_data *parent_range;
+	int changed;
+
+	if (commit->parents)
+		parent = commit->parents->item;
+
+	queue_diffs(range, &rev->diffopt, &queue, commit, parent);
+	changed = process_all_files(&parent_range, rev, &queue, range);
+	if (parent)
+		add_line_range(rev, parent, parent_range);
+	return changed;
+}
+
+static int process_ranges_merge_commit(struct rev_info *rev, struct commit *commit,
+				       struct line_log_data *range)
+{
+	struct diff_queue_struct *diffqueues;
+	struct line_log_data **cand;
+	struct commit **parents;
+	struct commit_list *p;
+	int i;
+	int nparents = count_parents(commit);
+
+	diffqueues = xmalloc(nparents * sizeof(*diffqueues));
+	cand = xmalloc(nparents * sizeof(*cand));
+	parents = xmalloc(nparents * sizeof(*parents));
+
+	p = commit->parents;
+	for (i = 0; i < nparents; i++) {
+		parents[i] = p->item;
+		p = p->next;
+		queue_diffs(range, &rev->diffopt, &diffqueues[i], commit, parents[i]);
+	}
+
+	for (i = 0; i < nparents; i++) {
+		int changed;
+		cand[i] = NULL;
+		changed = process_all_files(&cand[i], rev, &diffqueues[i], range);
+		if (!changed) {
+			/*
+			 * This parent can take all the blame, so we
+			 * don't follow any other path in history
+			 */
+			add_line_range(rev, parents[i], cand[i]);
+			clear_commit_line_range(rev, commit);
+			commit->parents = xmalloc(sizeof(struct commit_list));
+			commit->parents->item = parents[i];
+			commit->parents->next = NULL;
+			free(parents);
+			free(cand);
+			free_diffqueues(nparents, diffqueues);
+			/* NEEDSWORK leaking like a sieve */
+			return 0;
+		}
+	}
+
+	/*
+	 * No single parent took the blame.  We add the candidates
+	 * from the above loop to the parents.
+	 */
+	for (i = 0; i < nparents; i++) {
+		add_line_range(rev, parents[i], cand[i]);
+	}
+
+	clear_commit_line_range(rev, commit);
+	free(parents);
+	free(cand);
+	free_diffqueues(nparents, diffqueues);
+	return 1;
+
+	/* NEEDSWORK evil merge detection stuff */
+	/* NEEDSWORK leaking like a sieve */
+}
+
+static int process_ranges_arbitrary_commit(struct rev_info *rev, struct commit *commit)
+{
+	struct line_log_data *range = lookup_line_range(rev, commit);
+	int changed = 0;
+
+	if (range) {
+		if (!commit->parents || !commit->parents->next)
+			changed = process_ranges_ordinary_commit(rev, commit, range);
+		else
+			changed = process_ranges_merge_commit(rev, commit, range);
+	}
+
+	if (!changed)
+		commit->object.flags |= TREESAME;
+
+	return changed;
+}
+
+static enum rewrite_result line_log_rewrite_one(struct rev_info *rev, struct commit **pp)
+{
+	for (;;) {
+		struct commit *p = *pp;
+		if (p->parents && p->parents->next)
+			return rewrite_one_ok;
+		if (p->object.flags & UNINTERESTING)
+			return rewrite_one_ok;
+		if (!(p->object.flags & TREESAME))
+			return rewrite_one_ok;
+		if (!p->parents)
+			return rewrite_one_noparents;
+		*pp = p->parents->item;
+	}
+}
+
+int line_log_filter(struct rev_info *rev)
+{
+	struct commit *commit;
+	struct commit_list *list = rev->commits;
+	struct commit_list *out = NULL, **pp = &out;
+
+	while (list) {
+		struct commit_list *to_free = NULL;
+		commit = list->item;
+		if (process_ranges_arbitrary_commit(rev, commit)) {
+			*pp = list;
+			pp = &list->next;
+		} else
+			to_free = list;
+		list = list->next;
+		free(to_free);
+	}
+	*pp = NULL;
+
+	for (list = out; list; list = list->next)
+		rewrite_parents(rev, list->item, line_log_rewrite_one);
+
+	rev->commits = out;
+
+	return 0;
+}
diff --git a/line-log.h b/line-log.h
new file mode 100644
index 0000000..8bea45f
--- /dev/null
+++ b/line-log.h
@@ -0,0 +1,53 @@
+#ifndef LINE_LOG_H
+#define LINE_LOG_H
+
+#include "diffcore.h"
+
+struct rev_info;
+struct commit;
+
+/* A range [start,end].  Lines are numbered starting at 0, and the
+ * ranges include start but exclude end. */
+struct range {
+	long start, end;
+};
+
+/* A set of ranges.  The ranges must always be disjoint and sorted. */
+struct range_set {
+	int alloc, nr;
+	struct range *ranges;
+};
+
+/* A diff, encoded as the set of pre- and post-image ranges where the
+ * files differ. A pair of ranges corresponds to a hunk. */
+struct diff_ranges {
+	struct range_set parent;
+	struct range_set target;
+};
+
+/* Linked list of interesting files and their associated ranges.  The
+ * list must be kept sorted by path.
+ *
+ * For simplicity, even though this is highly redundant, each
+ * line_log_data owns its 'path'.
+ */
+struct line_log_data {
+	struct line_log_data *next;
+	char *path;
+	char status;
+	struct range_set ranges;
+	int arg_alloc, arg_nr;
+	const char **args;
+	struct diff_filepair *pair;
+	struct diff_ranges diff;
+};
+
+extern void line_log_data_init(struct line_log_data *r);
+
+extern void line_log_init(struct rev_info *rev, const char *prefix, struct string_list *args);
+
+extern int line_log_filter(struct rev_info *rev);
+
+extern int line_log_print(struct rev_info *rev, struct commit *commit);
+
+#endif /* LINE_LOG_H */
diff --git a/line-range.c b/line-range.c
new file mode 100644
index 0000000..3942475
--- /dev/null
+++ b/line-range.c
@@ -0,0 +1,250 @@
+#include "git-compat-util.h"
+#include "line-range.h"
+#include "xdiff-interface.h"
+#include "strbuf.h"
+#include "userdiff.h"
+
+/*
+ * Parse one item in the -L option
+ */
+static const char *parse_loc(const char *spec, nth_line_fn_t nth_line,
+			     void *data, long lines, long begin, long *ret)
+{
+	char *term;
+	const char *line;
+	long num;
+	int reg_error;
+	regex_t regexp;
+	regmatch_t match[1];
+
+	/* Allow "-L <something>,+20" to mean starting at <something>
+	 * for 20 lines, or "-L <something>,-5" for 5 lines ending at
+	 * <something>.
+	 */
+	if (1 < begin && (spec[0] == '+' || spec[0] == '-')) {
+		num = strtol(spec + 1, &term, 10);
+		if (term != spec + 1) {
+			if (!ret)
+				return term;
+			if (spec[0] == '-')
+				num = 0 - num;
+			if (0 < num)
+				*ret = begin + num - 2;
+			else if (!num)
+				*ret = begin;
+			else
+				*ret = begin + num;
+			return term;
+		}
+		return spec;
+	}
+	num = strtol(spec, &term, 10);
+	if (term != spec) {
+		if (ret)
+			*ret = num;
+		return term;
+	}
+	if (spec[0] != '/')
+		return spec;
+
+	/* it could be a regexp of form /.../ */
+	for (term = (char *) spec + 1; *term && *term != '/'; term++) {
+		if (*term == '\\')
+			term++;
+	}
+	if (*term != '/')
+		return spec;
+
+	/* in the scan-only case we are not interested in the regex */
+	if (!ret)
+		return term+1;
+
+	/* try [spec+1 .. term-1] as regexp */
+	*term = 0;
+	begin--; /* input is in human terms */
+	line = nth_line(data, begin);
+
+	if (!(reg_error = regcomp(&regexp, spec + 1, REG_NEWLINE)) &&
+	    !(reg_error = regexec(&regexp, line, 1, match, 0))) {
+		const char *cp = line + match[0].rm_so;
+		const char *nline;
+
+		while (begin++ < lines) {
+			nline = nth_line(data, begin);
+			if (line <= cp && cp < nline)
+				break;
+			line = nline;
+		}
+		*ret = begin;
+		regfree(&regexp);
+		*term++ = '/';
+		return term;
+	}
+	else {
+		char errbuf[1024];
+		regerror(reg_error, &regexp, errbuf, 1024);
+		die("-L parameter '%s': %s", spec + 1, errbuf);
+	}
+}
+
+static int match_funcname(xdemitconf_t *xecfg, const char *bol, const char *eol)
+{
+	if (xecfg) {
+		char buf[1];
+		return xecfg->find_func(bol, eol - bol, buf, 1,
+					xecfg->find_func_priv) >= 0;
+	}
+
+	if (bol == eol)
+		return 0;
+	if (isalpha(*bol) || *bol == '_' || *bol == '$')
+		return 1;
+	return 0;
+}
+
+static const char *find_funcname_matching_regexp(xdemitconf_t *xecfg, const char *start,
+						 regex_t *regexp)
+{
+	int reg_error;
+	regmatch_t match[1];
+	while (1) {
+		const char *bol, *eol;
+		reg_error = regexec(regexp, start, 1, match, 0);
+		if (reg_error == REG_NOMATCH)
+			return NULL;
+		else if (reg_error) {
+			char errbuf[1024];
+			regerror(reg_error, regexp, errbuf, 1024);
+			die("-L parameter: regexec() failed: %s", errbuf);
+		}
+		/* determine extent of line matched */
+		bol = start+match[0].rm_so;
+		eol = start+match[0].rm_eo;
+		while (bol > start && *bol != '\n')
+			bol--;
+		if (*bol == '\n')
+			bol++;
+		while (*eol && *eol != '\n')
+			eol++;
+		if (*eol == '\n')
+			eol++;
+		/* is it a funcname line? */
+		if (match_funcname(xecfg, (char*) bol, (char*) eol))
+			return bol;
+		start = eol;
+	}
+}
+
+static const char *parse_range_funcname(const char *arg, nth_line_fn_t nth_line_cb,
+					void *cb_data, long lines, long *begin, long *end,
+					const char *path)
+{
+	char *pattern;
+	const char *term;
+	struct userdiff_driver *drv;
+	xdemitconf_t *xecfg = NULL;
+	const char *start;
+	const char *p;
+	int reg_error;
+	regex_t regexp;
+
+	assert(*arg == ':');
+	term = arg+1;
+	while (*term && *term != ':') {
+		if (*term == '\\' && *(term+1))
+			term++;
+		term++;
+	}
+	if (term == arg+1)
+		return NULL;
+	if (!begin) /* skip_range_arg case */
+		return term;
+
+	pattern = xstrndup(arg+1, term-(arg+1));
+
+	start = nth_line_cb(cb_data, 0);
+
+	drv = userdiff_find_by_path(path);
+	if (drv && drv->funcname.pattern) {
+		const struct userdiff_funcname *pe = &drv->funcname;
+		xecfg = xcalloc(1, sizeof(*xecfg));
+		xdiff_set_find_func(xecfg, pe->pattern, pe->cflags);
+	}
+
+	reg_error = regcomp(&regexp, pattern, REG_NEWLINE);
+	if (reg_error) {
+		char errbuf[1024];
+		regerror(reg_error, &regexp, errbuf, 1024);
+		die("-L parameter '%s': %s", pattern, errbuf);
+	}
+
+	p = find_funcname_matching_regexp(xecfg, (char*) start, &regexp);
+	if (!p)
+		die("-L parameter '%s': no match", pattern);
+	*begin = 0;
+	while (p > nth_line_cb(cb_data, *begin))
+		(*begin)++;
+
+	if (*begin >= lines)
+		die("-L parameter '%s' matches at EOF", pattern);
+
+	*end = *begin+1;
+	while (*end < lines) {
+		const char *bol = nth_line_cb(cb_data, *end);
+		const char *eol = nth_line_cb(cb_data, *end+1);
+		if (match_funcname(xecfg, bol, eol))
+			break;
+		(*end)++;
+	}
+
+	regfree(&regexp);
+	free(xecfg);
+	free(pattern);
+
+	/* compensate for 1-based numbering */
+	(*begin)++;
+
+	return term;
+}
+
+int parse_range_arg(const char *arg, nth_line_fn_t nth_line_cb,
+		    void *cb_data, long lines, long *begin, long *end,
+		    const char *path)
+{
+	*begin = *end = 0;
+
+	if (*arg == ':') {
+		arg = parse_range_funcname(arg, nth_line_cb, cb_data, lines, begin, end, path);
+		if (!arg || *arg)
+			return -1;
+		return 0;
+	}
+
+	arg = parse_loc(arg, nth_line_cb, cb_data, lines, 1, begin);
+
+	if (*arg == ',')
+		arg = parse_loc(arg + 1, nth_line_cb, cb_data, lines, *begin + 1, end);
+
+	if (*arg)
+		return -1;
+
+	if (*begin && *end && *end < *begin) {
+		long tmp;
+		tmp = *end; *end = *begin; *begin = tmp;
+	}
+
+	return 0;
+}
+
+const char *skip_range_arg(const char *arg)
+{
+	if (*arg == ':')
+		return parse_range_funcname(arg, NULL, NULL, 0, NULL, NULL, NULL);
+
+	arg = parse_loc(arg, NULL, NULL, 0, -1, NULL);
+
+	if (*arg == ',')
+		arg = parse_loc(arg+1, NULL, NULL, 0, 0, NULL);
+
+	return arg;
+}
diff --git a/line-range.h b/line-range.h
new file mode 100644
index 0000000..ae3d012
--- /dev/null
+++ b/line-range.h
@@ -0,0 +1,36 @@
+#ifndef LINE_RANGE_H
+#define LINE_RANGE_H
+
+/*
+ * Parse one item in an -L begin,end option w.r.t. the notional file
+ * object 'cb_data' consisting of 'lines' lines.
+ *
+ * The 'nth_line_cb' callback is used to determine the start of the
+ * line 'lno' inside the 'cb_data'.  The caller is expected to already
+ * have a suitable map at hand to make this a constant-time lookup.
+ *
+ * Returns 0 in case of success and -1 if there was an error.  The
+ * actual range is stored in *begin and *end.  The counting starts
+ * at 1!  In case of error, the caller should show usage message.
+ */
+
+typedef const char *(*nth_line_fn_t)(void *data, long lno);
+
+extern int parse_range_arg(const char *arg,
+			   nth_line_fn_t nth_line_cb,
+			   void *cb_data, long lines,
+			   long *begin, long *end,
+			   const char *path);
+
+/*
+ * Scan past a range argument that could be parsed by
+ * 'parse_range_arg', to help the caller determine the start of the
+ * filename in '-L n,m:file' syntax.
+ *
+ * Returns a pointer to the first character after the 'n,m' part, or
+ * NULL in case the argument is obviously malformed.
+ */
+
+extern const char *skip_range_arg(const char *arg);
+
+#endif /* LINE_RANGE_H */
diff --git a/lockfile.c b/lockfile.c
index c6fb77b..8fbcb6a 100644
--- a/lockfile.c
+++ b/lockfile.c
@@ -124,15 +124,17 @@
 
 static int lock_file(struct lock_file *lk, const char *path, int flags)
 {
-	if (strlen(path) >= sizeof(lk->filename))
-		return -1;
-	strcpy(lk->filename, path);
 	/*
 	 * subtract 5 from size to make sure there's room for adding
 	 * ".lock" for the lock file name
 	 */
+	static const size_t max_path_len = sizeof(lk->filename) - 5;
+
+	if (strlen(path) >= max_path_len)
+		return -1;
+	strcpy(lk->filename, path);
 	if (!(flags & LOCK_NODEREF))
-		resolve_symlink(lk->filename, sizeof(lk->filename)-5);
+		resolve_symlink(lk->filename, max_path_len);
 	strcat(lk->filename, ".lock");
 	lk->fd = open(lk->filename, O_RDWR | O_CREAT | O_EXCL, 0666);
 	if (0 <= lk->fd) {
diff --git a/log-tree.c b/log-tree.c
index 1946e9c..8534d91 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -10,6 +10,7 @@
 #include "color.h"
 #include "gpg-interface.h"
 #include "sequencer.h"
+#include "line-log.h"
 
 struct decoration name_decoration = { "object names" };
 
@@ -616,6 +617,9 @@
 	ctx.fmt = opt->commit_format;
 	ctx.mailmap = opt->mailmap;
 	ctx.color = opt->diffopt.use_color;
+	ctx.output_encoding = get_log_output_encoding();
+	if (opt->from_ident.mail_begin && opt->from_ident.name_begin)
+		ctx.from_ident = &opt->from_ident;
 	pretty_print_commit(&ctx, commit, &msgbuf);
 
 	if (opt->add_signoff)
@@ -734,7 +738,7 @@
 	sha1 = commit->tree->object.sha1;
 
 	/* Root commit? */
-	parents = commit->parents;
+	parents = get_saved_parents(opt, commit);
 	if (!parents) {
 		if (opt->show_root_diff) {
 			diff_root_tree_sha1(sha1, "", &opt->diffopt);
@@ -796,6 +800,9 @@
 	log.parent = NULL;
 	opt->loginfo = &log;
 
+	if (opt->line_level_traverse)
+		return line_log_print(opt, commit);
+
 	shown = log_tree_diff(opt, commit, &log);
 	if (!shown && opt->loginfo && opt->always_show_header) {
 		log.parent = NULL;
diff --git a/mailmap.c b/mailmap.c
index 2a7b366..3061434 100644
--- a/mailmap.c
+++ b/mailmap.c
@@ -5,8 +5,10 @@
 #define DEBUG_MAILMAP 0
 #if DEBUG_MAILMAP
 #define debug_mm(...) fprintf(stderr, __VA_ARGS__)
+#define debug_str(X) ((X) ? (X) : "(none)")
 #else
 static inline void debug_mm(const char *format, ...) {}
+static inline const char *debug_str(const char *s) { return s; }
 #endif
 
 const char *git_mailmap_file;
@@ -29,7 +31,8 @@
 static void free_mailmap_info(void *p, const char *s)
 {
 	struct mailmap_info *mi = (struct mailmap_info *)p;
-	debug_mm("mailmap: -- complex: '%s' -> '%s' <%s>\n", s, mi->name, mi->email);
+	debug_mm("mailmap: -- complex: '%s' -> '%s' <%s>\n",
+		 s, debug_str(mi->name), debug_str(mi->email));
 	free(mi->name);
 	free(mi->email);
 }
@@ -37,8 +40,11 @@
 static void free_mailmap_entry(void *p, const char *s)
 {
 	struct mailmap_entry *me = (struct mailmap_entry *)p;
-	debug_mm("mailmap: removing entries for <%s>, with %d sub-entries\n", s, me->namemap.nr);
-	debug_mm("mailmap: - simple: '%s' <%s>\n", me->name, me->email);
+	debug_mm("mailmap: removing entries for <%s>, with %d sub-entries\n",
+		 s, me->namemap.nr);
+	debug_mm("mailmap: - simple: '%s' <%s>\n",
+		 debug_str(me->name), debug_str(me->email));
+
 	free(me->name);
 	free(me->email);
 
@@ -47,18 +53,11 @@
 }
 
 static void add_mapping(struct string_list *map,
-			char *new_name, char *new_email, char *old_name, char *old_email)
+			char *new_name, char *new_email,
+			char *old_name, char *old_email)
 {
 	struct mailmap_entry *me;
 	int index;
-	char *p;
-
-	if (old_email)
-		for (p = old_email; *p; p++)
-			*p = tolower(*p);
-	if (new_email)
-		for (p = new_email; *p; p++)
-			*p = tolower(*p);
 
 	if (old_email == NULL) {
 		old_email = new_email;
@@ -68,16 +67,21 @@
 	if ((index = string_list_find_insert_index(map, old_email, 1)) < 0) {
 		/* mailmap entry exists, invert index value */
 		index = -1 - index;
+		me = (struct mailmap_entry *)map->items[index].util;
 	} else {
 		/* create mailmap entry */
-		struct string_list_item *item = string_list_insert_at_index(map, index, old_email);
-		item->util = xcalloc(1, sizeof(struct mailmap_entry));
-		((struct mailmap_entry *)item->util)->namemap.strdup_strings = 1;
+		struct string_list_item *item;
+
+		item = string_list_insert_at_index(map, index, old_email);
+		me = xcalloc(1, sizeof(struct mailmap_entry));
+		me->namemap.strdup_strings = 1;
+		me->namemap.cmp = strcasecmp;
+		item->util = me;
 	}
-	me = (struct mailmap_entry *)map->items[index].util;
 
 	if (old_name == NULL) {
-		debug_mm("mailmap: adding (simple) entry for %s at index %d\n", old_email, index);
+		debug_mm("mailmap: adding (simple) entry for %s at index %d\n",
+			 old_email, index);
 		/* Replace current name and new email for simple entry */
 		if (new_name) {
 			free(me->name);
@@ -89,7 +93,8 @@
 		}
 	} else {
 		struct mailmap_info *mi = xcalloc(1, sizeof(struct mailmap_info));
-		debug_mm("mailmap: adding (complex) entry for %s at index %d\n", old_email, index);
+		debug_mm("mailmap: adding (complex) entry for %s at index %d\n",
+			 old_email, index);
 		if (new_name)
 			mi->name = xstrdup(new_name);
 		if (new_email)
@@ -98,11 +103,12 @@
 	}
 
 	debug_mm("mailmap:  '%s' <%s> -> '%s' <%s>\n",
-		 old_name, old_email, new_name, new_email);
+		 debug_str(old_name), old_email,
+		 debug_str(new_name), debug_str(new_email));
 }
 
 static char *parse_name_and_email(char *buffer, char **name,
-		char **email, int allow_empty_email)
+				  char **email, int allow_empty_email)
 {
 	char *left, *right, *nstart, *nend;
 	*name = *email = NULL;
@@ -122,7 +128,7 @@
 	while (nend > nstart && isspace(*nend))
 		--nend;
 
-	*name = (nstart < nend ? nstart : NULL);
+	*name = (nstart <= nend ? nstart : NULL);
 	*email = left+1;
 	*(nend+1) = '\0';
 	*right++ = '\0';
@@ -187,20 +193,17 @@
 	return 0;
 }
 
-static void read_mailmap_buf(struct string_list *map,
-			     const char *buf, unsigned long len,
-			     char **repo_abbrev)
+static void read_mailmap_string(struct string_list *map, char *buf,
+				char **repo_abbrev)
 {
-	while (len) {
-		const char *end = strchrnul(buf, '\n');
-		unsigned long linelen = end - buf + 1;
-		char *line = xmemdupz(buf, linelen);
+	while (*buf) {
+		char *end = strchrnul(buf, '\n');
 
-		read_mailmap_line(map, line, repo_abbrev);
+		if (*end)
+			*end++ = '\0';
 
-		free(line);
-		buf += linelen;
-		len -= linelen;
+		read_mailmap_line(map, buf, repo_abbrev);
+		buf = end;
 	}
 }
 
@@ -224,7 +227,7 @@
 	if (type != OBJ_BLOB)
 		return error("mailmap is not a blob: %s", name);
 
-	read_mailmap_buf(map, buf, size, repo_abbrev);
+	read_mailmap_string(map, buf, repo_abbrev);
 
 	free(buf);
 	return 0;
@@ -306,21 +309,25 @@
 }
 
 int map_user(struct string_list *map,
-			 const char **email, size_t *emaillen,
-			 const char **name, size_t *namelen)
+	     const char **email, size_t *emaillen,
+	     const char **name, size_t *namelen)
 {
 	struct string_list_item *item;
 	struct mailmap_entry *me;
 
 	debug_mm("map_user: map '%.*s' <%.*s>\n",
-		 *name, *namelen, *emaillen, *email);
+		 (int)*namelen, debug_str(*name),
+		 (int)*emaillen, debug_str(*email));
 
 	item = lookup_prefix(map, *email, *emaillen);
 	if (item != NULL) {
 		me = (struct mailmap_entry *)item->util;
 		if (me->namemap.nr) {
-			/* The item has multiple items, so we'll look up on name too */
-			/* If the name is not found, we choose the simple entry      */
+			/*
+			 * The item has multiple items, so we'll look up on
+			 * name too. If the name is not found, we choose the
+			 * simple entry.
+			 */
 			struct string_list_item *subitem;
 			subitem = lookup_prefix(&me->namemap, *name, *namelen);
 			if (subitem)
@@ -341,8 +348,9 @@
 				*name = mi->name;
 				*namelen = strlen(*name);
 		}
-		debug_mm("map_user:  to '%.*s' <.*%s>\n", *namelen, *name,
-				 *emaillen, *email);
+		debug_mm("map_user:  to '%.*s' <%.*s>\n",
+			 (int)*namelen, debug_str(*name),
+			 (int)*emaillen, debug_str(*email));
 		return 1;
 	}
 	debug_mm("map_user:  --\n");
diff --git a/match-trees.c b/match-trees.c
index 2bb734d..7873cde 100644
--- a/match-trees.c
+++ b/match-trees.c
@@ -47,6 +47,22 @@
 	return score;
 }
 
+static void *fill_tree_desc_strict(struct tree_desc *desc,
+				   const unsigned char *hash)
+{
+	void *buffer;
+	enum object_type type;
+	unsigned long size;
+
+	buffer = read_sha1_file(hash, &type, &size);
+	if (!buffer)
+		die("unable to read tree (%s)", sha1_to_hex(hash));
+	if (type != OBJ_TREE)
+		die("%s is not a tree", sha1_to_hex(hash));
+	init_tree_desc(desc, buffer, size);
+	return buffer;
+}
+
 static int base_name_entries_compare(const struct name_entry *a,
 				     const struct name_entry *b)
 {
@@ -61,23 +77,10 @@
 {
 	struct tree_desc one;
 	struct tree_desc two;
-	void *one_buf, *two_buf;
+	void *one_buf = fill_tree_desc_strict(&one, hash1);
+	void *two_buf = fill_tree_desc_strict(&two, hash2);
 	int score = 0;
-	enum object_type type;
-	unsigned long size;
 
-	one_buf = read_sha1_file(hash1, &type, &size);
-	if (!one_buf)
-		die("unable to read tree (%s)", sha1_to_hex(hash1));
-	if (type != OBJ_TREE)
-		die("%s is not a tree", sha1_to_hex(hash1));
-	init_tree_desc(&one, one_buf, size);
-	two_buf = read_sha1_file(hash2, &type, &size);
-	if (!two_buf)
-		die("unable to read tree (%s)", sha1_to_hex(hash2));
-	if (type != OBJ_TREE)
-		die("%s is not a tree", sha1_to_hex(hash2));
-	init_tree_desc(&two, two_buf, size);
 	for (;;) {
 		struct name_entry e1, e2;
 		int got_entry_from_one = tree_entry(&one, &e1);
@@ -124,16 +127,7 @@
 			int recurse_limit)
 {
 	struct tree_desc one;
-	void *one_buf;
-	enum object_type type;
-	unsigned long size;
-
-	one_buf = read_sha1_file(hash1, &type, &size);
-	if (!one_buf)
-		die("unable to read tree (%s)", sha1_to_hex(hash1));
-	if (type != OBJ_TREE)
-		die("%s is not a tree", sha1_to_hex(hash1));
-	init_tree_desc(&one, one_buf, size);
+	void *one_buf = fill_tree_desc_strict(&one, hash1);
 
 	while (one.size) {
 		const char *path;
diff --git a/merge-recursive.c b/merge-recursive.c
index ea9dbd3..f95933b 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -251,7 +251,7 @@
 		int i;
 		fprintf(stderr, "BUG: There are unmerged index entries:\n");
 		for (i = 0; i < active_nr; i++) {
-			struct cache_entry *ce = active_cache[i];
+			const struct cache_entry *ce = active_cache[i];
 			if (ce_stage(ce))
 				fprintf(stderr, "BUG: %d %.*s\n", ce_stage(ce),
 					(int)ce_namelen(ce), ce->name);
@@ -264,7 +264,8 @@
 
 	if (!cache_tree_fully_valid(active_cache_tree) &&
 	    cache_tree_update(active_cache_tree,
-			      active_cache, active_nr, 0) < 0)
+			      (const struct cache_entry * const *)active_cache,
+			      active_nr, 0) < 0)
 		die(_("error building trees"));
 
 	result = lookup_tree(active_cache_tree->sha1);
@@ -339,7 +340,7 @@
 	for (i = 0; i < active_nr; i++) {
 		struct string_list_item *item;
 		struct stage_data *e;
-		struct cache_entry *ce = active_cache[i];
+		const struct cache_entry *ce = active_cache[i];
 		if (!ce_stage(ce))
 			continue;
 
diff --git a/mergetools/kdiff3 b/mergetools/kdiff3
index 28fead4..a30034f 100644
--- a/mergetools/kdiff3
+++ b/mergetools/kdiff3
@@ -1,5 +1,5 @@
 diff_cmd () {
-	"$merge_tool_path" --auto \
+	"$merge_tool_path" \
 		--L1 "$MERGED (A)" --L2 "$MERGED (B)" \
 		"$LOCAL" "$REMOTE" >/dev/null 2>&1
 }
diff --git a/notes-merge.c b/notes-merge.c
index 0f67bd3..ab18857 100644
--- a/notes-merge.c
+++ b/notes-merge.c
@@ -9,6 +9,7 @@
 #include "notes.h"
 #include "notes-merge.h"
 #include "strbuf.h"
+#include "notes-utils.h"
 
 struct notes_merge_pair {
 	unsigned char obj[20], base[20], local[20], remote[20];
@@ -530,32 +531,6 @@
 	return conflicts ? -1 : 1;
 }
 
-void create_notes_commit(struct notes_tree *t, struct commit_list *parents,
-			 const struct strbuf *msg, unsigned char *result_sha1)
-{
-	unsigned char tree_sha1[20];
-
-	assert(t->initialized);
-
-	if (write_notes_tree(t, tree_sha1))
-		die("Failed to write notes tree to database");
-
-	if (!parents) {
-		/* Deduce parent commit from t->ref */
-		unsigned char parent_sha1[20];
-		if (!read_ref(t->ref, parent_sha1)) {
-			struct commit *parent = lookup_commit(parent_sha1);
-			if (!parent || parse_commit(parent))
-				die("Failed to find/parse commit %s", t->ref);
-			commit_list_insert(parent, &parents);
-		}
-		/* else: t->ref points to nothing, assume root/orphan commit */
-	}
-
-	if (commit_tree(msg, tree_sha1, parents, result_sha1, NULL, NULL))
-		die("Failed to commit notes tree to database");
-}
-
 int notes_merge(struct notes_merge_options *o,
 		struct notes_tree *local_tree,
 		unsigned char *result_sha1)
diff --git a/notes-merge.h b/notes-merge.h
index 0c11b17..1d01f6a 100644
--- a/notes-merge.h
+++ b/notes-merge.h
@@ -26,20 +26,6 @@
 void init_notes_merge_options(struct notes_merge_options *o);
 
 /*
- * Create new notes commit from the given notes tree
- *
- * Properties of the created commit:
- * - tree: the result of converting t to a tree object with write_notes_tree().
- * - parents: the given parents OR (if NULL) the commit referenced by t->ref.
- * - author/committer: the default determined by commmit_tree().
- * - commit message: msg
- *
- * The resulting commit SHA1 is stored in result_sha1.
- */
-void create_notes_commit(struct notes_tree *t, struct commit_list *parents,
-			 const struct strbuf *msg, unsigned char *result_sha1);
-
-/*
  * Merge notes from o->remote_ref into o->local_ref
  *
  * The given notes_tree 'local_tree' must be the notes_tree referenced by the
diff --git a/notes-utils.c b/notes-utils.c
new file mode 100644
index 0000000..9107c37
--- /dev/null
+++ b/notes-utils.c
@@ -0,0 +1,157 @@
+#include "cache.h"
+#include "commit.h"
+#include "refs.h"
+#include "notes-utils.h"
+
+void create_notes_commit(struct notes_tree *t, struct commit_list *parents,
+			 const struct strbuf *msg, unsigned char *result_sha1)
+{
+	unsigned char tree_sha1[20];
+
+	assert(t->initialized);
+
+	if (write_notes_tree(t, tree_sha1))
+		die("Failed to write notes tree to database");
+
+	if (!parents) {
+		/* Deduce parent commit from t->ref */
+		unsigned char parent_sha1[20];
+		if (!read_ref(t->ref, parent_sha1)) {
+			struct commit *parent = lookup_commit(parent_sha1);
+			if (!parent || parse_commit(parent))
+				die("Failed to find/parse commit %s", t->ref);
+			commit_list_insert(parent, &parents);
+		}
+		/* else: t->ref points to nothing, assume root/orphan commit */
+	}
+
+	if (commit_tree(msg, tree_sha1, parents, result_sha1, NULL, NULL))
+		die("Failed to commit notes tree to database");
+}
+
+void commit_notes(struct notes_tree *t, const char *msg)
+{
+	struct strbuf buf = STRBUF_INIT;
+	unsigned char commit_sha1[20];
+
+	if (!t)
+		t = &default_notes_tree;
+	if (!t->initialized || !t->ref || !*t->ref)
+		die(_("Cannot commit uninitialized/unreferenced notes tree"));
+	if (!t->dirty)
+		return; /* don't have to commit an unchanged tree */
+
+	/* Prepare commit message and reflog message */
+	strbuf_addstr(&buf, msg);
+	if (buf.buf[buf.len - 1] != '\n')
+		strbuf_addch(&buf, '\n'); /* Make sure msg ends with newline */
+
+	create_notes_commit(t, NULL, &buf, commit_sha1);
+	strbuf_insert(&buf, 0, "notes: ", 7); /* commit message starts at index 7 */
+	update_ref(buf.buf, t->ref, commit_sha1, NULL, 0, DIE_ON_ERR);
+
+	strbuf_release(&buf);
+}
+
+static combine_notes_fn parse_combine_notes_fn(const char *v)
+{
+	if (!strcasecmp(v, "overwrite"))
+		return combine_notes_overwrite;
+	else if (!strcasecmp(v, "ignore"))
+		return combine_notes_ignore;
+	else if (!strcasecmp(v, "concatenate"))
+		return combine_notes_concatenate;
+	else if (!strcasecmp(v, "cat_sort_uniq"))
+		return combine_notes_cat_sort_uniq;
+	else
+		return NULL;
+}
+
+static int notes_rewrite_config(const char *k, const char *v, void *cb)
+{
+	struct notes_rewrite_cfg *c = cb;
+	if (!prefixcmp(k, "notes.rewrite.") && !strcmp(k+14, c->cmd)) {
+		c->enabled = git_config_bool(k, v);
+		return 0;
+	} else if (!c->mode_from_env && !strcmp(k, "notes.rewritemode")) {
+		if (!v)
+			config_error_nonbool(k);
+		c->combine = parse_combine_notes_fn(v);
+		if (!c->combine) {
+			error(_("Bad notes.rewriteMode value: '%s'"), v);
+			return 1;
+		}
+		return 0;
+	} else if (!c->refs_from_env && !strcmp(k, "notes.rewriteref")) {
+		/* note that a refs/ prefix is implied in the
+		 * underlying for_each_glob_ref */
+		if (!prefixcmp(v, "refs/notes/"))
+			string_list_add_refs_by_glob(c->refs, v);
+		else
+			warning(_("Refusing to rewrite notes in %s"
+				" (outside of refs/notes/)"), v);
+		return 0;
+	}
+
+	return 0;
+}
+
+
+struct notes_rewrite_cfg *init_copy_notes_for_rewrite(const char *cmd)
+{
+	struct notes_rewrite_cfg *c = xmalloc(sizeof(struct notes_rewrite_cfg));
+	const char *rewrite_mode_env = getenv(GIT_NOTES_REWRITE_MODE_ENVIRONMENT);
+	const char *rewrite_refs_env = getenv(GIT_NOTES_REWRITE_REF_ENVIRONMENT);
+	c->cmd = cmd;
+	c->enabled = 1;
+	c->combine = combine_notes_concatenate;
+	c->refs = xcalloc(1, sizeof(struct string_list));
+	c->refs->strdup_strings = 1;
+	c->refs_from_env = 0;
+	c->mode_from_env = 0;
+	if (rewrite_mode_env) {
+		c->mode_from_env = 1;
+		c->combine = parse_combine_notes_fn(rewrite_mode_env);
+		if (!c->combine)
+			/* TRANSLATORS: The first %s is the name of the
+			   environment variable, the second %s is its value */
+			error(_("Bad %s value: '%s'"), GIT_NOTES_REWRITE_MODE_ENVIRONMENT,
+					rewrite_mode_env);
+	}
+	if (rewrite_refs_env) {
+		c->refs_from_env = 1;
+		string_list_add_refs_from_colon_sep(c->refs, rewrite_refs_env);
+	}
+	git_config(notes_rewrite_config, c);
+	if (!c->enabled || !c->refs->nr) {
+		string_list_clear(c->refs, 0);
+		free(c->refs);
+		free(c);
+		return NULL;
+	}
+	c->trees = load_notes_trees(c->refs);
+	string_list_clear(c->refs, 0);
+	free(c->refs);
+	return c;
+}
+
+int copy_note_for_rewrite(struct notes_rewrite_cfg *c,
+			  const unsigned char *from_obj, const unsigned char *to_obj)
+{
+	int ret = 0;
+	int i;
+	for (i = 0; c->trees[i]; i++)
+		ret = copy_note(c->trees[i], from_obj, to_obj, 1, c->combine) || ret;
+	return ret;
+}
+
+void finish_copy_notes_for_rewrite(struct notes_rewrite_cfg *c, const char *msg)
+{
+	int i;
+	for (i = 0; c->trees[i]; i++) {
+		commit_notes(c->trees[i], msg);
+		free_notes(c->trees[i]);
+	}
+	free(c->trees);
+	free(c);
+}
diff --git a/notes-utils.h b/notes-utils.h
new file mode 100644
index 0000000..b4cb1bf
--- /dev/null
+++ b/notes-utils.h
@@ -0,0 +1,37 @@
+#ifndef NOTES_UTILS_H
+#define NOTES_UTILS_H
+
+#include "notes.h"
+
+/*
+ * Create new notes commit from the given notes tree
+ *
+ * Properties of the created commit:
+ * - tree: the result of converting t to a tree object with write_notes_tree().
+ * - parents: the given parents OR (if NULL) the commit referenced by t->ref.
+ * - author/committer: the default determined by commmit_tree().
+ * - commit message: msg
+ *
+ * The resulting commit SHA1 is stored in result_sha1.
+ */
+void create_notes_commit(struct notes_tree *t, struct commit_list *parents,
+			 const struct strbuf *msg, unsigned char *result_sha1);
+
+void commit_notes(struct notes_tree *t, const char *msg);
+
+struct notes_rewrite_cfg {
+	struct notes_tree **trees;
+	const char *cmd;
+	int enabled;
+	combine_notes_fn combine;
+	struct string_list *refs;
+	int refs_from_env;
+	int mode_from_env;
+};
+
+struct notes_rewrite_cfg *init_copy_notes_for_rewrite(const char *cmd);
+int copy_note_for_rewrite(struct notes_rewrite_cfg *c,
+			  const unsigned char *from_obj, const unsigned char *to_obj);
+void finish_copy_notes_for_rewrite(struct notes_rewrite_cfg *c, const char *msg);
+
+#endif
diff --git a/notes.c b/notes.c
index f63fd57..b69c0b8 100644
--- a/notes.c
+++ b/notes.c
@@ -918,17 +918,21 @@
 	return ret;
 }
 
-static int string_list_add_one_ref(const char *path, const unsigned char *sha1,
+static int string_list_add_one_ref(const char *refname, const unsigned char *sha1,
 				   int flag, void *cb)
 {
 	struct string_list *refs = cb;
-	if (!unsorted_string_list_has_string(refs, path))
-		string_list_append(refs, path);
+	if (!unsorted_string_list_has_string(refs, refname))
+		string_list_append(refs, refname);
 	return 0;
 }
 
+/*
+ * The list argument must have strdup_strings set on it.
+ */
 void string_list_add_refs_by_glob(struct string_list *list, const char *glob)
 {
+	assert(list->strdup_strings);
 	if (has_glob_specials(glob)) {
 		for_each_glob_ref(string_list_add_one_ref, glob, list);
 	} else {
diff --git a/notes.h b/notes.h
index 3324c48..2a3f923 100644
--- a/notes.h
+++ b/notes.h
@@ -77,7 +77,7 @@
  * variable is used, and if that is missing, the default notes ref is used
  * ("refs/notes/commits").
  *
- * If you need to re-intialize a notes_tree structure (e.g. when switching from
+ * If you need to re-initialize a notes_tree structure (e.g. when switching from
  * one notes ref to another), you must first de-initialize the notes_tree
  * structure by calling free_notes(struct notes_tree *).
  *
diff --git a/object.c b/object.c
index 20703f5..d8a4b1f 100644
--- a/object.c
+++ b/object.c
@@ -71,13 +71,13 @@
 
 struct object *lookup_object(const unsigned char *sha1)
 {
-	unsigned int i;
+	unsigned int i, first;
 	struct object *obj;
 
 	if (!obj_hash)
 		return NULL;
 
-	i = hashtable_index(sha1);
+	first = i = hashtable_index(sha1);
 	while ((obj = obj_hash[i]) != NULL) {
 		if (!hashcmp(sha1, obj->sha1))
 			break;
@@ -85,6 +85,16 @@
 		if (i == obj_hash_size)
 			i = 0;
 	}
+	if (obj && i != first) {
+		/*
+		 * Move object to where we started to look for it so
+		 * that we do not need to walk the hash table the next
+		 * time we look for it.
+		 */
+		struct object *tmp = obj_hash[i];
+		obj_hash[i] = obj_hash[first];
+		obj_hash[first] = tmp;
+	}
 	return obj;
 }
 
@@ -135,7 +145,7 @@
 struct object *parse_object_buffer(const unsigned char *sha1, enum object_type type, unsigned long size, void *buffer, int *eaten_p)
 {
 	struct object *obj;
-	int eaten = 0;
+	*eaten_p = 0;
 
 	obj = NULL;
 	if (type == OBJ_BLOB) {
@@ -154,7 +164,7 @@
 			if (!tree->object.parsed) {
 				if (parse_tree_buffer(tree, buffer, size))
 					return NULL;
-				eaten = 1;
+				*eaten_p = 1;
 			}
 		}
 	} else if (type == OBJ_COMMIT) {
@@ -164,7 +174,7 @@
 				return NULL;
 			if (!commit->buffer) {
 				commit->buffer = buffer;
-				eaten = 1;
+				*eaten_p = 1;
 			}
 			obj = &commit->object;
 		}
@@ -181,7 +191,6 @@
 	}
 	if (obj && obj->type == OBJ_NONE)
 		obj->type = type;
-	*eaten_p = eaten;
 	return obj;
 }
 
@@ -260,11 +269,18 @@
 	add_object_array_with_mode(obj, name, array, S_IFINVALID);
 }
 
+/*
+ * A zero-length string to which object_array_entry::name can be
+ * initialized without requiring a malloc/free.
+ */
+static char object_array_slopbuf[1];
+
 void add_object_array_with_mode(struct object *obj, const char *name, struct object_array *array, unsigned mode)
 {
 	unsigned nr = array->nr;
 	unsigned alloc = array->alloc;
 	struct object_array_entry *objects = array->objects;
+	struct object_array_entry *entry;
 
 	if (nr >= alloc) {
 		alloc = (alloc + 32) * 2;
@@ -272,28 +288,67 @@
 		array->alloc = alloc;
 		array->objects = objects;
 	}
-	objects[nr].item = obj;
-	objects[nr].name = name;
-	objects[nr].mode = mode;
+	entry = &objects[nr];
+	entry->item = obj;
+	if (!name)
+		entry->name = NULL;
+	else if (!*name)
+		/* Use our own empty string instead of allocating one: */
+		entry->name = object_array_slopbuf;
+	else
+		entry->name = xstrdup(name);
+	entry->mode = mode;
 	array->nr = ++nr;
 }
 
+void object_array_filter(struct object_array *array,
+			 object_array_each_func_t want, void *cb_data)
+{
+	unsigned nr = array->nr, src, dst;
+	struct object_array_entry *objects = array->objects;
+
+	for (src = dst = 0; src < nr; src++) {
+		if (want(&objects[src], cb_data)) {
+			if (src != dst)
+				objects[dst] = objects[src];
+			dst++;
+		} else {
+			if (objects[src].name != object_array_slopbuf)
+				free(objects[src].name);
+		}
+	}
+	array->nr = dst;
+}
+
+/*
+ * Return true iff array already contains an entry with name.
+ */
+static int contains_name(struct object_array *array, const char *name)
+{
+	unsigned nr = array->nr, i;
+	struct object_array_entry *object = array->objects;
+
+	for (i = 0; i < nr; i++, object++)
+		if (!strcmp(object->name, name))
+			return 1;
+	return 0;
+}
+
 void object_array_remove_duplicates(struct object_array *array)
 {
-	unsigned int ref, src, dst;
+	unsigned nr = array->nr, src;
 	struct object_array_entry *objects = array->objects;
 
-	for (ref = 0; ref + 1 < array->nr; ref++) {
-		for (src = ref + 1, dst = src;
-		     src < array->nr;
-		     src++) {
-			if (!strcmp(objects[ref].name, objects[src].name))
-				continue;
-			if (src != dst)
-				objects[dst] = objects[src];
-			dst++;
+	array->nr = 0;
+	for (src = 0; src < nr; src++) {
+		if (!contains_name(array, objects[src].name)) {
+			if (src != array->nr)
+				objects[array->nr] = objects[src];
+			array->nr++;
+		} else {
+			if (objects[src].name != object_array_slopbuf)
+				free(objects[src].name);
 		}
-		array->nr = dst;
 	}
 }
 
diff --git a/object.h b/object.h
index 97d384b..2ff68c5 100644
--- a/object.h
+++ b/object.h
@@ -11,7 +11,13 @@
 	unsigned int alloc;
 	struct object_array_entry {
 		struct object *item;
-		const char *name;
+		/*
+		 * name or NULL.  If non-NULL, the memory pointed to
+		 * is owned by this object *except* if it points at
+		 * object_array_slopbuf, which is a static copy of the
+		 * empty string.
+		 */
+		char *name;
 		unsigned mode;
 	} *objects;
 };
@@ -85,7 +91,22 @@
 /* Object array handling .. */
 void add_object_array(struct object *obj, const char *name, struct object_array *array);
 void add_object_array_with_mode(struct object *obj, const char *name, struct object_array *array, unsigned mode);
-void object_array_remove_duplicates(struct object_array *);
+
+typedef int (*object_array_each_func_t)(struct object_array_entry *, void *);
+
+/*
+ * Apply want to each entry in array, retaining only the entries for
+ * which the function returns true.  Preserve the order of the entries
+ * that are retained.
+ */
+void object_array_filter(struct object_array *array,
+			 object_array_each_func_t want, void *cb_data);
+
+/*
+ * Remove from array all but the first entry with a given name.
+ * Warning: this function uses an O(N^2) algorithm.
+ */
+void object_array_remove_duplicates(struct object_array *array);
 
 void clear_object_flags(unsigned flags);
 
diff --git a/pack-refs.c b/pack-refs.c
deleted file mode 100644
index 4461f71..0000000
--- a/pack-refs.c
+++ /dev/null
@@ -1,148 +0,0 @@
-#include "cache.h"
-#include "refs.h"
-#include "tag.h"
-#include "pack-refs.h"
-
-struct ref_to_prune {
-	struct ref_to_prune *next;
-	unsigned char sha1[20];
-	char name[FLEX_ARRAY];
-};
-
-struct pack_refs_cb_data {
-	unsigned int flags;
-	struct ref_to_prune *ref_to_prune;
-	FILE *refs_file;
-};
-
-static int do_not_prune(int flags)
-{
-	/* If it is already packed or if it is a symref,
-	 * do not prune it.
-	 */
-	return (flags & (REF_ISSYMREF|REF_ISPACKED));
-}
-
-static int handle_one_ref(const char *path, const unsigned char *sha1,
-			  int flags, void *cb_data)
-{
-	struct pack_refs_cb_data *cb = cb_data;
-	struct object *o;
-	int is_tag_ref;
-
-	/* Do not pack the symbolic refs */
-	if ((flags & REF_ISSYMREF))
-		return 0;
-	is_tag_ref = !prefixcmp(path, "refs/tags/");
-
-	/* ALWAYS pack refs that were already packed or are tags */
-	if (!(cb->flags & PACK_REFS_ALL) && !is_tag_ref && !(flags & REF_ISPACKED))
-		return 0;
-
-	fprintf(cb->refs_file, "%s %s\n", sha1_to_hex(sha1), path);
-
-	o = parse_object_or_die(sha1, path);
-	if (o->type == OBJ_TAG) {
-		o = deref_tag(o, path, 0);
-		if (o)
-			fprintf(cb->refs_file, "^%s\n",
-				sha1_to_hex(o->sha1));
-	}
-
-	if ((cb->flags & PACK_REFS_PRUNE) && !do_not_prune(flags)) {
-		int namelen = strlen(path) + 1;
-		struct ref_to_prune *n = xcalloc(1, sizeof(*n) + namelen);
-		hashcpy(n->sha1, sha1);
-		strcpy(n->name, path);
-		n->next = cb->ref_to_prune;
-		cb->ref_to_prune = n;
-	}
-	return 0;
-}
-
-/*
- * Remove empty parents, but spare refs/ and immediate subdirs.
- * Note: munges *name.
- */
-static void try_remove_empty_parents(char *name)
-{
-	char *p, *q;
-	int i;
-	p = name;
-	for (i = 0; i < 2; i++) { /* refs/{heads,tags,...}/ */
-		while (*p && *p != '/')
-			p++;
-		/* tolerate duplicate slashes; see check_refname_format() */
-		while (*p == '/')
-			p++;
-	}
-	for (q = p; *q; q++)
-		;
-	while (1) {
-		while (q > p && *q != '/')
-			q--;
-		while (q > p && *(q-1) == '/')
-			q--;
-		if (q == p)
-			break;
-		*q = '\0';
-		if (rmdir(git_path("%s", name)))
-			break;
-	}
-}
-
-/* make sure nobody touched the ref, and unlink */
-static void prune_ref(struct ref_to_prune *r)
-{
-	struct ref_lock *lock = lock_ref_sha1(r->name + 5, r->sha1);
-
-	if (lock) {
-		unlink_or_warn(git_path("%s", r->name));
-		unlock_ref(lock);
-		try_remove_empty_parents(r->name);
-	}
-}
-
-static void prune_refs(struct ref_to_prune *r)
-{
-	while (r) {
-		prune_ref(r);
-		r = r->next;
-	}
-}
-
-static struct lock_file packed;
-
-int pack_refs(unsigned int flags)
-{
-	int fd;
-	struct pack_refs_cb_data cbdata;
-
-	memset(&cbdata, 0, sizeof(cbdata));
-	cbdata.flags = flags;
-
-	fd = hold_lock_file_for_update(&packed, git_path("packed-refs"),
-				       LOCK_DIE_ON_ERROR);
-	cbdata.refs_file = fdopen(fd, "w");
-	if (!cbdata.refs_file)
-		die_errno("unable to create ref-pack file structure");
-
-	/* perhaps other traits later as well */
-	fprintf(cbdata.refs_file, "# pack-refs with: peeled fully-peeled \n");
-
-	for_each_ref(handle_one_ref, &cbdata);
-	if (ferror(cbdata.refs_file))
-		die("failed to write ref-pack file");
-	if (fflush(cbdata.refs_file) || fsync(fd) || fclose(cbdata.refs_file))
-		die_errno("failed to write ref-pack file");
-	/*
-	 * Since the lock file was fdopen()'ed and then fclose()'ed above,
-	 * assign -1 to the lock file descriptor so that commit_lock_file()
-	 * won't try to close() it.
-	 */
-	packed.fd = -1;
-	if (commit_lock_file(&packed) < 0)
-		die_errno("unable to overwrite old ref-pack file");
-	prune_refs(cbdata.ref_to_prune);
-	return 0;
-}
diff --git a/pack-refs.h b/pack-refs.h
deleted file mode 100644
index 518acfb..0000000
--- a/pack-refs.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef PACK_REFS_H
-#define PACK_REFS_H
-
-/*
- * Flags for controlling behaviour of pack_refs()
- * PACK_REFS_PRUNE: Prune loose refs after packing
- * PACK_REFS_ALL:   Pack _all_ refs, not just tags and already packed refs
- */
-#define PACK_REFS_PRUNE 0x0001
-#define PACK_REFS_ALL   0x0002
-
-/*
- * Write a packed-refs file for the current repository.
- * flags: Combination of the above PACK_REFS_* flags.
- */
-int pack_refs(unsigned int flags);
-
-#endif /* PACK_REFS_H */
diff --git a/pack-revindex.c b/pack-revindex.c
index 77a0465..b4d2b35 100644
--- a/pack-revindex.c
+++ b/pack-revindex.c
@@ -59,11 +59,101 @@
 	/* revindex elements are lazily initialized */
 }
 
-static int cmp_offset(const void *a_, const void *b_)
+/*
+ * This is a least-significant-digit radix sort.
+ *
+ * It sorts each of the "n" items in "entries" by its offset field. The "max"
+ * parameter must be at least as large as the largest offset in the array,
+ * and lets us quit the sort early.
+ */
+static void sort_revindex(struct revindex_entry *entries, unsigned n, off_t max)
 {
-	const struct revindex_entry *a = a_;
-	const struct revindex_entry *b = b_;
-	return (a->offset < b->offset) ? -1 : (a->offset > b->offset) ? 1 : 0;
+	/*
+	 * We use a "digit" size of 16 bits. That keeps our memory
+	 * usage reasonable, and we can generally (for a 4G or smaller
+	 * packfile) quit after two rounds of radix-sorting.
+	 */
+#define DIGIT_SIZE (16)
+#define BUCKETS (1 << DIGIT_SIZE)
+	/*
+	 * We want to know the bucket that a[i] will go into when we are using
+	 * the digit that is N bits from the (least significant) end.
+	 */
+#define BUCKET_FOR(a, i, bits) (((a)[(i)].offset >> (bits)) & (BUCKETS-1))
+
+	/*
+	 * We need O(n) temporary storage. Rather than do an extra copy of the
+	 * partial results into "entries", we sort back and forth between the
+	 * real array and temporary storage. In each iteration of the loop, we
+	 * keep track of them with alias pointers, always sorting from "from"
+	 * to "to".
+	 */
+	struct revindex_entry *tmp = xmalloc(n * sizeof(*tmp));
+	struct revindex_entry *from = entries, *to = tmp;
+	int bits;
+	unsigned *pos = xmalloc(BUCKETS * sizeof(*pos));
+
+	/*
+	 * If (max >> bits) is zero, then we know that the radix digit we are
+	 * on (and any higher) will be zero for all entries, and our loop will
+	 * be a no-op, as everybody lands in the same zero-th bucket.
+	 */
+	for (bits = 0; max >> bits; bits += DIGIT_SIZE) {
+		struct revindex_entry *swap;
+		unsigned i;
+
+		memset(pos, 0, BUCKETS * sizeof(*pos));
+
+		/*
+		 * We want pos[i] to store the index of the last element that
+		 * will go in bucket "i" (actually one past the last element).
+		 * To do this, we first count the items that will go in each
+		 * bucket, which gives us a relative offset from the last
+		 * bucket. We can then cumulatively add the index from the
+		 * previous bucket to get the true index.
+		 */
+		for (i = 0; i < n; i++)
+			pos[BUCKET_FOR(from, i, bits)]++;
+		for (i = 1; i < BUCKETS; i++)
+			pos[i] += pos[i-1];
+
+		/*
+		 * Now we can drop the elements into their correct buckets (in
+		 * our temporary array).  We iterate the pos counter backwards
+		 * to avoid using an extra index to count up. And since we are
+		 * going backwards there, we must also go backwards through the
+		 * array itself, to keep the sort stable.
+		 *
+		 * Note that we use an unsigned iterator to make sure we can
+		 * handle 2^32-1 objects, even on a 32-bit system. But this
+		 * means we cannot use the more obvious "i >= 0" loop condition
+		 * for counting backwards, and must instead check for
+		 * wrap-around with UINT_MAX.
+		 */
+		for (i = n - 1; i != UINT_MAX; i--)
+			to[--pos[BUCKET_FOR(from, i, bits)]] = from[i];
+
+		/*
+		 * Now "to" contains the most sorted list, so we swap "from" and
+		 * "to" for the next iteration.
+		 */
+		swap = from;
+		from = to;
+		to = swap;
+	}
+
+	/*
+	 * If we ended with our data in the original array, great. If not,
+	 * we have to move it back from the temporary storage.
+	 */
+	if (from != entries)
+		memcpy(entries, tmp, n * sizeof(*entries));
+	free(tmp);
+	free(pos);
+
+#undef BUCKET_FOR
+#undef BUCKETS
+#undef DIGIT_SIZE
 }
 
 /*
@@ -72,8 +162,8 @@
 static void create_pack_revindex(struct pack_revindex *rix)
 {
 	struct packed_git *p = rix->p;
-	int num_ent = p->num_objects;
-	int i;
+	unsigned num_ent = p->num_objects;
+	unsigned i;
 	const char *index = p->index_data;
 
 	rix->revindex = xmalloc(sizeof(*rix->revindex) * (num_ent + 1));
@@ -108,13 +198,13 @@
 	 */
 	rix->revindex[num_ent].offset = p->pack_size - 20;
 	rix->revindex[num_ent].nr = -1;
-	qsort(rix->revindex, num_ent, sizeof(*rix->revindex), cmp_offset);
+	sort_revindex(rix->revindex, num_ent, p->pack_size);
 }
 
 struct revindex_entry *find_pack_revindex(struct packed_git *p, off_t ofs)
 {
 	int num;
-	int lo, hi;
+	unsigned lo, hi;
 	struct pack_revindex *rix;
 	struct revindex_entry *revindex;
 
@@ -132,7 +222,7 @@
 	lo = 0;
 	hi = p->num_objects + 1;
 	do {
-		int mi = (lo + hi) / 2;
+		unsigned mi = lo + (hi - lo) / 2;
 		if (revindex[mi].offset == ofs) {
 			return revindex + mi;
 		} else if (ofs < revindex[mi].offset)
diff --git a/parse-options-cb.c b/parse-options-cb.c
index 0de5fb1..be8c413 100644
--- a/parse-options-cb.c
+++ b/parse-options-cb.c
@@ -33,6 +33,12 @@
 	return 0;
 }
 
+int parse_opt_expiry_date_cb(const struct option *opt, const char *arg,
+			     int unset)
+{
+	return parse_expiry_date(arg, (unsigned long *)opt->value);
+}
+
 int parse_opt_color_flag_cb(const struct option *opt, const char *arg,
 			    int unset)
 {
diff --git a/parse-options.h b/parse-options.h
index 1c8bd8d..9b94596 100644
--- a/parse-options.h
+++ b/parse-options.h
@@ -140,6 +140,9 @@
 #define OPT_DATE(s, l, v, h) \
 	{ OPTION_CALLBACK, (s), (l), (v), N_("time"),(h), 0,	\
 	  parse_opt_approxidate_cb }
+#define OPT_EXPIRY_DATE(s, l, v, h) \
+	{ OPTION_CALLBACK, (s), (l), (v), N_("expiry date"),(h), 0,	\
+	  parse_opt_expiry_date_cb }
 #define OPT_CALLBACK(s, l, v, a, h, f) \
 	{ OPTION_CALLBACK, (s), (l), (v), (a), (h), 0, (f) }
 #define OPT_NUMBER_CALLBACK(v, h, f) \
@@ -177,7 +180,7 @@
 
 extern int optbug(const struct option *opt, const char *reason);
 extern int opterror(const struct option *opt, const char *reason, int flags);
-#if defined(__GNUC__) && ! defined(clang)
+#if defined(__GNUC__) && ! defined(__clang__)
 #define opterror(o,r,f) (opterror((o),(r),(f)), -1)
 #endif
 
@@ -219,6 +222,7 @@
 /*----- some often used options -----*/
 extern int parse_opt_abbrev_cb(const struct option *, const char *, int);
 extern int parse_opt_approxidate_cb(const struct option *, const char *, int);
+extern int parse_opt_expiry_date_cb(const struct option *, const char *, int);
 extern int parse_opt_color_flag_cb(const struct option *, const char *, int);
 extern int parse_opt_verbosity_cb(const struct option *, const char *, int);
 extern int parse_opt_with_commit(const struct option *, const char *, int);
diff --git a/path.c b/path.c
index 04ff148..3d244d3 100644
--- a/path.c
+++ b/path.c
@@ -5,13 +5,7 @@
 #include "strbuf.h"
 #include "string-list.h"
 
-#ifndef get_st_mode_bits
-/*
- * The replacement lstat(2) we use on Cygwin is incomplete and
- * may return wrong permission bits. Most of the time we do not care,
- * but the callsites of this wrapper do care.
- */
-int get_st_mode_bits(const char *path, int *mode)
+static int get_st_mode_bits(const char *path, int *mode)
 {
 	struct stat st;
 	if (lstat(path, &st) < 0)
@@ -19,7 +13,6 @@
 	*mode = st.st_mode;
 	return 0;
 }
-#endif
 
 static char bad_path[] = "/bad-path/";
 
@@ -441,42 +434,100 @@
 	return 0;
 }
 
-const char *relative_path(const char *abs, const char *base)
+/*
+ * Give path as relative to prefix.
+ *
+ * The strbuf may or may not be used, so do not assume it contains the
+ * returned path.
+ */
+const char *relative_path(const char *in, const char *prefix,
+			  struct strbuf *sb)
 {
-	static char buf[PATH_MAX + 1];
+	int in_len = in ? strlen(in) : 0;
+	int prefix_len = prefix ? strlen(prefix) : 0;
+	int in_off = 0;
+	int prefix_off = 0;
 	int i = 0, j = 0;
 
-	if (!base || !base[0])
-		return abs;
-	while (base[i]) {
-		if (is_dir_sep(base[i])) {
-			if (!is_dir_sep(abs[j]))
-				return abs;
-			while (is_dir_sep(base[i]))
+	if (!in_len)
+		return "./";
+	else if (!prefix_len)
+		return in;
+
+	while (i < prefix_len && j < in_len && prefix[i] == in[j]) {
+		if (is_dir_sep(prefix[i])) {
+			while (is_dir_sep(prefix[i]))
 				i++;
-			while (is_dir_sep(abs[j]))
+			while (is_dir_sep(in[j]))
 				j++;
+			prefix_off = i;
+			in_off = j;
+		} else {
+			i++;
+			j++;
+		}
+	}
+
+	if (
+	    /* "prefix" seems like prefix of "in" */
+	    i >= prefix_len &&
+	    /*
+	     * but "/foo" is not a prefix of "/foobar"
+	     * (i.e. prefix not end with '/')
+	     */
+	    prefix_off < prefix_len) {
+		if (j >= in_len) {
+			/* in="/a/b", prefix="/a/b" */
+			in_off = in_len;
+		} else if (is_dir_sep(in[j])) {
+			/* in="/a/b/c", prefix="/a/b" */
+			while (is_dir_sep(in[j]))
+				j++;
+			in_off = j;
+		} else {
+			/* in="/a/bbb/c", prefix="/a/b" */
+			i = prefix_off;
+		}
+	} else if (
+		   /* "in" is short than "prefix" */
+		   j >= in_len &&
+		   /* "in" not end with '/' */
+		   in_off < in_len) {
+		if (is_dir_sep(prefix[i])) {
+			/* in="/a/b", prefix="/a/b/c/" */
+			while (is_dir_sep(prefix[i]))
+				i++;
+			in_off = in_len;
+		}
+	}
+	in += in_off;
+	in_len -= in_off;
+
+	if (i >= prefix_len) {
+		if (!in_len)
+			return "./";
+		else
+			return in;
+	}
+
+	strbuf_reset(sb);
+	strbuf_grow(sb, in_len);
+
+	while (i < prefix_len) {
+		if (is_dir_sep(prefix[i])) {
+			strbuf_addstr(sb, "../");
+			while (is_dir_sep(prefix[i]))
+				i++;
 			continue;
-		} else if (abs[j] != base[i]) {
-			return abs;
 		}
 		i++;
-		j++;
 	}
-	if (
-	    /* "/foo" is a prefix of "/foo" */
-	    abs[j] &&
-	    /* "/foo" is not a prefix of "/foobar" */
-	    !is_dir_sep(base[i-1]) && !is_dir_sep(abs[j])
-	   )
-		return abs;
-	while (is_dir_sep(abs[j]))
-		j++;
-	if (!abs[j])
-		strcpy(buf, ".");
-	else
-		strcpy(buf, abs + j);
-	return buf;
+	if (!is_dir_sep(prefix[prefix_len - 1]))
+		strbuf_addstr(sb, "../");
+
+	strbuf_addstr(sb, in);
+
+	return sb->buf;
 }
 
 /*
diff --git a/pathspec.c b/pathspec.c
index 284f397..6ea0867 100644
--- a/pathspec.c
+++ b/pathspec.c
@@ -32,7 +32,7 @@
 	if (!num_unmatched)
 		return;
 	for (i = 0; i < active_nr; i++) {
-		struct cache_entry *ce = active_cache[i];
+		const struct cache_entry *ce = active_cache[i];
 		match_pathspec(pathspec, ce->name, ce_namelen(ce), 0, seen);
 	}
 }
@@ -67,7 +67,7 @@
 {
 	int i, path_len = strlen(path);
 	for (i = 0; i < active_nr; i++) {
-		struct cache_entry *ce = active_cache[i];
+		const struct cache_entry *ce = active_cache[i];
 		if (S_ISGITLINK(ce->ce_mode)) {
 			int ce_len = ce_namelen(ce);
 			if (path_len <= ce_len || path[ce_len] != '/' ||
diff --git a/perl/Git.pm b/perl/Git.pm
index 7a252ef..204fdc6 100644
--- a/perl/Git.pm
+++ b/perl/Git.pm
@@ -61,7 +61,7 @@
                 remote_refs prompt
                 get_tz_offset
                 credential credential_read credential_write
-                temp_acquire temp_release temp_reset temp_path);
+                temp_acquire temp_is_locked temp_release temp_reset temp_path);
 
 
 =head1 DESCRIPTION
@@ -1206,6 +1206,35 @@
 	$temp_fd;
 }
 
+=item temp_is_locked ( NAME )
+
+Returns true if the internal lock created by a previous C<temp_acquire()>
+call with C<NAME> is still in effect.
+
+When temp_acquire is called on a C<NAME>, it internally locks the temporary
+file mapped to C<NAME>.  That lock will not be released until C<temp_release()>
+is called with either the original C<NAME> or the L<File::Handle> that was
+returned from the original call to temp_acquire.
+
+Subsequent attempts to call C<temp_acquire()> with the same C<NAME> will fail
+unless there has been an intervening C<temp_release()> call for that C<NAME>
+(or its corresponding L<File::Handle> that was returned by the original
+C<temp_acquire()> call).
+
+If true is returned by C<temp_is_locked()> for a C<NAME>, an attempt to
+C<temp_acquire()> the same C<NAME> will cause an error unless
+C<temp_release> is first called on that C<NAME> (or its corresponding
+L<File::Handle> that was returned by the original C<temp_acquire()> call).
+
+=cut
+
+sub temp_is_locked {
+	my ($self, $name) = _maybe_self(@_);
+	my $temp_fd = \$TEMP_FILEMAP{$name};
+
+	defined $$temp_fd && $$temp_fd->opened && $TEMP_FILES{$$temp_fd}{locked};
+}
+
 =item temp_release ( NAME )
 
 =item temp_release ( FILEHANDLE )
diff --git a/perl/Git/SVN/Editor.pm b/perl/Git/SVN/Editor.pm
index fa0d3c6..b3bcd47 100644
--- a/perl/Git/SVN/Editor.pm
+++ b/perl/Git/SVN/Editor.pm
@@ -499,6 +499,8 @@
 1;
 __END__
 
+=head1 NAME
+
 Git::SVN::Editor - commit driver for "git svn set-tree" and dcommit
 
 =head1 SYNOPSIS
diff --git a/perl/Git/SVN/Fetcher.pm b/perl/Git/SVN/Fetcher.pm
index 046a7a2..10edb27 100644
--- a/perl/Git/SVN/Fetcher.pm
+++ b/perl/Git/SVN/Fetcher.pm
@@ -1,6 +1,7 @@
 package Git::SVN::Fetcher;
-use vars qw/@ISA $_ignore_regex $_preserve_empty_dirs $_placeholder_filename
-            @deleted_gpath %added_placeholder $repo_id/;
+use vars qw/@ISA $_ignore_regex $_include_regex $_preserve_empty_dirs
+            $_placeholder_filename @deleted_gpath %added_placeholder
+            $repo_id/;
 use strict;
 use warnings;
 use SVN::Delta;
@@ -33,6 +34,10 @@
 	my $v = eval { command_oneline('config', '--get', $k) };
 	$self->{ignore_regex} = $v;
 
+	$k = "svn-remote.$repo_id.include-paths";
+	$v = eval { command_oneline('config', '--get', $k) };
+	$self->{include_regex} = $v;
+
 	$k = "svn-remote.$repo_id.preserve-empty-dirs";
 	$v = eval { command_oneline('config', '--get', '--bool', $k) };
 	if ($v && $v eq 'true') {
@@ -117,11 +122,18 @@
 }
 
 # return value: 0 -- don't ignore, 1 -- ignore
+# This will also check whether the path is explicitly included
 sub is_path_ignored {
 	my ($self, $path) = @_;
 	return 1 if in_dot_git($path);
 	return 1 if defined($self->{ignore_regex}) &&
 	            $path =~ m!$self->{ignore_regex}!;
+	return 0 if defined($self->{include_regex}) &&
+	            $path =~ m!$self->{include_regex}!;
+	return 0 if defined($_include_regex) &&
+	            $path =~ m!$_include_regex!;
+	return 1 if defined($self->{include_regex});
+	return 1 if defined($_include_regex);
 	return 0 unless defined($_ignore_regex);
 	return 1 if $path =~ m!$_ignore_regex!o;
 	return 0;
@@ -303,11 +315,13 @@
 sub apply_textdelta {
 	my ($self, $fb, $exp) = @_;
 	return undef if $self->is_path_ignored($fb->{path});
-	my $fh = $::_repository->temp_acquire('svn_delta');
+	my $suffix = 0;
+	++$suffix while $::_repository->temp_is_locked("svn_delta_${$}_$suffix");
+	my $fh = $::_repository->temp_acquire("svn_delta_${$}_$suffix");
 	# $fh gets auto-closed() by SVN::TxDelta::apply(),
 	# (but $base does not,) so dup() it for reading in close_file
 	open my $dup, '<&', $fh or croak $!;
-	my $base = $::_repository->temp_acquire('git_blob');
+	my $base = $::_repository->temp_acquire("git_blob_${$}_$suffix");
 
 	if ($fb->{blob}) {
 		my ($base_is_link, $size);
@@ -512,6 +526,8 @@
 1;
 __END__
 
+=head1 NAME
+
 Git::SVN::Fetcher - tree delta consumer for "git svn fetch"
 
 =head1 SYNOPSIS
diff --git a/perl/Git/SVN/Prompt.pm b/perl/Git/SVN/Prompt.pm
index 74daa7a..e940b08 100644
--- a/perl/Git/SVN/Prompt.pm
+++ b/perl/Git/SVN/Prompt.pm
@@ -125,6 +125,8 @@
 1;
 __END__
 
+=head1 NAME
+
 Git::SVN::Prompt - authentication callbacks for git-svn
 
 =head1 SYNOPSIS
diff --git a/perl/Git/SVN/Ra.pm b/perl/Git/SVN/Ra.pm
index 6a212eb..75ecc42 100644
--- a/perl/Git/SVN/Ra.pm
+++ b/perl/Git/SVN/Ra.pm
@@ -627,6 +627,8 @@
 1;
 __END__
 
+=head1 NAME
+
 Git::SVN::Ra - Subversion remote access functions for git-svn
 
 =head1 SYNOPSIS
diff --git a/po/TEAMS b/po/TEAMS
index 5eb5aad..107aa59 100644
--- a/po/TEAMS
+++ b/po/TEAMS
@@ -12,6 +12,11 @@
 		Jan Krüger <jk@jk.gs>
 		Christian Stimming <stimming@tuhh.de>
 
+Language:	fr (French)
+Repository:	https://github.com/jnavila/git
+Leader:		Jean-Noël Avila <jn.avila@free.fr>
+Members:	Sébastien Helleu <flashcode@flashtux.org>
+
 Language:	is (Icelandic)
 Leader:		Ævar Arnfjörð Bjarmason <avarab@gmail.com>
 
diff --git a/po/de.po b/po/de.po
index 88d7919..f4076fb 100644
--- a/po/de.po
+++ b/po/de.po
@@ -5,10 +5,10 @@
 #
 msgid ""
 msgstr ""
-"Project-Id-Version: git 1.8.2\n"
+"Project-Id-Version: git 1.8.4\n"
 "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
-"POT-Creation-Date: 2013-04-10 15:16+0800\n"
-"PO-Revision-Date: 2012-10-02 19:35+0200\n"
+"POT-Creation-Date: 2013-08-06 14:10+0800\n"
+"PO-Revision-Date: 2013-07-28 18:42+0200\n"
 "Last-Translator: Ralf Thielow <ralf.thielow@gmail.com>\n"
 "Language-Team: German <>\n"
 "Language: de\n"
@@ -17,7 +17,7 @@
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n!=1);\n"
 
-#: advice.c:53
+#: advice.c:57
 #, c-format
 msgid "hint: %.*s\n"
 msgstr "Hinweis: %.*s\n"
@@ -26,21 +26,21 @@
 #. * Message used both when 'git commit' fails and when
 #. * other commands doing a merge do.
 #.
-#: advice.c:83
+#: advice.c:87
 msgid ""
 "Fix them up in the work tree,\n"
 "and then use 'git add/rm <file>' as\n"
 "appropriate to mark resolution and make a commit,\n"
 "or use 'git commit -a'."
 msgstr ""
-"Korrigieren Sie dies im Arbeitsbaum,\n"
+"Korrigieren Sie dies im Arbeitsverzeichnis,\n"
 "und benutzen Sie dann 'git add/rm <Datei>'\n"
-"um die Auflösung entsprechend zu markieren und einzutragen,\n"
+"um die Auflösung entsprechend zu markieren und zu committen,\n"
 "oder benutzen Sie 'git commit -a'."
 
 #: archive.c:10
 msgid "git archive [options] <tree-ish> [<path>...]"
-msgstr "git archive [Optionen] <Versionsreferenz> [<Pfad>...]"
+msgstr "git archive [Optionen] <Commit-Referenz> [<Pfad>...]"
 
 #: archive.c:11
 msgid "git archive --list"
@@ -50,12 +50,12 @@
 msgid ""
 "git archive --remote <repo> [--exec <cmd>] [options] <tree-ish> [<path>...]"
 msgstr ""
-"git archive --remote <Projektarchiv> [--exec <Programm>] [Optionen] "
-"<Versionsreferenz> [Pfad...]"
+"git archive --remote <Repository> [--exec <Programm>] [Optionen] <Commit-"
+"Referenz> [Pfad...]"
 
 #: archive.c:13
 msgid "git archive --remote <repo> [--exec <cmd>] --list"
-msgstr "git archive --remote <Projektarchiv> [--exec <Programm>] --list"
+msgstr "git archive --remote <Repository> [--exec <Programm>] --list"
 
 #: archive.c:323
 msgid "fmt"
@@ -63,27 +63,27 @@
 
 #: archive.c:323
 msgid "archive format"
-msgstr "Ausgabeformat"
+msgstr "Archivformat"
 
-#: archive.c:324 builtin/log.c:1117
+#: archive.c:324 builtin/log.c:1173
 msgid "prefix"
 msgstr "Prefix"
 
 #: archive.c:325
 msgid "prepend prefix to each pathname in the archive"
-msgstr "stellt einen Präfix vor jeden Pfadnamen in der Ausgabe"
+msgstr "stellt einen Präfix vor jeden Pfadnamen in dem Archiv"
 
-#: archive.c:326 builtin/archive.c:88 builtin/blame.c:2366
-#: builtin/blame.c:2367 builtin/config.c:55 builtin/fast-export.c:659
-#: builtin/fast-export.c:661 builtin/grep.c:715 builtin/hash-object.c:77
-#: builtin/ls-files.c:497 builtin/ls-files.c:500 builtin/notes.c:536
-#: builtin/notes.c:693 builtin/read-tree.c:107 parse-options.h:149
+#: archive.c:326 builtin/archive.c:88 builtin/blame.c:2292
+#: builtin/blame.c:2293 builtin/config.c:56 builtin/fast-export.c:673
+#: builtin/fast-export.c:675 builtin/grep.c:714 builtin/hash-object.c:77
+#: builtin/ls-files.c:496 builtin/ls-files.c:499 builtin/notes.c:408
+#: builtin/notes.c:565 builtin/read-tree.c:108 parse-options.h:152
 msgid "file"
 msgstr "Datei"
 
 #: archive.c:327 builtin/archive.c:89
 msgid "write the archive to this file"
-msgstr "schreibt die Ausgabe in diese Datei"
+msgstr "schreibt das Archiv in diese Datei"
 
 #: archive.c:329
 msgid "read .gitattributes in working directory"
@@ -107,17 +107,17 @@
 
 #: archive.c:343
 msgid "list supported archive formats"
-msgstr "listet unterstützte Ausgabeformate auf"
+msgstr "listet unterstützte Archivformate auf"
 
-#: archive.c:345 builtin/archive.c:90 builtin/clone.c:86
+#: archive.c:345 builtin/archive.c:90 builtin/clone.c:85
 msgid "repo"
-msgstr "Projektarchiv"
+msgstr "Repository"
 
 #: archive.c:346 builtin/archive.c:91
 msgid "retrieve the archive from remote repository <repo>"
-msgstr "ruft das Archiv von externem Projektarchiv <Projektarchiv> ab"
+msgstr "ruft das Archiv von Remote-Repository <Repository> ab"
 
-#: archive.c:347 builtin/archive.c:92 builtin/notes.c:615
+#: archive.c:347 builtin/archive.c:92 builtin/notes.c:487
 msgid "command"
 msgstr "Programm"
 
@@ -133,18 +133,93 @@
 "Verneinende Muster werden in Git-Attributen ignoriert.\n"
 "Benutzen Sie '\\!' für führende Ausrufezeichen."
 
-#: branch.c:201
+#: branch.c:60
+#, c-format
+msgid "Not setting branch %s as its own upstream."
+msgstr "Branch %s kann nicht sein eigener Upstream-Branch sein."
+
+#: branch.c:82
+#, c-format
+msgid "Branch %s set up to track remote branch %s from %s by rebasing."
+msgstr ""
+"Branch %s konfiguriert zum Folgen von Remote-Branch %s von %s durch Rebase."
+
+#: branch.c:83
+#, c-format
+msgid "Branch %s set up to track remote branch %s from %s."
+msgstr "Branch %s konfiguriert zum Folgen von Remote-Branch %s von %s."
+
+#: branch.c:87
+#, c-format
+msgid "Branch %s set up to track local branch %s by rebasing."
+msgstr "Branch %s konfiguriert zum Folgen von lokalem Branch %s durch Rebase."
+
+#: branch.c:88
+#, c-format
+msgid "Branch %s set up to track local branch %s."
+msgstr "Branch %s konfiguriert zum Folgen von lokalem Branch %s."
+
+#: branch.c:92
+#, c-format
+msgid "Branch %s set up to track remote ref %s by rebasing."
+msgstr "Branch %s konfiguriert zum Folgen von Remote-Referenz %s durch Rebase."
+
+#: branch.c:93
+#, c-format
+msgid "Branch %s set up to track remote ref %s."
+msgstr "Branch %s konfiguriert zum Folgen von Remote-Referenz %s."
+
+#: branch.c:97
+#, c-format
+msgid "Branch %s set up to track local ref %s by rebasing."
+msgstr ""
+"Branch %s konfiguriert zum Folgen von lokaler Referenz %s durch Rebase."
+
+#: branch.c:98
+#, c-format
+msgid "Branch %s set up to track local ref %s."
+msgstr "Branch %s konfiguriert zum Folgen von lokaler Referenz %s."
+
+#: branch.c:118
+#, c-format
+msgid "Tracking not set up: name too long: %s"
+msgstr ""
+"Konfiguration zum Folgen von Branch nicht eingerichtet. Name zu lang: %s"
+
+#: branch.c:137
+#, c-format
+msgid "Not tracking: ambiguous information for ref %s"
+msgstr ""
+"Konfiguration zum Folgen von Branch nicht eingerichtet. Referenz %s ist "
+"mehrdeutig."
+
+#: branch.c:182
+#, c-format
+msgid "'%s' is not a valid branch name."
+msgstr "'%s' ist kein gültiger Branchname."
+
+#: branch.c:187
+#, c-format
+msgid "A branch named '%s' already exists."
+msgstr "Branch '%s' existiert bereits."
+
+#: branch.c:195
+msgid "Cannot force update the current branch."
+msgstr "Kann Aktualisierung des aktuellen Branches nicht erzwingen."
+
+#: branch.c:216
 #, c-format
 msgid "Cannot setup tracking information; starting point '%s' is not a branch."
-msgstr "Kann Informationen zum Übernahmezweig nicht einrichten; "
-"Startpunkt '%s' ist kein Zweig."
+msgstr ""
+"Kann Tracking-Informationen nicht einrichten; Startpunkt '%s' ist kein "
+"Branch."
 
-#: branch.c:203
+#: branch.c:218
 #, c-format
 msgid "the requested upstream branch '%s' does not exist"
-msgstr "der angeforderte externe Übernahmezweig '%s' existiert nicht"
+msgstr "der angeforderte Upstream-Branch '%s' existiert nicht"
 
-#: branch.c:205
+#: branch.c:220
 msgid ""
 "\n"
 "If you are planning on basing your work on an upstream\n"
@@ -156,14 +231,37 @@
 "\"git push -u\" to set the upstream config as you push."
 msgstr ""
 "\n"
-"Falls Sie vorhaben, Ihre Arbeit auf einem bereits existierenden,\n"
-"externen Übernahmezweig aufzubauen, sollten Sie \"git fetch\"\n"
+"Falls Sie vorhaben, Ihre Arbeit auf einem bereits existierenden\n"
+"Upstream-Branch aufzubauen, sollten Sie \"git fetch\"\n"
 "ausführen, um diesen abzurufen.\n"
 "\n"
-"Falls Sie vorhaben, einen neuen lokalen Zweig zu versenden\n"
+"Falls Sie vorhaben, einen neuen lokalen Branch zu versenden\n"
 "der seinem externen Gegenstück folgen soll, können Sie\n"
-"\"git push -u\" verwenden, um den externen Übernahmezweig\n"
-"beim Versand zu konfigurieren."
+"\"git push -u\" verwenden, um den Upstream-Branch beim \"push\"\n"
+"zu konfigurieren."
+
+#: branch.c:265
+#, c-format
+msgid "Not a valid object name: '%s'."
+msgstr "Ungültiger Objekt-Name: '%s'"
+
+#: branch.c:285
+#, c-format
+msgid "Ambiguous object name: '%s'."
+msgstr "mehrdeutiger Objekt-Name: '%s'"
+
+#: branch.c:290
+#, c-format
+msgid "Not a valid branch point: '%s'."
+msgstr "Ungültiger Branchpunkt: '%s'"
+
+#: branch.c:296
+msgid "Failed to lock ref for update"
+msgstr "Fehler beim Sperren der Referenz zur Aktualisierung."
+
+#: branch.c:314
+msgid "Failed to write ref"
+msgstr "Fehler beim Schreiben der Referenz."
 
 #: bundle.c:36
 #, c-format
@@ -175,18 +273,18 @@
 msgid "unrecognized header: %s%s (%d)"
 msgstr "nicht erkannter Kopfbereich: %s%s (%d)"
 
-#: bundle.c:89 builtin/commit.c:676
+#: bundle.c:89 builtin/commit.c:697
 #, c-format
 msgid "could not open '%s'"
 msgstr "Konnte '%s' nicht öffnen"
 
 #: bundle.c:140
 msgid "Repository lacks these prerequisite commits:"
-msgstr "Dem Projektarchiv fehlen folgende vorausgesetzte Versionen:"
+msgstr "Dem Repository fehlen folgende vorausgesetzte Commits:"
 
-#: bundle.c:164 sequencer.c:651 sequencer.c:1083 builtin/log.c:300
-#: builtin/log.c:754 builtin/log.c:1350 builtin/log.c:1566 builtin/merge.c:349
-#: builtin/shortlog.c:157
+#: bundle.c:164 sequencer.c:661 sequencer.c:1111 builtin/log.c:331
+#: builtin/log.c:801 builtin/log.c:1399 builtin/log.c:1625 builtin/merge.c:364
+#: builtin/shortlog.c:156
 msgid "revision walk setup failed"
 msgstr "Einrichtung des Revisionsgangs fehlgeschlagen"
 
@@ -212,7 +310,7 @@
 msgid "rev-list died"
 msgstr "\"rev-list\" abgebrochen"
 
-#: bundle.c:300 builtin/log.c:1246 builtin/shortlog.c:260
+#: bundle.c:300 builtin/log.c:1310 builtin/shortlog.c:259
 #, c-format
 msgid "unrecognized argument: %s"
 msgstr "nicht erkanntes Argument: %s"
@@ -243,30 +341,30 @@
 msgid "index-pack died"
 msgstr "Erstellung der Paketindexdatei abgebrochen"
 
-#: commit.c:50
+#: commit.c:53
 #, c-format
 msgid "could not parse %s"
 msgstr "konnte %s nicht parsen"
 
-#: commit.c:52
+#: commit.c:55
 #, c-format
 msgid "%s %s is not a commit!"
-msgstr "%s %s ist keine Version!"
+msgstr "%s %s ist kein Commit!"
 
 #: compat/obstack.c:406 compat/obstack.c:408
 msgid "memory exhausted"
 msgstr "Speicher verbraucht"
 
-#: connected.c:39
+#: connected.c:60
 msgid "Could not run 'git rev-list'"
 msgstr "Konnte 'git rev-list' nicht ausführen"
 
-#: connected.c:48
+#: connected.c:80
 #, c-format
 msgid "failed write to rev-list: %s"
 msgstr "Fehler beim Schreiben nach rev-list: %s"
 
-#: connected.c:56
+#: connected.c:88
 #, c-format
 msgid "failed to close rev-list's stdin: %s"
 msgstr "Fehler beim Schließen von rev-list's Standard-Eingabe: %s"
@@ -363,7 +461,7 @@
 "Fehler in 'diff.dirstat' Konfigurationsvariable gefunden:\n"
 "%s"
 
-#: diff.c:3480
+#: diff.c:3487
 #, c-format
 msgid ""
 "Failed to parse --dirstat/-X option parameter:\n"
@@ -372,7 +470,7 @@
 "Fehler beim Parsen des --dirstat/-X Optionsparameters:\n"
 "%s"
 
-#: diff.c:3494
+#: diff.c:3501
 #, c-format
 msgid "Failed to parse --submodule option parameter: '%s'"
 msgstr "Fehler beim Parsen des --submodule Optionsparameters: '%s'"
@@ -414,20 +512,20 @@
 msgid "'%s': short read %s"
 msgstr "'%s': read() zu kurz %s"
 
-#: help.c:212
+#: help.c:210
 #, c-format
 msgid "available git commands in '%s'"
 msgstr "Vorhandene Git-Kommandos in '%s'"
 
-#: help.c:219
+#: help.c:217
 msgid "git commands available from elsewhere on your $PATH"
 msgstr "Vorhandene Git-Kommandos irgendwo in Ihrem $PATH"
 
-#: help.c:235
+#: help.c:233
 msgid "The most commonly used git commands are:"
 msgstr "Die allgemein verwendeten Git-Kommandos sind:"
 
-#: help.c:292
+#: help.c:290
 #, c-format
 msgid ""
 "'%s' appears to be a git command, but we were not\n"
@@ -436,11 +534,11 @@
 "'%s' scheint ein git-Kommando zu sein, konnte aber\n"
 "nicht ausgeführt werden. Vielleicht ist git-%s fehlerhaft?"
 
-#: help.c:349
+#: help.c:347
 msgid "Uh oh. Your system reports no Git commands at all."
 msgstr "Uh oh. Keine Git-Kommandos auf Ihrem System vorhanden."
 
-#: help.c:371
+#: help.c:369
 #, c-format
 msgid ""
 "WARNING: You called a Git command named '%s', which does not exist.\n"
@@ -449,17 +547,17 @@
 "Warnung: Sie haben das nicht existierende Git-Kommando '%s' ausgeführt.\n"
 "Setze fort unter der Annahme, dass Sie '%s' gemeint haben"
 
-#: help.c:376
+#: help.c:374
 #, c-format
 msgid "in %0.1f seconds automatically..."
 msgstr "automatisch in %0.1f Sekunden..."
 
-#: help.c:383
+#: help.c:381
 #, c-format
 msgid "git: '%s' is not a git command. See 'git --help'."
 msgstr "git: '%s' ist kein Git-Kommando. Siehe 'git --help'."
 
-#: help.c:387
+#: help.c:385 help.c:444
 msgid ""
 "\n"
 "Did you mean this?"
@@ -473,89 +571,94 @@
 "\n"
 "Haben Sie eines von diesen gemeint?"
 
+#: help.c:440
+#, c-format
+msgid "%s: %s - %s"
+msgstr "%s: %s - %s"
+
 #: merge.c:56
 msgid "failed to read the cache"
 msgstr "Lesen des Zwischenspeichers fehlgeschlagen"
 
-#: merge.c:110 builtin/checkout.c:362 builtin/checkout.c:563
-#: builtin/clone.c:635
+#: merge.c:110 builtin/checkout.c:365 builtin/checkout.c:566
+#: builtin/clone.c:656
 msgid "unable to write new index file"
-msgstr "Konnte neue Bereitstellungsdatei nicht schreiben."
+msgstr "Konnte neue Staging-Area-Datei nicht schreiben."
 
 #: merge-recursive.c:190
 #, c-format
 msgid "(bad commit)\n"
-msgstr "(ungültige Version)\n"
+msgstr "(ungültiger Commit)\n"
 
 #: merge-recursive.c:206
 #, c-format
 msgid "addinfo_cache failed for path '%s'"
 msgstr "addinfo_cache für Pfad '%s' fehlgeschlagen"
 
-#: merge-recursive.c:268
+#: merge-recursive.c:269
 msgid "error building trees"
-msgstr "Fehler beim Erstellen der Bäume"
+msgstr "Fehler beim Erstellen der \"Tree\"-Objekte"
 
-#: merge-recursive.c:672
+#: merge-recursive.c:673
 #, c-format
 msgid "failed to create path '%s'%s"
 msgstr "Fehler beim Erstellen des Pfades '%s'%s"
 
-#: merge-recursive.c:683
+#: merge-recursive.c:684
 #, c-format
 msgid "Removing %s to make room for subdirectory\n"
 msgstr "Entferne %s um Platz für Unterverzeichnis zu schaffen\n"
 
 #. something else exists
 #. .. but not some other error (who really cares what?)
-#: merge-recursive.c:697 merge-recursive.c:718
+#: merge-recursive.c:698 merge-recursive.c:719
 msgid ": perhaps a D/F conflict?"
 msgstr ": vielleicht ein Verzeichnis/Datei-Konflikt?"
 
-#: merge-recursive.c:708
+#: merge-recursive.c:709
 #, c-format
 msgid "refusing to lose untracked file at '%s'"
 msgstr "verweigere, da unbeobachtete Dateien in '%s' verloren gehen würden"
 
-#: merge-recursive.c:748
+#: merge-recursive.c:749
 #, c-format
 msgid "cannot read object %s '%s'"
 msgstr "kann Objekt %s '%s' nicht lesen"
 
-#: merge-recursive.c:750
+#: merge-recursive.c:751
 #, c-format
 msgid "blob expected for %s '%s'"
 msgstr "Blob erwartet für %s '%s'"
 
-#: merge-recursive.c:773 builtin/clone.c:303
+#: merge-recursive.c:774 builtin/clone.c:312
 #, c-format
 msgid "failed to open '%s'"
 msgstr "Fehler beim Öffnen von '%s'"
 
-#: merge-recursive.c:781
+#: merge-recursive.c:782
 #, c-format
 msgid "failed to symlink '%s'"
-msgstr "Fehler beim Erstellen einer symbolischen Verknüpfung für '%s'"
+msgstr "Fehler beim Erstellen eines symbolischen Verweises für '%s'"
 
-#: merge-recursive.c:784
+#: merge-recursive.c:785
 #, c-format
 msgid "do not know what to do with %06o %s '%s'"
 msgstr "weiß nicht was mit %06o %s '%s' zu machen ist"
 
-#: merge-recursive.c:922
+#: merge-recursive.c:923
 msgid "Failed to execute internal merge"
-msgstr "Fehler bei Ausführung der internen Zusammenführung"
+msgstr "Fehler bei Ausführung des internen Merges"
 
-#: merge-recursive.c:926
+#: merge-recursive.c:927
 #, c-format
 msgid "Unable to add %s to database"
 msgstr "Konnte %s nicht zur Datenbank hinzufügen"
 
-#: merge-recursive.c:942
+#: merge-recursive.c:943
 msgid "unsupported object type in the tree"
-msgstr "nicht unterstützter Objekttyp im Baum"
+msgstr "nicht unterstützter Objekttyp im Verzeichnis"
 
-#: merge-recursive.c:1021 merge-recursive.c:1035
+#: merge-recursive.c:1022 merge-recursive.c:1036
 #, c-format
 msgid ""
 "CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s left "
@@ -564,7 +667,7 @@
 "KONFLIKT (%s/löschen): %s gelöscht in %s und %s in %s. Stand %s von %s wurde "
 "im Arbeitsbereich gelassen."
 
-#: merge-recursive.c:1027 merge-recursive.c:1040
+#: merge-recursive.c:1028 merge-recursive.c:1041
 #, c-format
 msgid ""
 "CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s left "
@@ -573,174 +676,197 @@
 "KONFLIKT (%s/löschen): %s gelöscht in %s und %s in %s. Stand %s von %s wurde "
 "im Arbeitsbereich bei %s gelassen."
 
-#: merge-recursive.c:1081
+#: merge-recursive.c:1082
 msgid "rename"
 msgstr "umbenennen"
 
-#: merge-recursive.c:1081
+#: merge-recursive.c:1082
 msgid "renamed"
 msgstr "umbenannt"
 
-#: merge-recursive.c:1137
+#: merge-recursive.c:1138
 #, c-format
 msgid "%s is a directory in %s adding as %s instead"
 msgstr "%s ist ein Verzeichnis in %s, füge es stattdessen als %s hinzu"
 
-#: merge-recursive.c:1159
+#: merge-recursive.c:1160
 #, c-format
 msgid ""
 "CONFLICT (rename/rename): Rename \"%s\"->\"%s\" in branch \"%s\" rename \"%s"
 "\"->\"%s\" in \"%s\"%s"
 msgstr ""
-"KONFLIKT (umbenennen/umbenennen): Benenne um \"%s\"->\"%s\" in Zweig \"%s\" "
-"und \"%s\"->\"%s\" in Zweig \"%s\"%s"
+"KONFLIKT (umbenennen/umbenennen): Benenne um \"%s\"->\"%s\" in Branch \"%s\" "
+"und \"%s\"->\"%s\" in Branch \"%s\"%s"
 
-#: merge-recursive.c:1164
+#: merge-recursive.c:1165
 msgid " (left unresolved)"
 msgstr " (bleibt unaufgelöst)"
 
-#: merge-recursive.c:1218
+#: merge-recursive.c:1219
 #, c-format
 msgid "CONFLICT (rename/rename): Rename %s->%s in %s. Rename %s->%s in %s"
 msgstr ""
 "KONFLIKT (umbenennen/umbenennen): Benenne um %s->%s in %s. Benenne um %s->%s "
 "in %s"
 
-#: merge-recursive.c:1248
+#: merge-recursive.c:1249
 #, c-format
 msgid "Renaming %s to %s and %s to %s instead"
 msgstr "Benenne stattdessen %s nach %s und %s nach %s um"
 
-#: merge-recursive.c:1447
+#: merge-recursive.c:1448
 #, c-format
 msgid "CONFLICT (rename/add): Rename %s->%s in %s. %s added in %s"
 msgstr ""
 "KONFLIKT (umbenennen/hinzufügen): Benenne um %s->%s in %s. %s hinzugefügt in "
 "%s"
 
-#: merge-recursive.c:1457
+#: merge-recursive.c:1458
 #, c-format
 msgid "Adding merged %s"
 msgstr "Füge zusammengeführte Datei %s hinzu"
 
-#: merge-recursive.c:1462 merge-recursive.c:1660
+#: merge-recursive.c:1463 merge-recursive.c:1661
 #, c-format
 msgid "Adding as %s instead"
 msgstr "Füge stattdessen als %s hinzu"
 
-#: merge-recursive.c:1513
+#: merge-recursive.c:1514
 #, c-format
 msgid "cannot read object %s"
 msgstr "kann Objekt %s nicht lesen"
 
-#: merge-recursive.c:1516
+#: merge-recursive.c:1517
 #, c-format
 msgid "object %s is not a blob"
 msgstr "Objekt %s ist kein Blob"
 
-#: merge-recursive.c:1564
+#: merge-recursive.c:1565
 msgid "modify"
 msgstr "ändern"
 
-#: merge-recursive.c:1564
+#: merge-recursive.c:1565
 msgid "modified"
 msgstr "geändert"
 
-#: merge-recursive.c:1574
+#: merge-recursive.c:1575
 msgid "content"
 msgstr "Inhalt"
 
-#: merge-recursive.c:1581
+#: merge-recursive.c:1582
 msgid "add/add"
 msgstr "hinzufügen/hinzufügen"
 
-#: merge-recursive.c:1615
+#: merge-recursive.c:1616
 #, c-format
 msgid "Skipped %s (merged same as existing)"
-msgstr "%s ausgelassen (Ergebnis der Zusammenführung existiert bereits)"
+msgstr "%s ausgelassen (Ergebnis des Merges existiert bereits)"
 
-#: merge-recursive.c:1629
+#: merge-recursive.c:1630
 #, c-format
 msgid "Auto-merging %s"
-msgstr "automatische Zusammenführung von %s"
+msgstr "automatischer Merge von %s"
 
-#: merge-recursive.c:1633 git-submodule.sh:1029
+#: merge-recursive.c:1634 git-submodule.sh:1118
 msgid "submodule"
-msgstr "Unterprojekt"
+msgstr "Submodul"
 
-#: merge-recursive.c:1634
+#: merge-recursive.c:1635
 #, c-format
 msgid "CONFLICT (%s): Merge conflict in %s"
-msgstr "KONFLIKT (%s): Zusammenführungskonflikt in %s"
+msgstr "KONFLIKT (%s): Merge-Konflikt in %s"
 
-#: merge-recursive.c:1724
+#: merge-recursive.c:1725
 #, c-format
 msgid "Removing %s"
 msgstr "Entferne %s"
 
-#: merge-recursive.c:1749
+#: merge-recursive.c:1750
 msgid "file/directory"
 msgstr "Datei/Verzeichnis"
 
-#: merge-recursive.c:1755
+#: merge-recursive.c:1756
 msgid "directory/file"
 msgstr "Verzeichnis/Datei"
 
-#: merge-recursive.c:1760
+#: merge-recursive.c:1761
 #, c-format
 msgid "CONFLICT (%s): There is a directory with name %s in %s. Adding %s as %s"
 msgstr ""
 "KONFLIKT (%s): Es existiert bereits ein Verzeichnis %s in %s. Füge %s als %s "
 "hinzu."
 
-#: merge-recursive.c:1770
+#: merge-recursive.c:1771
 #, c-format
 msgid "Adding %s"
 msgstr "Füge %s hinzu"
 
-#: merge-recursive.c:1787
+#: merge-recursive.c:1788
 msgid "Fatal merge failure, shouldn't happen."
-msgstr "Fataler Fehler bei der Zusammenführung. Sollte nicht passieren."
+msgstr "Fataler Merge-Fehler. Sollte nicht passieren."
 
-#: merge-recursive.c:1806
+#: merge-recursive.c:1807
 msgid "Already up-to-date!"
 msgstr "Bereits aktuell!"
 
-#: merge-recursive.c:1815
+#: merge-recursive.c:1816
 #, c-format
 msgid "merging of trees %s and %s failed"
-msgstr "Zusammenführen der Bäume %s und %s fehlgeschlagen"
+msgstr "Zusammenführen der \"Tree\"-Objekte %s und %s fehlgeschlagen"
 
-#: merge-recursive.c:1845
+#: merge-recursive.c:1846
 #, c-format
 msgid "Unprocessed path??? %s"
 msgstr "unverarbeiteter Pfad??? %s"
 
-#: merge-recursive.c:1890
+#: merge-recursive.c:1891
 msgid "Merging:"
-msgstr "Zusammenführung:"
+msgstr "Merge:"
 
-#: merge-recursive.c:1903
+#: merge-recursive.c:1904
 #, c-format
 msgid "found %u common ancestor:"
 msgid_plural "found %u common ancestors:"
-msgstr[0] "%u gemeinsamen Vorfahren gefunden"
-msgstr[1] "%u gemeinsame Vorfahren gefunden"
+msgstr[0] "%u gemeinsamen Vorgänger-Commit gefunden"
+msgstr[1] "%u gemeinsame Vorgänger-Commits gefunden"
 
-#: merge-recursive.c:1940
+#: merge-recursive.c:1941
 msgid "merge returned no commit"
-msgstr "Zusammenführung hat keine Version zurückgegeben"
+msgstr "Merge hat keinen Commit zurückgegeben"
 
-#: merge-recursive.c:1997
+#: merge-recursive.c:1998
 #, c-format
 msgid "Could not parse object '%s'"
 msgstr "Konnte Objekt '%s' nicht parsen."
 
-#: merge-recursive.c:2009 builtin/merge.c:658
+#: merge-recursive.c:2010 builtin/merge.c:672
 msgid "Unable to write index."
-msgstr "Konnte Bereitstellung nicht schreiben."
+msgstr "Konnte Staging-Area nicht schreiben."
 
-#: object.c:195
+#: notes-utils.c:40
+msgid "Cannot commit uninitialized/unreferenced notes tree"
+msgstr ""
+"Kann uninitialisiertes/unreferenzierte Notiz-Verzeichnis nicht committen."
+
+#: notes-utils.c:81
+#, c-format
+msgid "Bad notes.rewriteMode value: '%s'"
+msgstr "Ungültiger notes.rewriteMode Wert: '%s'"
+
+#: notes-utils.c:91
+#, c-format
+msgid "Refusing to rewrite notes in %s (outside of refs/notes/)"
+msgstr ""
+"Umschreiben der Notizen in %s zurückgewiesen (außerhalb von refs/notes/)"
+
+#. TRANSLATORS: The first %s is the name of the
+#. environment variable, the second %s is its value
+#: notes-utils.c:118
+#, c-format
+msgid "Bad %s value: '%s'"
+msgstr "Ungültiger %s Wert: '%s'"
+
+#: object.c:204
 #, c-format
 msgid "unable to parse object: %s"
 msgstr "Konnte Objekt '%s' nicht parsen."
@@ -773,41 +899,40 @@
 #: pathspec.c:83
 #, c-format
 msgid "Path '%s' is in submodule '%.*s'"
-msgstr "Pfad '%s' befindet sich in Unterprojekt '%.*s'"
+msgstr "Pfad '%s' befindet sich in Submodul '%.*s'"
 
 #: pathspec.c:99
 #, c-format
 msgid "'%s' is beyond a symbolic link"
-msgstr "'%s' ist über einem symbolischen Link"
+msgstr "'%s' ist hinter einem symbolischen Verweis"
 
-#: remote.c:1781
+#: remote.c:1788
 #, c-format
 msgid "Your branch is ahead of '%s' by %d commit.\n"
 msgid_plural "Your branch is ahead of '%s' by %d commits.\n"
-msgstr[0] "Ihr Zweig ist vor '%s' um %d Version.\n"
-msgstr[1] "Ihr Zweig ist vor '%s' um %d Versionen.\n"
+msgstr[0] "Ihr Branch ist vor '%s' um %d Commit.\n"
+msgstr[1] "Ihr Branch ist vor '%s' um %d Commits.\n"
 
-#: remote.c:1787
+#: remote.c:1794
 msgid "  (use \"git push\" to publish your local commits)\n"
-msgstr "  (benutzen Sie \"git push\" um lokalen Versionen herauszubringen)\n"
+msgstr "  (benutzen Sie \"git push\" um lokale Commits zu publizieren)\n"
 
-#: remote.c:1790
+#: remote.c:1797
 #, c-format
 msgid "Your branch is behind '%s' by %d commit, and can be fast-forwarded.\n"
 msgid_plural ""
 "Your branch is behind '%s' by %d commits, and can be fast-forwarded.\n"
 msgstr[0] ""
-"Ihr Zweig ist zu '%s' um %d Version hinterher, und kann vorgespult werden.\n"
+"Ihr Branch ist zu '%s' um %d Commit hinterher, und kann vorgespult werden.\n"
 msgstr[1] ""
-"Ihr Zweig ist zu '%s' um %d Versionen hinterher, und kann vorgespult "
-"werden.\n"
+"Ihr Branch ist zu '%s' um %d Commits hinterher, und kann vorgespult werden.\n"
 
-#: remote.c:1798
+#: remote.c:1805
 msgid "  (use \"git pull\" to update your local branch)\n"
 msgstr ""
-"  (benutzen Sie \"git pull\" um Ihren lokalen Zweig zu aktualisieren)\n"
+"  (benutzen Sie \"git pull\" um Ihren lokalen Branch zu aktualisieren)\n"
 
-#: remote.c:1801
+#: remote.c:1808
 #, c-format
 msgid ""
 "Your branch and '%s' have diverged,\n"
@@ -816,26 +941,35 @@
 "Your branch and '%s' have diverged,\n"
 "and have %d and %d different commits each, respectively.\n"
 msgstr[0] ""
-"Ihr Zweig und '%s' sind divergiert,\n"
-"und haben jeweils %d und %d unterschiedliche Versionen.\n"
+"Ihr Branch und '%s' sind divergiert,\n"
+"und haben jeweils %d und %d unterschiedliche Commits.\n"
 msgstr[1] ""
-"Ihr Zweig und '%s' sind divergiert,\n"
-"und haben jeweils %d und %d unterschiedliche Versionen.\n"
+"Ihr Branch und '%s' sind divergiert,\n"
+"und haben jeweils %d und %d unterschiedliche Commits.\n"
 
-#: remote.c:1811
+#: remote.c:1818
 msgid "  (use \"git pull\" to merge the remote branch into yours)\n"
 msgstr ""
-"  (benutzen Sie \"git pull\" um Ihren Zweig mit dem externen "
+"  (benutzen Sie \"git pull\" um Ihren Branch mit dem Remote-Branch "
 "zusammenzuführen)\n"
 
-#: sequencer.c:206 builtin/merge.c:776 builtin/merge.c:889 builtin/merge.c:999
-#: builtin/merge.c:1009
+#: run-command.c:80
+msgid "open /dev/null failed"
+msgstr "Öffnen von /dev/null fehlgeschlagen"
+
+#: run-command.c:82
+#, c-format
+msgid "dup2(%d,%d) failed"
+msgstr "dup2(%d,%d) fehlgeschlagen"
+
+#: sequencer.c:206 builtin/merge.c:790 builtin/merge.c:903
+#: builtin/merge.c:1013 builtin/merge.c:1023
 #, c-format
 msgid "Could not open '%s' for writing"
 msgstr "Konnte '%s' nicht zum Schreiben öffnen."
 
-#: sequencer.c:208 builtin/merge.c:335 builtin/merge.c:779
-#: builtin/merge.c:1001 builtin/merge.c:1014
+#: sequencer.c:208 builtin/merge.c:350 builtin/merge.c:793
+#: builtin/merge.c:1015 builtin/merge.c:1028
 #, c-format
 msgid "Could not write to '%s'"
 msgstr "Konnte nicht nach '%s' schreiben."
@@ -858,7 +992,7 @@
 "mit 'git add <Pfade>' oder 'git rm <Pfade>'und tragen Sie das Ergebnis mit\n"
 "'git commit' ein"
 
-#: sequencer.c:245 sequencer.c:859 sequencer.c:942
+#: sequencer.c:245 sequencer.c:869 sequencer.c:952
 #, c-format
 msgid "Could not write to %s"
 msgstr "Konnte nicht nach %s schreiben"
@@ -883,512 +1017,559 @@
 "Tragen Sie Ihre Änderungen ein oder benutzen Sie \"stash\" um fortzufahren."
 
 #. TRANSLATORS: %s will be "revert" or "cherry-pick"
-#: sequencer.c:319
+#: sequencer.c:324
 #, c-format
 msgid "%s: Unable to write new index file"
-msgstr "%s: Konnte neue Bereitstellungsdatei nicht schreiben"
+msgstr "%s: Konnte neue Staging-Area-Datei nicht schreiben"
 
-#: sequencer.c:350
+#: sequencer.c:355
 msgid "Could not resolve HEAD commit\n"
-msgstr "Konnte Version der Zweigspitze (HEAD) nicht auflösen\n"
+msgstr "Konnte Commit von HEAD nicht auflösen\n"
 
-#: sequencer.c:371
+#: sequencer.c:377
 msgid "Unable to update cache tree\n"
-msgstr "Konnte zwischengespeicherten Baum nicht aktualisieren\n"
+msgstr "Konnte Cache-Verzeichnis nicht aktualisieren\n"
 
-#: sequencer.c:416
+#: sequencer.c:422
 #, c-format
 msgid "Could not parse commit %s\n"
-msgstr "Konnte Version %s nicht parsen\n"
+msgstr "Konnte Commit %s nicht parsen\n"
 
-#: sequencer.c:421
+#: sequencer.c:427
 #, c-format
 msgid "Could not parse parent commit %s\n"
-msgstr "Konnte Elternversion %s nicht parsen\n"
+msgstr "Konnte Eltern-Commit %s nicht parsen\n"
 
-#: sequencer.c:487
+#: sequencer.c:493
 msgid "Your index file is unmerged."
-msgstr "Ihre Bereitstellungsdatei ist nicht zusammengeführt."
+msgstr "Ihre Staging-Area-Datei ist nicht zusammengeführt."
 
-#: sequencer.c:506
+#: sequencer.c:512
 #, c-format
 msgid "Commit %s is a merge but no -m option was given."
-msgstr ""
-"Version %s ist eine Zusammenführung, aber die Option -m wurde nicht "
-"angegeben."
+msgstr "Commit %s ist ein Merge, aber die Option -m wurde nicht angegeben."
 
-#: sequencer.c:514
+#: sequencer.c:520
 #, c-format
 msgid "Commit %s does not have parent %d"
-msgstr "Version %s hat keinen Elternteil %d"
+msgstr "Commit %s hat keinen Elternteil %d"
 
-#: sequencer.c:518
+#: sequencer.c:524
 #, c-format
 msgid "Mainline was specified but commit %s is not a merge."
-msgstr ""
-"Hauptlinie wurde spezifiziert, aber Version %s ist keine Zusammenführung."
+msgstr "Hauptlinie wurde spezifiziert, aber Commit %s ist kein Merge."
 
 #. TRANSLATORS: The first %s will be "revert" or
 #. "cherry-pick", the second %s a SHA1
-#: sequencer.c:531
+#: sequencer.c:537
 #, c-format
 msgid "%s: cannot parse parent commit %s"
-msgstr "%s: kann Elternversion %s nicht parsen"
+msgstr "%s: kann Eltern-Commit %s nicht parsen"
 
-#: sequencer.c:535
+#: sequencer.c:541
 #, c-format
 msgid "Cannot get commit message for %s"
-msgstr "Kann keine Versionsbeschreibung für %s bekommen"
+msgstr "Kann keine Commit-Beschreibung für %s bekommen"
 
-#: sequencer.c:621
+#: sequencer.c:627
 #, c-format
 msgid "could not revert %s... %s"
-msgstr "Konnte %s nicht zurücknehmen... %s"
+msgstr "Konnte \"revert\" nicht auf %s ausführen... %s"
 
-#: sequencer.c:622
+#: sequencer.c:628
 #, c-format
 msgid "could not apply %s... %s"
 msgstr "Konnte %s nicht anwenden... %s"
 
-#: sequencer.c:654
+#: sequencer.c:664
 msgid "empty commit set passed"
-msgstr "leere Menge von Versionen übergeben"
+msgstr "leere Menge von Commits übergeben"
 
-#: sequencer.c:662
+#: sequencer.c:672
 #, c-format
 msgid "git %s: failed to read the index"
-msgstr "git %s: Fehler beim Lesen der Bereitstellung"
+msgstr "git %s: Fehler beim Lesen der Staging-Area"
 
-#: sequencer.c:667
+#: sequencer.c:677
 #, c-format
 msgid "git %s: failed to refresh the index"
-msgstr "git %s: Fehler beim Aktualisieren der Bereitstellung"
+msgstr "git %s: Fehler beim Aktualisieren der Staging-Area"
 
-#: sequencer.c:725
+#: sequencer.c:735
 #, c-format
 msgid "Cannot %s during a %s"
 msgstr "Kann %s nicht während eines %s durchführen"
 
-#: sequencer.c:747
+#: sequencer.c:757
 #, c-format
 msgid "Could not parse line %d."
 msgstr "Konnte Zeile %d nicht parsen."
 
-#: sequencer.c:752
+#: sequencer.c:762
 msgid "No commits parsed."
-msgstr "Keine Versionen geparst."
+msgstr "Keine Commits geparst."
 
-#: sequencer.c:765
+#: sequencer.c:775
 #, c-format
 msgid "Could not open %s"
 msgstr "Konnte %s nicht öffnen"
 
-#: sequencer.c:769
+#: sequencer.c:779
 #, c-format
 msgid "Could not read %s."
 msgstr "Konnte %s nicht lesen."
 
-#: sequencer.c:776
+#: sequencer.c:786
 #, c-format
 msgid "Unusable instruction sheet: %s"
 msgstr "Unbenutzbares Instruktionsblatt: %s"
 
-#: sequencer.c:804
+#: sequencer.c:814
 #, c-format
 msgid "Invalid key: %s"
 msgstr "Ungültiger Schlüssel: %s"
 
-#: sequencer.c:807
+#: sequencer.c:817
 #, c-format
 msgid "Invalid value for %s: %s"
 msgstr "Ungültiger Wert für %s: %s"
 
-#: sequencer.c:819
+#: sequencer.c:829
 #, c-format
 msgid "Malformed options sheet: %s"
 msgstr "Fehlerhaftes Optionsblatt: %s"
 
-#: sequencer.c:840
+#: sequencer.c:850
 msgid "a cherry-pick or revert is already in progress"
 msgstr "\"cherry-pick\" oder \"revert\" ist bereits im Gang"
 
-#: sequencer.c:841
+#: sequencer.c:851
 msgid "try \"git cherry-pick (--continue | --quit | --abort)\""
 msgstr "versuchen Sie \"git cherry-pick (--continue | --quit | --abort)\""
 
-#: sequencer.c:845
+#: sequencer.c:855
 #, c-format
 msgid "Could not create sequencer directory %s"
 msgstr "Konnte \"sequencer\"-Verzeichnis %s nicht erstellen"
 
-#: sequencer.c:861 sequencer.c:946
+#: sequencer.c:871 sequencer.c:956
 #, c-format
 msgid "Error wrapping up %s."
 msgstr "Fehler beim Einpacken von %s."
 
-#: sequencer.c:880 sequencer.c:1014
+#: sequencer.c:890 sequencer.c:1024
 msgid "no cherry-pick or revert in progress"
 msgstr "kein \"cherry-pick\" oder \"revert\" im Gang"
 
-#: sequencer.c:882
+#: sequencer.c:892
 msgid "cannot resolve HEAD"
-msgstr "kann Zweigspitze (HEAD) nicht auflösen"
+msgstr "kann HEAD nicht auflösen"
 
-#: sequencer.c:884
+#: sequencer.c:894
 msgid "cannot abort from a branch yet to be born"
-msgstr "kann nicht abbrechen: bin auf einem Zweig, der noch geboren wird"
+msgstr "kann nicht abbrechen: bin auf einem Branch, der noch geboren wird"
 
-#: sequencer.c:906 builtin/apply.c:4060
+#: sequencer.c:916 builtin/apply.c:4061
 #, c-format
 msgid "cannot open %s: %s"
 msgstr "Kann %s nicht öffnen: %s"
 
-#: sequencer.c:909
+#: sequencer.c:919
 #, c-format
 msgid "cannot read %s: %s"
 msgstr "Kann %s nicht lesen: %s"
 
-#: sequencer.c:910
+#: sequencer.c:920
 msgid "unexpected end of file"
 msgstr "Unerwartetes Dateiende"
 
-#: sequencer.c:916
+#: sequencer.c:926
 #, c-format
 msgid "stored pre-cherry-pick HEAD file '%s' is corrupt"
-msgstr ""
-"gespeicherte \"pre-cherry-pick\" Datei der Zweigspitze (HEAD) '%s' ist "
-"beschädigt"
+msgstr "gespeicherte \"pre-cherry-pick\" HEAD Datei '%s' ist beschädigt"
 
-#: sequencer.c:939
+#: sequencer.c:949
 #, c-format
 msgid "Could not format %s."
 msgstr "Konnte %s nicht formatieren."
 
-#: sequencer.c:1101
+#: sequencer.c:1092
+#, c-format
+msgid "%s: can't cherry-pick a %s"
+msgstr "%s: %s kann nicht in \"cherry-pick\" benutzt werden"
+
+#: sequencer.c:1095
+#, c-format
+msgid "%s: bad revision"
+msgstr "%s: ungültiger Commit"
+
+#: sequencer.c:1129
 msgid "Can't revert as initial commit"
-msgstr "Rücknahme-Version kann nicht initial sein."
+msgstr "Kann nicht als allerersten Commit einen Revert ausführen."
 
-#: sequencer.c:1102
+#: sequencer.c:1130
 msgid "Can't cherry-pick into empty head"
-msgstr "Kann \"cherry-pick\" nicht in einem leeren Zweig ausführen."
+msgstr "Kann nicht als allerersten Commit einen Cherry-Pick ausführen."
 
-#: sha1_name.c:1036
+#: sha1_name.c:440
+msgid ""
+"Git normally never creates a ref that ends with 40 hex characters\n"
+"because it will be ignored when you just specify 40-hex. These refs\n"
+"may be created by mistake. For example,\n"
+"\n"
+"  git checkout -b $br $(git rev-parse ...)\n"
+"\n"
+"where \"$br\" is somehow empty and a 40-hex ref is created. Please\n"
+"examine these refs and maybe delete them. Turn this message off by\n"
+"running \"git config advice.objectNameWarning false\""
+msgstr ""
+"Git erzeugt normalerweise keine Referenzen die mit\n"
+"40 Hex-Zeichen enden, da diese ignoriert werden wenn\n"
+"Sie diese angeben. Diese Referenzen könnten aus Versehen\n"
+"erzeugt worden sein. Zum Beispiel,\n"
+"\n"
+"  git checkout -b $br $(git rev-parse ...)\n"
+"\n"
+"wobei \"$br\" leer ist und eine 40-Hex-Referenz erzeugt\n"
+"wurde. Bitte prüfen Sie diese Referenzen und löschen\n"
+"Sie sie gegebenenfalls. Unterdrücken Sie diese Meldung\n"
+"indem Sie \"git config advice.objectNameWarning false\"\n"
+"ausführen."
+
+#: sha1_name.c:1097
 msgid "HEAD does not point to a branch"
-msgstr "Zweigspitze (HEAD) zeigt auf keinen Zweig"
+msgstr "HEAD zeigt auf keinen Branch"
 
-#: sha1_name.c:1039
+#: sha1_name.c:1100
 #, c-format
 msgid "No such branch: '%s'"
-msgstr "Kein solcher Zweig '%s'"
+msgstr "Kein solcher Branch '%s'"
 
-#: sha1_name.c:1041
+#: sha1_name.c:1102
 #, c-format
 msgid "No upstream configured for branch '%s'"
-msgstr "Kein entferntes Projektarchiv für Zweig '%s' konfiguriert."
+msgstr "Kein Upstream-Branch für Branch '%s' konfiguriert."
 
-#: sha1_name.c:1044
+#: sha1_name.c:1106
 #, c-format
 msgid "Upstream branch '%s' not stored as a remote-tracking branch"
-msgstr ""
-"Zweig '%s' des entfernten Projektarchivs ist kein gefolgter Übernahmezweig"
+msgstr "Upstream-Branch '%s' ist nicht als Remote-Tracking-Branch gespeichert"
 
 #: wrapper.c:408
 #, c-format
 msgid "unable to access '%s': %s"
 msgstr "konnte nicht auf '%s' zugreifen: %s"
 
-#: wrapper.c:423
+#: wrapper.c:429
 #, c-format
 msgid "unable to access '%s'"
 msgstr "konnte nicht auf '%s' zugreifen"
 
-#: wrapper.c:434
+#: wrapper.c:440
 #, c-format
 msgid "unable to look up current user in the passwd file: %s"
 msgstr "konnte aktuellen Benutzer nicht in Passwort-Datei finden: %s"
 
-#: wrapper.c:435
+#: wrapper.c:441
 msgid "no such user"
 msgstr "kein solcher Benutzer"
 
-#: wt-status.c:140
+#: wt-status.c:141
 msgid "Unmerged paths:"
 msgstr "Nicht zusammengeführte Pfade:"
 
-#: wt-status.c:167 wt-status.c:194
+#: wt-status.c:168 wt-status.c:195
 #, c-format
 msgid "  (use \"git reset %s <file>...\" to unstage)"
 msgstr ""
-"  (benutzen Sie \"git reset %s <Datei>...\" zum Herausnehmen aus der "
-"Bereitstellung)"
+"  (benutzen Sie \"git reset %s <Datei>...\" zum Entfernen aus der Staging-"
+"Area)"
 
-#: wt-status.c:169 wt-status.c:196
+#: wt-status.c:170 wt-status.c:197
 msgid "  (use \"git rm --cached <file>...\" to unstage)"
 msgstr ""
-"  (benutzen Sie \"git rm --cached <Datei>...\" zum Herausnehmen aus der "
-"Bereitstellung)"
+"  (benutzen Sie \"git rm --cached <Datei>...\" zum Entfernen aus der Staging-"
+"Area)"
 
-#: wt-status.c:173
+#: wt-status.c:174
 msgid "  (use \"git add <file>...\" to mark resolution)"
 msgstr ""
 "  (benutzen Sie \"git add/rm <Datei>...\" um die Auflösung zu markieren)"
 
-#: wt-status.c:175 wt-status.c:179
+#: wt-status.c:176 wt-status.c:180
 msgid "  (use \"git add/rm <file>...\" as appropriate to mark resolution)"
 msgstr ""
 "  (benutzen Sie \"git add/rm <Datei>...\" um die Auflösung entsprechend zu "
 "markieren)"
 
-#: wt-status.c:177
+#: wt-status.c:178
 msgid "  (use \"git rm <file>...\" to mark resolution)"
 msgstr ""
 "  (benutzen Sie \"git add/rm <Datei>...\" um die Auflösung zu markieren)"
 
-#: wt-status.c:188
+#: wt-status.c:189
 msgid "Changes to be committed:"
-msgstr "zum Eintragen bereitgestellte Änderungen:"
+msgstr "zum Commit vorgemerkte Änderungen:"
 
-#: wt-status.c:206
+#: wt-status.c:207
 msgid "Changes not staged for commit:"
-msgstr "Änderungen, die nicht zum Eintragen bereitgestellt sind:"
+msgstr "Änderungen, die nicht zum Commit vorgemerkt sind:"
 
-#: wt-status.c:210
+#: wt-status.c:211
 msgid "  (use \"git add <file>...\" to update what will be committed)"
-msgstr "  (benutzen Sie \"git add <Datei>...\" zum Bereitstellen)"
-
-#: wt-status.c:212
-msgid "  (use \"git add/rm <file>...\" to update what will be committed)"
-msgstr "  (benutzen Sie \"git add/rm <Datei>...\" zum Bereitstellen)"
+msgstr ""
+"  (benutzen Sie \"git add <Datei>...\" um die Änderungen zum Commit "
+"vorzumerken)"
 
 #: wt-status.c:213
+msgid "  (use \"git add/rm <file>...\" to update what will be committed)"
+msgstr ""
+"  (benutzen Sie \"git add/rm <Datei>...\" um die Änderungen zum Commit "
+"vorzumerken)"
+
+#: wt-status.c:214
 msgid ""
 "  (use \"git checkout -- <file>...\" to discard changes in working directory)"
 msgstr ""
 "  (benutzen Sie \"git checkout -- <Datei>...\" um die Änderungen im "
 "Arbeitsverzeichnis zu verwerfen)"
 
-#: wt-status.c:215
+#: wt-status.c:216
 msgid "  (commit or discard the untracked or modified content in submodules)"
 msgstr ""
-"  (tragen Sie ein oder verwerfen Sie den unbeobachteten oder geänderten "
-"Inhalt in den Unterprojekten)"
+"  (committen oder verwerfen Sie den unbeobachteten oder geänderten Inhalt in "
+"den Submodulen)"
 
-#: wt-status.c:227
+#: wt-status.c:228
 #, c-format
 msgid "  (use \"git %s <file>...\" to include in what will be committed)"
-msgstr "  (benutzen Sie \"git %s <Datei>...\" zum Einfügen in die Eintragung)"
+msgstr ""
+"  (benutzen Sie \"git %s <Datei>...\" um die Änderungen zum Commit "
+"vorzumerken)"
 
-#: wt-status.c:244
+#: wt-status.c:245
 msgid "bug"
 msgstr "Fehler"
 
-#: wt-status.c:249
+#: wt-status.c:250
 msgid "both deleted:"
 msgstr "beide gelöscht:"
 
-#: wt-status.c:250
+#: wt-status.c:251
 msgid "added by us:"
 msgstr "von uns hinzugefügt:"
 
-#: wt-status.c:251
+#: wt-status.c:252
 msgid "deleted by them:"
 msgstr "von denen gelöscht:"
 
-#: wt-status.c:252
+#: wt-status.c:253
 msgid "added by them:"
 msgstr "von denen hinzugefügt:"
 
-#: wt-status.c:253
+#: wt-status.c:254
 msgid "deleted by us:"
 msgstr "von uns gelöscht:"
 
-#: wt-status.c:254
+#: wt-status.c:255
 msgid "both added:"
 msgstr "von beiden hinzugefügt:"
 
-#: wt-status.c:255
+#: wt-status.c:256
 msgid "both modified:"
 msgstr "von beiden geändert:"
 
-#: wt-status.c:285
+#: wt-status.c:286
 msgid "new commits, "
-msgstr "neue Versionen, "
+msgstr "neue Commits, "
 
-#: wt-status.c:287
+#: wt-status.c:288
 msgid "modified content, "
 msgstr "geänderter Inhalt, "
 
-#: wt-status.c:289
+#: wt-status.c:290
 msgid "untracked content, "
 msgstr "unbeobachteter Inhalt, "
 
-#: wt-status.c:306
+#: wt-status.c:307
 #, c-format
 msgid "new file:   %s"
 msgstr "neue Datei:   %s"
 
-#: wt-status.c:309
+#: wt-status.c:310
 #, c-format
 msgid "copied:     %s -> %s"
 msgstr "kopiert:     %s -> %s"
 
-#: wt-status.c:312
+#: wt-status.c:313
 #, c-format
 msgid "deleted:    %s"
 msgstr "gelöscht:    %s"
 
-#: wt-status.c:315
+#: wt-status.c:316
 #, c-format
 msgid "modified:   %s"
 msgstr "geändert:   %s"
 
-#: wt-status.c:318
+#: wt-status.c:319
 #, c-format
 msgid "renamed:    %s -> %s"
 msgstr "umbenannt:    %s -> %s"
 
-#: wt-status.c:321
+#: wt-status.c:322
 #, c-format
 msgid "typechange: %s"
 msgstr "Typänderung: %s"
 
-#: wt-status.c:324
+#: wt-status.c:325
 #, c-format
 msgid "unknown:    %s"
 msgstr "unbekannt:    %s"
 
-#: wt-status.c:327
+#: wt-status.c:328
 #, c-format
 msgid "unmerged:   %s"
 msgstr "nicht zusammengeführt:   %s"
 
-#: wt-status.c:330
+#: wt-status.c:331
 #, c-format
 msgid "bug: unhandled diff status %c"
 msgstr "Fehler: unbehandelter Differenz-Status %c"
 
-#: wt-status.c:805
+#: wt-status.c:803
 msgid "You have unmerged paths."
 msgstr "Sie haben nicht zusammengeführte Pfade."
 
-#: wt-status.c:808 wt-status.c:960
+#: wt-status.c:806
 msgid "  (fix conflicts and run \"git commit\")"
 msgstr " (beheben Sie die Konflikte und führen Sie \"git commit\" aus)"
 
-#: wt-status.c:811
+#: wt-status.c:809
 msgid "All conflicts fixed but you are still merging."
-msgstr ""
-"Alle Konflikte sind behoben, aber Sie sind immer noch beim Zusammenführen."
+msgstr "Alle Konflikte sind behoben, aber Sie sind immer noch beim Merge."
 
-#: wt-status.c:814
+#: wt-status.c:812
 msgid "  (use \"git commit\" to conclude merge)"
-msgstr "  (benutzen Sie \"git commit\" um die Zusammenführung abzuschließen)"
+msgstr "  (benutzen Sie \"git commit\" um den Merge abzuschließen)"
 
-#: wt-status.c:824
+#: wt-status.c:822
 msgid "You are in the middle of an am session."
 msgstr "Eine \"am\"-Sitzung ist im Gange."
 
-#: wt-status.c:827
+#: wt-status.c:825
 msgid "The current patch is empty."
 msgstr "Der aktuelle Patch ist leer."
 
-#: wt-status.c:831
-msgid "  (fix conflicts and then run \"git am --resolved\")"
+#: wt-status.c:829
+msgid "  (fix conflicts and then run \"git am --continue\")"
 msgstr ""
-"  (beheben Sie die Konflikte und führen Sie dann \"git am --resolved\" aus)"
+"  (beheben Sie die Konflikte und führen Sie dann \"git am --continue\" aus)"
+
+#: wt-status.c:831
+msgid "  (use \"git am --skip\" to skip this patch)"
+msgstr "  (benutzen Sie \"git am --skip\" um diesen Patch auszulassen)"
 
 #: wt-status.c:833
-msgid "  (use \"git am --skip\" to skip this patch)"
-msgstr " (benutzen Sie \"git am --skip\" um diesen Patch auszulassen)"
-
-#: wt-status.c:835
 msgid "  (use \"git am --abort\" to restore the original branch)"
 msgstr ""
-"  (benutzen Sie \"git am --abort\" um den ursprünglichen Zweig "
+"  (benutzen Sie \"git am --abort\" um den ursprünglichen Branch "
 "wiederherzustellen)"
 
-#: wt-status.c:895 wt-status.c:912
+#: wt-status.c:893 wt-status.c:910
 #, c-format
 msgid "You are currently rebasing branch '%s' on '%s'."
-msgstr "Sie sind gerade beim Neuaufbau von Zweig '%s' auf '%s'."
+msgstr "Sie sind gerade beim Rebase von Branch '%s' auf '%s'."
 
-#: wt-status.c:900 wt-status.c:917
+#: wt-status.c:898 wt-status.c:915
 msgid "You are currently rebasing."
-msgstr "Sie sind gerade beim Neuaufbau."
+msgstr "Sie sind gerade beim Rebase."
 
-#: wt-status.c:903
+#: wt-status.c:901
 msgid "  (fix conflicts and then run \"git rebase --continue\")"
 msgstr ""
 "  (beheben Sie die Konflikte und führen Sie dann \"git rebase --continue\" "
 "aus)"
 
-#: wt-status.c:905
+#: wt-status.c:903
 msgid "  (use \"git rebase --skip\" to skip this patch)"
 msgstr "  (benutzen Sie \"git rebase --skip\" um diesen Patch auszulassen)"
 
-#: wt-status.c:907
+#: wt-status.c:905
 msgid "  (use \"git rebase --abort\" to check out the original branch)"
 msgstr ""
-"  (benutzen Sie \"git rebase --abort\" um den ursprünglichen Zweig "
+"  (benutzen Sie \"git rebase --abort\" um den ursprünglichen Branch "
 "auszuchecken)"
 
-#: wt-status.c:920
+#: wt-status.c:918
 msgid "  (all conflicts fixed: run \"git rebase --continue\")"
 msgstr "  (alle Konflikte behoben: führen Sie \"git rebase --continue\" aus)"
 
-#: wt-status.c:924
+#: wt-status.c:922
 #, c-format
 msgid ""
 "You are currently splitting a commit while rebasing branch '%s' on '%s'."
 msgstr ""
-"Sie teilen gerade eine Version auf, während ein Neuaufbau von Zweig '%s' auf "
+"Sie teilen gerade einen Commit auf, während ein Rebase von Branch '%s' auf "
 "'%s' im Gange ist."
 
-#: wt-status.c:929
+#: wt-status.c:927
 msgid "You are currently splitting a commit during a rebase."
-msgstr "Sie teilen gerade eine Version während eines Neuaufbaus auf."
+msgstr "Sie teilen gerade einen Commit während eines Rebase auf."
 
-#: wt-status.c:932
+#: wt-status.c:930
 msgid "  (Once your working directory is clean, run \"git rebase --continue\")"
 msgstr ""
-"  (Sobald Ihr Arbeitsverzeichnis sauber ist, führen Sie \"git rebase --"
+"  (Sobald Ihr Arbeitsverzeichnis unverändert ist, führen Sie \"git rebase --"
 "continue\" aus)"
 
-#: wt-status.c:936
+#: wt-status.c:934
 #, c-format
 msgid "You are currently editing a commit while rebasing branch '%s' on '%s'."
 msgstr ""
-"Sie editieren gerade eine Version während eines Neuaufbaus von Zweig '%s' "
-"auf '%s'."
+"Sie editieren gerade einen Commit während eines Rebase von Branch '%s' auf "
+"'%s'."
 
-#: wt-status.c:941
+#: wt-status.c:939
 msgid "You are currently editing a commit during a rebase."
-msgstr "Sie editieren gerade eine Version während eines Neuaufbaus."
+msgstr "Sie editieren gerade einen Commit während eines Rebase."
 
-#: wt-status.c:944
+#: wt-status.c:942
 msgid "  (use \"git commit --amend\" to amend the current commit)"
 msgstr ""
-"  (benutzen Sie \"git commit --amend\" um die aktuelle Version nachzubessern)"
+"  (benutzen Sie \"git commit --amend\" um den aktuellen Commit nachzubessern)"
 
-#: wt-status.c:946
+#: wt-status.c:944
 msgid ""
 "  (use \"git rebase --continue\" once you are satisfied with your changes)"
 msgstr ""
 "  (benutzen Sie \"git rebase --continue\" sobald Ihre Änderungen "
 "abgeschlossen sind)"
 
-#: wt-status.c:956
+#: wt-status.c:954
 msgid "You are currently cherry-picking."
 msgstr "Sie führen gerade \"cherry-pick\" aus."
 
+#: wt-status.c:958
+msgid "  (fix conflicts and run \"git cherry-pick --continue\")"
+msgstr ""
+"  (beheben Sie die Konflikte und führen Sie dann \"git cherry-pick --continue"
+"\" aus)"
+
+#: wt-status.c:961
+msgid "  (all conflicts fixed: run \"git cherry-pick --continue\")"
+msgstr ""
+"  (alle Konflikte behoben: führen Sie \"git cherry-pick --continue\" aus)"
+
 #: wt-status.c:963
-msgid "  (all conflicts fixed: run \"git commit\")"
-msgstr "  (alle Konflikte behoben: führen Sie \"git commit\" aus)"
+msgid "  (use \"git cherry-pick --abort\" to cancel the cherry-pick operation)"
+msgstr ""
+"  (benutzen Sie \"git cherry-pick --abort\" um die Cherry-Pick-Operation "
+"abzubrechen)"
 
 #: wt-status.c:972
 #, c-format
 msgid "You are currently reverting commit %s."
-msgstr "Sie nehmen gerade Version '%s' zurück."
+msgstr "Sie sind gerade an einem Revert von Commit '%s'."
 
 #: wt-status.c:977
 msgid "  (fix conflicts and run \"git revert --continue\")"
@@ -1403,12 +1584,12 @@
 #: wt-status.c:982
 msgid "  (use \"git revert --abort\" to cancel the revert operation)"
 msgstr ""
-"  (benutzen Sie \"git revert --abort\" um die Umkehroperation abzubrechen)"
+"  (benutzen Sie \"git revert --abort\" um die Revert-Operation abzubrechen)"
 
 #: wt-status.c:993
 #, c-format
 msgid "You are currently bisecting, started from branch '%s'."
-msgstr "Sie sind gerade bei einer binären Suche, gestartet von Zweig '%s'."
+msgstr "Sie sind gerade bei einer binären Suche, gestartet von Branch '%s'."
 
 #: wt-status.c:997
 msgid "You are currently bisecting."
@@ -1417,135 +1598,136 @@
 #: wt-status.c:1000
 msgid "  (use \"git bisect reset\" to get back to the original branch)"
 msgstr ""
-"  (benutzen Sie \"git bisect reset\" um zum ursprünglichen Zweig "
+"  (benutzen Sie \"git bisect reset\" um zum ursprünglichen Branch "
 "zurückzukehren)"
 
-#: wt-status.c:1175
+#: wt-status.c:1173
 msgid "On branch "
-msgstr "Auf Zweig "
+msgstr "Auf Branch "
 
-#: wt-status.c:1186
+#: wt-status.c:1180
+msgid "rebase in progress; onto "
+msgstr "Rebase im Gange; auf "
+
+#: wt-status.c:1187
 msgid "HEAD detached at "
-msgstr "Zweigspitze (HEAD) losgelöst bei "
+msgstr "HEAD losgelöst bei "
 
-#: wt-status.c:1188
+#: wt-status.c:1189
 msgid "HEAD detached from "
-msgstr "Zweigspitze (HEAD) losgelöst von "
+msgstr "HEAD losgelöst von "
 
-#: wt-status.c:1191
+#: wt-status.c:1192
 msgid "Not currently on any branch."
-msgstr "Im Moment auf keinem Zweig."
+msgstr "Im Moment auf keinem Branch."
 
-#: wt-status.c:1208
+#: wt-status.c:1209
 msgid "Initial commit"
-msgstr "Initiale Version"
+msgstr "Initialer Commit"
 
-#: wt-status.c:1222
+#: wt-status.c:1223
 msgid "Untracked files"
 msgstr "Unbeobachtete Dateien"
 
-#: wt-status.c:1224
+#: wt-status.c:1225
 msgid "Ignored files"
 msgstr "Ignorierte Dateien"
 
-#: wt-status.c:1228
+#: wt-status.c:1229
 #, c-format
-msgid "It took %.2f seconds to enumerate untracked files.  'status -uno'"
-msgstr "Es dauerte %.2f Sekunden die unbeobachteten Dateien zu bestimmen."
-"'status -uno'"
-
-#: wt-status.c:1232
-msgid "may speed it up, but you have to be careful not to forget to add"
-msgstr "könnte das beschleunigen, aber Sie müssen darauf achten, neue"
+msgid ""
+"It took %.2f seconds to enumerate untracked files. 'status -uno'\n"
+"may speed it up, but you have to be careful not to forget to add\n"
+"new files yourself (see 'git help status')."
+msgstr ""
+"Es dauerte %.2f Sekunden die unbeobachteten Dateien zu bestimmen.\n"
+"'status -uno' könnte das beschleunigen, aber Sie müssen darauf achten,\n"
+"neue Dateien selbstständig hinzuzufügen (siehe 'git help status')."
 
 #: wt-status.c:1235
-msgid "new files yourself (see 'git help status')."
-msgstr "Dateien selbstständig hinzuzufügen (siehe 'git help status')."
-
-#: wt-status.c:1238
 #, c-format
 msgid "Untracked files not listed%s"
 msgstr "Unbeobachtete Dateien nicht aufgelistet%s"
 
-#: wt-status.c:1240
+#: wt-status.c:1237
 msgid " (use -u option to show untracked files)"
 msgstr " (benutzen Sie die Option -u um unbeobachteten Dateien anzuzeigen)"
 
-#: wt-status.c:1246
+#: wt-status.c:1243
 msgid "No changes"
 msgstr "Keine Änderungen"
 
-#: wt-status.c:1251
+#: wt-status.c:1248
 #, c-format
 msgid "no changes added to commit (use \"git add\" and/or \"git commit -a\")\n"
 msgstr ""
-"keine Änderungen zum Eintragen hinzugefügt (benutzen Sie \"git add\" und/"
-"oder \"git commit -a\")\n"
+"keine Änderungen zum Commit vorgemerkt (benutzen Sie \"git add\" und/oder "
+"\"git commit -a\")\n"
 
-#: wt-status.c:1254
+#: wt-status.c:1251
 #, c-format
 msgid "no changes added to commit\n"
-msgstr "keine Änderungen zum Eintragen hinzugefügt\n"
+msgstr "keine Änderungen zum Commit vorgemerkt\n"
 
-#: wt-status.c:1257
+#: wt-status.c:1254
 #, c-format
 msgid ""
 "nothing added to commit but untracked files present (use \"git add\" to "
 "track)\n"
 msgstr ""
-"nichts zum Eintragen hinzugefügt, aber es gibt unbeobachtete Dateien "
-"(benutzen Sie \"git add\" zum Beobachten)\n"
+"nichts zum Commit vorgemerkt, aber es gibt unbeobachtete Dateien (benutzen "
+"Sie \"git add\" zum Beobachten)\n"
+
+#: wt-status.c:1257
+#, c-format
+msgid "nothing added to commit but untracked files present\n"
+msgstr "nichts zum Commit vorgemerkt, aber es gibt unbeobachtete Dateien\n"
 
 #: wt-status.c:1260
 #, c-format
-msgid "nothing added to commit but untracked files present\n"
-msgstr "nichts zum Eintragen hinzugefügt, aber es gibt unbeobachtete Dateien\n"
-
-#: wt-status.c:1263
-#, c-format
 msgid "nothing to commit (create/copy files and use \"git add\" to track)\n"
 msgstr ""
-"nichts einzutragen (Erstellen/Kopieren Sie Dateien und benutzen Sie \"git add"
-"\" zum Beobachten)\n"
+"nichts zu committen (Erstellen/Kopieren Sie Dateien und benutzen Sie \"git "
+"add\" zum Beobachten)\n"
 
-#: wt-status.c:1266 wt-status.c:1271
+#: wt-status.c:1263 wt-status.c:1268
 #, c-format
 msgid "nothing to commit\n"
-msgstr "nichts einzutragen\n"
+msgstr "nichts zu committen\n"
 
-#: wt-status.c:1269
+#: wt-status.c:1266
 #, c-format
 msgid "nothing to commit (use -u to show untracked files)\n"
 msgstr ""
-"nichts einzutragen (benutzen Sie die Option -u, um unbeobachtete Dateien "
+"nichts zu committen (benutzen Sie die Option -u, um unbeobachtete Dateien "
 "anzuzeigen)\n"
 
-#: wt-status.c:1273
+#: wt-status.c:1270
 #, c-format
 msgid "nothing to commit, working directory clean\n"
-msgstr "nichts einzutragen, Arbeitsverzeichnis sauber\n"
+msgstr "nichts zu committen, Arbeitsverzeichnis unverändert\n"
 
-#: wt-status.c:1381
+#: wt-status.c:1378
 msgid "HEAD (no branch)"
-msgstr "HEAD (kein Zweig)"
+msgstr "HEAD (kein Branch)"
 
-#: wt-status.c:1387
+#: wt-status.c:1384
 msgid "Initial commit on "
-msgstr "Initiale Version auf "
+msgstr "Initialer Commit auf "
 
-#: wt-status.c:1402
+#: wt-status.c:1399
 msgid "behind "
 msgstr "hinterher "
 
-#: wt-status.c:1405 wt-status.c:1408
+#: wt-status.c:1402 wt-status.c:1405
 msgid "ahead "
 msgstr "voraus "
 
-#: wt-status.c:1410
+#: wt-status.c:1407
 msgid ", behind "
 msgstr ", hinterher "
 
-#: compat/precompose_utf8.c:58 builtin/clone.c:342
+#: compat/precompose_utf8.c:58 builtin/clone.c:351
 #, c-format
 msgid "failed to unlink '%s'"
 msgstr "Konnte '%s' nicht entfernen."
@@ -1554,131 +1736,6 @@
 msgid "git add [options] [--] <pathspec>..."
 msgstr "git add [Optionen] [--] [<Pfadspezifikation>...]"
 
-#: builtin/add.c:63
-#, c-format
-msgid "unexpected diff status %c"
-msgstr "unerwarteter Differenz-Status %c"
-
-#: builtin/add.c:68 builtin/commit.c:233
-msgid "updating files failed"
-msgstr "Aktualisierung der Dateien fehlgeschlagen"
-
-#: builtin/add.c:78
-#, c-format
-msgid "remove '%s'\n"
-msgstr "lösche '%s'\n"
-
-#: builtin/add.c:148
-msgid "Unstaged changes after refreshing the index:"
-msgstr ""
-"Nicht bereitgestellte Änderungen nach Aktualisierung der Bereitstellung:"
-
-#: builtin/add.c:151 builtin/add.c:460 builtin/rm.c:275
-#, c-format
-msgid "pathspec '%s' did not match any files"
-msgstr "Pfadspezifikation '%s' stimmt mit keinen Dateien überein"
-
-#: builtin/add.c:234
-msgid "Could not read the index"
-msgstr "Konnte die Bereitstellung nicht lesen"
-
-#: builtin/add.c:244
-#, c-format
-msgid "Could not open '%s' for writing."
-msgstr "Konnte '%s' nicht zum Schreiben öffnen."
-
-#: builtin/add.c:248
-msgid "Could not write patch"
-msgstr "Konnte Patch nicht schreiben"
-
-#: builtin/add.c:253
-#, c-format
-msgid "Could not stat '%s'"
-msgstr "Konnte Verzeichnis '%s' nicht lesen"
-
-#: builtin/add.c:255
-msgid "Empty patch. Aborted."
-msgstr "Leerer Patch. Abgebrochen."
-
-#: builtin/add.c:261
-#, c-format
-msgid "Could not apply '%s'"
-msgstr "Konnte '%s' nicht anwenden."
-
-#: builtin/add.c:271
-msgid "The following paths are ignored by one of your .gitignore files:\n"
-msgstr ""
-"Die folgenden Pfade werden durch eine Ihrer \".gitignore\" Dateien "
-"ignoriert:\n"
-
-#: builtin/add.c:277 builtin/clean.c:161 builtin/fetch.c:78 builtin/mv.c:63
-#: builtin/prune-packed.c:76 builtin/push.c:425 builtin/remote.c:1253
-#: builtin/rm.c:206
-msgid "dry run"
-msgstr "Probelauf"
-
-#: builtin/add.c:278 builtin/apply.c:4409 builtin/check-ignore.c:19
-#: builtin/commit.c:1152 builtin/count-objects.c:95 builtin/fsck.c:613
-#: builtin/log.c:1514 builtin/mv.c:62 builtin/read-tree.c:112
-msgid "be verbose"
-msgstr "erweiterte Ausgaben"
-
-#: builtin/add.c:280
-msgid "interactive picking"
-msgstr "interaktives Auswählen"
-
-#: builtin/add.c:281 builtin/checkout.c:1060 builtin/reset.c:258
-msgid "select hunks interactively"
-msgstr "interaktiv Bereiche auswählen"
-
-#: builtin/add.c:282
-msgid "edit current diff and apply"
-msgstr "aktuelle Unterschiede editieren und anwenden"
-
-#: builtin/add.c:283
-msgid "allow adding otherwise ignored files"
-msgstr "erlaubt das Hinzufügen andernfalls ignorierter Dateien"
-
-#: builtin/add.c:284
-msgid "update tracked files"
-msgstr "aktualisiert beobachtete Dateien"
-
-#: builtin/add.c:285
-msgid "record only the fact that the path will be added later"
-msgstr "speichert nur, dass der Pfad später hinzugefügt werden soll"
-
-#: builtin/add.c:286
-msgid "add changes from all tracked and untracked files"
-msgstr ""
-"fügt Änderungen von allen beobachteten und unbeobachteten Dateien hinzu"
-
-#: builtin/add.c:287
-msgid "don't add, only refresh the index"
-msgstr "fügt nichts hinzu, aktualisiert nur die Bereitstellung"
-
-#: builtin/add.c:288
-msgid "just skip files which cannot be added because of errors"
-msgstr ""
-"überspringt Dateien, die aufgrund von Fehlern nicht hinzugefügt werden "
-"konnten"
-
-#: builtin/add.c:289
-msgid "check if - even missing - files are ignored in dry run"
-msgstr "prüft ob - auch fehlende - Dateien im Probelauf ignoriert werden"
-
-#: builtin/add.c:311
-#, c-format
-msgid "Use -f if you really want to add them.\n"
-msgstr "Verwenden Sie -f wenn Sie diese wirklich hinzufügen möchten.\n"
-
-#: builtin/add.c:312
-msgid "no files added"
-msgstr "keine Dateien hinzugefügt"
-
-#: builtin/add.c:318
-msgid "adding files failed"
-msgstr "Hinzufügen von Dateien fehlgeschlagen"
-
 #.
 #. * To be consistent with "git add -p" and most Git
 #. * commands, we should default to being tree-wide, but
@@ -1689,7 +1746,7 @@
 #. * to tree-wide, keeping the warning for a while, and
 #. * eventually we can drop the warning.
 #.
-#: builtin/add.c:335
+#: builtin/add.c:58
 #, c-format
 msgid ""
 "The behavior of 'git add %s (or %s)' with no path argument from a\n"
@@ -1706,7 +1763,7 @@
 "  (or git add %s .)\n"
 "\n"
 "With the current Git version, the command is restricted to the current "
-"directory."
+"directory.\n"
 msgstr ""
 "Das Verhalten von 'git add %s (oder %s)' ohne ein Pfad-Argument von\n"
 "einem Unterverzeichnis aus wird in Git 2.0 geändert und sollte nicht\n"
@@ -1722,35 +1779,192 @@
 "  (oder git add %s .)\n"
 "\n"
 "Mit der aktuellen Version von Git ist das Kommando auf das aktuelle\n"
-"Verzeichnis beschränkt."
+"Verzeichnis beschränkt.\n"
 
-#: builtin/add.c:381
+#: builtin/add.c:100
+#, c-format
+msgid ""
+"You ran 'git add' with neither '-A (--all)' or '--ignore-removal',\n"
+"whose behaviour will change in Git 2.0 with respect to paths you removed.\n"
+"Paths like '%s' that are\n"
+"removed from your working tree are ignored with this version of Git.\n"
+"\n"
+"* 'git add --ignore-removal <pathspec>', which is the current default,\n"
+"  ignores paths you removed from your working tree.\n"
+"\n"
+"* 'git add --all <pathspec>' will let you also record the removals.\n"
+"\n"
+"Run 'git status' to check the paths you removed from your working tree.\n"
+msgstr ""
+"Sie haben 'git add' weder mit '-A (--all)' noch mit '--ignore-removal'\n"
+"ausgeführt. Das Verhalten des Kommandos ändert sich in Git 2.0 durch\n"
+"Berücksichtigung der gelöschten Pfade.\n"
+"Pfade wie '%s', die im Arbeitsverzeichnis gelöscht wurden, werden in\n"
+"dieser Version von Git ignoriert.\n"
+"\n"
+"* 'git add --ignore-removal <Pfadspezifikation>', was der aktuelle\n"
+"  Standardwert ist, ignoriert gelöschte Pfade im Arbeitsverzeichnis.\n"
+"* 'git add --all <Pfadspezifikation>' berücksichtigt ebenfalls gelöschte\n"
+"  Pfade.\n"
+"Führen Sie 'git status' aus, um die gelöschten Pfade zu überprüfen.\n"
+
+#: builtin/add.c:144
+#, c-format
+msgid "unexpected diff status %c"
+msgstr "unerwarteter Differenz-Status %c"
+
+#: builtin/add.c:149 builtin/commit.c:252
+msgid "updating files failed"
+msgstr "Aktualisierung der Dateien fehlgeschlagen"
+
+#: builtin/add.c:163
+#, c-format
+msgid "remove '%s'\n"
+msgstr "lösche '%s'\n"
+
+#: builtin/add.c:253
+msgid "Unstaged changes after refreshing the index:"
+msgstr ""
+"Nicht zum Commit vorgemerkte Änderungen nach Aktualisierung der Staging-Area:"
+
+#: builtin/add.c:256 builtin/add.c:573 builtin/rm.c:337
+#, c-format
+msgid "pathspec '%s' did not match any files"
+msgstr "Pfadspezifikation '%s' stimmt mit keinen Dateien überein"
+
+#: builtin/add.c:339
+msgid "Could not read the index"
+msgstr "Konnte die Staging-Area nicht lesen"
+
+#: builtin/add.c:350
+#, c-format
+msgid "Could not open '%s' for writing."
+msgstr "Konnte '%s' nicht zum Schreiben öffnen."
+
+#: builtin/add.c:354
+msgid "Could not write patch"
+msgstr "Konnte Patch nicht schreiben"
+
+#: builtin/add.c:359
+#, c-format
+msgid "Could not stat '%s'"
+msgstr "Konnte Verzeichnis '%s' nicht lesen"
+
+#: builtin/add.c:361
+msgid "Empty patch. Aborted."
+msgstr "Leerer Patch. Abgebrochen."
+
+#: builtin/add.c:367
+#, c-format
+msgid "Could not apply '%s'"
+msgstr "Konnte '%s' nicht anwenden."
+
+#: builtin/add.c:377
+msgid "The following paths are ignored by one of your .gitignore files:\n"
+msgstr ""
+"Die folgenden Pfade werden durch eine Ihrer \".gitignore\" Dateien "
+"ignoriert:\n"
+
+#: builtin/add.c:394 builtin/clean.c:875 builtin/fetch.c:78 builtin/mv.c:63
+#: builtin/prune-packed.c:73 builtin/push.c:451 builtin/remote.c:1253
+#: builtin/rm.c:268
+msgid "dry run"
+msgstr "Probelauf"
+
+#: builtin/add.c:395 builtin/apply.c:4410 builtin/check-ignore.c:19
+#: builtin/commit.c:1220 builtin/count-objects.c:95 builtin/fsck.c:613
+#: builtin/log.c:1573 builtin/mv.c:62 builtin/read-tree.c:113
+msgid "be verbose"
+msgstr "erweiterte Ausgaben"
+
+#: builtin/add.c:397
+msgid "interactive picking"
+msgstr "interaktives Auswählen"
+
+#: builtin/add.c:398 builtin/checkout.c:1073 builtin/reset.c:261
+msgid "select hunks interactively"
+msgstr "Blöcke interaktiv auswählen"
+
+#: builtin/add.c:399
+msgid "edit current diff and apply"
+msgstr "aktuelle Unterschiede editieren und anwenden"
+
+#: builtin/add.c:400
+msgid "allow adding otherwise ignored files"
+msgstr "erlaubt das Hinzufügen andernfalls ignorierter Dateien"
+
+#: builtin/add.c:401
+msgid "update tracked files"
+msgstr "aktualisiert beobachtete Dateien"
+
+#: builtin/add.c:402
+msgid "record only the fact that the path will be added later"
+msgstr "speichert nur, dass der Pfad später hinzugefügt werden soll"
+
+#: builtin/add.c:403
+msgid "add changes from all tracked and untracked files"
+msgstr ""
+"fügt Änderungen von allen beobachteten und unbeobachteten Dateien hinzu"
+
+#. takes no arguments
+#: builtin/add.c:406
+msgid "ignore paths removed in the working tree (same as --no-all)"
+msgstr "ignoriert gelöschte Pfade im Arbeitsverzeichnis (genau wie --no-all)"
+
+#: builtin/add.c:408
+msgid "don't add, only refresh the index"
+msgstr "fügt nichts hinzu, aktualisiert nur die Staging-Area"
+
+#: builtin/add.c:409
+msgid "just skip files which cannot be added because of errors"
+msgstr ""
+"überspringt Dateien, die aufgrund von Fehlern nicht hinzugefügt werden "
+"konnten"
+
+#: builtin/add.c:410
+msgid "check if - even missing - files are ignored in dry run"
+msgstr "prüft ob - auch fehlende - Dateien im Probelauf ignoriert werden"
+
+#: builtin/add.c:432
+#, c-format
+msgid "Use -f if you really want to add them.\n"
+msgstr "Verwenden Sie -f wenn Sie diese wirklich hinzufügen möchten.\n"
+
+#: builtin/add.c:433
+msgid "no files added"
+msgstr "keine Dateien hinzugefügt"
+
+#: builtin/add.c:439
+msgid "adding files failed"
+msgstr "Hinzufügen von Dateien fehlgeschlagen"
+
+#: builtin/add.c:478
 msgid "-A and -u are mutually incompatible"
 msgstr "Die Optionen -A und -u sind zueinander inkompatibel."
 
-#: builtin/add.c:383
+#: builtin/add.c:496
 msgid "Option --ignore-missing can only be used together with --dry-run"
 msgstr ""
 "Die Option --ignore-missing kann nur zusammen mit --dry-run verwendet werden."
 
-#: builtin/add.c:414
+#: builtin/add.c:526
 #, c-format
 msgid "Nothing specified, nothing added.\n"
 msgstr "Nichts spezifiziert, nichts hinzugefügt.\n"
 
-#: builtin/add.c:415
+#: builtin/add.c:527
 #, c-format
 msgid "Maybe you wanted to say 'git add .'?\n"
 msgstr "Wollten Sie vielleicht 'git add .' sagen?\n"
 
-#: builtin/add.c:421 builtin/check-ignore.c:67 builtin/clean.c:204
-#: builtin/commit.c:293 builtin/mv.c:82 builtin/rm.c:235
+#: builtin/add.c:533 builtin/check-ignore.c:161 builtin/clean.c:919
+#: builtin/commit.c:312 builtin/mv.c:82 builtin/rm.c:297
 msgid "index file corrupt"
-msgstr "Bereitstellungsdatei beschädigt"
+msgstr "Staging-Area-Datei beschädigt"
 
-#: builtin/add.c:481 builtin/apply.c:4505 builtin/mv.c:229 builtin/rm.c:370
+#: builtin/add.c:605 builtin/apply.c:4506 builtin/mv.c:229 builtin/rm.c:432
 msgid "Unable to write new index file"
-msgstr "Konnte neue Bereitstellungsdatei nicht schreiben."
+msgstr "Konnte neue Staging-Area-Datei nicht schreiben."
 
 #: builtin/apply.c:57
 msgid "git apply [options] [<patch>...]"
@@ -1759,12 +1973,12 @@
 #: builtin/apply.c:110
 #, c-format
 msgid "unrecognized whitespace option '%s'"
-msgstr "nicht erkannte Option für Leerzeichen: '%s'"
+msgstr "nicht erkannte Whitespace-Option: '%s'"
 
 #: builtin/apply.c:125
 #, c-format
 msgid "unrecognized whitespace ignore option '%s'"
-msgstr "nicht erkannte Option zum Ignorieren von Leerzeichen: '%s'"
+msgstr "nicht erkannte Option zum Ignorieren von Whitespace: '%s'"
 
 #: builtin/apply.c:823
 #, c-format
@@ -1877,7 +2091,7 @@
 #: builtin/apply.c:2076
 #, c-format
 msgid "unable to read symlink %s"
-msgstr "konnte symbolische Verknüpfung %s nicht lesen"
+msgstr "konnte symbolischen Verweis %s nicht lesen"
 
 #: builtin/apply.c:2080
 #, c-format
@@ -1937,319 +2151,315 @@
 msgid "cannot checkout %s"
 msgstr "kann %s nicht auschecken"
 
-#: builtin/apply.c:3140 builtin/apply.c:3149 builtin/apply.c:3193
+#: builtin/apply.c:3140 builtin/apply.c:3149 builtin/apply.c:3194
 #, c-format
 msgid "read of %s failed"
 msgstr "Konnte %s nicht lesen"
 
-#: builtin/apply.c:3173 builtin/apply.c:3395
+#: builtin/apply.c:3174 builtin/apply.c:3396
 #, c-format
 msgid "path %s has been renamed/deleted"
 msgstr "Pfad %s wurde umbenannt/gelöscht"
 
-#: builtin/apply.c:3254 builtin/apply.c:3409
+#: builtin/apply.c:3255 builtin/apply.c:3410
 #, c-format
 msgid "%s: does not exist in index"
-msgstr "%s ist nicht bereitgestellt"
+msgstr "%s ist nicht in der Staging-Area"
 
-#: builtin/apply.c:3258 builtin/apply.c:3401 builtin/apply.c:3423
+#: builtin/apply.c:3259 builtin/apply.c:3402 builtin/apply.c:3424
 #, c-format
 msgid "%s: %s"
 msgstr "%s: %s"
 
-#: builtin/apply.c:3263 builtin/apply.c:3417
+#: builtin/apply.c:3264 builtin/apply.c:3418
 #, c-format
 msgid "%s: does not match index"
-msgstr "%s entspricht nicht der Bereitstellung"
+msgstr "%s entspricht nicht der Version in der Staging-Area"
 
-#: builtin/apply.c:3365
+#: builtin/apply.c:3366
 msgid "removal patch leaves file contents"
 msgstr "Lösch-Patch hinterlässt Dateiinhalte"
 
-#: builtin/apply.c:3434
+#: builtin/apply.c:3435
 #, c-format
 msgid "%s: wrong type"
 msgstr "%s: falscher Typ"
 
-#: builtin/apply.c:3436
+#: builtin/apply.c:3437
 #, c-format
 msgid "%s has type %o, expected %o"
 msgstr "%s ist vom Typ %o, erwartete %o"
 
-#: builtin/apply.c:3537
+#: builtin/apply.c:3538
 #, c-format
 msgid "%s: already exists in index"
 msgstr "%s ist bereits bereitgestellt"
 
-#: builtin/apply.c:3540
+#: builtin/apply.c:3541
 #, c-format
 msgid "%s: already exists in working directory"
 msgstr "%s existiert bereits im Arbeitsverzeichnis"
 
-#: builtin/apply.c:3560
+#: builtin/apply.c:3561
 #, c-format
 msgid "new mode (%o) of %s does not match old mode (%o)"
 msgstr "neuer Modus (%o) von %s entspricht nicht dem alten Modus (%o)"
 
-#: builtin/apply.c:3565
+#: builtin/apply.c:3566
 #, c-format
 msgid "new mode (%o) of %s does not match old mode (%o) of %s"
 msgstr "neuer Modus (%o) von %s entspricht nicht dem alten Modus (%o) von %s"
 
-#: builtin/apply.c:3573
+#: builtin/apply.c:3574
 #, c-format
 msgid "%s: patch does not apply"
 msgstr "%s: Patch konnte nicht angewendet werden"
 
-#: builtin/apply.c:3586
+#: builtin/apply.c:3587
 #, c-format
 msgid "Checking patch %s..."
 msgstr "Prüfe Patch %s..."
 
-#: builtin/apply.c:3679 builtin/checkout.c:215 builtin/reset.c:124
+#: builtin/apply.c:3680 builtin/checkout.c:216 builtin/reset.c:127
 #, c-format
 msgid "make_cache_entry failed for path '%s'"
 msgstr "make_cache_entry für Pfad '%s' fehlgeschlagen"
 
-#: builtin/apply.c:3822
+#: builtin/apply.c:3823
 #, c-format
 msgid "unable to remove %s from index"
-msgstr "konnte %s nicht aus der Bereitstellung entfernen"
+msgstr "konnte %s nicht aus der Staging-Area entfernen"
 
-#: builtin/apply.c:3850
+#: builtin/apply.c:3851
 #, c-format
-msgid "corrupt patch for subproject %s"
-msgstr "fehlerhafter Patch für Unterprojekt %s"
+msgid "corrupt patch for submodule %s"
+msgstr "fehlerhafter Patch für Submodul %s"
 
-#: builtin/apply.c:3854
+#: builtin/apply.c:3855
 #, c-format
 msgid "unable to stat newly created file '%s'"
 msgstr "konnte neu erstellte Datei '%s' nicht lesen"
 
-#: builtin/apply.c:3859
+#: builtin/apply.c:3860
 #, c-format
 msgid "unable to create backing store for newly created file %s"
 msgstr "kann internen Speicher für eben erstellte Datei %s nicht erzeugen"
 
-#: builtin/apply.c:3862 builtin/apply.c:3970
+#: builtin/apply.c:3863 builtin/apply.c:3971
 #, c-format
 msgid "unable to add cache entry for %s"
 msgstr "kann für %s keinen Eintrag in den Zwischenspeicher hinzufügen"
 
-#: builtin/apply.c:3895
+#: builtin/apply.c:3896
 #, c-format
 msgid "closing file '%s'"
 msgstr "schließe Datei '%s'"
 
-#: builtin/apply.c:3944
+#: builtin/apply.c:3945
 #, c-format
 msgid "unable to write file '%s' mode %o"
 msgstr "konnte Datei '%s' mit Modus %o nicht schreiben"
 
-#: builtin/apply.c:4031
+#: builtin/apply.c:4032
 #, c-format
 msgid "Applied patch %s cleanly."
 msgstr "Patch %s sauber angewendet"
 
-#: builtin/apply.c:4039
+#: builtin/apply.c:4040
 msgid "internal error"
 msgstr "interner Fehler"
 
 #. Say this even without --verbose
-#: builtin/apply.c:4042
+#: builtin/apply.c:4043
 #, c-format
 msgid "Applying patch %%s with %d reject..."
 msgid_plural "Applying patch %%s with %d rejects..."
 msgstr[0] "Wende Patch %%s mit %d Zurückweisung an..."
 msgstr[1] "Wende Patch %%s mit %d Zurückweisungen an..."
 
-#: builtin/apply.c:4052
+#: builtin/apply.c:4053
 #, c-format
 msgid "truncating .rej filename to %.*s.rej"
 msgstr "Verkürze Name von .rej Datei zu %.*s.rej"
 
-#: builtin/apply.c:4073
+#: builtin/apply.c:4074
 #, c-format
 msgid "Hunk #%d applied cleanly."
 msgstr "Patch-Bereich #%d sauber angewendet."
 
-#: builtin/apply.c:4076
+#: builtin/apply.c:4077
 #, c-format
 msgid "Rejected hunk #%d."
-msgstr "Patch-Bereich #%d zurückgewiesen."
+msgstr "Patch-Block #%d zurückgewiesen."
 
-#: builtin/apply.c:4226
+#: builtin/apply.c:4227
 msgid "unrecognized input"
 msgstr "nicht erkannte Eingabe"
 
-#: builtin/apply.c:4237
+#: builtin/apply.c:4238
 msgid "unable to read index file"
-msgstr "Konnte Bereitstellungsdatei nicht lesen"
+msgstr "Konnte Staging-Area-Datei nicht lesen"
 
-#: builtin/apply.c:4356 builtin/apply.c:4359 builtin/clone.c:92
+#: builtin/apply.c:4357 builtin/apply.c:4360 builtin/clone.c:91
 #: builtin/fetch.c:63
 msgid "path"
 msgstr "Pfad"
 
-#: builtin/apply.c:4357
+#: builtin/apply.c:4358
 msgid "don't apply changes matching the given path"
 msgstr "wendet keine Änderungen im angegebenen Pfad an"
 
-#: builtin/apply.c:4360
+#: builtin/apply.c:4361
 msgid "apply changes matching the given path"
 msgstr "wendet Änderungen nur im angegebenen Pfad an"
 
-#: builtin/apply.c:4362
+#: builtin/apply.c:4363
 msgid "num"
 msgstr "Anzahl"
 
-#: builtin/apply.c:4363
+#: builtin/apply.c:4364
 msgid "remove <num> leading slashes from traditional diff paths"
 msgstr ""
 "entfernt <Anzahl> vorangestellte Schrägstriche von herkömmlichen "
 "Differenzpfaden"
 
-#: builtin/apply.c:4366
+#: builtin/apply.c:4367
 msgid "ignore additions made by the patch"
 msgstr "ignoriert hinzugefügte Zeilen des Patches"
 
-#: builtin/apply.c:4368
+#: builtin/apply.c:4369
 msgid "instead of applying the patch, output diffstat for the input"
 msgstr ""
 "anstatt der Anwendung des Patches, wird der \"diffstat\" für die Eingabe "
 "ausgegeben"
 
-#: builtin/apply.c:4372
+#: builtin/apply.c:4373
 msgid "show number of added and deleted lines in decimal notation"
 msgstr ""
 "zeigt die Anzahl von hinzugefügten/entfernten Zeilen in Dezimalnotation"
 
-#: builtin/apply.c:4374
+#: builtin/apply.c:4375
 msgid "instead of applying the patch, output a summary for the input"
 msgstr ""
 "anstatt der Anwendung des Patches, wird eine Zusammenfassung für die Eingabe "
 "ausgegeben"
 
-#: builtin/apply.c:4376
+#: builtin/apply.c:4377
 msgid "instead of applying the patch, see if the patch is applicable"
 msgstr ""
 "anstatt der Anwendung des Patches, zeige ob Patch angewendet werden kann"
 
-#: builtin/apply.c:4378
+#: builtin/apply.c:4379
 msgid "make sure the patch is applicable to the current index"
 msgstr ""
-"stellt sicher, dass der Patch in der aktuellen Bereitstellung angewendet "
+"stellt sicher, dass der Patch in der aktuellen Staging-Area angewendet "
 "werden kann"
 
-#: builtin/apply.c:4380
+#: builtin/apply.c:4381
 msgid "apply a patch without touching the working tree"
-msgstr "wendet einen Patch an, ohne Änderungen im Arbeitszweig vorzunehmen"
+msgstr ""
+"wendet einen Patch an, ohne Änderungen im Arbeitsverzeichnis vorzunehmen"
 
-#: builtin/apply.c:4382
+#: builtin/apply.c:4383
 msgid "also apply the patch (use with --stat/--summary/--check)"
 msgstr "wendet den Patch an (Benutzung mit --stat/--summary/--check)"
 
-#: builtin/apply.c:4384
+#: builtin/apply.c:4385
 msgid "attempt three-way merge if a patch does not apply"
-msgstr ""
-"versucht 3-Wege-Zusammenführung, wenn der Patch nicht angewendet werden "
-"konnte"
+msgstr "versucht 3-Wege-Merge, wenn der Patch nicht angewendet werden konnte"
 
-#: builtin/apply.c:4386
+#: builtin/apply.c:4387
 msgid "build a temporary index based on embedded index information"
 msgstr ""
-"erstellt eine temporäre Bereitstellung basierend auf den integrierten "
-"Bereitstellungsinformationen"
+"erstellt eine temporäre Staging-Area basierend auf den integrierten Staging-"
+"Area-Informationen"
 
-#: builtin/apply.c:4388 builtin/checkout-index.c:197 builtin/ls-files.c:463
+#: builtin/apply.c:4389 builtin/checkout-index.c:197 builtin/ls-files.c:462
 msgid "paths are separated with NUL character"
 msgstr "Pfade sind getrennt durch NUL Zeichen"
 
-#: builtin/apply.c:4391
+#: builtin/apply.c:4392
 msgid "ensure at least <n> lines of context match"
 msgstr "stellt sicher, dass mindestens <n> Zeilen des Kontextes übereinstimmen"
 
-#: builtin/apply.c:4392
+#: builtin/apply.c:4393
 msgid "action"
 msgstr "Aktion"
 
-#: builtin/apply.c:4393
+#: builtin/apply.c:4394
 msgid "detect new or modified lines that have whitespace errors"
-msgstr "ermittelt neue oder geänderte Zeilen die Fehler in Leerzeichen haben"
+msgstr "ermittelt neue oder geänderte Zeilen die Whitespace-Fehler haben"
 
-#: builtin/apply.c:4396 builtin/apply.c:4399
+#: builtin/apply.c:4397 builtin/apply.c:4400
 msgid "ignore changes in whitespace when finding context"
-msgstr "ignoriert Änderungen in Leerzeichen bei der Suche des Kontextes"
+msgstr "ignoriert Änderungen im Whitespace bei der Suche des Kontextes"
 
-#: builtin/apply.c:4402
+#: builtin/apply.c:4403
 msgid "apply the patch in reverse"
 msgstr "wendet den Patch in umgekehrter Reihenfolge an"
 
-#: builtin/apply.c:4404
+#: builtin/apply.c:4405
 msgid "don't expect at least one line of context"
 msgstr "erwartet keinen Kontext"
 
-#: builtin/apply.c:4406
+#: builtin/apply.c:4407
 msgid "leave the rejected hunks in corresponding *.rej files"
 msgstr ""
-"hinterlässt zurückgewiesene Patch-Bereiche in den entsprechenden *.rej "
-"Dateien"
+"hinterlässt zurückgewiesene Patch-Blöcke in entsprechenden *.rej Dateien"
 
-#: builtin/apply.c:4408
+#: builtin/apply.c:4409
 msgid "allow overlapping hunks"
-msgstr "erlaubt sich überlappende Patch-Bereiche"
+msgstr "erlaubt sich überlappende Patch-Blöcke"
 
-#: builtin/apply.c:4411
+#: builtin/apply.c:4412
 msgid "tolerate incorrectly detected missing new-line at the end of file"
 msgstr "toleriert fehlerhaft erkannten fehlenden Zeilenumbruch am Dateiende"
 
-#: builtin/apply.c:4414
+#: builtin/apply.c:4415
 msgid "do not trust the line counts in the hunk headers"
-msgstr "vertraut nicht den Zeilennummern im Kopf des Patch-Bereiches"
+msgstr "vertraut nicht den Zeilennummern im Kopf des Patch-Blocks"
 
-#: builtin/apply.c:4416
+#: builtin/apply.c:4417
 msgid "root"
 msgstr "Wurzelverzeichnis"
 
-#: builtin/apply.c:4417
+#: builtin/apply.c:4418
 msgid "prepend <root> to all filenames"
 msgstr "stellt <Wurzelverzeichnis> vor alle Dateinamen"
 
-#: builtin/apply.c:4439
+#: builtin/apply.c:4440
 msgid "--3way outside a repository"
 msgstr ""
-"Die Option --3way kann nicht außerhalb eines Projektarchivs verwendet werden."
+"Die Option --3way kann nicht außerhalb eines Repositories verwendet werden."
 
-#: builtin/apply.c:4447
+#: builtin/apply.c:4448
 msgid "--index outside a repository"
 msgstr ""
-"Die Option --index kann nicht außerhalb eines Projektarchivs verwendet "
-"werden."
+"Die Option --index kann nicht außerhalb eines Repositories verwendet werden."
 
-#: builtin/apply.c:4450
+#: builtin/apply.c:4451
 msgid "--cached outside a repository"
 msgstr ""
-"Die Option --cached kann nicht außerhalb eines Projektarchivs verwendet "
-"werden."
+"Die Option --cached kann nicht außerhalb eines Repositories verwendet werden."
 
-#: builtin/apply.c:4466
+#: builtin/apply.c:4467
 #, c-format
 msgid "can't open patch '%s'"
 msgstr "kann Patch '%s' nicht öffnen"
 
-#: builtin/apply.c:4480
+#: builtin/apply.c:4481
 #, c-format
 msgid "squelched %d whitespace error"
 msgid_plural "squelched %d whitespace errors"
-msgstr[0] "unterdrückte %d Fehler in Leerzeichen"
-msgstr[1] "unterdrückte %d Fehler in Leerzeichen"
+msgstr[0] "unterdrückte %d Whitespace-Fehler"
+msgstr[1] "unterdrückte %d Whitespace-Fehler"
 
-#: builtin/apply.c:4486 builtin/apply.c:4496
+#: builtin/apply.c:4487 builtin/apply.c:4497
 #, c-format
 msgid "%d line adds whitespace errors."
 msgid_plural "%d lines add whitespace errors."
-msgstr[0] "%d Zeile fügt Fehler in Leerzeichen hinzu."
-msgstr[1] "%d Zeilen fügen Fehler in Leerzeichen hinzu."
+msgstr[0] "%d Zeile fügt Whitespace-Fehler hinzu."
+msgstr[1] "%d Zeilen fügen Whitespace-Fehler hinzu."
 
 #: builtin/archive.c:17
 #, c-format
@@ -2296,106 +2506,106 @@
 
 #: builtin/bisect--helper.c:19
 msgid "update BISECT_HEAD instead of checking out the current commit"
-msgstr "aktualisiert BISECT_HEAD, anstatt die aktuelle Version auszuchecken"
+msgstr "aktualisiert BISECT_HEAD, anstatt den aktuellen Commit auszuchecken"
 
-#: builtin/blame.c:25
+#: builtin/blame.c:26
 msgid "git blame [options] [rev-opts] [rev] [--] file"
 msgstr "git blame [Optionen] [rev-opts] [rev] [--] Datei"
 
-#: builtin/blame.c:30 builtin/shortlog.c:15
+#: builtin/blame.c:31
 msgid "[rev-opts] are documented in git-rev-list(1)"
 msgstr "[rev-opts] sind dokumentiert in git-rev-list(1)"
 
-#: builtin/blame.c:2350
+#: builtin/blame.c:2276
 msgid "Show blame entries as we find them, incrementally"
 msgstr "Zeigt \"blame\"-Einträge schrittweise, während wir sie generieren"
 
-#: builtin/blame.c:2351
+#: builtin/blame.c:2277
 msgid "Show blank SHA-1 for boundary commits (Default: off)"
-msgstr "Zeigt leere SHA-1 für Grenzversionen (Standard: aus)"
+msgstr "Zeigt leere SHA-1 für Grenz-Commits (Standard: aus)"
 
-#: builtin/blame.c:2352
+#: builtin/blame.c:2278
 msgid "Do not treat root commits as boundaries (Default: off)"
-msgstr "Behandelt Ursprungsversionen nicht als Grenzen (Standard: aus)"
+msgstr "Behandelt Ursprungs-Commit nicht als Grenzen (Standard: aus)"
 
-#: builtin/blame.c:2353
+#: builtin/blame.c:2279
 msgid "Show work cost statistics"
 msgstr "Zeigt Statistiken zum Arbeitsaufwand"
 
-#: builtin/blame.c:2354
+#: builtin/blame.c:2280
 msgid "Show output score for blame entries"
 msgstr "Zeigt Ausgabebewertung für \"blame\"-Einträge"
 
-#: builtin/blame.c:2355
+#: builtin/blame.c:2281
 msgid "Show original filename (Default: auto)"
 msgstr "Zeigt ursprünglichen Dateinamen (Standard: auto)"
 
-#: builtin/blame.c:2356
+#: builtin/blame.c:2282
 msgid "Show original linenumber (Default: off)"
 msgstr "Zeigt ursprüngliche Zeilennummer (Standard: aus)"
 
-#: builtin/blame.c:2357
+#: builtin/blame.c:2283
 msgid "Show in a format designed for machine consumption"
 msgstr "Anzeige in einem Format für maschinelle Auswertung"
 
-#: builtin/blame.c:2358
+#: builtin/blame.c:2284
 msgid "Show porcelain format with per-line commit information"
 msgstr ""
-"Anzeige in Format für Fremdprogramme mit Versionsinformationen pro Zeile"
+"Anzeige in Format für Fremdprogramme mit Commit-Informationen pro Zeile"
 
-#: builtin/blame.c:2359
+#: builtin/blame.c:2285
 msgid "Use the same output mode as git-annotate (Default: off)"
 msgstr "Benutzt den gleichen Ausgabemodus wie \"git-annotate\" (Standard: aus)"
 
-#: builtin/blame.c:2360
+#: builtin/blame.c:2286
 msgid "Show raw timestamp (Default: off)"
 msgstr "Zeigt unbearbeiteten Zeitstempel (Standard: aus)"
 
-#: builtin/blame.c:2361
+#: builtin/blame.c:2287
 msgid "Show long commit SHA1 (Default: off)"
-msgstr "Zeigt langen Versions-SHA1 (Standard: aus)"
+msgstr "Zeigt langen Commit-SHA1 (Standard: aus)"
 
-#: builtin/blame.c:2362
+#: builtin/blame.c:2288
 msgid "Suppress author name and timestamp (Default: off)"
 msgstr "Unterdrückt den Namen des Autors und den Zeitstempel (Standard: aus)"
 
-#: builtin/blame.c:2363
+#: builtin/blame.c:2289
 msgid "Show author email instead of name (Default: off)"
 msgstr "Zeigt anstatt des Namens die Email-Adresse des Autors (Standard: aus)"
 
-#: builtin/blame.c:2364
+#: builtin/blame.c:2290
 msgid "Ignore whitespace differences"
-msgstr "Ignoriert Unterschiede in Leerzeichen"
+msgstr "Ignoriert Unterschiede im Whitespace"
 
-#: builtin/blame.c:2365
+#: builtin/blame.c:2291
 msgid "Spend extra cycles to find better match"
 msgstr "arbeite länger, um bessere Übereinstimmungen zu finden"
 
-#: builtin/blame.c:2366
+#: builtin/blame.c:2292
 msgid "Use revisions from <file> instead of calling git-rev-list"
-msgstr "Benutzt Revisionen von <Datei> anstatt \"git-rev-list\" aufzurufen"
+msgstr "Benutzt Commits von <Datei> anstatt \"git-rev-list\" aufzurufen"
 
-#: builtin/blame.c:2367
+#: builtin/blame.c:2293
 msgid "Use <file>'s contents as the final image"
 msgstr "Benutzt Inhalte der <Datei>en als entgültiges Abbild"
 
-#: builtin/blame.c:2368 builtin/blame.c:2369
+#: builtin/blame.c:2294 builtin/blame.c:2295
 msgid "score"
 msgstr "Bewertung"
 
-#: builtin/blame.c:2368
+#: builtin/blame.c:2294
 msgid "Find line copies within and across files"
 msgstr "Findet kopierte Zeilen innerhalb oder zwischen Dateien"
 
-#: builtin/blame.c:2369
+#: builtin/blame.c:2295
 msgid "Find line movements within and across files"
 msgstr "Findet verschobene Zeilen innerhalb oder zwischen Dateien"
 
-#: builtin/blame.c:2370
+#: builtin/blame.c:2296
 msgid "n,m"
 msgstr "n,m"
 
-#: builtin/blame.c:2370
+#: builtin/blame.c:2296
 msgid "Process only line range n,m, counting from 1"
 msgstr "Verarbeitet nur Zeilen im Bereich n,m, gezählt von 1"
 
@@ -2405,382 +2615,382 @@
 
 #: builtin/branch.c:25
 msgid "git branch [options] [-l] [-f] <branchname> [<start-point>]"
-msgstr "git branch [Optionen] [-l] [-f] <Zweigname> [<Startpunkt>]"
+msgstr "git branch [Optionen] [-l] [-f] <Branchname> [<Startpunkt>]"
 
 #: builtin/branch.c:26
 msgid "git branch [options] [-r] (-d | -D) <branchname>..."
-msgstr "git branch [Optionen] [-r] (-d | -D) <Zweigname>..."
+msgstr "git branch [Optionen] [-r] (-d | -D) <Branchname>..."
 
 #: builtin/branch.c:27
 msgid "git branch [options] (-m | -M) [<oldbranch>] <newbranch>"
-msgstr "git branch [Optionen] (-m | -M) [<alterZweig>] <neuerZweig>"
+msgstr "git branch [Optionen] (-m | -M) [<alterBranch>] <neuerBranch>"
 
-#: builtin/branch.c:146
+#: builtin/branch.c:150
 #, c-format
 msgid ""
 "deleting branch '%s' that has been merged to\n"
 "         '%s', but not yet merged to HEAD."
 msgstr ""
-"entferne Zweig '%s', der zusammengeführt wurde mit\n"
-"         '%s', aber noch nicht mit der Zweigspitze (HEAD) zusammengeführt "
-"wurde."
+"entferne Branch '%s', der zusammengeführt wurde mit\n"
+"         '%s', aber noch nicht mit HEAD zusammengeführt wurde."
 
-#: builtin/branch.c:150
+#: builtin/branch.c:154
 #, c-format
 msgid ""
 "not deleting branch '%s' that is not yet merged to\n"
 "         '%s', even though it is merged to HEAD."
 msgstr ""
-"entferne Zweig '%s' nicht, der noch nicht zusammengeführt wurde mit\n"
-"         '%s', obwohl er mit der Zweigspitze (HEAD) zusammengeführt wurde."
-
-#: builtin/branch.c:164
-#, c-format
-msgid "Couldn't look up commit object for '%s'"
-msgstr "Konnte Versionsobjekt für '%s' nicht nachschlagen."
+"entferne Branch '%s' nicht, der noch nicht zusammengeführt wurde mit\n"
+"         '%s', obwohl er mit HEAD zusammengeführt wurde."
 
 #: builtin/branch.c:168
 #, c-format
+msgid "Couldn't look up commit object for '%s'"
+msgstr "Konnte Commit-Objekt für '%s' nicht nachschlagen."
+
+#: builtin/branch.c:172
+#, c-format
 msgid ""
 "The branch '%s' is not fully merged.\n"
 "If you are sure you want to delete it, run 'git branch -D %s'."
 msgstr ""
-"Der Zweig '%s' ist nicht vollständig zusammengeführt.\n"
-"Wenn Sie sicher sind diesen Zweig zu entfernen, führen Sie 'git branch -D "
+"Der Branch '%s' ist nicht vollständig zusammengeführt.\n"
+"Wenn Sie sicher sind diesen Branch zu entfernen, führen Sie 'git branch -D "
 "%s' aus."
 
-#: builtin/branch.c:181
+#: builtin/branch.c:185
 msgid "Update of config-file failed"
 msgstr "Aktualisierung der Konfigurationsdatei fehlgeschlagen."
 
-#: builtin/branch.c:209
+#: builtin/branch.c:213
 msgid "cannot use -a with -d"
 msgstr "kann -a nicht mit -d benutzen"
 
-#: builtin/branch.c:215
+#: builtin/branch.c:219
 msgid "Couldn't look up commit object for HEAD"
-msgstr "Konnte Versionsobjekt für Zweigspitze (HEAD) nicht nachschlagen."
+msgstr "Konnte Commit-Objekt für HEAD nicht nachschlagen."
 
-#: builtin/branch.c:223
+#: builtin/branch.c:227
 #, c-format
 msgid "Cannot delete the branch '%s' which you are currently on."
 msgstr ""
-"Kann Zweig '%s' nicht entfernen, da Sie sich gerade auf diesem befinden."
+"Kann Branch '%s' nicht entfernen, da Sie sich gerade auf diesem befinden."
 
-#: builtin/branch.c:236
+#: builtin/branch.c:240
 #, c-format
 msgid "remote branch '%s' not found."
-msgstr "externer Zweig '%s' nicht gefunden"
+msgstr "Remote-Branch '%s' nicht gefunden"
 
-#: builtin/branch.c:237
+#: builtin/branch.c:241
 #, c-format
 msgid "branch '%s' not found."
-msgstr "Zweig '%s' nicht gefunden."
+msgstr "Branch '%s' nicht gefunden."
 
-#: builtin/branch.c:251
+#: builtin/branch.c:255
 #, c-format
 msgid "Error deleting remote branch '%s'"
-msgstr "Fehler beim Entfernen des externen Zweiges '%s'"
+msgstr "Fehler beim Entfernen des Remote-Branches '%s'"
 
-#: builtin/branch.c:252
+#: builtin/branch.c:256
 #, c-format
 msgid "Error deleting branch '%s'"
-msgstr "Fehler beim Entfernen des Zweiges '%s'"
+msgstr "Fehler beim Entfernen des Branches '%s'"
 
-#: builtin/branch.c:259
+#: builtin/branch.c:263
 #, c-format
 msgid "Deleted remote branch %s (was %s).\n"
-msgstr "Externer Zweig %s entfernt (war %s).\n"
+msgstr "Remote-Branch %s entfernt (war %s).\n"
 
-#: builtin/branch.c:260
+#: builtin/branch.c:264
 #, c-format
 msgid "Deleted branch %s (was %s).\n"
-msgstr "Zweig %s entfernt (war %s).\n"
+msgstr "Branch %s entfernt (war %s).\n"
 
-#: builtin/branch.c:362
+#: builtin/branch.c:366
 #, c-format
 msgid "branch '%s' does not point at a commit"
-msgstr "Zweig '%s' zeigt auf keine Version"
+msgstr "Branch '%s' zeigt auf keinen Commit"
 
-#: builtin/branch.c:434
+#: builtin/branch.c:453
 #, c-format
 msgid "[%s: behind %d]"
 msgstr "[%s: %d hinterher]"
 
-#: builtin/branch.c:436
+#: builtin/branch.c:455
 #, c-format
 msgid "[behind %d]"
 msgstr "[%d hinterher]"
 
-#: builtin/branch.c:440
+#: builtin/branch.c:459
 #, c-format
 msgid "[%s: ahead %d]"
 msgstr "[%s: %d voraus]"
 
-#: builtin/branch.c:442
+#: builtin/branch.c:461
 #, c-format
 msgid "[ahead %d]"
 msgstr "[%d voraus]"
 
-#: builtin/branch.c:445
+#: builtin/branch.c:464
 #, c-format
 msgid "[%s: ahead %d, behind %d]"
 msgstr "[%s: %d voraus, %d hinterher]"
 
-#: builtin/branch.c:448
+#: builtin/branch.c:467
 #, c-format
 msgid "[ahead %d, behind %d]"
 msgstr "[%d voraus, %d hinterher]"
 
-#: builtin/branch.c:470
+#: builtin/branch.c:490
 msgid " **** invalid ref ****"
 msgstr " **** ungültige Referenz ****"
 
-#: builtin/branch.c:562
+#: builtin/branch.c:582
 #, c-format
 msgid "(no branch, rebasing %s)"
-msgstr "(kein Zweig, Neuaufbau von Zweig %s im Gange)"
+msgstr "(kein Branch, Rebase von Branch %s im Gange)"
 
-#: builtin/branch.c:565
+#: builtin/branch.c:585
 #, c-format
 msgid "(no branch, bisect started on %s)"
-msgstr "(kein Zweig, Neuaufbau begonnen bei %s)"
+msgstr "(kein Branch, binäre Suche begonnen bei %s)"
 
-#: builtin/branch.c:568
+#: builtin/branch.c:588
 #, c-format
 msgid "(detached from %s)"
 msgstr "(losgelöst von %s)"
 
-#: builtin/branch.c:571
+#: builtin/branch.c:591
 msgid "(no branch)"
-msgstr "(kein Zweig)"
+msgstr "(kein Branch)"
 
-#: builtin/branch.c:617
+#: builtin/branch.c:637
 #, c-format
 msgid "object '%s' does not point to a commit"
-msgstr "Objekt '%s' zeigt auf keine Version"
+msgstr "Objekt '%s' zeigt auf keinen Commit"
 
-#: builtin/branch.c:649
+#: builtin/branch.c:669
 msgid "some refs could not be read"
 msgstr "Konnte einige Referenzen nicht lesen"
 
-#: builtin/branch.c:662
+#: builtin/branch.c:682
 msgid "cannot rename the current branch while not on any."
 msgstr ""
-"Kann aktuellen Zweig nicht umbenennen, solange Sie sich auf keinem befinden."
+"Kann aktuellen Branch nicht umbenennen, solange Sie sich auf keinem befinden."
 
-#: builtin/branch.c:672
+#: builtin/branch.c:692
 #, c-format
 msgid "Invalid branch name: '%s'"
-msgstr "Ungültiger Zweig-Name: '%s'"
+msgstr "Ungültiger Branchname: '%s'"
 
-#: builtin/branch.c:687
+#: builtin/branch.c:707
 msgid "Branch rename failed"
-msgstr "Umbenennung des Zweiges fehlgeschlagen"
+msgstr "Umbenennung des Branches fehlgeschlagen"
 
-#: builtin/branch.c:691
+#: builtin/branch.c:711
 #, c-format
 msgid "Renamed a misnamed branch '%s' away"
-msgstr "falsch benannten Zweig '%s' umbenannt"
+msgstr "falsch benannten Branch '%s' umbenannt"
 
-#: builtin/branch.c:695
+#: builtin/branch.c:715
 #, c-format
 msgid "Branch renamed to %s, but HEAD is not updated!"
-msgstr "Zweig umbenannt zu %s, aber Zweigspitze (HEAD) ist nicht aktualisiert!"
+msgstr "Branch umbenannt zu %s, aber HEAD ist nicht aktualisiert!"
 
-#: builtin/branch.c:702
+#: builtin/branch.c:722
 msgid "Branch is renamed, but update of config-file failed"
 msgstr ""
-"Zweig ist umbenannt, aber die Aktualisierung der Konfigurationsdatei ist "
+"Branch ist umbenannt, aber die Aktualisierung der Konfigurationsdatei ist "
 "fehlgeschlagen."
 
-#: builtin/branch.c:717
+#: builtin/branch.c:737
 #, c-format
 msgid "malformed object name %s"
 msgstr "Missgebildeter Objektname %s"
 
-#: builtin/branch.c:741
+#: builtin/branch.c:761
 #, c-format
 msgid "could not write branch description template: %s"
-msgstr "Konnte Beschreibungsvorlage für Zweig nicht schreiben: %s"
+msgstr "Konnte Beschreibungsvorlage für Branch nicht schreiben: %s"
 
-#: builtin/branch.c:771
+#: builtin/branch.c:791
 msgid "Generic options"
 msgstr "Allgemeine Optionen"
 
-#: builtin/branch.c:773
+#: builtin/branch.c:793
 msgid "show hash and subject, give twice for upstream branch"
-msgstr "Zeigt Hash und Betreff; -vv: zusätzlich externen Übernahmezweig"
+msgstr "Zeigt Hash und Betreff; -vv: zusätzlich Upstream-Branch"
 
-#: builtin/branch.c:774
+#: builtin/branch.c:794
 msgid "suppress informational messages"
 msgstr "unterdrückt Informationsmeldungen"
 
-#: builtin/branch.c:775
+#: builtin/branch.c:795
 msgid "set up tracking mode (see git-pull(1))"
 msgstr "stellt den Übernahmemodus ein (siehe git-pull(1))"
 
-#: builtin/branch.c:777
+#: builtin/branch.c:797
 msgid "change upstream info"
-msgstr "ändert Informationen zum externen Übernahmezweig"
+msgstr "ändert Informationen zum Upstream-Branch"
 
-#: builtin/branch.c:781
+#: builtin/branch.c:801
 msgid "use colored output"
 msgstr "verwendet farbliche Ausgaben"
 
-#: builtin/branch.c:782
+#: builtin/branch.c:802
 msgid "act on remote-tracking branches"
-msgstr "wirkt auf externe Übernahmezweige"
+msgstr "wirkt auf Remote-Tracking-Branches"
 
-#: builtin/branch.c:785 builtin/branch.c:791 builtin/branch.c:812
-#: builtin/branch.c:818 builtin/commit.c:1368 builtin/commit.c:1369
-#: builtin/commit.c:1370 builtin/commit.c:1371 builtin/tag.c:468
+#: builtin/branch.c:805 builtin/branch.c:811 builtin/branch.c:832
+#: builtin/branch.c:838 builtin/commit.c:1433 builtin/commit.c:1434
+#: builtin/commit.c:1435 builtin/commit.c:1436 builtin/tag.c:468
 msgid "commit"
-msgstr "Version"
+msgstr "Commit"
 
-#: builtin/branch.c:786 builtin/branch.c:792
+#: builtin/branch.c:806 builtin/branch.c:812
 msgid "print only branches that contain the commit"
-msgstr "gibt nur Zweige aus, welche diese Version beinhalten"
+msgstr "gibt nur Branches aus, welche diesen Commit beinhalten"
 
-#: builtin/branch.c:798
+#: builtin/branch.c:818
 msgid "Specific git-branch actions:"
 msgstr "spezifische Aktionen für \"git-branch\":"
 
-#: builtin/branch.c:799
+#: builtin/branch.c:819
 msgid "list both remote-tracking and local branches"
-msgstr "listet externe Übernahmezweige und lokale Zweige auf"
+msgstr "listet Remote-Tracking und lokale Branches auf"
 
-#: builtin/branch.c:801
+#: builtin/branch.c:821
 msgid "delete fully merged branch"
-msgstr "entfernt vollständig zusammengeführten Zweig"
-
-#: builtin/branch.c:802
-msgid "delete branch (even if not merged)"
-msgstr "löscht Zweig (auch wenn nicht zusammengeführt)"
-
-#: builtin/branch.c:803
-msgid "move/rename a branch and its reflog"
-msgstr "verschiebt/benennt einen Zweig und dessen Referenzprotokoll um"
-
-#: builtin/branch.c:804
-msgid "move/rename a branch, even if target exists"
-msgstr ""
-"verschiebt/benennt einen Zweig um, auch wenn das Ziel bereits existiert"
-
-#: builtin/branch.c:805
-msgid "list branch names"
-msgstr "listet Zweignamen auf"
-
-#: builtin/branch.c:806
-msgid "create the branch's reflog"
-msgstr "erzeugt das Referenzprotokoll des Zweiges"
-
-#: builtin/branch.c:808
-msgid "edit the description for the branch"
-msgstr "bearbeitet die Beschreibung für den Zweig"
-
-#: builtin/branch.c:809
-msgid "force creation (when already exists)"
-msgstr "erzeuge auch, wenn der Zweig bereits existiert"
-
-#: builtin/branch.c:812
-msgid "print only not merged branches"
-msgstr "gibt nur Zweige aus, die nicht zusammengeführt sind"
-
-#: builtin/branch.c:818
-msgid "print only merged branches"
-msgstr "gibt nur Zweige aus, die zusammengeführt sind"
+msgstr "entfernt vollständig zusammengeführten Branch"
 
 #: builtin/branch.c:822
+msgid "delete branch (even if not merged)"
+msgstr "löscht Branch (auch wenn nicht zusammengeführt)"
+
+#: builtin/branch.c:823
+msgid "move/rename a branch and its reflog"
+msgstr "verschiebt/benennt einen Branch und dessen Reflog um"
+
+#: builtin/branch.c:824
+msgid "move/rename a branch, even if target exists"
+msgstr ""
+"verschiebt/benennt einen Branch um, auch wenn das Ziel bereits existiert"
+
+#: builtin/branch.c:825
+msgid "list branch names"
+msgstr "listet Branchnamen auf"
+
+#: builtin/branch.c:826
+msgid "create the branch's reflog"
+msgstr "erzeugt das Reflog des Branches"
+
+#: builtin/branch.c:828
+msgid "edit the description for the branch"
+msgstr "bearbeitet die Beschreibung für den Branch"
+
+#: builtin/branch.c:829
+msgid "force creation (when already exists)"
+msgstr "erzeuge auch, wenn der Branch bereits existiert"
+
+#: builtin/branch.c:832
+msgid "print only not merged branches"
+msgstr "gibt nur Branches aus, die nicht zusammengeführt sind"
+
+#: builtin/branch.c:838
+msgid "print only merged branches"
+msgstr "gibt nur Branches aus, die zusammengeführt sind"
+
+#: builtin/branch.c:842
 msgid "list branches in columns"
-msgstr "listet Zweige in Spalten auf"
+msgstr "listet Branches in Spalten auf"
 
-#: builtin/branch.c:835
+#: builtin/branch.c:855
 msgid "Failed to resolve HEAD as a valid ref."
-msgstr "Konnte Zweigspitze (HEAD) nicht als gültige Referenz auflösen."
+msgstr "Konnte HEAD nicht als gültige Referenz auflösen."
 
-#: builtin/branch.c:840 builtin/clone.c:609
+#: builtin/branch.c:860 builtin/clone.c:630
 msgid "HEAD not found below refs/heads!"
-msgstr "Zweigspitze (HEAD) wurde nicht unter \"refs/heads\" gefunden!"
+msgstr "HEAD wurde nicht unter \"refs/heads\" gefunden!"
 
-#: builtin/branch.c:863
+#: builtin/branch.c:883
 msgid "--column and --verbose are incompatible"
 msgstr "Die Optionen --column und --verbose sind inkompatibel."
 
-#: builtin/branch.c:869 builtin/branch.c:908
+#: builtin/branch.c:889 builtin/branch.c:928
 msgid "branch name required"
-msgstr "Zweigname erforderlich"
+msgstr "Branchname erforderlich"
 
-#: builtin/branch.c:884
+#: builtin/branch.c:904
 msgid "Cannot give description to detached HEAD"
-msgstr ""
-"zu losgelöster Zweigspitze (HEAD) kann keine Beschreibung hinterlegt werden"
+msgstr "zu losgelöstem HEAD kann keine Beschreibung hinterlegt werden"
 
-#: builtin/branch.c:889
+#: builtin/branch.c:909
 msgid "cannot edit description of more than one branch"
-msgstr "Beschreibung von mehr als einem Zweig kann nicht bearbeitet werden"
+msgstr "Beschreibung von mehr als einem Branch kann nicht bearbeitet werden"
 
-#: builtin/branch.c:896
+#: builtin/branch.c:916
 #, c-format
 msgid "No commit on branch '%s' yet."
-msgstr "Noch keine Version in Zweig '%s'."
-
-#: builtin/branch.c:899
-#, c-format
-msgid "No branch named '%s'."
-msgstr "Zweig '%s' nicht vorhanden."
-
-#: builtin/branch.c:914
-msgid "too many branches for a rename operation"
-msgstr "zu viele Zweige für eine Umbenennen-Operation angegeben"
+msgstr "Noch kein Commit in Branch '%s'."
 
 #: builtin/branch.c:919
-msgid "too many branches to set new upstream"
-msgstr "zu viele Zweige angegeben um neuen Übernahmezweig zu setzen"
+#, c-format
+msgid "No branch named '%s'."
+msgstr "Branch '%s' nicht vorhanden."
 
-#: builtin/branch.c:923
+#: builtin/branch.c:934
+msgid "too many branches for a rename operation"
+msgstr "zu viele Branches für eine Umbenennen-Operation angegeben"
+
+#: builtin/branch.c:939
+msgid "too many branches to set new upstream"
+msgstr "zu viele Branches angegeben um Upstream-Branch zu setzen"
+
+#: builtin/branch.c:943
 #, c-format
 msgid ""
 "could not set upstream of HEAD to %s when it does not point to any branch."
 msgstr ""
-"Konnte keinen neuen Übernahmezweig von Zweigspitze (HEAD) zu %s setzen,\n"
-"da diese auf keinen Zweig zeigt."
+"Konnte keinen neuen Upstream-Branch von HEAD zu %s setzen, da dieser auf\n"
+"keinen Branch zeigt."
 
-#: builtin/branch.c:926 builtin/branch.c:948 builtin/branch.c:970
+#: builtin/branch.c:946 builtin/branch.c:968 builtin/branch.c:990
 #, c-format
 msgid "no such branch '%s'"
-msgstr "Kein solcher Zweig '%s'"
+msgstr "Kein solcher Branch '%s'"
 
-#: builtin/branch.c:930
+#: builtin/branch.c:950
 #, c-format
 msgid "branch '%s' does not exist"
-msgstr "Zweig '%s' existiert nicht"
+msgstr "Branch '%s' existiert nicht"
 
-#: builtin/branch.c:942
+#: builtin/branch.c:962
 msgid "too many branches to unset upstream"
-msgstr "zu viele Zweige angegeben um Konfiguration zu Übernahmezweig zu entfernen"
+msgstr ""
+"zu viele Branches angegeben um Konfiguration zu Upstream-Branch zu entfernen"
 
-#: builtin/branch.c:946
+#: builtin/branch.c:966
 msgid "could not unset upstream of HEAD when it does not point to any branch."
-msgstr "Konnte Konfiguration zum Übernahmezweig von Zweigspitze (HEAD) nicht\n"
-"entfernen, da diese auf keinen Zweig zeigt."
+msgstr ""
+"Konnte Konfiguration zu Upstream-Branch von HEAD nicht entfernen, da dieser\n"
+"auf keinen Branch zeigt."
 
-#: builtin/branch.c:952
+#: builtin/branch.c:972
 #, c-format
 msgid "Branch '%s' has no upstream information"
-msgstr "Zweig '%s' hat keinen externen Übernahmezweig gesetzt"
+msgstr "Branch '%s' hat keinen Upstream-Branch gesetzt"
 
-#: builtin/branch.c:967
+#: builtin/branch.c:987
 msgid "it does not make sense to create 'HEAD' manually"
 msgstr "'HEAD' darf nicht manuell erstellt werden"
 
-#: builtin/branch.c:973
+#: builtin/branch.c:993
 msgid "-a and -r options to 'git branch' do not make sense with a branch name"
 msgstr ""
 "Die Optionen -a und -r bei 'git branch' können nicht gemeimsam mit einem "
-"Zweignamen verwendet werden."
+"Branchnamen verwendet werden."
 
-#: builtin/branch.c:976
+#: builtin/branch.c:996
 #, c-format
 msgid ""
 "The --set-upstream flag is deprecated and will be removed. Consider using --"
@@ -2789,7 +2999,7 @@
 "Die --set-upstream Option ist veraltet und wird entfernt. Benutzen Sie --"
 "track oder --set-upstream-to\n"
 
-#: builtin/branch.c:993
+#: builtin/branch.c:1013
 #, c-format
 msgid ""
 "\n"
@@ -2797,15 +3007,15 @@
 "\n"
 msgstr ""
 "\n"
-"Wenn Sie wollten, dass '%s' den Zweig '%s' als externen Übernahmezweig hat, "
-"führen Sie aus:\n"
+"Wenn Sie wollten, dass '%s' den Branch '%s' als Upstream-Branch hat, führen "
+"Sie aus:\n"
 
-#: builtin/branch.c:994
+#: builtin/branch.c:1014
 #, c-format
 msgid "    git branch -d %s\n"
 msgstr "    git branch -d %s\n"
 
-#: builtin/branch.c:995
+#: builtin/branch.c:1015
 #, c-format
 msgid "    git branch --set-upstream-to %s\n"
 msgstr "    git branch --set-upstream-to %s\n"
@@ -2817,51 +3027,51 @@
 
 #: builtin/bundle.c:56
 msgid "Need a repository to create a bundle."
-msgstr "Um ein Paket zu erstellen wird ein Projektarchiv benötigt."
+msgstr "Um ein Paket zu erstellen wird ein Repository benötigt."
 
 #: builtin/bundle.c:60
 msgid "Need a repository to unbundle."
-msgstr "Zum Entpacken wird ein Projektarchiv benötigt."
+msgstr "Zum Entpacken wird ein Repository benötigt."
 
-#: builtin/cat-file.c:247
+#: builtin/cat-file.c:285
 msgid "git cat-file (-t|-s|-e|-p|<type>|--textconv) <object>"
 msgstr "git cat-file (-t|-s|-e|-p|<Art>|--textconv) <Objekt>"
 
-#: builtin/cat-file.c:248
+#: builtin/cat-file.c:286
 msgid "git cat-file (--batch|--batch-check) < <list_of_objects>"
 msgstr "git cat-file (--batch|--batch-check) < <Liste_von_Objekten>"
 
-#: builtin/cat-file.c:266
+#: builtin/cat-file.c:323
 msgid "<type> can be one of: blob, tree, commit, tag"
 msgstr "<Art> kann sein: blob, tree, commit, tag"
 
-#: builtin/cat-file.c:267
+#: builtin/cat-file.c:324
 msgid "show object type"
 msgstr "zeigt Objektart"
 
-#: builtin/cat-file.c:268
+#: builtin/cat-file.c:325
 msgid "show object size"
 msgstr "zeigt Objektgröße"
 
-#: builtin/cat-file.c:270
+#: builtin/cat-file.c:327
 msgid "exit with zero when there's no error"
 msgstr "beendet mit Rückgabewert 0, wenn kein Fehler aufgetreten ist"
 
-#: builtin/cat-file.c:271
+#: builtin/cat-file.c:328
 msgid "pretty-print object's content"
 msgstr "ansprechende Anzeige des Objektinhaltes"
 
-#: builtin/cat-file.c:273
+#: builtin/cat-file.c:330
 msgid "for blob objects, run textconv on object's content"
 msgstr "führt eine Textkonvertierung auf den Inhalt von Blob-Objekten aus"
 
-#: builtin/cat-file.c:275
+#: builtin/cat-file.c:332
 msgid "show info and content of objects fed from the standard input"
 msgstr ""
 "Anzeige von Informationen und Inhalt von Objekten, gelesen von der Standard-"
 "Eingabe"
 
-#: builtin/cat-file.c:278
+#: builtin/cat-file.c:335
 msgid "show info about objects fed from the standard input"
 msgstr ""
 "Anzeige von Informationen über Objekte, gelesen von der Standard-Eingabe"
@@ -2881,7 +3091,7 @@
 
 #: builtin/check-attr.c:20
 msgid "use .gitattributes only from the index"
-msgstr "verwendet .gitattributes nur von der Bereitstellung"
+msgstr "verwendet .gitattributes nur von der Staging-Area"
 
 #: builtin/check-attr.c:21 builtin/check-ignore.c:22 builtin/hash-object.c:75
 msgid "read file names from stdin"
@@ -2891,38 +3101,63 @@
 msgid "input paths are terminated by a null character"
 msgstr "Eingabepfade sind durch ein NUL Zeichen abgeschlossen"
 
-#: builtin/check-ignore.c:18 builtin/checkout.c:1041 builtin/gc.c:177
+#: builtin/check-ignore.c:18 builtin/checkout.c:1054 builtin/gc.c:177
 msgid "suppress progress reporting"
 msgstr "unterdrückt Fortschrittsanzeige"
 
-#: builtin/check-ignore.c:151
+#: builtin/check-ignore.c:26
+msgid "show non-matching input paths"
+msgstr "zeigt Eingabe-Pfade ohne Übereinstimmungen"
+
+#: builtin/check-ignore.c:143
 msgid "cannot specify pathnames with --stdin"
 msgstr "Angabe von Pfadnamen kann nicht gemeinsam mit --stdin verwendet werden"
 
-#: builtin/check-ignore.c:154
+#: builtin/check-ignore.c:146
 msgid "-z only makes sense with --stdin"
 msgstr "Die Option -z kann nur mit --stdin verwendet werden."
 
-#: builtin/check-ignore.c:156
+#: builtin/check-ignore.c:148
 msgid "no path specified"
 msgstr "kein Pfad angegeben"
 
-#: builtin/check-ignore.c:160
+#: builtin/check-ignore.c:152
 msgid "--quiet is only valid with a single pathname"
 msgstr "Die Option --quiet ist nur mit einem einzelnen Pfadnamen gültig."
 
-#: builtin/check-ignore.c:162
+#: builtin/check-ignore.c:154
 msgid "cannot have both --quiet and --verbose"
 msgstr ""
 "Die Optionen --quiet und --verbose können nicht gemeinsam verwendet werden."
 
+#: builtin/check-ignore.c:157
+msgid "--non-matching is only valid with --verbose"
+msgstr "--non-matching ist nur mit --verbose zulässig"
+
+#: builtin/check-mailmap.c:8
+msgid "git check-mailmap [options] <contact>..."
+msgstr "git check-mailmap [Optionen] <Kontakt>..."
+
+#: builtin/check-mailmap.c:13
+msgid "also read contacts from stdin"
+msgstr "liest ebenfalls Kontakte von der Standard-Eingabe"
+
+#: builtin/check-mailmap.c:24
+#, c-format
+msgid "unable to parse contact: %s"
+msgstr "Konnte Kontakt '%s' nicht parsen."
+
+#: builtin/check-mailmap.c:47
+msgid "no contacts specified"
+msgstr "keine Kontakte angegeben"
+
 #: builtin/checkout-index.c:126
 msgid "git checkout-index [options] [--] [<file>...]"
 msgstr "git checkout-index [Optionen] [--] [<Datei>...]"
 
 #: builtin/checkout-index.c:187
 msgid "check out all files in the index"
-msgstr "checkt alle Dateien in der Bereitstellung aus"
+msgstr "checkt alle Dateien in der Staging-Area aus"
 
 #: builtin/checkout-index.c:188
 msgid "force overwrite of existing files"
@@ -2932,7 +3167,7 @@
 msgid "no warning for existing files and files not in index"
 msgstr ""
 "keine Warnung für existierende Dateien, und Dateien, die sich nicht in der "
-"Bereitstellung befinden"
+"Staging-Area befinden"
 
 #: builtin/checkout-index.c:192
 msgid "don't checkout new files"
@@ -2940,7 +3175,7 @@
 
 #: builtin/checkout-index.c:194
 msgid "update stat information in the index file"
-msgstr "aktualisiert Dateiinformationen in der Bereitstellungsdatei"
+msgstr "aktualisiert Dateiinformationen in der Staging-Area-Datei"
 
 #: builtin/checkout-index.c:200
 msgid "read list of paths from the standard input"
@@ -2965,112 +3200,113 @@
 
 #: builtin/checkout.c:25
 msgid "git checkout [options] <branch>"
-msgstr "git checkout [Optionen] <Zweig>"
+msgstr "git checkout [Optionen] <Branch>"
 
 #: builtin/checkout.c:26
 msgid "git checkout [options] [<branch>] -- <file>..."
-msgstr "git checkout [Optionen] [Zweig>] -- <Datei>..."
+msgstr "git checkout [Optionen] [<Branch>] -- <Datei>..."
 
-#: builtin/checkout.c:116 builtin/checkout.c:149
+#: builtin/checkout.c:117 builtin/checkout.c:150
 #, c-format
 msgid "path '%s' does not have our version"
 msgstr "Pfad '%s' hat nicht unsere Version."
 
-#: builtin/checkout.c:118 builtin/checkout.c:151
+#: builtin/checkout.c:119 builtin/checkout.c:152
 #, c-format
 msgid "path '%s' does not have their version"
 msgstr "Pfad '%s' hat nicht deren Version."
 
-#: builtin/checkout.c:134
+#: builtin/checkout.c:135
 #, c-format
 msgid "path '%s' does not have all necessary versions"
 msgstr "Pfad '%s' hat nicht alle notwendigen Versionen."
 
-#: builtin/checkout.c:178
+#: builtin/checkout.c:179
 #, c-format
 msgid "path '%s' does not have necessary versions"
 msgstr "Pfad '%s' hat nicht die notwendigen Versionen."
 
-#: builtin/checkout.c:195
+#: builtin/checkout.c:196
 #, c-format
 msgid "path '%s': cannot merge"
 msgstr "Pfad '%s': kann nicht zusammenführen"
 
-#: builtin/checkout.c:212
+#: builtin/checkout.c:213
 #, c-format
 msgid "Unable to add merge result for '%s'"
-msgstr "Konnte Ergebnis der Zusammenführung von '%s' nicht hinzufügen."
+msgstr "Konnte Merge-Ergebnis von '%s' nicht hinzufügen."
 
-#: builtin/checkout.c:236 builtin/checkout.c:239 builtin/checkout.c:242
-#: builtin/checkout.c:245
+#: builtin/checkout.c:237 builtin/checkout.c:240 builtin/checkout.c:243
+#: builtin/checkout.c:246
 #, c-format
 msgid "'%s' cannot be used with updating paths"
 msgstr "'%s' kann nicht mit Pfaden verwendet werden"
 
-#: builtin/checkout.c:248 builtin/checkout.c:251
+#: builtin/checkout.c:249 builtin/checkout.c:252
 #, c-format
 msgid "'%s' cannot be used with %s"
 msgstr "'%s' kann nicht mit '%s' verwendet werden"
 
-#: builtin/checkout.c:254
+#: builtin/checkout.c:255
 #, c-format
 msgid "Cannot update paths and switch to branch '%s' at the same time."
-msgstr "Kann nicht gleichzeitig Pfade aktualisieren und zu Zweig '%s' wechseln"
+msgstr ""
+"Kann nicht gleichzeitig Pfade aktualisieren und zu Branch '%s' wechseln"
 
-#: builtin/checkout.c:265 builtin/checkout.c:455
+#: builtin/checkout.c:266 builtin/checkout.c:458
 msgid "corrupt index file"
-msgstr "beschädigte Bereitstellungsdatei"
+msgstr "beschädigte Staging-Area-Datei"
 
-#: builtin/checkout.c:326 builtin/checkout.c:333
+#: builtin/checkout.c:329 builtin/checkout.c:336
 #, c-format
 msgid "path '%s' is unmerged"
 msgstr "Pfad '%s' ist nicht zusammengeführt."
 
-#: builtin/checkout.c:477
+#: builtin/checkout.c:480
 msgid "you need to resolve your current index first"
-msgstr "Sie müssen zuerst Ihre aktuelle Bereitstellung auflösen."
+msgstr "Sie müssen zuerst Ihre aktuelle Staging-Area auflösen."
 
-#: builtin/checkout.c:598
+#: builtin/checkout.c:601
 #, c-format
 msgid "Can not do reflog for '%s'\n"
 msgstr "Konnte \"reflog\" für '%s' nicht durchführen\n"
 
-#: builtin/checkout.c:631
+#: builtin/checkout.c:639
 msgid "HEAD is now at"
-msgstr "Zweigspitze (HEAD) ist jetzt bei"
+msgstr "HEAD ist jetzt bei"
 
-#: builtin/checkout.c:638
+#: builtin/checkout.c:646
 #, c-format
 msgid "Reset branch '%s'\n"
-msgstr "Setze Zweig '%s' neu\n"
+msgstr "Setze Branch '%s' neu\n"
 
-#: builtin/checkout.c:641
+#: builtin/checkout.c:649
 #, c-format
 msgid "Already on '%s'\n"
 msgstr "Bereits auf '%s'\n"
 
-#: builtin/checkout.c:645
+#: builtin/checkout.c:653
 #, c-format
 msgid "Switched to and reset branch '%s'\n"
-msgstr "Gewechselt zu neu gesetztem Zweig '%s'\n"
+msgstr "Gewechselt zu umgesetzten Branch '%s'\n"
 
-#: builtin/checkout.c:647 builtin/checkout.c:984
+#: builtin/checkout.c:655 builtin/checkout.c:997
 #, c-format
 msgid "Switched to a new branch '%s'\n"
-msgstr "Gewechselt zu einem neuen Zweig '%s'\n"
+msgstr "Gewechselt zu einem neuem Branch '%s'\n"
 
-#: builtin/checkout.c:649
+#: builtin/checkout.c:657
 #, c-format
 msgid "Switched to branch '%s'\n"
-msgstr "Gewechselt zu Zweig '%s'\n"
+msgstr "Gewechselt zu Branch '%s'\n"
 
-#: builtin/checkout.c:705
+#: builtin/checkout.c:713
 #, c-format
 msgid " ... and %d more.\n"
 msgstr " ... und %d weitere.\n"
 
 #. The singular version
-#: builtin/checkout.c:711
+#: builtin/checkout.c:719
 #, c-format
 msgid ""
 "Warning: you are leaving %d commit behind, not connected to\n"
@@ -3083,17 +3319,17 @@
 "\n"
 "%s\n"
 msgstr[0] ""
-"Warnung: Sie sind um %d Version hinterher, nicht verbunden zu\n"
-"einem Ihrer Zweige:\n"
+"Warnung: Sie sind um %d Commit hinterher, nicht verbunden zu\n"
+"einem Ihrer Branches:\n"
 "\n"
 "%s\n"
 msgstr[1] ""
-"Warnung: Sie sind um %d Versionen hinterher, nicht verbunden zu\n"
-"einem Ihrer Zweige:\n"
+"Warnung: Sie sind um %d Commits hinterher, nicht verbunden zu\n"
+"einem Ihrer Branches:\n"
 "\n"
 "%s\n"
 
-#: builtin/checkout.c:729
+#: builtin/checkout.c:737
 #, c-format
 msgid ""
 "If you want to keep them by creating a new branch, this may be a good time\n"
@@ -3102,372 +3338,478 @@
 " git branch new_branch_name %s\n"
 "\n"
 msgstr ""
-"Wenn Sie diese durch einen neuen Zweig behalten möchten, dann könnte jetzt\n"
+"Wenn Sie diese durch einen neuen Branch behalten möchten, dann könnte jetzt\n"
 "ein guter Zeitpunkt sein dies zu tun mit:\n"
 "\n"
-" git branch neuer_zweig_name %s\n"
+" git branch neuer_branch_name %s\n"
 "\n"
 
-#: builtin/checkout.c:759
+#: builtin/checkout.c:767
 msgid "internal error in revision walk"
 msgstr "interner Fehler im Revisionsgang"
 
-#: builtin/checkout.c:763
+#: builtin/checkout.c:771
 msgid "Previous HEAD position was"
-msgstr "Vorherige Position der Zweigspitze (HEAD) war"
+msgstr "Vorherige Position von HEAD war"
 
-#: builtin/checkout.c:790 builtin/checkout.c:979
+#: builtin/checkout.c:798 builtin/checkout.c:992
 msgid "You are on a branch yet to be born"
-msgstr "Sie sind auf einem Zweig, der noch geboren wird"
+msgstr "Sie sind auf einem Branch, der noch geboren wird"
 
 #. case (1)
-#: builtin/checkout.c:915
+#: builtin/checkout.c:928
 #, c-format
 msgid "invalid reference: %s"
 msgstr "Ungültige Referenz: %s"
 
 #. case (1): want a tree
-#: builtin/checkout.c:954
+#: builtin/checkout.c:967
 #, c-format
 msgid "reference is not a tree: %s"
-msgstr "Referenz ist kein Baum: %s"
+msgstr "Referenz ist kein \"Tree\"-Objekt: %s"
 
-#: builtin/checkout.c:993
+#: builtin/checkout.c:1006
 msgid "paths cannot be used with switching branches"
-msgstr "Pfade können nicht beim Wechseln von Zweigen verwendet werden"
+msgstr "Pfade können nicht beim Wechseln von Branches verwendet werden"
 
-#: builtin/checkout.c:996 builtin/checkout.c:1000
+#: builtin/checkout.c:1009 builtin/checkout.c:1013
 #, c-format
 msgid "'%s' cannot be used with switching branches"
-msgstr "'%s' kann nicht beim Wechseln von Zweigen verwendet werden"
+msgstr "'%s' kann nicht beim Wechseln von Branches verwendet werden"
 
-#: builtin/checkout.c:1004 builtin/checkout.c:1007 builtin/checkout.c:1012
-#: builtin/checkout.c:1015
+#: builtin/checkout.c:1017 builtin/checkout.c:1020 builtin/checkout.c:1025
+#: builtin/checkout.c:1028
 #, c-format
 msgid "'%s' cannot be used with '%s'"
 msgstr "'%s' kann nicht mit '%s' verwendet werden"
 
-#: builtin/checkout.c:1020
+#: builtin/checkout.c:1033
 #, c-format
 msgid "Cannot switch branch to a non-commit '%s'"
-msgstr "Kann Zweig nicht zu Nicht-Version '%s' wechseln"
+msgstr "Kann Branch nicht zu Nicht-Commit '%s' wechseln"
 
-#: builtin/checkout.c:1042 builtin/checkout.c:1044 builtin/clone.c:90
+#: builtin/checkout.c:1055 builtin/checkout.c:1057 builtin/clone.c:89
 #: builtin/remote.c:169 builtin/remote.c:171
 msgid "branch"
-msgstr "Zweig"
+msgstr "Branch"
 
-#: builtin/checkout.c:1043
+#: builtin/checkout.c:1056
 msgid "create and checkout a new branch"
-msgstr "erzeugt und checkt einen neuen Zweig aus"
+msgstr "erzeugt und checkt einen neuen Branch aus"
 
-#: builtin/checkout.c:1045
+#: builtin/checkout.c:1058
 msgid "create/reset and checkout a branch"
-msgstr "erzeugt/setzt neu und checkt einen Zweig aus"
+msgstr "erzeugt/setzt um und checkt einen Branch aus"
 
-#: builtin/checkout.c:1046
+#: builtin/checkout.c:1059
 msgid "create reflog for new branch"
-msgstr "erzeugt Referenzprotokoll für den neuen Zweig"
+msgstr "erzeugt das Reflog für den neuen Branch"
 
-#: builtin/checkout.c:1047
+#: builtin/checkout.c:1060
 msgid "detach the HEAD at named commit"
-msgstr "setzt die Zweigspitze (HEAD) zu benannter Version"
+msgstr "setzt HEAD zu benanntem Commit"
 
-#: builtin/checkout.c:1048
+#: builtin/checkout.c:1061
 msgid "set upstream info for new branch"
-msgstr "setzt Informationen zum externen Übernahmezweig für den neuen Zweig"
+msgstr "setzt Informationen zum Upstream-Branch für den neuen Branch"
 
-#: builtin/checkout.c:1050
+#: builtin/checkout.c:1063
 msgid "new branch"
-msgstr "neuer Zweig"
+msgstr "neuer Branch"
 
-#: builtin/checkout.c:1050
+#: builtin/checkout.c:1063
 msgid "new unparented branch"
-msgstr "neuer Zweig ohne Elternversion"
+msgstr "neuer Branch ohne Eltern-Commit"
 
-#: builtin/checkout.c:1051
+#: builtin/checkout.c:1064
 msgid "checkout our version for unmerged files"
 msgstr "checkt unsere Variante für nicht zusammengeführte Dateien aus"
 
-#: builtin/checkout.c:1053
+#: builtin/checkout.c:1066
 msgid "checkout their version for unmerged files"
 msgstr "checkt ihre Variante für nicht zusammengeführte Dateien aus"
 
-#: builtin/checkout.c:1055
+#: builtin/checkout.c:1068
 msgid "force checkout (throw away local modifications)"
 msgstr "erzwingt Auschecken (verwirft lokale Änderungen)"
 
-#: builtin/checkout.c:1056
+#: builtin/checkout.c:1069
 msgid "perform a 3-way merge with the new branch"
-msgstr "führt eine 3-Wege-Zusammenführung mit dem neuen Zweig aus"
+msgstr "führt einen 3-Wege-Merge mit dem neuen Branch aus"
 
-#: builtin/checkout.c:1057 builtin/merge.c:217
+#: builtin/checkout.c:1070 builtin/merge.c:232
 msgid "update ignored files (default)"
 msgstr "aktualisiert ignorierte Dateien (Standard)"
 
-#: builtin/checkout.c:1058 builtin/log.c:1149 parse-options.h:245
+#: builtin/checkout.c:1071 builtin/log.c:1208 parse-options.h:249
 msgid "style"
 msgstr "Stil"
 
-#: builtin/checkout.c:1059
+#: builtin/checkout.c:1072
 msgid "conflict style (merge or diff3)"
 msgstr "Konfliktstil (merge oder diff3)"
 
-#: builtin/checkout.c:1062
+#: builtin/checkout.c:1075
+msgid "do not limit pathspecs to sparse entries only"
+msgstr "Pfadspezifikationen ignorieren Einstellungen zum partiellen Auschecken"
+
+#: builtin/checkout.c:1077
 msgid "second guess 'git checkout no-such-branch'"
 msgstr "second guess 'git checkout no-such-branch'"
 
-#: builtin/checkout.c:1086
+#: builtin/checkout.c:1101
 msgid "-b, -B and --orphan are mutually exclusive"
 msgstr "Die Optionen -b, -B und --orphan schließen sich gegenseitig aus."
 
-#: builtin/checkout.c:1103
+#: builtin/checkout.c:1118
 msgid "--track needs a branch name"
-msgstr "Bei der Option --track muss ein Zweigname angegeben werden."
+msgstr "Bei der Option --track muss ein Branchname angegeben werden."
 
-#: builtin/checkout.c:1110
+#: builtin/checkout.c:1125
 msgid "Missing branch name; try -b"
-msgstr "Vermisse Zweignamen; versuchen Sie -b"
+msgstr "Vermisse Branchnamen; versuchen Sie -b"
 
-#: builtin/checkout.c:1145
+#: builtin/checkout.c:1160
 msgid "invalid path specification"
 msgstr "ungültige Pfadspezifikation"
 
-#: builtin/checkout.c:1152
+#: builtin/checkout.c:1167
 #, c-format
 msgid ""
 "Cannot update paths and switch to branch '%s' at the same time.\n"
 "Did you intend to checkout '%s' which can not be resolved as commit?"
 msgstr ""
-"Kann nicht gleichzeitig Pfade aktualisieren und zu Zweig '%s' wechseln.\n"
-"Haben Sie beabsichtigt '%s' auszuchecken, welcher nicht als Version "
-"aufgelöst werden kann?"
+"Kann nicht gleichzeitig Pfade aktualisieren und zu Branch '%s' wechseln.\n"
+"Haben Sie beabsichtigt '%s' auszuchecken, welcher nicht als Commit aufgelöst "
+"werden kann?"
 
-#: builtin/checkout.c:1157
+#: builtin/checkout.c:1172
 #, c-format
 msgid "git checkout: --detach does not take a path argument '%s'"
 msgstr "git checkout: --detach nimmt kein Pfad-Argument '%s'"
 
-#: builtin/checkout.c:1161
+#: builtin/checkout.c:1176
 msgid ""
 "git checkout: --ours/--theirs, --force and --merge are incompatible when\n"
 "checking out of the index."
 msgstr ""
 "git checkout: --ours/--theirs, --force und --merge sind inkompatibel wenn\n"
-"Sie aus der Bereitstellung auschecken."
+"Sie aus der Staging-Area auschecken."
 
-#: builtin/clean.c:20
-msgid "git clean [-d] [-f] [-n] [-q] [-e <pattern>] [-x | -X] [--] <paths>..."
-msgstr "git clean [-d] [-f] [-n] [-q] [-e <Muster>] [-x | -X] [--] <Pfade>..."
+#: builtin/clean.c:25
+msgid ""
+"git clean [-d] [-f] [-i] [-n] [-q] [-e <pattern>] [-x | -X] [--] <paths>..."
+msgstr ""
+"git clean [-d] [-f] [-i] [-n] [-q] [-e <Muster>] [-x | -X] [--] <Pfade>..."
 
-#: builtin/clean.c:24
+#: builtin/clean.c:29
 #, c-format
 msgid "Removing %s\n"
 msgstr "Lösche %s\n"
 
-#: builtin/clean.c:25
+#: builtin/clean.c:30
 #, c-format
 msgid "Would remove %s\n"
 msgstr "Würde %s löschen\n"
 
-#: builtin/clean.c:26
+#: builtin/clean.c:31
 #, c-format
 msgid "Skipping repository %s\n"
-msgstr "Überspringe Projektarchiv %s\n"
+msgstr "Überspringe Repository %s\n"
 
-#: builtin/clean.c:27
+#: builtin/clean.c:32
 #, c-format
 msgid "Would skip repository %s\n"
-msgstr "Würde Projektarchiv %s überspringen\n"
+msgstr "Würde Repository %s überspringen\n"
 
-#: builtin/clean.c:28
+#: builtin/clean.c:33
 #, c-format
 msgid "failed to remove %s"
 msgstr "Fehler beim Löschen von %s"
 
-#: builtin/clean.c:160
+#: builtin/clean.c:293
+msgid ""
+"Prompt help:\n"
+"1          - select a numbered item\n"
+"foo        - select item based on unique prefix\n"
+"           - (empty) select nothing"
+msgstr ""
+"Eingabehilfe:\n"
+"1          - nummeriertes Element auswählen\n"
+"foo        - Element anhand eines eindeutigen Prefix auswählen\n"
+"           - (leer) nichts auswählen"
+
+#: builtin/clean.c:297
+msgid ""
+"Prompt help:\n"
+"1          - select a single item\n"
+"3-5        - select a range of items\n"
+"2-3,6-9    - select multiple ranges\n"
+"foo        - select item based on unique prefix\n"
+"-...       - unselect specified items\n"
+"*          - choose all items\n"
+"           - (empty) finish selecting"
+msgstr ""
+"Eingabehilfe:\n"
+"1          - einzelnes Element auswählen\n"
+"3-5        - Bereich von Elementen auswählen\n"
+"2-3,6-9    - mehrere Bereiche auswählen\n"
+"foo        - Element anhand eines eindeutigen Prefix auswählen\n"
+"-...       - angegebenes Element abwählen\n"
+"*          - alle Elemente auswählen\n"
+"           - (leer) Auswahl beenden"
+
+#: builtin/clean.c:515
+#, c-format
+msgid "Huh (%s)?"
+msgstr "Wie bitte (%s)?"
+
+#: builtin/clean.c:658
+#, c-format
+msgid "Input ignore patterns>> "
+msgstr "Ignorier-Muster eingeben>> "
+
+#: builtin/clean.c:695
+#, c-format
+msgid "WARNING: Cannot find items matched by: %s"
+msgstr "WARNUNG: Kann keine Einträge finden die Muster entsprechen: %s"
+
+#: builtin/clean.c:716
+msgid "Select items to delete"
+msgstr "Wählen Sie Einträge zum Löschen"
+
+#: builtin/clean.c:756
+#, c-format
+msgid "remove %s? "
+msgstr "'%s' löschen? "
+
+#: builtin/clean.c:781
+msgid "Bye."
+msgstr "Tschüss."
+
+#: builtin/clean.c:789
+msgid ""
+"clean               - start cleaning\n"
+"filter by pattern   - exclude items from deletion\n"
+"select by numbers   - select items to be deleted by numbers\n"
+"ask each            - confirm each deletion (like \"rm -i\")\n"
+"quit                - stop cleaning\n"
+"help                - this screen\n"
+"?                   - help for prompt selection"
+msgstr ""
+"clean               - Clean starten\n"
+"filter by pattern   - Einträge von Löschung ausschließen\n"
+"select by numbers   - Auswahl von Einträgen über Nummern\n"
+"ask each            - jede Löschung bestätigen (wie \"rm -i\")\n"
+"quit                - Clean beenden\n"
+"help                - diese Meldung anzeigen\n"
+"?                   - Hilfe zur Auswahl mittels Eingabe anzeigen"
+
+#: builtin/clean.c:816
+msgid "*** Commands ***"
+msgstr "*** Kommandos ***"
+
+#: builtin/clean.c:817
+msgid "What now"
+msgstr "Was nun"
+
+#: builtin/clean.c:825
+msgid "Would remove the following item:"
+msgid_plural "Would remove the following items:"
+msgstr[0] "Würde das folgende Element entfernen:"
+msgstr[1] "Würde die folgenden Elemente entfernen:"
+
+#: builtin/clean.c:842
+msgid "No more files to clean, exiting."
+msgstr "Keine Dateien mehr zum Löschen, beende."
+
+#: builtin/clean.c:874
 msgid "do not print names of files removed"
 msgstr "gibt keine Namen von gelöschten Dateien aus"
 
-#: builtin/clean.c:162
+#: builtin/clean.c:876
 msgid "force"
 msgstr "erzwingt Aktion"
 
-#: builtin/clean.c:164
+#: builtin/clean.c:877
+msgid "interactive cleaning"
+msgstr "interaktives Clean"
+
+#: builtin/clean.c:879
 msgid "remove whole directories"
 msgstr "löscht ganze Verzeichnisse"
 
-#: builtin/clean.c:165 builtin/describe.c:412 builtin/grep.c:717
-#: builtin/ls-files.c:494 builtin/name-rev.c:231 builtin/show-ref.c:182
+#: builtin/clean.c:880 builtin/describe.c:420 builtin/grep.c:716
+#: builtin/ls-files.c:493 builtin/name-rev.c:315 builtin/show-ref.c:186
 msgid "pattern"
 msgstr "Muster"
 
-#: builtin/clean.c:166
+#: builtin/clean.c:881
 msgid "add <pattern> to ignore rules"
 msgstr "fügt <Muster> zu den Regeln für ignorierte Pfade hinzu"
 
-#: builtin/clean.c:167
+#: builtin/clean.c:882
 msgid "remove ignored files, too"
 msgstr "löscht auch ignorierte Dateien"
 
-#: builtin/clean.c:169
+#: builtin/clean.c:884
 msgid "remove only ignored files"
 msgstr "löscht nur ignorierte Dateien"
 
-#: builtin/clean.c:187
+#: builtin/clean.c:902
 msgid "-x and -X cannot be used together"
 msgstr "Die Optionen -x und -X können nicht gemeinsam verwendet werden."
 
-#: builtin/clean.c:191
+#: builtin/clean.c:906
 msgid ""
-"clean.requireForce set to true and neither -n nor -f given; refusing to clean"
-msgstr ""
-"clean.requireForce auf \"true\" gesetzt und weder -n noch -f gegeben; "
-"Säuberung verweigert"
-
-#: builtin/clean.c:194
-msgid ""
-"clean.requireForce defaults to true and neither -n nor -f given; refusing to "
+"clean.requireForce set to true and neither -i, -n nor -f given; refusing to "
 "clean"
 msgstr ""
-"clean.requireForce standardmäßig auf \"true\" gesetzt und weder -n noch -f "
-"gegeben; Säuberung verweigert"
+"clean.requireForce auf \"true\" gesetzt und weder -i, -n noch -f gegeben; "
+"\"clean\" verweigert"
 
-#: builtin/clone.c:37
+#: builtin/clean.c:909
+msgid ""
+"clean.requireForce defaults to true and neither -i, -n nor -f given; "
+"refusing to clean"
+msgstr ""
+"clean.requireForce standardmäßig auf \"true\" gesetzt und weder -i, -n noch -"
+"f gegeben; \"clean\" verweigert"
+
+#: builtin/clone.c:36
 msgid "git clone [options] [--] <repo> [<dir>]"
-msgstr "git clone [Optionen] [--] <Projektarchiv> [<Verzeichnis>]"
+msgstr "git clone [Optionen] [--] <Repository> [<Verzeichnis>]"
 
-#: builtin/clone.c:65 builtin/fetch.c:82 builtin/merge.c:214
-#: builtin/push.c:436
+#: builtin/clone.c:64 builtin/fetch.c:82 builtin/merge.c:229
+#: builtin/push.c:462
 msgid "force progress reporting"
 msgstr "erzwingt Fortschrittsanzeige"
 
-#: builtin/clone.c:67
+#: builtin/clone.c:66
 msgid "don't create a checkout"
 msgstr "kein Auschecken"
 
-#: builtin/clone.c:68 builtin/clone.c:70 builtin/init-db.c:488
+#: builtin/clone.c:67 builtin/clone.c:69 builtin/init-db.c:488
 msgid "create a bare repository"
-msgstr "erstellt ein bloßes Projektarchiv"
+msgstr "erstellt ein Bare-Repository"
 
-#: builtin/clone.c:73
+#: builtin/clone.c:72
 msgid "create a mirror repository (implies bare)"
-msgstr "erstellt ein Spiegelarchiv (impliziert bloßes Projektarchiv)"
+msgstr "erstellt ein Spiegelarchiv (impliziert --bare)"
 
-#: builtin/clone.c:75
+#: builtin/clone.c:74
 msgid "to clone from a local repository"
-msgstr "um von einem lokalen Projektarchiv zu klonen"
+msgstr "um von einem lokalen Repository zu klonen"
 
-#: builtin/clone.c:77
+#: builtin/clone.c:76
 msgid "don't use local hardlinks, always copy"
-msgstr "verwendet lokal keine harten Links, immer Kopien"
+msgstr "verwendet lokal keine harten Verweise, immer Kopien"
 
-#: builtin/clone.c:79
+#: builtin/clone.c:78
 msgid "setup as shared repository"
-msgstr "Einrichtung als verteiltes Projektarchiv"
+msgstr "Einrichtung als verteiltes Repository"
 
-#: builtin/clone.c:81 builtin/clone.c:83
+#: builtin/clone.c:80 builtin/clone.c:82
 msgid "initialize submodules in the clone"
-msgstr "initialisiert Unterprojekte im Klon"
+msgstr "initialisiert Submodule im Klon"
 
-#: builtin/clone.c:84 builtin/init-db.c:485
+#: builtin/clone.c:83 builtin/init-db.c:485
 msgid "template-directory"
 msgstr "Vorlagenverzeichnis"
 
-#: builtin/clone.c:85 builtin/init-db.c:486
+#: builtin/clone.c:84 builtin/init-db.c:486
 msgid "directory from which templates will be used"
 msgstr "Verzeichnis, von welchem die Vorlagen verwendet werden"
 
-#: builtin/clone.c:87
+#: builtin/clone.c:86
 msgid "reference repository"
-msgstr "referenziert Projektarchiv"
+msgstr "referenziert Repository"
 
-#: builtin/clone.c:88 builtin/column.c:26 builtin/merge-file.c:44
+#: builtin/clone.c:87 builtin/column.c:26 builtin/merge-file.c:44
 msgid "name"
 msgstr "Name"
 
-#: builtin/clone.c:89
+#: builtin/clone.c:88
 msgid "use <name> instead of 'origin' to track upstream"
-msgstr "verwendet <Name> statt 'origin' für externes Projektarchiv"
+msgstr "verwendet <Name> statt 'origin' für Upstream-Repository"
 
-#: builtin/clone.c:91
+#: builtin/clone.c:90
 msgid "checkout <branch> instead of the remote's HEAD"
-msgstr ""
-"checkt <Zweig> aus, anstatt Zweigspitze (HEAD) des externen Projektarchivs"
+msgstr "checkt <Branch> aus, anstatt HEAD des Remote-Repositories"
 
-#: builtin/clone.c:93
+#: builtin/clone.c:92
 msgid "path to git-upload-pack on the remote"
 msgstr "Pfad zu \"git-upload-pack\" auf der Gegenseite"
 
-#: builtin/clone.c:94 builtin/fetch.c:83 builtin/grep.c:662
+#: builtin/clone.c:93 builtin/fetch.c:83 builtin/grep.c:661
 msgid "depth"
 msgstr "Tiefe"
 
-#: builtin/clone.c:95
+#: builtin/clone.c:94
 msgid "create a shallow clone of that depth"
 msgstr "erstellt einen flachen Klon mit dieser Tiefe"
 
-#: builtin/clone.c:97
+#: builtin/clone.c:96
 msgid "clone only one branch, HEAD or --branch"
-msgstr "klont nur einen Zweig, Zweigspitze (HEAD) oder --branch"
+msgstr "klont nur einen Branch, HEAD oder --branch"
 
-#: builtin/clone.c:98 builtin/init-db.c:494
+#: builtin/clone.c:97 builtin/init-db.c:494
 msgid "gitdir"
 msgstr ".git-Verzeichnis"
 
-#: builtin/clone.c:99 builtin/init-db.c:495
+#: builtin/clone.c:98 builtin/init-db.c:495
 msgid "separate git dir from working tree"
-msgstr "separiert Git-Verzeichnis vom Arbeitsbaum"
+msgstr "separiert Git-Verzeichnis vom Arbeitsverzeichnis"
 
-#: builtin/clone.c:100
+#: builtin/clone.c:99
 msgid "key=value"
 msgstr "Schlüssel=Wert"
 
-#: builtin/clone.c:101
+#: builtin/clone.c:100
 msgid "set config inside the new repository"
-msgstr "setzt Konfiguration innerhalb des neuen Projektarchivs"
+msgstr "setzt Konfiguration innerhalb des neuen Repositories"
 
-#: builtin/clone.c:244
+#: builtin/clone.c:253
 #, c-format
-msgid "reference repository '%s' is not a local directory."
-msgstr "Referenziertes Projektarchiv '%s' ist kein lokales Verzeichnis."
+msgid "reference repository '%s' is not a local repository."
+msgstr "Referenziertes Repository '%s' ist kein lokales Repository."
 
-#: builtin/clone.c:307
+#: builtin/clone.c:316
 #, c-format
 msgid "failed to create directory '%s'"
 msgstr "Fehler beim Erstellen von Verzeichnis '%s'"
 
-#: builtin/clone.c:309 builtin/diff.c:77
+#: builtin/clone.c:318 builtin/diff.c:77
 #, c-format
 msgid "failed to stat '%s'"
 msgstr "Konnte '%s' nicht lesen"
 
-#: builtin/clone.c:311
+#: builtin/clone.c:320
 #, c-format
 msgid "%s exists and is not a directory"
 msgstr "%s existiert und ist kein Verzeichnis"
 
-#: builtin/clone.c:325
+#: builtin/clone.c:334
 #, c-format
 msgid "failed to stat %s\n"
 msgstr "Konnte %s nicht lesen\n"
 
-#: builtin/clone.c:347
+#: builtin/clone.c:356
 #, c-format
 msgid "failed to create link '%s'"
-msgstr "Konnte Verknüpfung '%s' nicht erstellen"
+msgstr "Konnte Verweis '%s' nicht erstellen"
 
-#: builtin/clone.c:351
+#: builtin/clone.c:360
 #, c-format
 msgid "failed to copy file to '%s'"
 msgstr "Konnte Datei nicht nach '%s' kopieren"
 
-#: builtin/clone.c:374
+#: builtin/clone.c:383
 #, c-format
 msgid "done.\n"
 msgstr "Fertig.\n"
 
-#: builtin/clone.c:387
+#: builtin/clone.c:396
 msgid ""
 "Clone succeeded, but checkout failed.\n"
 "You can inspect what was checked out with 'git status'\n"
@@ -3477,96 +3819,110 @@
 "Sie können mit 'git status' prüfen, was ausgecheckt worden ist\n"
 "und das Auschecken mit 'git checkout -f HEAD' erneut versuchen.\n"
 
-#: builtin/clone.c:466
+#: builtin/clone.c:475
 #, c-format
 msgid "Could not find remote branch %s to clone."
-msgstr "Konnte zu klonenden externer Zweig %s nicht finden."
+msgstr "Konnte zu klonenden Remote-Branch %s nicht finden."
 
-#: builtin/clone.c:540
+#: builtin/clone.c:555
+#, c-format
+msgid "Checking connectivity... "
+msgstr "Prüfe Konnektivität... "
+
+#: builtin/clone.c:558
 msgid "remote did not send all necessary objects"
-msgstr "Fernarchiv hat nicht alle erforderlichen Objekte gesendet."
+msgstr "Remote-Repository hat nicht alle erforderlichen Objekte gesendet."
 
-#: builtin/clone.c:600
+#: builtin/clone.c:560
+#, c-format
+msgid "done\n"
+msgstr "Fertig\n"
+
+#: builtin/clone.c:621
 msgid "remote HEAD refers to nonexistent ref, unable to checkout.\n"
 msgstr ""
-"Externe Zweigspitze (HEAD) bezieht sich auf eine nicht existierende Referenz "
-"und kann nicht ausgecheckt werden.\n"
+"Externer HEAD bezieht sich auf eine nicht existierende Referenz und kann "
+"nicht ausgecheckt werden.\n"
 
-#: builtin/clone.c:631
+#: builtin/clone.c:652
 msgid "unable to checkout working tree"
-msgstr "Arbeitsbaum konnte nicht ausgecheckt werden"
+msgstr "Arbeitsverzeichnis konnte nicht ausgecheckt werden"
 
-#: builtin/clone.c:739
+#: builtin/clone.c:760
 msgid "Too many arguments."
 msgstr "Zu viele Argumente."
 
-#: builtin/clone.c:743
+#: builtin/clone.c:764
 msgid "You must specify a repository to clone."
-msgstr "Sie müssen ein Projektarchiv zum Klonen angeben."
+msgstr "Sie müssen ein Repository zum Klonen angeben."
 
-#: builtin/clone.c:754
+#: builtin/clone.c:775
 #, c-format
 msgid "--bare and --origin %s options are incompatible."
 msgstr "Die Optionen --bare und --origin %s sind inkompatibel."
 
-#: builtin/clone.c:757
+#: builtin/clone.c:778
 msgid "--bare and --separate-git-dir are incompatible."
 msgstr "Die Optionen --bare und --separate-git-dir sind inkompatibel."
 
-#: builtin/clone.c:770
+#: builtin/clone.c:791
 #, c-format
 msgid "repository '%s' does not exist"
-msgstr "Projektarchiv '%s' existiert nicht."
+msgstr "Repository '%s' existiert nicht."
 
-#: builtin/clone.c:775
+#: builtin/clone.c:796
 msgid "--depth is ignored in local clones; use file:// instead."
 msgstr ""
 "Die Option --depth wird in lokalen Klonen ignoriert; benutzen Sie "
 "stattdessen file://"
 
-#: builtin/clone.c:785
+#: builtin/clone.c:798
+msgid "--local is ignored"
+msgstr "--local wird ignoriert"
+
+#: builtin/clone.c:808
 #, c-format
 msgid "destination path '%s' already exists and is not an empty directory."
 msgstr "Zielpfad '%s' existiert bereits und ist kein leeres Verzeichnis."
 
-#: builtin/clone.c:795
+#: builtin/clone.c:818
 #, c-format
 msgid "working tree '%s' already exists."
-msgstr "Arbeitsbaum '%s' existiert bereits."
+msgstr "Arbeitsverzeichnis '%s' existiert bereits."
 
-#: builtin/clone.c:808 builtin/clone.c:820
+#: builtin/clone.c:831 builtin/clone.c:843
 #, c-format
 msgid "could not create leading directories of '%s'"
 msgstr "Konnte führende Verzeichnisse von '%s' nicht erstellen."
 
-#: builtin/clone.c:811
+#: builtin/clone.c:834
 #, c-format
 msgid "could not create work tree dir '%s'."
 msgstr "Konnte Arbeitsverzeichnis '%s' nicht erstellen."
 
-#: builtin/clone.c:830
+#: builtin/clone.c:853
 #, c-format
 msgid "Cloning into bare repository '%s'...\n"
-msgstr "Klone in bloßes Projektarchiv '%s'...\n"
+msgstr "Klone in Bare-Repository '%s'...\n"
 
-#: builtin/clone.c:832
+#: builtin/clone.c:855
 #, c-format
 msgid "Cloning into '%s'...\n"
 msgstr "Klone nach '%s'...\n"
 
-#: builtin/clone.c:867
+#: builtin/clone.c:890
 #, c-format
 msgid "Don't know how to clone %s"
 msgstr "Weiß nicht wie %s zu klonen ist."
 
-#: builtin/clone.c:916
+#: builtin/clone.c:942
 #, c-format
 msgid "Remote branch %s not found in upstream %s"
-msgstr "externer Zweig %s nicht im anderen Projektarchiv %s gefunden"
+msgstr "Remote-Branch %s nicht im Upstream-Repository %s gefunden"
 
-#: builtin/clone.c:923
+#: builtin/clone.c:949
 msgid "You appear to have cloned an empty repository."
-msgstr "Sie scheinen ein leeres Projektarchiv geklont zu haben."
+msgstr "Sie scheinen ein leeres Repository geklont zu haben."
 
 #: builtin/column.c:9
 msgid "git column [options]"
@@ -3600,15 +3956,15 @@
 msgid "--command must be the first argument"
 msgstr "Die Option --command muss an erster Stelle stehen."
 
-#: builtin/commit.c:34
+#: builtin/commit.c:35
 msgid "git commit [options] [--] <pathspec>..."
 msgstr "git commit [Optionen] [--] <Pfadspezifikation>..."
 
-#: builtin/commit.c:39
+#: builtin/commit.c:40
 msgid "git status [options] [--] <pathspec>..."
 msgstr "git status [Optionen] [--] <Pfadspezifikation>..."
 
-#: builtin/commit.c:44
+#: builtin/commit.c:45
 msgid ""
 "Your name and email address were configured automatically based\n"
 "on your username and hostname. Please check that they are accurate.\n"
@@ -3629,129 +3985,144 @@
 "    git config --global user.name \"Ihr Name\"\n"
 "    git config --global user.email ihre@emailadresse.de\n"
 "\n"
-"Nachdem Sie das getan hast, können Sie Ihre Identität für diese Version "
+"Nachdem Sie das getan hast, können Sie Ihre Identität für diesen Commit "
 "ändern mit:\n"
 "\n"
 "    git commit --amend --reset-author\n"
 
-#: builtin/commit.c:56
+#: builtin/commit.c:57
 msgid ""
 "You asked to amend the most recent commit, but doing so would make\n"
 "it empty. You can repeat your command with --allow-empty, or you can\n"
 "remove the commit entirely with \"git reset HEAD^\".\n"
 msgstr ""
-"Sie fragten die jüngste Version nachzubessern, aber das würde diese leer\n"
-"machen. Sie können Ihr Kommando mit --allow-empty wiederholen, oder die\n"
-"Version mit \"git reset HEAD^\" vollständig entfernen.\n"
+"Sie fragten den jüngsten Commit nachzubessern, aber das würde diesen leer\n"
+"machen. Sie können Ihr Kommando mit --allow-empty wiederholen, oder diesen\n"
+"Commit mit \"git reset HEAD^\" vollständig entfernen.\n"
 
-#: builtin/commit.c:61
+#: builtin/commit.c:62
 msgid ""
 "The previous cherry-pick is now empty, possibly due to conflict resolution.\n"
 "If you wish to commit it anyway, use:\n"
 "\n"
 "    git commit --allow-empty\n"
 "\n"
-"Otherwise, please use 'git reset'\n"
 msgstr ""
 "Der letzte \"cherry-pick\" ist jetzt leer, möglicherweise durch eine "
 "Konfliktauflösung.\n"
-"Wenn Sie dies trotzdem eintragen wollen, benutzen Sie:\n"
+"Wenn Sie dies trotzdem committen wollen, benutzen Sie:\n"
 "\n"
 "    git commit --allow-empty\n"
 "\n"
-"Andernfalls benutzen Sie bitte 'git reset'\n"
 
-#: builtin/commit.c:260
+#: builtin/commit.c:69
+msgid "Otherwise, please use 'git reset'\n"
+msgstr "Andernfalls benutzen Sie bitte 'git reset'\n"
+
+#: builtin/commit.c:72
+msgid ""
+"If you wish to skip this commit, use:\n"
+"\n"
+"    git reset\n"
+"\n"
+"Then \"git cherry-pick --continue\" will resume cherry-picking\n"
+"the remaining commits.\n"
+msgstr ""
+"Wenn Sie diesen Commit auslassen möchten, benutzen Sie:\n"
+"\n"
+"    git reset\n"
+"\n"
+"Benutzen Sie anschließend \"git cherry-pick --continue\", um die\n"
+"Cherry-Pick-Operation mit den verbleibenden Commits fortzusetzen.\n"
+
+#: builtin/commit.c:279
 msgid "failed to unpack HEAD tree object"
-msgstr "Fehler beim Entpacken des Baum-Objektes der Zweigspitze (HEAD)."
+msgstr "Fehler beim Entpacken des \"Tree\"-Objektes von HEAD."
 
-#: builtin/commit.c:302
+#: builtin/commit.c:321
 msgid "unable to create temporary index"
-msgstr "Konnte temporäre Bereitstellung nicht erstellen."
+msgstr "Konnte temporäre Staging-Area nicht erstellen."
 
-#: builtin/commit.c:308
+#: builtin/commit.c:327
 msgid "interactive add failed"
 msgstr "interaktives Hinzufügen fehlgeschlagen"
 
-#: builtin/commit.c:341 builtin/commit.c:362 builtin/commit.c:412
+#: builtin/commit.c:360 builtin/commit.c:381 builtin/commit.c:431
 msgid "unable to write new_index file"
 msgstr "Konnte new_index Datei nicht schreiben"
 
-#: builtin/commit.c:393
+#: builtin/commit.c:412
 msgid "cannot do a partial commit during a merge."
-msgstr ""
-"Kann keine partielle Eintragung durchführen, während eine Zusammenführung im "
-"Gange ist."
+msgstr "Kann keinen Teil-Commit durchführen, während ein Merge im Gange ist."
 
-#: builtin/commit.c:395
+#: builtin/commit.c:414
 msgid "cannot do a partial commit during a cherry-pick."
 msgstr ""
-"Kann keine partielle Eintragung durchführen, während \"cherry-pick\" im "
-"Gange ist."
+"Kann keinen Teil-Commit durchführen, während \"cherry-pick\" im Gange ist."
 
-#: builtin/commit.c:405
+#: builtin/commit.c:424
 msgid "cannot read the index"
-msgstr "Kann Bereitstellung nicht lesen"
+msgstr "Kann Staging-Area nicht lesen"
 
-#: builtin/commit.c:425
+#: builtin/commit.c:444
 msgid "unable to write temporary index file"
-msgstr "Konnte temporäre Bereitstellungsdatei nicht schreiben."
+msgstr "Konnte temporäre Staging-Area-Datei nicht schreiben."
 
-#: builtin/commit.c:513 builtin/commit.c:519
+#: builtin/commit.c:535 builtin/commit.c:541
 #, c-format
 msgid "invalid commit: %s"
-msgstr "Ungültige Version: %s"
+msgstr "Ungültiger Commit: %s"
 
-#: builtin/commit.c:542
+#: builtin/commit.c:563
 msgid "malformed --author parameter"
 msgstr "Fehlerhafter --author Parameter"
 
-#: builtin/commit.c:562
+#: builtin/commit.c:583
 #, c-format
 msgid "Malformed ident string: '%s'"
-msgstr "Fehlerhafte Identifikations-String: '%s'"
+msgstr "Fehlerhafter Ident-String: '%s'"
 
-#: builtin/commit.c:600 builtin/commit.c:633 builtin/commit.c:956
+#: builtin/commit.c:621 builtin/commit.c:654 builtin/commit.c:982
 #, c-format
 msgid "could not lookup commit %s"
-msgstr "Konnte Version %s nicht nachschlagen"
+msgstr "Konnte Commit %s nicht nachschlagen"
 
-#: builtin/commit.c:612 builtin/shortlog.c:272
+#: builtin/commit.c:633 builtin/shortlog.c:271
 #, c-format
 msgid "(reading log message from standard input)\n"
 msgstr "(lese Log-Nachricht von Standard-Eingabe)\n"
 
-#: builtin/commit.c:614
+#: builtin/commit.c:635
 msgid "could not read log from standard input"
 msgstr "Konnte Log nicht von Standard-Eingabe lesen."
 
-#: builtin/commit.c:618
+#: builtin/commit.c:639
 #, c-format
 msgid "could not read log file '%s'"
 msgstr "Konnte Log-Datei '%s' nicht lesen"
 
-#: builtin/commit.c:624
+#: builtin/commit.c:645
 msgid "commit has empty message"
-msgstr "Version hat eine leere Beschreibung"
+msgstr "Commit hat eine leere Beschreibung"
 
-#: builtin/commit.c:640
+#: builtin/commit.c:661
 msgid "could not read MERGE_MSG"
 msgstr "Konnte MERGE_MSG nicht lesen"
 
-#: builtin/commit.c:644
+#: builtin/commit.c:665
 msgid "could not read SQUASH_MSG"
 msgstr "Konnte SQUASH_MSG nicht lesen"
 
-#: builtin/commit.c:648
+#: builtin/commit.c:669
 #, c-format
 msgid "could not read '%s'"
 msgstr "Konnte '%s' nicht lesen"
 
-#: builtin/commit.c:709
+#: builtin/commit.c:730
 msgid "could not write commit template"
-msgstr "Konnte Versionsvorlage nicht schreiben"
+msgstr "Konnte Commit-Vorlage nicht schreiben"
 
-#: builtin/commit.c:720
+#: builtin/commit.c:741
 #, c-format
 msgid ""
 "\n"
@@ -3761,12 +4132,12 @@
 "and try again.\n"
 msgstr ""
 "\n"
-"Es sieht so aus, als tragen Sie eine Zusammenführung ein.\n"
+"Es sieht so aus, als committen Sie einen Merge.\n"
 "Falls das nicht korrekt ist, löschen Sie bitte die Datei\n"
 "\t%s\n"
 "und versuchen Sie es erneut.\n"
 
-#: builtin/commit.c:725
+#: builtin/commit.c:746
 #, c-format
 msgid ""
 "\n"
@@ -3776,406 +4147,406 @@
 "and try again.\n"
 msgstr ""
 "\n"
-"Es sieht so aus, als tragen Sie ein \"cherry-pick\" ein.\n"
+"Es sieht so aus, als committen Sie einen \"cherry-pick\".\n"
 "Falls das nicht korrekt ist, löschen Sie bitte die Datei\n"
 "\t%s\n"
 "und versuchen Sie es erneut.\n"
 
-#: builtin/commit.c:737
+#: builtin/commit.c:758
 #, c-format
 msgid ""
 "Please enter the commit message for your changes. Lines starting\n"
 "with '%c' will be ignored, and an empty message aborts the commit.\n"
 msgstr ""
-"Bitte geben Sie eine Versionsbeschreibung für Ihre Änderungen ein. Zeilen,\n"
-"die mit '%c' beginnen, werden ignoriert, und eine leere "
-"Versionsbeschreibung\n"
-"bricht die Eintragung ab.\n"
+"Bitte geben Sie eine Commit-Beschreibung für Ihre Änderungen ein. Zeilen,\n"
+"die mit '%c' beginnen, werden ignoriert, und eine leere Beschreibung\n"
+"bricht den Commit ab.\n"
 
-#: builtin/commit.c:742
+#: builtin/commit.c:763
 #, c-format
 msgid ""
 "Please enter the commit message for your changes. Lines starting\n"
 "with '%c' will be kept; you may remove them yourself if you want to.\n"
 "An empty message aborts the commit.\n"
 msgstr ""
-"Bitte geben Sie eine Versionsbeschreibung für Ihre Änderungen ein. Zeilen, "
+"Bitte geben Sie eine Commit-Beschreibung für Ihre Änderungen ein. Zeilen, "
 "die\n"
 "mit '%c' beginnen, werden beibehalten; wenn Sie möchten, können Sie diese "
 "entfernen.\n"
-"Eine leere Versionsbeschreibung bricht die Eintragung ab.\n"
+"Eine leere Beschreibung bricht den Commit ab.\n"
 
-#: builtin/commit.c:755
+#: builtin/commit.c:776
 #, c-format
 msgid "%sAuthor:    %s"
 msgstr "%sAutor:    %s"
 
-#: builtin/commit.c:762
+#: builtin/commit.c:783
 #, c-format
 msgid "%sCommitter: %s"
-msgstr "%sEintragender: %s"
+msgstr "%sCommit-Ersteller: %s"
 
-#: builtin/commit.c:782
+#: builtin/commit.c:803
 msgid "Cannot read index"
-msgstr "Kann Bereitstellung nicht lesen"
+msgstr "Kann Staging-Area nicht lesen"
 
-#: builtin/commit.c:819
+#: builtin/commit.c:845
 msgid "Error building trees"
-msgstr "Fehler beim Erzeugen der Zweige"
+msgstr "Fehler beim Erzeugen der \"Tree\"-Objekte"
 
-#: builtin/commit.c:834 builtin/tag.c:359
+#: builtin/commit.c:860 builtin/tag.c:359
 #, c-format
 msgid "Please supply the message using either -m or -F option.\n"
-msgstr "Bitte liefere eine Beschreibung entweder mit der Option -m oder -F.\n"
+msgstr ""
+"Bitte liefern Sie eine Beschreibung entweder mit der Option -m oder -F.\n"
 
-#: builtin/commit.c:931
+#: builtin/commit.c:957
 #, c-format
 msgid "No existing author found with '%s'"
 msgstr "Kein existierender Autor mit '%s' gefunden."
 
-#: builtin/commit.c:946 builtin/commit.c:1140
+#: builtin/commit.c:972 builtin/commit.c:1208
 #, c-format
 msgid "Invalid untracked files mode '%s'"
 msgstr "Ungültiger Modus '%s' für unbeobachtete Dateien"
 
-#: builtin/commit.c:976
+#: builtin/commit.c:1009
+msgid "--long and -z are incompatible"
+msgstr "Die Optionen --long und -z sind inkompatibel."
+
+#: builtin/commit.c:1039
 msgid "Using both --reset-author and --author does not make sense"
 msgstr ""
 "Die Optionen --reset-author und --author können nicht gemeinsam verwendet "
 "werden."
 
-#: builtin/commit.c:987
+#: builtin/commit.c:1050
 msgid "You have nothing to amend."
-msgstr "Sie haben nichts zum nachbessern."
+msgstr "Sie haben nichts für \"--amend\"."
 
-#: builtin/commit.c:990
+#: builtin/commit.c:1053
 msgid "You are in the middle of a merge -- cannot amend."
-msgstr "Eine Zusammenführung ist im Gange -- kann nicht nachbessern."
+msgstr "Ein Merge ist im Gange -- kann \"--amend\" nicht ausführen."
 
-#: builtin/commit.c:992
+#: builtin/commit.c:1055
 msgid "You are in the middle of a cherry-pick -- cannot amend."
-msgstr "\"cherry-pick\" ist im Gange -- kann nicht nachbessern."
+msgstr "\"cherry-pick\" ist im Gange -- kann \"--amend\" nicht ausführen."
 
-#: builtin/commit.c:995
+#: builtin/commit.c:1058
 msgid "Options --squash and --fixup cannot be used together"
 msgstr ""
 "Die Optionen --squash und --fixup können nicht gemeinsam verwendet werden."
 
-#: builtin/commit.c:1005
+#: builtin/commit.c:1068
 msgid "Only one of -c/-C/-F/--fixup can be used."
 msgstr "Es kann nur eine Option von -c/-C/-F/--fixup verwendet werden."
 
-#: builtin/commit.c:1007
+#: builtin/commit.c:1070
 msgid "Option -m cannot be combined with -c/-C/-F/--fixup."
 msgstr "Die Option -m kann nicht mit -c/-C/-F/--fixup kombiniert werden."
 
-#: builtin/commit.c:1015
+#: builtin/commit.c:1078
 msgid "--reset-author can be used only with -C, -c or --amend."
 msgstr ""
 "Die Option --reset--author kann nur mit -C, -c oder --amend verwendet werden."
 
-#: builtin/commit.c:1032
+#: builtin/commit.c:1095
 msgid "Only one of --include/--only/--all/--interactive/--patch can be used."
 msgstr ""
 "Es kann nur eine Option von --include/--only/--all/--interactive/--patch "
 "verwendet werden."
 
-#: builtin/commit.c:1034
+#: builtin/commit.c:1097
 msgid "No paths with --include/--only does not make sense."
 msgstr ""
 "Die Optionen --include und --only können nur mit der Angabe von Pfaden "
 "verwendet werden."
 
-#: builtin/commit.c:1036
+#: builtin/commit.c:1099
 msgid "Clever... amending the last one with dirty index."
 msgstr ""
-"Klug... die letzte Version mit einer unsauberen Bereitstellung nachbessern."
+"Klug... den letzten Commit mit einer geänderten Staging-Area nachbessern."
 
-#: builtin/commit.c:1038
+#: builtin/commit.c:1101
 msgid "Explicit paths specified without -i nor -o; assuming --only paths..."
 msgstr ""
 "Explizite Pfade ohne -i oder -o angegeben; unter der Annahme von --only "
 "Pfaden..."
 
-#: builtin/commit.c:1048 builtin/tag.c:575
+#: builtin/commit.c:1111 builtin/tag.c:575
 #, c-format
 msgid "Invalid cleanup mode %s"
 msgstr "Ungültiger \"cleanup\" Modus %s"
 
-#: builtin/commit.c:1053
+#: builtin/commit.c:1116
 msgid "Paths with -a does not make sense."
 msgstr "Die Option -a kann nur mit der Angabe von Pfaden verwendet werden."
 
-#: builtin/commit.c:1059 builtin/commit.c:1194
-msgid "--long and -z are incompatible"
-msgstr "Die Optionen --long und -z sind inkompatibel."
-
-#: builtin/commit.c:1154 builtin/commit.c:1390
+#: builtin/commit.c:1222 builtin/commit.c:1455
 msgid "show status concisely"
 msgstr "zeigt Status im Kurzformat"
 
-#: builtin/commit.c:1156 builtin/commit.c:1392
+#: builtin/commit.c:1224 builtin/commit.c:1457
 msgid "show branch information"
-msgstr "zeigt Zweiginformationen"
+msgstr "zeigt Branchinformationen"
 
-#: builtin/commit.c:1158 builtin/commit.c:1394 builtin/push.c:426
+#: builtin/commit.c:1226 builtin/commit.c:1459 builtin/push.c:452
 msgid "machine-readable output"
 msgstr "maschinenlesbare Ausgabe"
 
-#: builtin/commit.c:1161 builtin/commit.c:1396
+#: builtin/commit.c:1229 builtin/commit.c:1461
 msgid "show status in long format (default)"
 msgstr "zeigt Status im Langformat (Standard)"
 
-#: builtin/commit.c:1164 builtin/commit.c:1399
+#: builtin/commit.c:1232 builtin/commit.c:1464
 msgid "terminate entries with NUL"
 msgstr "schließt Einträge mit NUL-Zeichen ab"
 
-#: builtin/commit.c:1166 builtin/commit.c:1402 builtin/fast-export.c:653
-#: builtin/fast-export.c:656 builtin/tag.c:459
+#: builtin/commit.c:1234 builtin/commit.c:1467 builtin/fast-export.c:667
+#: builtin/fast-export.c:670 builtin/tag.c:459
 msgid "mode"
 msgstr "Modus"
 
-#: builtin/commit.c:1167 builtin/commit.c:1402
+#: builtin/commit.c:1235 builtin/commit.c:1467
 msgid "show untracked files, optional modes: all, normal, no. (Default: all)"
 msgstr ""
 "zeigt nicht beobachtete Dateien, optionale Modi: all, normal, no. (Standard: "
 "all)"
 
-#: builtin/commit.c:1170
+#: builtin/commit.c:1238
 msgid "show ignored files"
 msgstr "zeigt ignorierte Dateien"
 
-#: builtin/commit.c:1171 parse-options.h:151
+#: builtin/commit.c:1239 parse-options.h:154
 msgid "when"
 msgstr "wann"
 
-#: builtin/commit.c:1172
+#: builtin/commit.c:1240
 msgid ""
 "ignore changes to submodules, optional when: all, dirty, untracked. "
 "(Default: all)"
 msgstr ""
-"ignoriert Änderungen in Unterprojekten, optional wenn: all, dirty, "
-"untracked. (Standard: all)"
+"ignoriert Änderungen in Submodulen, optional wenn: all, dirty, untracked. "
+"(Standard: all)"
 
-#: builtin/commit.c:1174
+#: builtin/commit.c:1242
 msgid "list untracked files in columns"
 msgstr "listet unbeobachtete Dateien in Spalten auf"
 
-#: builtin/commit.c:1248
+#: builtin/commit.c:1313
 msgid "couldn't look up newly created commit"
-msgstr "Konnte neu erstellte Version nicht nachschlagen."
+msgstr "Konnte neu erstellten Commit nicht nachschlagen."
 
-#: builtin/commit.c:1250
+#: builtin/commit.c:1315
 msgid "could not parse newly created commit"
-msgstr "Konnte neulich erstellte Version nicht analysieren."
+msgstr "Konnte neulich erstellten Commit nicht analysieren."
 
-#: builtin/commit.c:1291
+#: builtin/commit.c:1356
 msgid "detached HEAD"
-msgstr "losgelöste Zweigspitze (HEAD)"
+msgstr "losgelöster HEAD"
 
-#: builtin/commit.c:1293
+#: builtin/commit.c:1358
 msgid " (root-commit)"
-msgstr " (Basis-Version)"
+msgstr " (Basis-Commit)"
 
-#: builtin/commit.c:1360
+#: builtin/commit.c:1425
 msgid "suppress summary after successful commit"
-msgstr "unterdrückt Zusammenfassung nach erfolgreicher Eintragung"
+msgstr "unterdrückt Zusammenfassung nach erfolgreichem Commit"
 
-#: builtin/commit.c:1361
+#: builtin/commit.c:1426
 msgid "show diff in commit message template"
-msgstr "zeigt Unterschiede in Versionsbeschreibungsvorlage an"
+msgstr "zeigt Unterschiede in Commit-Beschreibungsvorlage an"
 
-#: builtin/commit.c:1363
+#: builtin/commit.c:1428
 msgid "Commit message options"
-msgstr "Optionen für Versionsbeschreibung"
+msgstr "Optionen für Commit-Beschreibung"
 
-#: builtin/commit.c:1364 builtin/tag.c:457
+#: builtin/commit.c:1429 builtin/tag.c:457
 msgid "read message from file"
 msgstr "liest Beschreibung von Datei"
 
-#: builtin/commit.c:1365
+#: builtin/commit.c:1430
 msgid "author"
 msgstr "Autor"
 
-#: builtin/commit.c:1365
+#: builtin/commit.c:1430
 msgid "override author for commit"
-msgstr "überschreibt Autor von Version"
+msgstr "überschreibt Autor eines Commits"
 
-#: builtin/commit.c:1366 builtin/gc.c:178
+#: builtin/commit.c:1431 builtin/gc.c:178
 msgid "date"
 msgstr "Datum"
 
-#: builtin/commit.c:1366
+#: builtin/commit.c:1431
 msgid "override date for commit"
-msgstr "überschreibt Datum von Version"
+msgstr "überschreibt Datum eines Commits"
 
-#: builtin/commit.c:1367 builtin/merge.c:208 builtin/notes.c:533
-#: builtin/notes.c:690 builtin/tag.c:455
+#: builtin/commit.c:1432 builtin/merge.c:223 builtin/notes.c:405
+#: builtin/notes.c:562 builtin/tag.c:455
 msgid "message"
 msgstr "Beschreibung"
 
-#: builtin/commit.c:1367
+#: builtin/commit.c:1432
 msgid "commit message"
-msgstr "Versionsbeschreibung"
+msgstr "Commit-Beschreibung"
 
-#: builtin/commit.c:1368
+#: builtin/commit.c:1433
 msgid "reuse and edit message from specified commit"
-msgstr "verwendet wieder und editiert Beschreibung von der angegebenen Version"
+msgstr "verwendet wieder und editiert Beschreibung des angegebenen Commits"
 
-#: builtin/commit.c:1369
+#: builtin/commit.c:1434
 msgid "reuse message from specified commit"
-msgstr "verwendet Beschreibung der angegebenen Version wieder"
+msgstr "verwendet Beschreibung des angegebenen Commits wieder"
 
-#: builtin/commit.c:1370
+#: builtin/commit.c:1435
 msgid "use autosquash formatted message to fixup specified commit"
 msgstr ""
-"verwendet eine automatisch zusammengesetzte Beschreibung zum Nachbessern der "
-"angegebenen Version"
+"verwendet eine automatisch zusammengesetzte Beschreibung zum Nachbessern des "
+"angegebenen Commits"
 
-#: builtin/commit.c:1371
+#: builtin/commit.c:1436
 msgid "use autosquash formatted message to squash specified commit"
 msgstr ""
-"verwendet eine automatisch zusammengesetzte Beschreibung zum Zusammenführen "
-"der angegebenen Version"
+"verwendet eine automatisch zusammengesetzte Beschreibung beim \"squash\" des "
+"angegebenen Commits"
 
-#: builtin/commit.c:1372
+#: builtin/commit.c:1437
 msgid "the commit is authored by me now (used with -C/-c/--amend)"
-msgstr "Setzt Sie als Autor der Version (verwendet mit -C/-c/--amend)"
+msgstr "Setzt Sie als Autor des Commits (verwendet mit -C/-c/--amend)"
 
-#: builtin/commit.c:1373 builtin/log.c:1104 builtin/revert.c:109
+#: builtin/commit.c:1438 builtin/log.c:1160 builtin/revert.c:111
 msgid "add Signed-off-by:"
 msgstr "fügt 'Signed-off-by:'-Zeile hinzu"
 
-#: builtin/commit.c:1374
+#: builtin/commit.c:1439
 msgid "use specified template file"
 msgstr "verwendet angegebene Vorlagendatei"
 
-#: builtin/commit.c:1375
+#: builtin/commit.c:1440
 msgid "force edit of commit"
-msgstr "erzwingt Bearbeitung der Version"
+msgstr "erzwingt Bearbeitung des Commits"
 
-#: builtin/commit.c:1376
+#: builtin/commit.c:1441
 msgid "default"
 msgstr "Standard"
 
-#: builtin/commit.c:1376 builtin/tag.c:460
+#: builtin/commit.c:1441 builtin/tag.c:460
 msgid "how to strip spaces and #comments from message"
 msgstr ""
 "wie Leerzeichen und #Kommentare von der Beschreibung getrennt werden sollen"
 
-#: builtin/commit.c:1377
+#: builtin/commit.c:1442
 msgid "include status in commit message template"
-msgstr "fügt Status in die Versionsbeschreibungsvorlage ein"
+msgstr "fügt Status in die Commit-Beschreibungsvorlage ein"
 
-#: builtin/commit.c:1378 builtin/merge.c:215 builtin/tag.c:461
+#: builtin/commit.c:1443 builtin/merge.c:230 builtin/tag.c:461
 msgid "key id"
 msgstr "Schlüssel-ID"
 
-#: builtin/commit.c:1379 builtin/merge.c:216
+#: builtin/commit.c:1444 builtin/merge.c:231
 msgid "GPG sign commit"
-msgstr "signiert Version mit GPG"
+msgstr "signiert Commit mit GPG"
 
 #. end commit message options
-#: builtin/commit.c:1382
+#: builtin/commit.c:1447
 msgid "Commit contents options"
-msgstr "Optionen für Versionsinhalt"
+msgstr "Optionen für Commit-Inhalt"
 
-#: builtin/commit.c:1383
+#: builtin/commit.c:1448
 msgid "commit all changed files"
-msgstr "trägt alle geänderten Dateien ein"
+msgstr "committet alle geänderten Dateien"
 
-#: builtin/commit.c:1384
+#: builtin/commit.c:1449
 msgid "add specified files to index for commit"
-msgstr "trägt die angegebenen Dateien zusätzlich zur Bereitstellung ein"
+msgstr "merkt die angegebenen Dateien zusätzlich zum Commit vor"
 
-#: builtin/commit.c:1385
+#: builtin/commit.c:1450
 msgid "interactively add files"
 msgstr "interaktives Hinzufügen von Dateien"
 
-#: builtin/commit.c:1386
+#: builtin/commit.c:1451
 msgid "interactively add changes"
 msgstr "interaktives Hinzufügen von Änderungen"
 
-#: builtin/commit.c:1387
+#: builtin/commit.c:1452
 msgid "commit only specified files"
-msgstr "trägt nur die angegebenen Dateien ein"
+msgstr "committet nur die angegebenen Dateien"
 
-#: builtin/commit.c:1388
+#: builtin/commit.c:1453
 msgid "bypass pre-commit hook"
 msgstr "umgeht \"pre-commit hook\""
 
-#: builtin/commit.c:1389
+#: builtin/commit.c:1454
 msgid "show what would be committed"
-msgstr "zeigt an, was eingetragen werden würde"
+msgstr "zeigt an, was committet werden würde"
 
-#: builtin/commit.c:1400
+#: builtin/commit.c:1465
 msgid "amend previous commit"
-msgstr "ändert vorherige Version"
+msgstr "ändert vorherigen Commit"
 
-#: builtin/commit.c:1401
+#: builtin/commit.c:1466
 msgid "bypass post-rewrite hook"
 msgstr "umgeht \"post-rewrite hook\""
 
-#: builtin/commit.c:1406
+#: builtin/commit.c:1471
 msgid "ok to record an empty change"
 msgstr "erlaubt Aufzeichnung einer leeren Änderung"
 
-#: builtin/commit.c:1409
+#: builtin/commit.c:1474
 msgid "ok to record a change with an empty message"
 msgstr "erlaubt Aufzeichnung einer Änderung mit einer leeren Beschreibung"
 
-#: builtin/commit.c:1441
+#: builtin/commit.c:1507
 msgid "could not parse HEAD commit"
-msgstr "Konnte Version der Zweigspitze (HEAD) nicht analysieren."
+msgstr "Konnte Commit von HEAD nicht analysieren."
 
-#: builtin/commit.c:1479 builtin/merge.c:510
+#: builtin/commit.c:1545 builtin/merge.c:525
 #, c-format
 msgid "could not open '%s' for reading"
 msgstr "Konnte '%s' nicht zum Lesen öffnen."
 
-#: builtin/commit.c:1486
+#: builtin/commit.c:1552
 #, c-format
 msgid "Corrupt MERGE_HEAD file (%s)"
 msgstr "Beschädigte MERGE_HEAD-Datei (%s)"
 
-#: builtin/commit.c:1493
+#: builtin/commit.c:1559
 msgid "could not read MERGE_MODE"
 msgstr "Konnte MERGE_MODE nicht lesen"
 
-#: builtin/commit.c:1512
+#: builtin/commit.c:1578
 #, c-format
 msgid "could not read commit message: %s"
-msgstr "Konnte Versionsbeschreibung nicht lesen: %s"
+msgstr "Konnte Commit-Beschreibung nicht lesen: %s"
 
-#: builtin/commit.c:1526
+#: builtin/commit.c:1592
 #, c-format
 msgid "Aborting commit; you did not edit the message.\n"
-msgstr "Eintragung abgebrochen; Sie haben die Beschreibung nicht editiert.\n"
+msgstr "Commit abgebrochen; Sie haben die Beschreibung nicht editiert.\n"
 
-#: builtin/commit.c:1531
+#: builtin/commit.c:1597
 #, c-format
 msgid "Aborting commit due to empty commit message.\n"
-msgstr "Eintragung aufgrund leerer Versionsbeschreibung abgebrochen.\n"
+msgstr "Commit aufgrund leerer Beschreibung abgebrochen.\n"
 
-#: builtin/commit.c:1546 builtin/merge.c:847 builtin/merge.c:872
+#: builtin/commit.c:1612 builtin/merge.c:861 builtin/merge.c:886
 msgid "failed to write commit object"
-msgstr "Fehler beim Schreiben des Versionsobjektes."
+msgstr "Fehler beim Schreiben des Commit-Objektes."
 
-#: builtin/commit.c:1567
+#: builtin/commit.c:1633
 msgid "cannot lock HEAD ref"
-msgstr "Kann Referenz der Zweigspitze (HEAD) nicht sperren."
+msgstr "Kann Referenz von HEAD nicht sperren."
 
-#: builtin/commit.c:1571
+#: builtin/commit.c:1637
 msgid "cannot update HEAD ref"
-msgstr "Kann Referenz der Zweigspitze (HEAD) nicht aktualisieren."
+msgstr "Kann Referenz von HEAD nicht aktualisieren."
 
-#: builtin/commit.c:1582
+#: builtin/commit.c:1648
 msgid ""
 "Repository has been updated, but unable to write\n"
 "new_index file. Check that disk is not full or quota is\n"
 "not exceeded, and then \"git reset HEAD\" to recover."
 msgstr ""
-"Das Projektarchiv wurde aktualisiert, aber die \"new_index\"-Datei\n"
+"Das Repository wurde aktualisiert, aber die \"new_index\"-Datei\n"
 "konnte nicht geschrieben werden. Prüfen Sie, dass Ihre Festplatte nicht\n"
 "voll und Ihr Kontingent nicht aufgebraucht ist und führen Sie\n"
 "anschließend \"git reset HEAD\" zu Wiederherstellung aus."
@@ -4184,289 +4555,301 @@
 msgid "git config [options]"
 msgstr "git config [Optionen]"
 
-#: builtin/config.c:51
+#: builtin/config.c:52
 msgid "Config file location"
 msgstr "Ort der Konfigurationsdatei"
 
-#: builtin/config.c:52
+#: builtin/config.c:53
 msgid "use global config file"
 msgstr "verwendet globale Konfigurationsdatei"
 
-#: builtin/config.c:53
+#: builtin/config.c:54
 msgid "use system config file"
 msgstr "verwendet systemweite Konfigurationsdatei"
 
-#: builtin/config.c:54
-msgid "use repository config file"
-msgstr "verwendet Konfigurationsdatei des Projektarchivs"
-
 #: builtin/config.c:55
+msgid "use repository config file"
+msgstr "verwendet Konfigurationsdatei des Repositories"
+
+#: builtin/config.c:56
 msgid "use given config file"
 msgstr "verwendet die angegebene Konfigurationsdatei"
 
-#: builtin/config.c:56
+#: builtin/config.c:57
+msgid "blob-id"
+msgstr "Blob-Id"
+
+#: builtin/config.c:57
+msgid "read config from given blob object"
+msgstr "liest Konfiguration von angegebenem Blob-Objekt"
+
+#: builtin/config.c:58
 msgid "Action"
 msgstr "Aktion"
 
-#: builtin/config.c:57
+#: builtin/config.c:59
 msgid "get value: name [value-regex]"
 msgstr "gibt Wert zurück: Name [Wert-regex]"
 
-#: builtin/config.c:58
+#: builtin/config.c:60
 msgid "get all values: key [value-regex]"
 msgstr "gibt alle Werte zurück: Schlüssel [Wert-regex]"
 
-#: builtin/config.c:59
+#: builtin/config.c:61
 msgid "get values for regexp: name-regex [value-regex]"
 msgstr "gibt Werte für den regulären Ausdruck zurück: Name-regex [Wert-regex]"
 
-#: builtin/config.c:60
+#: builtin/config.c:62
 msgid "replace all matching variables: name value [value_regex]"
 msgstr "ersetzt alle passenden Variablen: Name Wert [Wert-regex] "
 
-#: builtin/config.c:61
+#: builtin/config.c:63
 msgid "add a new variable: name value"
 msgstr "fügt neue Variable hinzu: Name Wert"
 
-#: builtin/config.c:62
+#: builtin/config.c:64
 msgid "remove a variable: name [value-regex]"
 msgstr "entfernt eine Variable: Name [Wert-regex]"
 
-#: builtin/config.c:63
+#: builtin/config.c:65
 msgid "remove all matches: name [value-regex]"
 msgstr "entfernt alle Übereinstimmungen: Name [Wert-regex]"
 
-#: builtin/config.c:64
+#: builtin/config.c:66
 msgid "rename section: old-name new-name"
 msgstr "benennt eine Sektion um: alter-Name neuer-Name"
 
-#: builtin/config.c:65
+#: builtin/config.c:67
 msgid "remove a section: name"
 msgstr "entfernt eine Sektion: Name"
 
-#: builtin/config.c:66
+#: builtin/config.c:68
 msgid "list all"
 msgstr "listet alles auf"
 
-#: builtin/config.c:67
+#: builtin/config.c:69
 msgid "open an editor"
 msgstr "öffnet einen Editor"
 
-#: builtin/config.c:68 builtin/config.c:69
+#: builtin/config.c:70 builtin/config.c:71
 msgid "slot"
 msgstr "Slot"
 
-#: builtin/config.c:68
+#: builtin/config.c:70
 msgid "find the color configured: [default]"
 msgstr "findet die konfigurierte Farbe: [Standard]"
 
-#: builtin/config.c:69
+#: builtin/config.c:71
 msgid "find the color setting: [stdout-is-tty]"
 msgstr "findet die Farbeinstellung: [Standard-Ausgabe-ist-Terminal]"
 
-#: builtin/config.c:70
+#: builtin/config.c:72
 msgid "Type"
 msgstr "Typ"
 
-#: builtin/config.c:71
+#: builtin/config.c:73
 msgid "value is \"true\" or \"false\""
 msgstr "Wert ist \"true\" oder \"false\""
 
-#: builtin/config.c:72
+#: builtin/config.c:74
 msgid "value is decimal number"
 msgstr "Wert ist eine Dezimalzahl"
 
-#: builtin/config.c:73
+#: builtin/config.c:75
 msgid "value is --bool or --int"
 msgstr "Wert ist --bool oder --int"
 
-#: builtin/config.c:74
+#: builtin/config.c:76
 msgid "value is a path (file or directory name)"
 msgstr "Wert ist ein Pfad (Datei oder Verzeichnisname)"
 
-#: builtin/config.c:75
+#: builtin/config.c:77
 msgid "Other"
 msgstr "Sonstiges"
 
-#: builtin/config.c:76
+#: builtin/config.c:78
 msgid "terminate values with NUL byte"
 msgstr "schließt Werte mit NUL-Byte ab"
 
-#: builtin/config.c:77
+#: builtin/config.c:79
 msgid "respect include directives on lookup"
 msgstr "beachtet \"include\"-Direktiven beim Nachschlagen"
 
 #: builtin/count-objects.c:82
-msgid "git count-objects [-v]"
-msgstr "git count-objects [-v]"
+msgid "git count-objects [-v] [-H | --human-readable]"
+msgstr "git count-objects [-v] [-H | --human-readable]"
 
-#: builtin/describe.c:15
+#: builtin/count-objects.c:97
+msgid "print sizes in human readable format"
+msgstr "gibt Größenangaben in menschenlesbaren Format aus"
+
+#: builtin/describe.c:16
 msgid "git describe [options] <committish>*"
 msgstr "git describe [Optionen] <committish>*"
 
-#: builtin/describe.c:16
+#: builtin/describe.c:17
 msgid "git describe [options] --dirty"
 msgstr "git describe [Optionen] --dirty"
 
-#: builtin/describe.c:233
-#, c-format
-msgid "annotated tag %s not available"
-msgstr "annotierte Markierung %s ist nicht verfügbar"
-
 #: builtin/describe.c:237
 #, c-format
-msgid "annotated tag %s has no embedded name"
-msgstr "annotierte Markierung %s hat keinen eingebetteten Namen"
+msgid "annotated tag %s not available"
+msgstr "annotiertes Tag %s ist nicht verfügbar"
 
-#: builtin/describe.c:239
+#: builtin/describe.c:241
+#, c-format
+msgid "annotated tag %s has no embedded name"
+msgstr "annotiertes Tag %s hat keinen eingebetteten Namen"
+
+#: builtin/describe.c:243
 #, c-format
 msgid "tag '%s' is really '%s' here"
-msgstr "Markierung '%s' ist eigentlich '%s' hier"
+msgstr "Tag '%s' ist eigentlich '%s' hier"
 
-#: builtin/describe.c:266
+#: builtin/describe.c:270
 #, c-format
 msgid "Not a valid object name %s"
 msgstr "%s ist kein gültiger Objekt-Name"
 
-#: builtin/describe.c:269
+#: builtin/describe.c:273
 #, c-format
 msgid "%s is not a valid '%s' object"
 msgstr "%s ist kein gültiges '%s' Objekt"
 
-#: builtin/describe.c:286
+#: builtin/describe.c:290
 #, c-format
 msgid "no tag exactly matches '%s'"
-msgstr "kein Markierung entspricht exakt '%s'"
+msgstr "kein Tag entspricht exakt '%s'"
 
-#: builtin/describe.c:288
+#: builtin/describe.c:292
 #, c-format
 msgid "searching to describe %s\n"
 msgstr "suche zur Beschreibung von %s\n"
 
-#: builtin/describe.c:328
+#: builtin/describe.c:332
 #, c-format
 msgid "finished search at %s\n"
 msgstr "beendete Suche bei %s\n"
 
-#: builtin/describe.c:352
+#: builtin/describe.c:359
 #, c-format
 msgid ""
 "No annotated tags can describe '%s'.\n"
 "However, there were unannotated tags: try --tags."
 msgstr ""
-"Keine annotierten Markierungen können '%s' beschreiben.\n"
-"Jedoch gab es nicht annotierte Markierungen: versuchen Sie --tags."
+"Keine annotierten Tags können '%s' beschreiben.\n"
+"Jedoch gab es nicht-annotierte Tags: versuchen Sie --tags."
 
-#: builtin/describe.c:356
+#: builtin/describe.c:363
 #, c-format
 msgid ""
 "No tags can describe '%s'.\n"
 "Try --always, or create some tags."
 msgstr ""
-"Keine Markierungen können '%s' beschreiben.\n"
-"Versuchen Sie --always oder erstellen Sie einige Markierungen."
+"Keine Tags können '%s' beschreiben.\n"
+"Versuchen Sie --always oder erstellen Sie einige Tags."
 
-#: builtin/describe.c:377
+#: builtin/describe.c:384
 #, c-format
 msgid "traversed %lu commits\n"
-msgstr "%lu Versionen durchlaufen\n"
+msgstr "%lu Commits durchlaufen\n"
 
-#: builtin/describe.c:380
+#: builtin/describe.c:387
 #, c-format
 msgid ""
 "more than %i tags found; listed %i most recent\n"
 "gave up search at %s\n"
 msgstr ""
-"mehr als %i Markierungen gefunden; Führe die ersten %i auf\n"
+"mehr als %i Tags gefunden; Führe die ersten %i auf\n"
 "Suche bei %s aufgegeben\n"
 
-#: builtin/describe.c:402
+#: builtin/describe.c:409
 msgid "find the tag that comes after the commit"
-msgstr "findet die Markierung, die nach der Version kommt"
+msgstr "findet das Tag, das nach Commit kommt"
 
-#: builtin/describe.c:403
+#: builtin/describe.c:410
 msgid "debug search strategy on stderr"
 msgstr "protokolliert die Suchstrategie in der Standard-Fehlerausgabe"
 
-#: builtin/describe.c:404
+#: builtin/describe.c:411
 msgid "use any ref"
 msgstr "verwendet alle Referenzen"
 
-#: builtin/describe.c:405
+#: builtin/describe.c:412
 msgid "use any tag, even unannotated"
-msgstr "verwendet jede Markierung, auch nicht-annotierte"
+msgstr "verwendet jedes Tag, auch nicht-annotierte"
 
-#: builtin/describe.c:406
+#: builtin/describe.c:413
 msgid "always use long format"
 msgstr "verwendet immer langes Format"
 
-#: builtin/describe.c:409
+#: builtin/describe.c:414
+msgid "only follow first parent"
+msgstr "folgt nur erstem Elternteil"
+
+#: builtin/describe.c:417
 msgid "only output exact matches"
 msgstr "gibt nur exakte Übereinstimmungen aus"
 
-#: builtin/describe.c:411
+#: builtin/describe.c:419
 msgid "consider <n> most recent tags (default: 10)"
-msgstr "betrachtet die jüngsten <n> Markierungen (Standard: 10)"
+msgstr "betrachtet die jüngsten <n> Tags (Standard: 10)"
 
-#: builtin/describe.c:413
+#: builtin/describe.c:421
 msgid "only consider tags matching <pattern>"
-msgstr "betrachtet nur Markierungen die <Muster> entsprechen"
+msgstr "betrachtet nur Tags die <Muster> entsprechen"
 
-#: builtin/describe.c:415 builtin/name-rev.c:238
+#: builtin/describe.c:423 builtin/name-rev.c:322
 msgid "show abbreviated commit object as fallback"
-msgstr "zeigt gekürztes Versionsobjekt, wenn sonst nichts zutrifft"
+msgstr "zeigt gekürztes Commit-Objekt, wenn sonst nichts zutrifft"
 
-#: builtin/describe.c:416
+#: builtin/describe.c:424
 msgid "mark"
 msgstr "Kennzeichen"
 
-#: builtin/describe.c:417
+#: builtin/describe.c:425
 msgid "append <mark> on dirty working tree (default: \"-dirty\")"
 msgstr ""
-"fügt <Kennzeichen> bei geändertem Arbeitsbaum hinzu (Standard: \"-dirty\")"
+"fügt <Kennzeichen> bei geändertem Arbeitsverzeichnis hinzu (Standard: \"-"
+"dirty\")"
 
-#: builtin/describe.c:435
+#: builtin/describe.c:443
 msgid "--long is incompatible with --abbrev=0"
 msgstr "Die Optionen --long und --abbrev=0 sind inkompatibel."
 
-#: builtin/describe.c:461
+#: builtin/describe.c:469
 msgid "No names found, cannot describe anything."
 msgstr "Keine Namen gefunden, kann nichts beschreiben."
 
-#: builtin/describe.c:481
+#: builtin/describe.c:489
 msgid "--dirty is incompatible with committishes"
-msgstr "Die Option --dirty kann nicht mit Versionen verwendet werden."
+msgstr "Die Option --dirty kann nicht mit Commits verwendet werden."
 
 #: builtin/diff.c:79
 #, c-format
 msgid "'%s': not a regular file or symlink"
-msgstr "'%s': keine reguläre Datei oder symbolischer Link"
+msgstr "'%s': keine reguläre Datei oder symbolischer Verweis"
 
-#: builtin/diff.c:228
+#: builtin/diff.c:230
 #, c-format
 msgid "invalid option: %s"
 msgstr "Ungültige Option: %s"
 
-#: builtin/diff.c:305
+#: builtin/diff.c:307
 msgid "Not a git repository"
-msgstr "Kein Git-Projektarchiv"
+msgstr "Kein Git-Repository"
 
-#: builtin/diff.c:348
+#: builtin/diff.c:350
 #, c-format
 msgid "invalid object '%s' given."
 msgstr "Objekt '%s' ist ungültig."
 
-#: builtin/diff.c:353
-#, c-format
-msgid "more than %d trees given: '%s'"
-msgstr "Mehr als %d Zweige angegeben: '%s'"
-
-#: builtin/diff.c:363
+#: builtin/diff.c:359
 #, c-format
 msgid "more than two blobs given: '%s'"
 msgstr "Mehr als zwei Blobs angegeben: '%s'"
 
-#: builtin/diff.c:371
+#: builtin/diff.c:366
 #, c-format
 msgid "unhandled object '%s' given."
 msgstr "unbehandeltes Objekt '%s' angegeben"
@@ -4475,46 +4858,45 @@
 msgid "git fast-export [rev-list-opts]"
 msgstr "git fast-export [rev-list-opts]"
 
-#: builtin/fast-export.c:652
+#: builtin/fast-export.c:666
 msgid "show progress after <n> objects"
 msgstr "zeigt Fortschritt nach <n> Objekten an"
 
-#: builtin/fast-export.c:654
+#: builtin/fast-export.c:668
 msgid "select handling of signed tags"
-msgstr "wählt Behandlung von signierten Markierungen"
+msgstr "wählt Behandlung von signierten Tags"
 
-#: builtin/fast-export.c:657
+#: builtin/fast-export.c:671
 msgid "select handling of tags that tag filtered objects"
-msgstr "wählt Behandlung von Markierungen, die gefilterte Objekte markieren"
+msgstr "wählt Behandlung von Tags, die gefilterte Objekte markieren"
 
-#: builtin/fast-export.c:660
+#: builtin/fast-export.c:674
 msgid "Dump marks to this file"
 msgstr "Schreibt Kennzeichen in diese Datei"
 
-#: builtin/fast-export.c:662
+#: builtin/fast-export.c:676
 msgid "Import marks from this file"
 msgstr "Importiert Kennzeichen von dieser Datei"
 
-#: builtin/fast-export.c:664
+#: builtin/fast-export.c:678
 msgid "Fake a tagger when tags lack one"
-msgstr ""
-"erzeugt künstlich einen Markierungsersteller, wenn die Markierung keinen hat"
+msgstr "erzeugt künstlich einen Tag-Ersteller, wenn das Tag keinen hat"
 
-#: builtin/fast-export.c:666
+#: builtin/fast-export.c:680
 msgid "Output full tree for each commit"
-msgstr "gibt für jede Version den gesamten Baum aus"
+msgstr "gibt für jeden Commit das gesamte Verzeichnis aus"
 
-#: builtin/fast-export.c:668
+#: builtin/fast-export.c:682
 msgid "Use the done feature to terminate the stream"
 msgstr "Benutzt die \"done\"-Funktion um den Strom abzuschließen"
 
-#: builtin/fast-export.c:669
+#: builtin/fast-export.c:683
 msgid "Skip output of blob data"
 msgstr "Überspringt Ausgabe von Blob-Daten"
 
 #: builtin/fetch.c:20
 msgid "git fetch [<options>] [<repository> [<refspec>...]]"
-msgstr "git fetch [<Optionen>] [<Projektarchiv> [<Referenzspezifikation>...]]"
+msgstr "git fetch [<Optionen>] [<Repository> [<Refspec>...]]"
 
 #: builtin/fetch.c:21
 msgid "git fetch [<options>] <group>"
@@ -4522,7 +4904,7 @@
 
 #: builtin/fetch.c:22
 msgid "git fetch --multiple [<options>] [(<repository> | <group>)...]"
-msgstr "git fetch --multiple [<Optionen>] [(<Projektarchiv> | <Gruppe>)...]"
+msgstr "git fetch --multiple [<Optionen>] [(<Repository> | <Gruppe>)...]"
 
 #: builtin/fetch.c:23
 msgid "git fetch --all [<options>]"
@@ -4530,7 +4912,7 @@
 
 #: builtin/fetch.c:60
 msgid "fetch from all remotes"
-msgstr "fordert von allen externen Projektarchiven an"
+msgstr "fordert von allen Remote-Repositories an"
 
 #: builtin/fetch.c:62
 msgid "append to .git/FETCH_HEAD instead of overwriting"
@@ -4542,24 +4924,25 @@
 
 #: builtin/fetch.c:65
 msgid "force overwrite of local branch"
-msgstr "erzwingt das Überschreiben von lokalen Zweigen"
+msgstr "erzwingt das Überschreiben von lokalen Branches"
 
 #: builtin/fetch.c:67
 msgid "fetch from multiple remotes"
-msgstr "fordert von mehreren externen Projektarchiven an"
+msgstr "fordert von mehreren Remote-Repositories an"
 
 #: builtin/fetch.c:69
 msgid "fetch all tags and associated objects"
-msgstr "fordert alle Markierungen und verbundene Objekte an"
+msgstr "fordert alle Tags und verbundene Objekte an"
 
 #: builtin/fetch.c:71
 msgid "do not fetch all tags (--no-tags)"
-msgstr "fordert nicht alle Markierungen an (--no-tags)"
+msgstr "fordert nicht alle Tags an (--no-tags)"
 
 #: builtin/fetch.c:73
 msgid "prune remote-tracking branches no longer on remote"
 msgstr ""
-"entfernt externe Übernahmezweige, die sich nicht mehr im Fernarchiv befinden"
+"entfernt Remote-Tracking-Branches, die sich nicht mehr im Remote-Repository "
+"befinden"
 
 #: builtin/fetch.c:74
 msgid "on-demand"
@@ -4567,7 +4950,7 @@
 
 #: builtin/fetch.c:75
 msgid "control recursive fetching of submodules"
-msgstr "kontrolliert rekursive Anforderungen von Unterprojekten"
+msgstr "kontrolliert rekursive Anforderungen von Submodulen"
 
 #: builtin/fetch.c:79
 msgid "keep downloaded pack"
@@ -4579,223 +4962,224 @@
 
 #: builtin/fetch.c:84
 msgid "deepen history of shallow clone"
-msgstr "vertieft die Historie eines flachen Klon"
+msgstr "vertieft die Historie eines flachen Klons"
 
 #: builtin/fetch.c:86
 msgid "convert to a complete repository"
-msgstr "konvertiert zu einem vollständigen Projektarchiv"
+msgstr "konvertiert zu einem vollständigen Repository"
 
-#: builtin/fetch.c:88 builtin/log.c:1121
+#: builtin/fetch.c:88 builtin/log.c:1177
 msgid "dir"
 msgstr "Verzeichnis"
 
 #: builtin/fetch.c:89
 msgid "prepend this to submodule path output"
-msgstr "stellt dies an die Ausgabe der Unterprojekt-Pfade voran"
+msgstr "stellt dies an die Ausgabe der Submodul-Pfade voran"
 
 #: builtin/fetch.c:92
 msgid "default mode for recursion"
 msgstr "Standard-Modus für Rekursion"
 
-#: builtin/fetch.c:204
+#: builtin/fetch.c:220
 msgid "Couldn't find remote ref HEAD"
-msgstr "Konnte externe Referenz der Zweigspitze (HEAD) nicht finden."
+msgstr "Konnte Remote-Referenz von HEAD nicht finden."
 
-#: builtin/fetch.c:257
+#: builtin/fetch.c:273
 #, c-format
 msgid "object %s not found"
 msgstr "Objekt %s nicht gefunden"
 
-#: builtin/fetch.c:262
+#: builtin/fetch.c:278
 msgid "[up to date]"
 msgstr "[aktuell]"
 
-#: builtin/fetch.c:276
+#: builtin/fetch.c:292
 #, c-format
 msgid "! %-*s %-*s -> %s  (can't fetch in current branch)"
-msgstr "! %-*s %-*s -> %s  (kann nicht im aktuellen Zweig anfordern)"
+msgstr ""
+"! %-*s %-*s -> %s  (kann \"fetch\" im aktuellen Branch nicht ausführen)"
 
-#: builtin/fetch.c:277 builtin/fetch.c:363
+#: builtin/fetch.c:293 builtin/fetch.c:379
 msgid "[rejected]"
 msgstr "[zurückgewiesen]"
 
-#: builtin/fetch.c:288
+#: builtin/fetch.c:304
 msgid "[tag update]"
-msgstr "[Markierungsaktualisierung]"
+msgstr "[Tag Aktualisierung]"
 
-#: builtin/fetch.c:290 builtin/fetch.c:325 builtin/fetch.c:343
+#: builtin/fetch.c:306 builtin/fetch.c:341 builtin/fetch.c:359
 msgid "  (unable to update local ref)"
 msgstr "  (kann lokale Referenz nicht aktualisieren)"
 
-#: builtin/fetch.c:308
+#: builtin/fetch.c:324
 msgid "[new tag]"
-msgstr "[neue Markierung]"
+msgstr "[neues Tag]"
 
-#: builtin/fetch.c:311
+#: builtin/fetch.c:327
 msgid "[new branch]"
-msgstr "[neuer Zweig]"
+msgstr "[neuer Branch]"
 
-#: builtin/fetch.c:314
+#: builtin/fetch.c:330
 msgid "[new ref]"
 msgstr "[neue Referenz]"
 
-#: builtin/fetch.c:359
+#: builtin/fetch.c:375
 msgid "unable to update local ref"
 msgstr "kann lokale Referenz nicht aktualisieren"
 
-#: builtin/fetch.c:359
+#: builtin/fetch.c:375
 msgid "forced update"
 msgstr "Aktualisierung erzwungen"
 
-#: builtin/fetch.c:365
+#: builtin/fetch.c:381
 msgid "(non-fast-forward)"
 msgstr "(kein Vorspulen)"
 
-#: builtin/fetch.c:396 builtin/fetch.c:688
+#: builtin/fetch.c:412 builtin/fetch.c:718
 #, c-format
 msgid "cannot open %s: %s\n"
 msgstr "kann %s nicht öffnen: %s\n"
 
-#: builtin/fetch.c:405
+#: builtin/fetch.c:421
 #, c-format
 msgid "%s did not send all necessary objects\n"
 msgstr "%s hat nicht alle erforderlichen Objekte gesendet\n"
 
-#: builtin/fetch.c:491
+#: builtin/fetch.c:520
 #, c-format
 msgid "From %.*s\n"
 msgstr "Von %.*s\n"
 
-#: builtin/fetch.c:502
+#: builtin/fetch.c:531
 #, c-format
 msgid ""
 "some local refs could not be updated; try running\n"
 " 'git remote prune %s' to remove any old, conflicting branches"
 msgstr ""
 "Einige lokale Referenzen konnten nicht aktualisiert werden; versuchen Sie\n"
-"'git remote prune %s' um jeden älteren, widersprüchlichen Zweig zu löschen."
+"'git remote prune %s' um jeden älteren, widersprüchlichen Branch zu löschen."
 
-#: builtin/fetch.c:552
+#: builtin/fetch.c:581
 #, c-format
 msgid "   (%s will become dangling)"
 msgstr "   (%s wird unreferenziert)"
 
-#: builtin/fetch.c:553
+#: builtin/fetch.c:582
 #, c-format
 msgid "   (%s has become dangling)"
 msgstr "   (%s wurde unreferenziert)"
 
-#: builtin/fetch.c:560
+#: builtin/fetch.c:589
 msgid "[deleted]"
 msgstr "[gelöscht]"
 
-#: builtin/fetch.c:561 builtin/remote.c:1055
+#: builtin/fetch.c:590 builtin/remote.c:1055
 msgid "(none)"
 msgstr "(nichts)"
 
-#: builtin/fetch.c:678
+#: builtin/fetch.c:708
 #, c-format
 msgid "Refusing to fetch into current branch %s of non-bare repository"
 msgstr ""
-"Das Anfordern in den aktuellen Zweig %s von einem nicht-bloßen Projektarchiv "
+"Der \"fetch\" in den aktuellen Branch %s von einem nicht-Bare-Repository "
 "wurde verweigert."
 
-#: builtin/fetch.c:712
+#: builtin/fetch.c:742
 #, c-format
 msgid "Don't know how to fetch from %s"
 msgstr "Weiß nicht wie von %s angefordert wird."
 
-#: builtin/fetch.c:789
+#: builtin/fetch.c:823
 #, c-format
 msgid "Option \"%s\" value \"%s\" is not valid for %s"
 msgstr "Option \"%s\" Wert \"%s\" ist nicht gültig für %s"
 
-#: builtin/fetch.c:792
+#: builtin/fetch.c:826
 #, c-format
 msgid "Option \"%s\" is ignored for %s\n"
 msgstr "Option \"%s\" wird ignoriert für %s\n"
 
-#: builtin/fetch.c:894
+#: builtin/fetch.c:928
 #, c-format
 msgid "Fetching %s\n"
 msgstr "Fordere an von %s\n"
 
-#: builtin/fetch.c:896 builtin/remote.c:100
+#: builtin/fetch.c:930 builtin/remote.c:100
 #, c-format
 msgid "Could not fetch %s"
 msgstr "Konnte nicht von %s anfordern"
 
-#: builtin/fetch.c:915
+#: builtin/fetch.c:949
 msgid ""
 "No remote repository specified.  Please, specify either a URL or a\n"
 "remote name from which new revisions should be fetched."
 msgstr ""
-"Kein externes Projektarchiv angegeben. Bitte geben Sie entweder eine URL\n"
-"oder den Namen des externen Archivs an, von welchem neue\n"
-"Revisionen angefordert werden sollen."
+"Kein Remote-Repository angegeben. Bitte geben Sie entweder eine URL\n"
+"oder den Namen des Remote-Repositories an, von welchem neue\n"
+"Commits angefordert werden sollen."
 
-#: builtin/fetch.c:935
+#: builtin/fetch.c:969
 msgid "You need to specify a tag name."
-msgstr "Sie müssen den Namen der Markierung angeben."
+msgstr "Sie müssen den Namen des Tags angeben."
 
-#: builtin/fetch.c:981
+#: builtin/fetch.c:1015
 msgid "--depth and --unshallow cannot be used together"
 msgstr ""
 "Die Optionen --depth und --unshallow können nicht gemeinsam verwendet werden."
 
-#: builtin/fetch.c:983
+#: builtin/fetch.c:1017
 msgid "--unshallow on a complete repository does not make sense"
 msgstr ""
-"Die Option --unshallow kann nicht in einem vollständigen Projektarchiv "
+"Die Option --unshallow kann nicht in einem vollständigen Repository "
 "verwendet werden."
 
-#: builtin/fetch.c:1002
+#: builtin/fetch.c:1036
 msgid "fetch --all does not take a repository argument"
-msgstr "fetch --all akzeptiert kein Projektarchiv als Argument"
+msgstr "fetch --all akzeptiert kein Repository als Argument"
 
-#: builtin/fetch.c:1004
+#: builtin/fetch.c:1038
 msgid "fetch --all does not make sense with refspecs"
-msgstr "fetch --all kann nicht mit Referenzspezifikationen verwendet werden."
+msgstr "fetch --all kann nicht mit Refspecs verwendet werden."
 
-#: builtin/fetch.c:1015
+#: builtin/fetch.c:1049
 #, c-format
 msgid "No such remote or remote group: %s"
-msgstr "Kein externes Archiv (einzeln oder Gruppe): %s"
+msgstr "Kein Remote-Repository (einzeln oder Gruppe): %s"
 
-#: builtin/fetch.c:1023
+#: builtin/fetch.c:1057
 msgid "Fetching a group and specifying refspecs does not make sense"
 msgstr ""
-"Das Abholen einer Gruppe von externen Archiven kann nicht mit der Angabe\n"
-"von Referenzspezifikationen verwendet werden."
+"Das Abholen einer Gruppe von Remote-Repositories kann nicht mit der Angabe\n"
+"von Refspecs verwendet werden."
 
 #: builtin/fmt-merge-msg.c:13
 msgid "git fmt-merge-msg [-m <message>] [--log[=<n>]|--no-log] [--file <file>]"
 msgstr ""
 "git fmt-merge-msg [-m <Beschreibung>] [--log[=<n>]|--no-log] [--file <Datei>]"
 
-#: builtin/fmt-merge-msg.c:659 builtin/fmt-merge-msg.c:662 builtin/grep.c:701
-#: builtin/merge.c:188 builtin/show-branch.c:656 builtin/show-ref.c:175
-#: builtin/tag.c:446 parse-options.h:133 parse-options.h:239
+#: builtin/fmt-merge-msg.c:663 builtin/fmt-merge-msg.c:666 builtin/grep.c:700
+#: builtin/merge.c:203 builtin/show-branch.c:655 builtin/show-ref.c:179
+#: builtin/tag.c:446 parse-options.h:133 parse-options.h:243
 msgid "n"
 msgstr "Anzahl"
 
-#: builtin/fmt-merge-msg.c:660
+#: builtin/fmt-merge-msg.c:664
 msgid "populate log with at most <n> entries from shortlog"
 msgstr "fügt Historie mit höchstens <n> Einträgen von \"shortlog\" hinzu"
 
-#: builtin/fmt-merge-msg.c:663
+#: builtin/fmt-merge-msg.c:667
 msgid "alias for --log (deprecated)"
 msgstr "Alias für --log (veraltet)"
 
-#: builtin/fmt-merge-msg.c:666
+#: builtin/fmt-merge-msg.c:670
 msgid "text"
 msgstr "Text"
 
-#: builtin/fmt-merge-msg.c:667
+#: builtin/fmt-merge-msg.c:671
 msgid "use <text> as start of message"
 msgstr "verwendet <Text> als Beschreibungsanfang"
 
-#: builtin/fmt-merge-msg.c:668
+#: builtin/fmt-merge-msg.c:672
 msgid "file to read from"
 msgstr "Datei zum Einlesen"
 
@@ -4853,7 +5237,7 @@
 
 #: builtin/fsck.c:616
 msgid "report tags"
-msgstr "meldet Markierungen"
+msgstr "meldet Tags"
 
 #: builtin/fsck.c:617
 msgid "report root nodes"
@@ -4861,11 +5245,11 @@
 
 #: builtin/fsck.c:618
 msgid "make index objects head nodes"
-msgstr "erzeugt Kopfknoten der Bereitstellungsobjekte"
+msgstr "prüft Objekte in der Staging-Area"
 
 #: builtin/fsck.c:619
 msgid "make reflogs head nodes (default)"
-msgstr "erzeugt Kopfknoten des Referenzprotokolls (Standard)"
+msgstr "prüft die Reflogs (Standard)"
 
 #: builtin/fsck.c:620
 msgid "also consider packs and alternate objects"
@@ -4915,7 +5299,7 @@
 "Auto packing the repository for optimum performance. You may also\n"
 "run \"git gc\" manually. See \"git help gc\" for more information.\n"
 msgstr ""
-"Die Datenbank des Projektarchivs wird für eine optimale Performance\n"
+"Die Datenbank des Repositories wird für eine optimale Performance\n"
 "komprimiert. Sie können auch \"git gc\" manuell ausführen.\n"
 "Siehe \"git help gc\" für weitere Informationen.\n"
 
@@ -4928,240 +5312,240 @@
 
 #: builtin/grep.c:22
 msgid "git grep [options] [-e] <pattern> [<rev>...] [[--] <path>...]"
-msgstr "git grep [Optionen] [-e] <Muster> [<Revision>...] [[--] <Pfad>...]"
+msgstr "git grep [Optionen] [-e] <Muster> [<Commit>...] [[--] <Pfad>...]"
 
 #: builtin/grep.c:217
 #, c-format
 msgid "grep: failed to create thread: %s"
 msgstr "grep: Fehler beim Erzeugen eines Thread: %s"
 
-#: builtin/grep.c:365
+#: builtin/grep.c:364
 #, c-format
 msgid "Failed to chdir: %s"
 msgstr "Fehler beim Verzeichniswechsel: %s"
 
-#: builtin/grep.c:443 builtin/grep.c:478
+#: builtin/grep.c:442 builtin/grep.c:477
 #, c-format
 msgid "unable to read tree (%s)"
-msgstr "konnte Zweig (%s) nicht lesen"
+msgstr "konnte \"Tree\"-Objekt (%s) nicht lesen"
 
-#: builtin/grep.c:493
+#: builtin/grep.c:492
 #, c-format
 msgid "unable to grep from object of type %s"
 msgstr "kann \"grep\" nicht mit Objekten des Typs %s durchführen"
 
-#: builtin/grep.c:551
+#: builtin/grep.c:550
 #, c-format
 msgid "switch `%c' expects a numerical value"
 msgstr "Schalter '%c' erwartet einen numerischen Wert"
 
-#: builtin/grep.c:568
+#: builtin/grep.c:567
 #, c-format
 msgid "cannot open '%s'"
 msgstr "kann '%s' nicht öffnen"
 
-#: builtin/grep.c:643
+#: builtin/grep.c:642
 msgid "search in index instead of in the work tree"
-msgstr "sucht in der Bereitstellung anstatt im Arbeitsbaum"
+msgstr "sucht in der Staging-Area anstatt im Arbeitsverzeichnis"
 
-#: builtin/grep.c:645
+#: builtin/grep.c:644
 msgid "find in contents not managed by git"
 msgstr "findet auch in Inhalten, die nicht von Git verwaltet werden"
 
-#: builtin/grep.c:647
+#: builtin/grep.c:646
 msgid "search in both tracked and untracked files"
 msgstr "sucht in beobachteten und unbeobachteten Dateien"
 
-#: builtin/grep.c:649
+#: builtin/grep.c:648
 msgid "search also in ignored files"
 msgstr "sucht auch in ignorierten Dateien"
 
-#: builtin/grep.c:652
+#: builtin/grep.c:651
 msgid "show non-matching lines"
 msgstr "zeigt Zeilen ohne Übereinstimmungen"
 
-#: builtin/grep.c:654
+#: builtin/grep.c:653
 msgid "case insensitive matching"
 msgstr "findet Übereinstimmungen unabhängig von Groß- und Kleinschreibung"
 
-#: builtin/grep.c:656
+#: builtin/grep.c:655
 msgid "match patterns only at word boundaries"
 msgstr "sucht nur ganze Wörter"
 
-#: builtin/grep.c:658
+#: builtin/grep.c:657
 msgid "process binary files as text"
 msgstr "verarbeitet binäre Dateien als Text"
 
-#: builtin/grep.c:660
+#: builtin/grep.c:659
 msgid "don't match patterns in binary files"
 msgstr "findet keine Muster in Binärdateien"
 
-#: builtin/grep.c:663
+#: builtin/grep.c:662
 msgid "descend at most <depth> levels"
 msgstr "durchläuft höchstens <Tiefe> Ebenen"
 
-#: builtin/grep.c:667
+#: builtin/grep.c:666
 msgid "use extended POSIX regular expressions"
 msgstr "verwendet erweiterte reguläre Ausdrücke aus POSIX"
 
-#: builtin/grep.c:670
+#: builtin/grep.c:669
 msgid "use basic POSIX regular expressions (default)"
 msgstr "verwendet grundlegende reguläre Ausdrücke aus POSIX (Standard)"
 
-#: builtin/grep.c:673
+#: builtin/grep.c:672
 msgid "interpret patterns as fixed strings"
 msgstr "interpretiert Muster als feste Zeichenketten"
 
-#: builtin/grep.c:676
+#: builtin/grep.c:675
 msgid "use Perl-compatible regular expressions"
 msgstr "verwendet Perl-kompatible reguläre Ausdrücke"
 
-#: builtin/grep.c:679
+#: builtin/grep.c:678
 msgid "show line numbers"
 msgstr "zeigt Zeilennummern"
 
-#: builtin/grep.c:680
+#: builtin/grep.c:679
 msgid "don't show filenames"
 msgstr "zeigt keine Dateinamen"
 
-#: builtin/grep.c:681
+#: builtin/grep.c:680
 msgid "show filenames"
 msgstr "zeigt Dateinamen"
 
-#: builtin/grep.c:683
+#: builtin/grep.c:682
 msgid "show filenames relative to top directory"
 msgstr "zeigt Dateinamen relativ zum Projektverzeichnis"
 
-#: builtin/grep.c:685
+#: builtin/grep.c:684
 msgid "show only filenames instead of matching lines"
 msgstr "zeigt nur Dateinamen anstatt übereinstimmende Zeilen"
 
-#: builtin/grep.c:687
+#: builtin/grep.c:686
 msgid "synonym for --files-with-matches"
 msgstr "Synonym für --files-with-matches"
 
-#: builtin/grep.c:690
+#: builtin/grep.c:689
 msgid "show only the names of files without match"
 msgstr "zeigt nur die Dateinamen ohne Übereinstimmungen"
 
-#: builtin/grep.c:692
+#: builtin/grep.c:691
 msgid "print NUL after filenames"
 msgstr "gibt NUL-Zeichen nach Dateinamen aus"
 
-#: builtin/grep.c:694
+#: builtin/grep.c:693
 msgid "show the number of matches instead of matching lines"
 msgstr "zeigt, anstatt der Zeilen, die Anzahl der übereinstimmenden Zeilen"
 
-#: builtin/grep.c:695
+#: builtin/grep.c:694
 msgid "highlight matches"
 msgstr "hebt Übereinstimmungen hervor"
 
-#: builtin/grep.c:697
+#: builtin/grep.c:696
 msgid "print empty line between matches from different files"
 msgstr ""
 "gibt eine Leerzeile zwischen Übereinstimmungen in verschiedenen Dateien aus"
 
-#: builtin/grep.c:699
+#: builtin/grep.c:698
 msgid "show filename only once above matches from same file"
 msgstr ""
 "zeigt den Dateinamen nur einmal oberhalb der Übereinstimmungen aus dieser "
 "Datei an"
 
-#: builtin/grep.c:702
+#: builtin/grep.c:701
 msgid "show <n> context lines before and after matches"
 msgstr "zeigt <n> Zeilen vor und nach den Übereinstimmungen an"
 
-#: builtin/grep.c:705
+#: builtin/grep.c:704
 msgid "show <n> context lines before matches"
 msgstr "zeigt <n> Zeilen vor den Übereinstimmungen an"
 
-#: builtin/grep.c:707
+#: builtin/grep.c:706
 msgid "show <n> context lines after matches"
 msgstr "zeigt <n> Zeilen nach den Übereinstimmungen an"
 
-#: builtin/grep.c:708
+#: builtin/grep.c:707
 msgid "shortcut for -C NUM"
 msgstr "Kurzform für -C NUM"
 
-#: builtin/grep.c:711
+#: builtin/grep.c:710
 msgid "show a line with the function name before matches"
 msgstr "zeigt eine Zeile mit dem Funktionsnamen vor Übereinstimmungen an"
 
-#: builtin/grep.c:713
+#: builtin/grep.c:712
 msgid "show the surrounding function"
 msgstr "zeigt die umgebende Funktion an"
 
-#: builtin/grep.c:716
+#: builtin/grep.c:715
 msgid "read patterns from file"
 msgstr "liest Muster von einer Datei"
 
-#: builtin/grep.c:718
+#: builtin/grep.c:717
 msgid "match <pattern>"
 msgstr "findet <Muster>"
 
-#: builtin/grep.c:720
+#: builtin/grep.c:719
 msgid "combine patterns specified with -e"
 msgstr "kombiniert Muster, die mit -e angegeben wurden"
 
-#: builtin/grep.c:732
+#: builtin/grep.c:731
 msgid "indicate hit with exit status without output"
 msgstr "zeigt Übereinstimmungen nur durch Beendigungsstatus an"
 
-#: builtin/grep.c:734
+#: builtin/grep.c:733
 msgid "show only matches from files that match all patterns"
 msgstr "zeigt nur Übereinstimmungen von Dateien, die allen Mustern entsprechen"
 
-#: builtin/grep.c:736
+#: builtin/grep.c:735
 msgid "show parse tree for grep expression"
-msgstr "zeigt geparsten Baum für \"grep\"-Ausdruck"
+msgstr "zeigt geparstes Verzeichnis für \"grep\"-Ausdruck"
 
-#: builtin/grep.c:740
+#: builtin/grep.c:739
 msgid "pager"
 msgstr "Anzeigeprogramm"
 
-#: builtin/grep.c:740
+#: builtin/grep.c:739
 msgid "show matching files in the pager"
 msgstr "zeigt Dateien mit Übereinstimmungen im Anzeigeprogramm"
 
-#: builtin/grep.c:743
+#: builtin/grep.c:742
 msgid "allow calling of grep(1) (ignored by this build)"
 msgstr "erlaubt den Aufruf von grep(1) (von dieser Programmversion ignoriert)"
 
-#: builtin/grep.c:744 builtin/show-ref.c:184
+#: builtin/grep.c:743 builtin/show-ref.c:188
 msgid "show usage"
 msgstr "zeigt Verwendung"
 
-#: builtin/grep.c:811
+#: builtin/grep.c:810
 msgid "no pattern given."
 msgstr "keine Muster angegeben"
 
-#: builtin/grep.c:866
+#: builtin/grep.c:865
 msgid "--open-files-in-pager only works on the worktree"
 msgstr ""
-"Die Option --open-files-in-pager kann nur innerhalb des Arbeitsbaums "
-"verwendet werden."
+"Die Option --open-files-in-pager kann nur innerhalb des "
+"Arbeitsverzeichnisses verwendet werden."
 
-#: builtin/grep.c:889
+#: builtin/grep.c:888
 msgid "--cached or --untracked cannot be used with --no-index."
 msgstr ""
 "Die Optionen --cached und --untracked können nicht mit --no-index verwendet "
 "werden."
 
-#: builtin/grep.c:894
+#: builtin/grep.c:893
 msgid "--no-index or --untracked cannot be used with revs."
 msgstr ""
-"Die Optionen --no-index und --untracked können nicht mit Versionen verwendet "
+"Die Optionen --no-index und --untracked können nicht mit Commits verwendet "
 "werden."
 
-#: builtin/grep.c:897
+#: builtin/grep.c:896
 msgid "--[no-]exclude-standard cannot be used for tracked contents."
 msgstr ""
 "Die Option --[no-]exclude-standard kann nicht mit beobachteten Inhalten "
 "verwendet werden."
 
-#: builtin/grep.c:905
+#: builtin/grep.c:904
 msgid "both --cached and trees are given."
-msgstr "Die Option --cached kann nicht mit Zweigen verwendet werden."
+msgstr "Die Option --cached kann nicht mit \"Tree\"-Objekten verwendet werden."
 
 #: builtin/hash-object.c:60
 msgid ""
@@ -5199,10 +5583,14 @@
 msgid "process file as it were from this path"
 msgstr "verarbeitet Datei, als ob sie von diesem Pfad wäre"
 
-#: builtin/help.c:42
+#: builtin/help.c:41
 msgid "print all available commands"
 msgstr "Anzeige aller vorhandenen Kommandos"
 
+#: builtin/help.c:42
+msgid "print list of useful guides"
+msgstr "zeigt Liste von allgemein verwendeten Anleitungen"
+
 #: builtin/help.c:43
 msgid "show man page"
 msgstr "zeigt Handbuch"
@@ -5216,8 +5604,8 @@
 msgstr "zeigt Info-Seite"
 
 #: builtin/help.c:52
-msgid "git help [--all] [--man|--web|--info] [command]"
-msgstr "git help [--all] [--man|--web|--info] [Kommando]"
+msgid "git help [--all] [--guides] [--man|--web|--info] [command]"
+msgstr "git help [--all] [--guides] [--man|--web|--info] [Kommando]"
 
 #: builtin/help.c:64
 #, c-format
@@ -5273,291 +5661,323 @@
 msgid "no info viewer handled the request"
 msgstr "kein Informations-Betrachter konnte mit dieser Anfrage umgehen"
 
-#: builtin/help.c:429 builtin/help.c:436
+#: builtin/help.c:420
+msgid "Defining attributes per path"
+msgstr "Definition von Attributen pro Pfad"
+
+#: builtin/help.c:421
+msgid "A Git glossary"
+msgstr "Ein Git-Glossar"
+
+#: builtin/help.c:422
+msgid "Specifies intentionally untracked files to ignore"
+msgstr "Spezifikation von bewusst ignorierten, unbeobachteten Dateien"
+
+#: builtin/help.c:423
+msgid "Defining submodule properties"
+msgstr "Definition von Submodul-Eigenschaften"
+
+#: builtin/help.c:424
+msgid "Specifying revisions and ranges for Git"
+msgstr "Spezifikation von Commits und Bereichen für Git"
+
+#: builtin/help.c:425
+msgid "A tutorial introduction to Git (for version 1.5.1 or newer)"
+msgstr "Eine einführende Anleitung zu Git (für Version 1.5.1 oder neuer)"
+
+#: builtin/help.c:426
+msgid "An overview of recommended workflows with Git"
+msgstr "Eine Übersicht über empfohlene Arbeitsabläufe mit Git"
+
+#: builtin/help.c:438
+msgid "The common Git guides are:\n"
+msgstr "Die allgemein verwendeten Git-Anleitungen sind:\n"
+
+#: builtin/help.c:460 builtin/help.c:476
 #, c-format
 msgid "usage: %s%s"
 msgstr "Verwendung: %s%s"
 
-#: builtin/help.c:452
+#: builtin/help.c:492
 #, c-format
 msgid "`git %s' is aliased to `%s'"
 msgstr "für `git %s' wurde der Alias `%s' angelegt"
 
-#: builtin/index-pack.c:182
+#: builtin/index-pack.c:184
 #, c-format
 msgid "object type mismatch at %s"
 msgstr "Objekt-Typen passen bei %s nicht zusammen"
 
-#: builtin/index-pack.c:202
+#: builtin/index-pack.c:204
 msgid "object of unexpected type"
 msgstr "Objekt hat unerwarteten Typ"
 
-#: builtin/index-pack.c:239
+#: builtin/index-pack.c:244
 #, c-format
 msgid "cannot fill %d byte"
 msgid_plural "cannot fill %d bytes"
 msgstr[0] "kann %d Byte nicht lesen"
 msgstr[1] "kann %d Bytes nicht lesen"
 
-#: builtin/index-pack.c:249
+#: builtin/index-pack.c:254
 msgid "early EOF"
 msgstr "zu frühes Dateiende"
 
-#: builtin/index-pack.c:250
+#: builtin/index-pack.c:255
 msgid "read error on input"
 msgstr "Fehler beim Lesen der Eingabe"
 
-#: builtin/index-pack.c:262
+#: builtin/index-pack.c:267
 msgid "used more bytes than were available"
 msgstr "verwendete mehr Bytes als verfügbar waren"
 
-#: builtin/index-pack.c:269
+#: builtin/index-pack.c:274
 msgid "pack too large for current definition of off_t"
 msgstr "Paket ist zu groß für die aktuelle Definition von off_t"
 
-#: builtin/index-pack.c:285
+#: builtin/index-pack.c:290
 #, c-format
 msgid "unable to create '%s'"
 msgstr "konnte '%s' nicht erstellen"
 
-#: builtin/index-pack.c:290
+#: builtin/index-pack.c:295
 #, c-format
 msgid "cannot open packfile '%s'"
 msgstr "Kann Paketdatei '%s' nicht öffnen"
 
-#: builtin/index-pack.c:304
+#: builtin/index-pack.c:309
 msgid "pack signature mismatch"
 msgstr "Paketsignatur stimmt nicht überein"
 
-#: builtin/index-pack.c:306
+#: builtin/index-pack.c:311
 #, c-format
 msgid "pack version %<PRIu32> unsupported"
 msgstr "Paketversion %<PRIu32> nicht unterstützt"
 
-#: builtin/index-pack.c:324
+#: builtin/index-pack.c:329
 #, c-format
 msgid "pack has bad object at offset %lu: %s"
 msgstr "Paket hat ein ungültiges Objekt bei Versatz %lu: %s"
 
-#: builtin/index-pack.c:446
+#: builtin/index-pack.c:451
 #, c-format
 msgid "inflate returned %d"
 msgstr "Dekomprimierung gab %d zurück"
 
-#: builtin/index-pack.c:495
+#: builtin/index-pack.c:500
 msgid "offset value overflow for delta base object"
 msgstr "Wert für Versatz bei Differenzobjekt übergelaufen"
 
-#: builtin/index-pack.c:503
+#: builtin/index-pack.c:508
 msgid "delta base offset is out of bound"
 msgstr ""
 "Wert für Versatz bei Differenzobjekt liegt außerhalb des gültigen Bereichs"
 
-#: builtin/index-pack.c:511
+#: builtin/index-pack.c:516
 #, c-format
 msgid "unknown object type %d"
 msgstr "Unbekannter Objekt-Typ %d"
 
-#: builtin/index-pack.c:542
+#: builtin/index-pack.c:547
 msgid "cannot pread pack file"
 msgstr "Kann Paketdatei %s nicht lesen"
 
-#: builtin/index-pack.c:544
+#: builtin/index-pack.c:549
 #, c-format
 msgid "premature end of pack file, %lu byte missing"
 msgid_plural "premature end of pack file, %lu bytes missing"
 msgstr[0] "frühzeitiges Ende der Paketdatei, vermisse %lu Byte"
 msgstr[1] "frühzeitiges Ende der Paketdatei, vermisse %lu Bytes"
 
-#: builtin/index-pack.c:570
+#: builtin/index-pack.c:575
 msgid "serious inflate inconsistency"
 msgstr "ernsthafte Inkonsistenz nach Dekomprimierung"
 
-#: builtin/index-pack.c:661 builtin/index-pack.c:667 builtin/index-pack.c:690
-#: builtin/index-pack.c:724 builtin/index-pack.c:733
+#: builtin/index-pack.c:666 builtin/index-pack.c:672 builtin/index-pack.c:695
+#: builtin/index-pack.c:729 builtin/index-pack.c:738
 #, c-format
 msgid "SHA1 COLLISION FOUND WITH %s !"
 msgstr "SHA1 KOLLISION MIT %s GEFUNDEN !"
 
-#: builtin/index-pack.c:664 builtin/pack-objects.c:170
+#: builtin/index-pack.c:669 builtin/pack-objects.c:170
 #: builtin/pack-objects.c:262
 #, c-format
 msgid "unable to read %s"
 msgstr "kann %s nicht lesen"
 
-#: builtin/index-pack.c:730
+#: builtin/index-pack.c:735
 #, c-format
 msgid "cannot read existing object %s"
 msgstr "Kann existierendes Objekt %s nicht lesen."
 
-#: builtin/index-pack.c:744
+#: builtin/index-pack.c:749
 #, c-format
 msgid "invalid blob object %s"
 msgstr "ungültiges Blob-Objekt %s"
 
-#: builtin/index-pack.c:759
+#: builtin/index-pack.c:763
 #, c-format
 msgid "invalid %s"
 msgstr "Ungültiger Objekt-Typ %s"
 
-#: builtin/index-pack.c:761
+#: builtin/index-pack.c:766
 msgid "Error in object"
 msgstr "Fehler in Objekt"
 
-#: builtin/index-pack.c:763
+#: builtin/index-pack.c:768
 #, c-format
 msgid "Not all child objects of %s are reachable"
 msgstr "Nicht alle Kind-Objekte von %s sind erreichbar"
 
-#: builtin/index-pack.c:833 builtin/index-pack.c:863
+#: builtin/index-pack.c:838 builtin/index-pack.c:868
 msgid "failed to apply delta"
 msgstr "Konnte Dateiunterschied nicht anwenden"
 
-#: builtin/index-pack.c:1004
+#: builtin/index-pack.c:1009
 msgid "Receiving objects"
 msgstr "Empfange Objekte"
 
-#: builtin/index-pack.c:1004
+#: builtin/index-pack.c:1009
 msgid "Indexing objects"
 msgstr "Indiziere Objekte"
 
-#: builtin/index-pack.c:1030
+#: builtin/index-pack.c:1035
 msgid "pack is corrupted (SHA1 mismatch)"
 msgstr "Paket ist beschädigt (SHA1 unterschiedlich)"
 
-#: builtin/index-pack.c:1035
+#: builtin/index-pack.c:1040
 msgid "cannot fstat packfile"
 msgstr "kann Paketdatei nicht lesen"
 
-#: builtin/index-pack.c:1038
+#: builtin/index-pack.c:1043
 msgid "pack has junk at the end"
 msgstr "Paketende enthält nicht verwendbaren Inhalt"
 
-#: builtin/index-pack.c:1049
+#: builtin/index-pack.c:1054
 msgid "confusion beyond insanity in parse_pack_objects()"
 msgstr "Fehler beim Ausführen von \"parse_pack_objects()\""
 
-#: builtin/index-pack.c:1072
+#: builtin/index-pack.c:1077
 msgid "Resolving deltas"
 msgstr "Löse Unterschiede auf"
 
-#: builtin/index-pack.c:1082
+#: builtin/index-pack.c:1087
 #, c-format
 msgid "unable to create thread: %s"
 msgstr "kann Thread nicht erzeugen: %s"
 
-#: builtin/index-pack.c:1124
+#: builtin/index-pack.c:1129
 msgid "confusion beyond insanity"
 msgstr "Fehler beim Auflösen der Unterschiede"
 
-#: builtin/index-pack.c:1132
+#: builtin/index-pack.c:1137
 #, c-format
 msgid "completed with %d local objects"
 msgstr "vervollständigt mit %d lokalen Objekten"
 
-#: builtin/index-pack.c:1142
+#: builtin/index-pack.c:1147
 #, c-format
 msgid "Unexpected tail checksum for %s (disk corruption?)"
 msgstr "Unerwartete Prüfsumme für %s (Festplattenfehler?)"
 
-#: builtin/index-pack.c:1146
+#: builtin/index-pack.c:1151
 #, c-format
 msgid "pack has %d unresolved delta"
 msgid_plural "pack has %d unresolved deltas"
 msgstr[0] "Paket hat %d unaufgelöste Unterschied"
 msgstr[1] "Paket hat %d unaufgelöste Unterschiede"
 
-#: builtin/index-pack.c:1171
+#: builtin/index-pack.c:1176
 #, c-format
 msgid "unable to deflate appended object (%d)"
 msgstr "Konnte angehängtes Objekt (%d) nicht komprimieren"
 
-#: builtin/index-pack.c:1250
+#: builtin/index-pack.c:1255
 #, c-format
 msgid "local object %s is corrupt"
 msgstr "lokales Objekt %s ist beschädigt"
 
-#: builtin/index-pack.c:1274
+#: builtin/index-pack.c:1279
 msgid "error while closing pack file"
 msgstr "Fehler beim Schließen der Paketdatei"
 
-#: builtin/index-pack.c:1287
+#: builtin/index-pack.c:1292
 #, c-format
 msgid "cannot write keep file '%s'"
 msgstr "Kann Paketbeschreibungsdatei '%s' nicht schreiben"
 
-#: builtin/index-pack.c:1295
+#: builtin/index-pack.c:1300
 #, c-format
 msgid "cannot close written keep file '%s'"
 msgstr "Kann eben erstellte Paketbeschreibungsdatei '%s' nicht schließen"
 
-#: builtin/index-pack.c:1308
+#: builtin/index-pack.c:1313
 msgid "cannot store pack file"
 msgstr "Kann Paketdatei nicht speichern"
 
-#: builtin/index-pack.c:1319
+#: builtin/index-pack.c:1324
 msgid "cannot store index file"
 msgstr "Kann Indexdatei nicht speichern"
 
-#: builtin/index-pack.c:1352
+#: builtin/index-pack.c:1357
 #, c-format
 msgid "bad pack.indexversion=%<PRIu32>"
 msgstr "\"pack.indexversion=%<PRIu32>\" ist ungültig"
 
-#: builtin/index-pack.c:1358
+#: builtin/index-pack.c:1363
 #, c-format
 msgid "invalid number of threads specified (%d)"
 msgstr "ungültige Anzahl von Threads angegeben (%d)"
 
-#: builtin/index-pack.c:1362 builtin/index-pack.c:1535
+#: builtin/index-pack.c:1367 builtin/index-pack.c:1545
 #, c-format
 msgid "no threads support, ignoring %s"
 msgstr "keine Unterstützung von Threads, '%s' wird ignoriert"
 
-#: builtin/index-pack.c:1420
+#: builtin/index-pack.c:1425
 #, c-format
 msgid "Cannot open existing pack file '%s'"
 msgstr "Kann existierende Paketdatei '%s' nicht öffnen"
 
-#: builtin/index-pack.c:1422
+#: builtin/index-pack.c:1427
 #, c-format
 msgid "Cannot open existing pack idx file for '%s'"
 msgstr "Kann existierende Indexdatei für Paket '%s' nicht öffnen"
 
-#: builtin/index-pack.c:1469
+#: builtin/index-pack.c:1474
 #, c-format
 msgid "non delta: %d object"
 msgid_plural "non delta: %d objects"
 msgstr[0] "kein Unterschied: %d Objekt"
 msgstr[1] "kein Unterschied: %d Objekte"
 
-#: builtin/index-pack.c:1476
+#: builtin/index-pack.c:1481
 #, c-format
 msgid "chain length = %d: %lu object"
 msgid_plural "chain length = %d: %lu objects"
 msgstr[0] "Länge der Objekt-Liste = %d: %lu Objekt"
 msgstr[1] "Länge der Objekt-Liste = %d: %lu Objekte"
 
-#: builtin/index-pack.c:1503
+#: builtin/index-pack.c:1509
 msgid "Cannot come back to cwd"
 msgstr "Kann nicht zurück zu Arbeitsverzeichnis wechseln"
 
-#: builtin/index-pack.c:1547 builtin/index-pack.c:1550
-#: builtin/index-pack.c:1562 builtin/index-pack.c:1566
+#: builtin/index-pack.c:1557 builtin/index-pack.c:1560
+#: builtin/index-pack.c:1572 builtin/index-pack.c:1576
 #, c-format
 msgid "bad %s"
 msgstr "%s ist ungültig"
 
-#: builtin/index-pack.c:1580
+#: builtin/index-pack.c:1590
 msgid "--fix-thin cannot be used without --stdin"
 msgstr "Die Option --fix-thin kann nicht ohne --stdin verwendet werden."
 
-#: builtin/index-pack.c:1584 builtin/index-pack.c:1594
+#: builtin/index-pack.c:1594 builtin/index-pack.c:1604
 #, c-format
 msgid "packfile name '%s' does not end with '.pack'"
 msgstr "Name der Paketdatei '%s' endet nicht mit '.pack'"
 
-#: builtin/index-pack.c:1603
+#: builtin/index-pack.c:1613
 msgid "--verify with no packfile name given"
 msgstr "Die Option --verify wurde ohne Namen der Paketdatei angegeben."
 
@@ -5589,17 +6009,17 @@
 #: builtin/init-db.c:97
 #, c-format
 msgid "cannot readlink '%s'"
-msgstr "kann Verknüpfung '%s' nicht lesen"
+msgstr "kann Verweis '%s' nicht lesen"
 
 #: builtin/init-db.c:99
 #, c-format
 msgid "insanely long symlink %s"
-msgstr "zu lange symbolische Verknüpfung %s"
+msgstr "zu langer symbolischer Verweis %s"
 
 #: builtin/init-db.c:102
 #, c-format
 msgid "cannot symlink '%s' '%s'"
-msgstr "kann '%s' nicht mit '%s' symbolisch verknüpfen"
+msgstr "kann symbolischen Verweis '%s' auf '%s' nicht erstellen"
 
 #: builtin/init-db.c:106
 #, c-format
@@ -5649,7 +6069,7 @@
 #: builtin/init-db.c:363
 #, c-format
 msgid "Could not create git link %s"
-msgstr "Konnte git-Verknüpfung %s nicht erstellen"
+msgstr "Konnte git-Verweis %s nicht erstellen"
 
 #.
 #. * TRANSLATORS: The first '%s' is either "Reinitialized
@@ -5659,7 +6079,7 @@
 #: builtin/init-db.c:420
 #, c-format
 msgid "%s%s Git repository in %s%s\n"
-msgstr "%s%s Git-Projektarchiv in %s%s\n"
+msgstr "%s%s Git-Repository in %s%s\n"
 
 #: builtin/init-db.c:421
 msgid "Reinitialized existing"
@@ -5691,10 +6111,9 @@
 
 #: builtin/init-db.c:491
 msgid "specify that the git repository is to be shared amongst several users"
-msgstr ""
-"gibt an, dass das Git-Projektarchiv mit mehreren Benutzern geteilt wird"
+msgstr "gibt an, dass das Git-Repository mit mehreren Benutzern geteilt wird"
 
-#: builtin/init-db.c:493 builtin/prune-packed.c:77
+#: builtin/init-db.c:493 builtin/prune-packed.c:75
 msgid "be quiet"
 msgstr "weniger Ausgaben"
 
@@ -5724,368 +6143,385 @@
 #: builtin/init-db.c:586
 #, c-format
 msgid "Cannot access work tree '%s'"
-msgstr "Kann nicht auf Arbeitsbaum '%s' zugreifen."
-
-#: builtin/log.c:40
-msgid "git log [<options>] [<since>..<until>] [[--] <path>...]\n"
-msgstr "git log [<Optionen>] [<seit>..<bis>] [[--] <Pfad>...]\n"
+msgstr "Kann nicht auf Arbeitsverzeichnis '%s' zugreifen."
 
 #: builtin/log.c:41
+msgid "git log [<options>] [<revision range>] [[--] <path>...]\n"
+msgstr "git log [<Optionen>] [Commitbereich>] [[--] <Pfad>...]\n"
+
+#: builtin/log.c:42
 msgid "   or: git show [options] <object>..."
 msgstr "   oder: git show [Optionen] <Objekt>..."
 
-#: builtin/log.c:103
+#: builtin/log.c:124
 msgid "suppress diff output"
 msgstr "unterdrückt Ausgabe der Unterschiede"
 
-#: builtin/log.c:104
+#: builtin/log.c:125
 msgid "show source"
 msgstr "zeigt Quelle"
 
-#: builtin/log.c:105
+#: builtin/log.c:126
 msgid "Use mail map file"
 msgstr "verwendet \"mailmap\"-Datei"
 
-#: builtin/log.c:106
+#: builtin/log.c:127
 msgid "decorate options"
 msgstr "decorate-Optionen"
 
-#: builtin/log.c:199
+#: builtin/log.c:230
 #, c-format
 msgid "Final output: %d %s\n"
 msgstr "letzte Ausgabe: %d %s\n"
 
-#: builtin/log.c:422 builtin/log.c:514
+#: builtin/log.c:453 builtin/log.c:545
 #, c-format
 msgid "Could not read object %s"
 msgstr "Kann Objekt %s nicht lesen."
 
-#: builtin/log.c:538
+#: builtin/log.c:569
 #, c-format
 msgid "Unknown type: %d"
 msgstr "Unbekannter Typ: %d"
 
-#: builtin/log.c:630
+#: builtin/log.c:669
 msgid "format.headers without value"
 msgstr "format.headers ohne Wert"
 
-#: builtin/log.c:704
+#: builtin/log.c:751
 msgid "name of output directory is too long"
 msgstr "Name des Ausgabeverzeichnisses ist zu lang."
 
-#: builtin/log.c:720
+#: builtin/log.c:767
 #, c-format
 msgid "Cannot open patch file %s"
 msgstr "Kann Patch-Datei %s nicht öffnen"
 
-#: builtin/log.c:734
+#: builtin/log.c:781
 msgid "Need exactly one range."
-msgstr "Brauche genau einen Versionsbereich."
+msgstr "Brauche genau einen Commit-Bereich."
 
-#: builtin/log.c:742
+#: builtin/log.c:789
 msgid "Not a range."
-msgstr "Kein Versionsbereich."
+msgstr "Kein Commit-Bereich."
 
-#: builtin/log.c:815
+#: builtin/log.c:891
 msgid "Cover letter needs email format"
 msgstr "Anschreiben benötigt E-Mail-Format"
 
-#: builtin/log.c:888
+#: builtin/log.c:967
 #, c-format
 msgid "insane in-reply-to: %s"
 msgstr "ungültiges in-reply-to: %s"
 
-#: builtin/log.c:916
+#: builtin/log.c:995
 msgid "git format-patch [options] [<since> | <revision range>]"
-msgstr "git format-patch [Optionen] [<seit> | <Revisionsbereich>]"
+msgstr "git format-patch [Optionen] [<seit> | <Commitbereich>]"
 
-#: builtin/log.c:961
+#: builtin/log.c:1040
 msgid "Two output directories?"
 msgstr "Zwei Ausgabeverzeichnisse?"
 
-#: builtin/log.c:1099
+#: builtin/log.c:1155
 msgid "use [PATCH n/m] even with a single patch"
 msgstr "verwendet [PATCH n/m] auch mit einzelnem Patch"
 
-#: builtin/log.c:1102
+#: builtin/log.c:1158
 msgid "use [PATCH] even with multiple patches"
 msgstr "verwendet [PATCH] auch mit mehreren Patches"
 
-#: builtin/log.c:1106
+#: builtin/log.c:1162
 msgid "print patches to standard out"
 msgstr "Ausgabe der Patches in Standard-Ausgabe"
 
-#: builtin/log.c:1108
+#: builtin/log.c:1164
 msgid "generate a cover letter"
 msgstr "erzeugt ein Deckblatt"
 
-#: builtin/log.c:1110
+#: builtin/log.c:1166
 msgid "use simple number sequence for output file names"
 msgstr "verwendet einfache Nummernfolge für die Namen der Ausgabedateien"
 
-#: builtin/log.c:1111
+#: builtin/log.c:1167
 msgid "sfx"
 msgstr "Dateiendung"
 
-#: builtin/log.c:1112
+#: builtin/log.c:1168
 msgid "use <sfx> instead of '.patch'"
 msgstr "verwendet <Dateiendung> anstatt '.patch'"
 
-#: builtin/log.c:1114
+#: builtin/log.c:1170
 msgid "start numbering patches at <n> instead of 1"
 msgstr "beginnt die Nummerierung der Patches bei <n> anstatt bei 1"
 
-#: builtin/log.c:1116
+#: builtin/log.c:1172
 msgid "mark the series as Nth re-roll"
 msgstr "kennzeichnet die Serie als n-te Fassung"
 
-#: builtin/log.c:1118
+#: builtin/log.c:1174
 msgid "Use [<prefix>] instead of [PATCH]"
 msgstr "verwendet [<Prefix>] anstatt [PATCH]"
 
-#: builtin/log.c:1121
+#: builtin/log.c:1177
 msgid "store resulting files in <dir>"
 msgstr "speichert erzeugte Dateien in <Verzeichnis>"
 
-#: builtin/log.c:1124
+#: builtin/log.c:1180
 msgid "don't strip/add [PATCH]"
 msgstr "[PATCH] wird nicht entfernt/hinzugefügt"
 
-#: builtin/log.c:1127
+#: builtin/log.c:1183
 msgid "don't output binary diffs"
 msgstr "gibt keine binären Unterschiede aus"
 
-#: builtin/log.c:1129
+#: builtin/log.c:1185
 msgid "don't include a patch matching a commit upstream"
 msgstr ""
-"schließt keine Patches ein, die einer Version im Übernahmezweig entsprechen"
+"schließt keine Patches ein, die einem Commit im Upstream-Branch entsprechen"
 
-#: builtin/log.c:1131
+#: builtin/log.c:1187
 msgid "show patch format instead of default (patch + stat)"
 msgstr "zeigt Patchformat anstatt des Standards (Patch + Zusammenfassung)"
 
-#: builtin/log.c:1133
+#: builtin/log.c:1189
 msgid "Messaging"
 msgstr "Email-Einstellungen"
 
-#: builtin/log.c:1134
+#: builtin/log.c:1190
 msgid "header"
 msgstr "Header"
 
-#: builtin/log.c:1135
+#: builtin/log.c:1191
 msgid "add email header"
 msgstr "fügt Email-Header hinzu"
 
-#: builtin/log.c:1136 builtin/log.c:1138
+#: builtin/log.c:1192 builtin/log.c:1194
 msgid "email"
 msgstr "Email"
 
-#: builtin/log.c:1136
+#: builtin/log.c:1192
 msgid "add To: header"
 msgstr "fügt  \"To:\"-Header hinzu"
 
-#: builtin/log.c:1138
+#: builtin/log.c:1194
 msgid "add Cc: header"
 msgstr "fügt \"Cc:\"-Header hinzu"
 
-#: builtin/log.c:1140
+#: builtin/log.c:1196
+msgid "ident"
+msgstr "Ident"
+
+#: builtin/log.c:1197
+msgid "set From address to <ident> (or committer ident if absent)"
+msgstr ""
+"setzt \"From\"-Adresse auf <Ident> (oder Ident des Commit-Erstellers,wenn "
+"fehlend)"
+
+#: builtin/log.c:1199
 msgid "message-id"
 msgstr "message-id"
 
-#: builtin/log.c:1141
+#: builtin/log.c:1200
 msgid "make first mail a reply to <message-id>"
 msgstr "macht aus erster Email eine Antwort zu <message-id>"
 
-#: builtin/log.c:1142 builtin/log.c:1145
+#: builtin/log.c:1201 builtin/log.c:1204
 msgid "boundary"
 msgstr "Grenze"
 
-#: builtin/log.c:1143
+#: builtin/log.c:1202
 msgid "attach the patch"
 msgstr "hängt einen Patch an"
 
-#: builtin/log.c:1146
+#: builtin/log.c:1205
 msgid "inline the patch"
 msgstr "fügt den Patch direkt in die Nachricht ein"
 
-#: builtin/log.c:1150
+#: builtin/log.c:1209
 msgid "enable message threading, styles: shallow, deep"
 msgstr "aktiviert Nachrichtenverkettung, Stile: shallow, deep"
 
-#: builtin/log.c:1152
+#: builtin/log.c:1211
 msgid "signature"
 msgstr "Signatur"
 
-#: builtin/log.c:1153
+#: builtin/log.c:1212
 msgid "add a signature"
 msgstr "fügt eine Signatur hinzu"
 
-#: builtin/log.c:1155
+#: builtin/log.c:1214
 msgid "don't print the patch filenames"
 msgstr "zeigt keine Dateinamen der Patches"
 
-#: builtin/log.c:1239
+#: builtin/log.c:1288
+#, c-format
+msgid "invalid ident line: %s"
+msgstr "Ungültige Identifikationszeile: %s"
+
+#: builtin/log.c:1303
 msgid "-n and -k are mutually exclusive."
 msgstr "Die Optionen -n und -k schließen sich gegenseitig aus."
 
-#: builtin/log.c:1241
+#: builtin/log.c:1305
 msgid "--subject-prefix and -k are mutually exclusive."
 msgstr "Die Optionen --subject-prefix und -k schließen sich gegenseitig aus."
 
-#: builtin/log.c:1249
+#: builtin/log.c:1313
 msgid "--name-only does not make sense"
 msgstr "Die Option --name-only kann nicht verwendet werden."
 
-#: builtin/log.c:1251
+#: builtin/log.c:1315
 msgid "--name-status does not make sense"
 msgstr "Die Option --name-status kann nicht verwendet werden."
 
-#: builtin/log.c:1253
+#: builtin/log.c:1317
 msgid "--check does not make sense"
 msgstr "Die Option --check kann nicht verwendet werden."
 
-#: builtin/log.c:1276
+#: builtin/log.c:1340
 msgid "standard output, or directory, which one?"
 msgstr "Standard-Ausgabe oder Verzeichnis, welches von beidem?"
 
-#: builtin/log.c:1278
+#: builtin/log.c:1342
 #, c-format
 msgid "Could not create directory '%s'"
 msgstr "Konnte Verzeichnis '%s' nicht erstellen."
 
-#: builtin/log.c:1431
+#: builtin/log.c:1490
 msgid "Failed to create output files"
 msgstr "Fehler beim Erstellen der Ausgabedateien."
 
-#: builtin/log.c:1480
+#: builtin/log.c:1539
 msgid "git cherry [-v] [<upstream> [<head> [<limit>]]]"
-msgstr "git cherry [-v] [<Übernahmezweig> [<Arbeitszweig> [<Limit>]]]"
+msgstr "git cherry [-v] [<Upstream> [<Branch> [<Limit>]]]"
 
-#: builtin/log.c:1535
+#: builtin/log.c:1594
 #, c-format
 msgid ""
 "Could not find a tracked remote branch, please specify <upstream> manually.\n"
 msgstr ""
-"Konnte gefolgten, externen Zweig nicht finden, bitte geben Sie <upstream> "
+"Konnte gefolgten Remote-Branch nicht finden, bitte geben Sie <Upstream> "
 "manuell an.\n"
 
-#: builtin/log.c:1548 builtin/log.c:1550 builtin/log.c:1562
+#: builtin/log.c:1607 builtin/log.c:1609 builtin/log.c:1621
 #, c-format
 msgid "Unknown commit %s"
-msgstr "Unbekannte Version %s"
+msgstr "Unbekannter Commit %s"
 
-#: builtin/ls-files.c:409
+#: builtin/ls-files.c:408
 msgid "git ls-files [options] [<file>...]"
 msgstr "git ls-files [Optionen] [<Datei>...]"
 
-#: builtin/ls-files.c:466
+#: builtin/ls-files.c:465
 msgid "identify the file status with tags"
-msgstr "zeigt den Dateistatus mit Markierungen"
+msgstr "zeigt den Dateistatus mit Tags"
 
-#: builtin/ls-files.c:468
+#: builtin/ls-files.c:467
 msgid "use lowercase letters for 'assume unchanged' files"
 msgstr ""
 "verwendet Kleinbuchstaben für Dateien mit 'assume unchanged' Markierung"
 
-#: builtin/ls-files.c:470
+#: builtin/ls-files.c:469
 msgid "show cached files in the output (default)"
 msgstr "zeigt zwischengespeicherten Dateien in der Ausgabe an (Standard)"
 
-#: builtin/ls-files.c:472
+#: builtin/ls-files.c:471
 msgid "show deleted files in the output"
 msgstr "zeigt entfernte Dateien in der Ausgabe an"
 
-#: builtin/ls-files.c:474
+#: builtin/ls-files.c:473
 msgid "show modified files in the output"
 msgstr "zeigt geänderte Dateien in der Ausgabe an"
 
-#: builtin/ls-files.c:476
+#: builtin/ls-files.c:475
 msgid "show other files in the output"
 msgstr "zeigt sonstige Dateien in der Ausgabe an"
 
-#: builtin/ls-files.c:478
+#: builtin/ls-files.c:477
 msgid "show ignored files in the output"
 msgstr "zeigt ignorierte Dateien in der Ausgabe an"
 
-#: builtin/ls-files.c:481
+#: builtin/ls-files.c:480
 msgid "show staged contents' object name in the output"
-msgstr "zeigt Objektnamen von Inhalten in der Bereitstellung in der Ausgabe an"
+msgstr ""
+"zeigt Objektnamen von Inhalten, die zum Commit vorgemerkt sind, in der "
+"Ausgabe an"
 
-#: builtin/ls-files.c:483
+#: builtin/ls-files.c:482
 msgid "show files on the filesystem that need to be removed"
 msgstr "zeigt Dateien im Dateisystem, die gelöscht werden müssen, an"
 
-#: builtin/ls-files.c:485
+#: builtin/ls-files.c:484
 msgid "show 'other' directories' name only"
 msgstr "zeigt nur Namen von 'sonstigen' Verzeichnissen an"
 
-#: builtin/ls-files.c:488
+#: builtin/ls-files.c:487
 msgid "don't show empty directories"
 msgstr "zeigt keine leeren Verzeichnisse an"
 
-#: builtin/ls-files.c:491
+#: builtin/ls-files.c:490
 msgid "show unmerged files in the output"
 msgstr "zeigt nicht zusammengeführte Dateien in der Ausgabe an"
 
-#: builtin/ls-files.c:493
+#: builtin/ls-files.c:492
 msgid "show resolve-undo information"
 msgstr "zeigt 'resolve-undo' Informationen an"
 
-#: builtin/ls-files.c:495
+#: builtin/ls-files.c:494
 msgid "skip files matching pattern"
 msgstr "lässt Dateien aus, die einem Muster entsprechen"
 
-#: builtin/ls-files.c:498
+#: builtin/ls-files.c:497
 msgid "exclude patterns are read from <file>"
 msgstr "schließt Muster, gelesen von <Datei>, aus"
 
-#: builtin/ls-files.c:501
+#: builtin/ls-files.c:500
 msgid "read additional per-directory exclude patterns in <file>"
 msgstr "liest zusätzliche pro-Verzeichnis Auschlussmuster aus <Datei>"
 
-#: builtin/ls-files.c:503
+#: builtin/ls-files.c:502
 msgid "add the standard git exclusions"
 msgstr "fügt die standardmäßigen Git-Ausschlüsse hinzu"
 
-#: builtin/ls-files.c:506
+#: builtin/ls-files.c:505
 msgid "make the output relative to the project top directory"
 msgstr "Ausgabe relativ zum Projektverzeichnis"
 
-#: builtin/ls-files.c:509
+#: builtin/ls-files.c:508
 msgid "if any <file> is not in the index, treat this as an error"
 msgstr ""
-"behandle es als Fehler, wenn sich eine <Datei> nicht in der Bereitstellung "
+"behandle es als Fehler, wenn sich eine <Datei> nicht in der Staging-Area "
 "befindet"
 
-#: builtin/ls-files.c:510
+#: builtin/ls-files.c:509
 msgid "tree-ish"
-msgstr "Versionsreferenz"
+msgstr "Commit-Referenz"
 
-#: builtin/ls-files.c:511
+#: builtin/ls-files.c:510
 msgid "pretend that paths removed since <tree-ish> are still present"
 msgstr ""
-"gibt vor, dass Pfade, die seit <Versionsreferenz> gelöscht wurden, immer "
-"noch vorhanden sind"
+"gibt vor, dass Pfade, die seit <Commit-Referenz> gelöscht wurden, immer noch "
+"vorhanden sind"
 
-#: builtin/ls-files.c:513
+#: builtin/ls-files.c:512
 msgid "show debugging data"
 msgstr "zeigt Ausgaben zur Fehlersuche an"
 
 #: builtin/ls-tree.c:27
 msgid "git ls-tree [<options>] <tree-ish> [<path>...]"
-msgstr "git ls-tree [<Optionen>] <Versionsreferenz> [<Pfad>...]"
+msgstr "git ls-tree [<Optionen>] <Commit-Referenz> [<Pfad>...]"
 
 #: builtin/ls-tree.c:125
 msgid "only show trees"
-msgstr "zeigt nur Bäume an"
+msgstr "zeigt nur Verzeichnisse an"
 
 #: builtin/ls-tree.c:127
 msgid "recurse into subtrees"
-msgstr "führt Rekursion in Teilbäumen durch"
+msgstr "führt Rekursion in Unterverzeichnissen durch"
 
 #: builtin/ls-tree.c:129
 msgid "show trees when recursing"
-msgstr "zeigt Bäume bei Rekursion an"
+msgstr "zeigt Verzeichnisse bei Rekursion an"
 
 #: builtin/ls-tree.c:132
 msgid "terminate entries with NUL byte"
@@ -6106,195 +6542,187 @@
 #: builtin/ls-tree.c:142
 msgid "list entire tree; not just current directory (implies --full-name)"
 msgstr ""
-"listet den gesamten Baum auf; nicht nur das aktuelle Verzeichnis (impliziert "
-"--full-name)"
+"listet das gesamte Verzeichnis auf; nicht nur das aktuelle Verzeichnis "
+"(impliziert --full-name)"
 
 #: builtin/merge.c:43
 msgid "git merge [options] [<commit>...]"
-msgstr "git merge [Optionen] [<Version>...]"
+msgstr "git merge [Optionen] [<Commit>...]"
 
 #: builtin/merge.c:44
 msgid "git merge [options] <msg> HEAD <commit>"
-msgstr "git merge [Optionen] <Beschreibung> HEAD <Version>"
+msgstr "git merge [Optionen] <Beschreibung> HEAD <Commit>"
 
 #: builtin/merge.c:45
 msgid "git merge --abort"
 msgstr "git merge --abort"
 
-#: builtin/merge.c:90
+#: builtin/merge.c:98
 msgid "switch `m' requires a value"
 msgstr "Schalter 'm' erfordert einen Wert."
 
-#: builtin/merge.c:127
+#: builtin/merge.c:135
 #, c-format
 msgid "Could not find merge strategy '%s'.\n"
-msgstr "Konnte Zusammenführungsstrategie '%s' nicht finden.\n"
+msgstr "Konnte Merge-Strategie '%s' nicht finden.\n"
 
-#: builtin/merge.c:128
+#: builtin/merge.c:136
 #, c-format
 msgid "Available strategies are:"
 msgstr "Verfügbare Strategien sind:"
 
-#: builtin/merge.c:133
+#: builtin/merge.c:141
 #, c-format
 msgid "Available custom strategies are:"
 msgstr "Verfügbare benutzerdefinierte Strategien sind:"
 
-#: builtin/merge.c:183
+#: builtin/merge.c:198
 msgid "do not show a diffstat at the end of the merge"
-msgstr ""
-"zeigt keine Zusammenfassung der Unterschiede am Schluss der Zusammenführung "
-"an"
+msgstr "zeigt keine Zusammenfassung der Unterschiede am Schluss des Merges an"
 
-#: builtin/merge.c:186
+#: builtin/merge.c:201
 msgid "show a diffstat at the end of the merge"
-msgstr ""
-"zeigt eine Zusammenfassung der Unterschiede am Schluss der Zusammenführung an"
+msgstr "zeigt eine Zusammenfassung der Unterschiede am Schluss des Merges an"
 
-#: builtin/merge.c:187
+#: builtin/merge.c:202
 msgid "(synonym to --stat)"
 msgstr "(Synonym für --stat)"
 
-#: builtin/merge.c:189
+#: builtin/merge.c:204
 msgid "add (at most <n>) entries from shortlog to merge commit message"
 msgstr ""
-"fügt (höchstens <n>) Einträge von \"shortlog\" zur Beschreibung der "
-"Zusammenführung hinzu"
+"fügt (höchstens <n>) Einträge von \"shortlog\" zur Beschreibung des Merge-"
+"Commits hinzu"
 
-#: builtin/merge.c:192
+#: builtin/merge.c:207
 msgid "create a single commit instead of doing a merge"
-msgstr "erzeugt eine einzelne Version anstatt einer Zusammenführung"
+msgstr "erzeugt einen einzelnen Commit anstatt eines Merges"
 
-#: builtin/merge.c:194
+#: builtin/merge.c:209
 msgid "perform a commit if the merge succeeds (default)"
-msgstr ""
-"führt eine Eintragung durch, wenn die Zusammenführung erfolgreich war "
-"(Standard)"
+msgstr "führt einen Commit durch, wenn der Merge erfolgreich war (Standard)"
 
-#: builtin/merge.c:196
+#: builtin/merge.c:211
 msgid "edit message before committing"
-msgstr "Bearbeitung der Versionsbeschreibung vor der Eintragung"
+msgstr "Bearbeitung der Beschreibung vor dem Commit"
 
-#: builtin/merge.c:198
+#: builtin/merge.c:212
 msgid "allow fast-forward (default)"
 msgstr "erlaubt Vorspulen (Standard)"
 
-#: builtin/merge.c:200
+#: builtin/merge.c:214
 msgid "abort if fast-forward is not possible"
 msgstr "bricht ab, wenn kein Vorspulen möglich ist"
 
-#: builtin/merge.c:203
+#: builtin/merge.c:218
 msgid "Verify that the named commit has a valid GPG signature"
-msgstr "überprüft die genannte Version auf eine gültige GPG-Signatur"
+msgstr "überprüft den genannten Commit auf eine gültige GPG-Signatur"
 
-#: builtin/merge.c:204 builtin/notes.c:866 builtin/revert.c:112
+#: builtin/merge.c:219 builtin/notes.c:738 builtin/revert.c:114
 msgid "strategy"
 msgstr "Strategie"
 
-#: builtin/merge.c:205
+#: builtin/merge.c:220
 msgid "merge strategy to use"
-msgstr "zu verwendende Zusammenführungsstrategie"
+msgstr "zu verwendende Merge-Strategie"
 
-#: builtin/merge.c:206
+#: builtin/merge.c:221
 msgid "option=value"
 msgstr "Option=Wert"
 
-#: builtin/merge.c:207
+#: builtin/merge.c:222
 msgid "option for selected merge strategy"
-msgstr "Option für ausgewählte Zusammenführungsstrategie"
+msgstr "Option für ausgewählte Merge-Strategie"
 
-#: builtin/merge.c:209
+#: builtin/merge.c:224
 msgid "merge commit message (for a non-fast-forward merge)"
 msgstr ""
-"führt Versionsbeschreibung zusammen (für eine Zusammenführung, die kein "
-"Vorspulen war)"
+"führt Commit-Beschreibung zusammen (für einen Merge, der kein Vorspulen war)"
 
-#: builtin/merge.c:213
+#: builtin/merge.c:228
 msgid "abort the current in-progress merge"
-msgstr "bricht die sich im Gange befindliche Zusammenführung ab"
+msgstr "bricht den sich im Gange befindlichen Merge ab"
 
-#: builtin/merge.c:242
+#: builtin/merge.c:257
 msgid "could not run stash."
 msgstr "Konnte \"stash\" nicht ausführen."
 
-#: builtin/merge.c:247
+#: builtin/merge.c:262
 msgid "stash failed"
 msgstr "\"stash\" fehlgeschlagen"
 
-#: builtin/merge.c:252
+#: builtin/merge.c:267
 #, c-format
 msgid "not a valid object: %s"
 msgstr "kein gültiges Objekt: %s"
 
-#: builtin/merge.c:271 builtin/merge.c:288
+#: builtin/merge.c:286 builtin/merge.c:303
 msgid "read-tree failed"
 msgstr "read-tree fehlgeschlagen"
 
-#: builtin/merge.c:318
+#: builtin/merge.c:333
 msgid " (nothing to squash)"
 msgstr " (nichts zu quetschen)"
 
-#: builtin/merge.c:331
+#: builtin/merge.c:346
 #, c-format
 msgid "Squash commit -- not updating HEAD\n"
-msgstr "Quetsche Version -- Zweigspitze (HEAD) wird nicht aktualisiert\n"
+msgstr "Quetsche Commit -- HEAD wird nicht aktualisiert\n"
 
-#: builtin/merge.c:363
+#: builtin/merge.c:378
 msgid "Writing SQUASH_MSG"
 msgstr "Schreibe SQUASH_MSG"
 
-#: builtin/merge.c:365
+#: builtin/merge.c:380
 msgid "Finishing SQUASH_MSG"
 msgstr "Schließe SQUASH_MSG ab"
 
-#: builtin/merge.c:388
+#: builtin/merge.c:403
 #, c-format
 msgid "No merge message -- not updating HEAD\n"
-msgstr ""
-"Keine Zusammenführungsbeschreibung -- Zweigspitze (HEAD) wird nicht "
-"aktualisiert\n"
+msgstr "Keine Merge-Commit-Beschreibung -- HEAD wird nicht aktualisiert\n"
 
-#: builtin/merge.c:438
+#: builtin/merge.c:453
 #, c-format
 msgid "'%s' does not point to a commit"
-msgstr "'%s' zeigt auf keine Version"
+msgstr "'%s' zeigt auf keinen Commit"
 
-#: builtin/merge.c:550
+#: builtin/merge.c:565
 #, c-format
 msgid "Bad branch.%s.mergeoptions string: %s"
 msgstr "Ungültiger branch.%s.mergeoptions String: %s"
 
-#: builtin/merge.c:643
+#: builtin/merge.c:657
 msgid "git write-tree failed to write a tree"
-msgstr "\"git write-tree\" schlug beim Schreiben eines Baumes fehl"
-
-#: builtin/merge.c:671
-msgid "Not handling anything other than two heads merge."
-msgstr "Es wird nur die Zusammenführung von zwei Zweigen behandelt."
+msgstr "\"git write-tree\" schlug beim Schreiben eines \"Tree\"-Objektes fehl"
 
 #: builtin/merge.c:685
+msgid "Not handling anything other than two heads merge."
+msgstr "Es wird nur der Merge von zwei Branches behandelt."
+
+#: builtin/merge.c:699
 #, c-format
 msgid "Unknown option for merge-recursive: -X%s"
 msgstr "Unbekannte Option für merge-recursive: -X%s"
 
-#: builtin/merge.c:699
+#: builtin/merge.c:713
 #, c-format
 msgid "unable to write %s"
 msgstr "konnte %s nicht schreiben"
 
-#: builtin/merge.c:788
+#: builtin/merge.c:802
 #, c-format
 msgid "Could not read from '%s'"
 msgstr "konnte nicht von '%s' lesen"
 
-#: builtin/merge.c:797
+#: builtin/merge.c:811
 #, c-format
 msgid "Not committing merge; use 'git commit' to complete the merge.\n"
 msgstr ""
-"Zusammenführung wurde nicht eingetragen; benutzen Sie 'git commit' um die "
-"Zusammenführung abzuschließen.\n"
+"Merge wurde nicht committet; benutzen Sie 'git commit' um den Merge "
+"abzuschließen.\n"
 
-#: builtin/merge.c:803
+#: builtin/merge.c:817
 #, c-format
 msgid ""
 "Please enter a commit message to explain why this merge is necessary,\n"
@@ -6303,219 +6731,212 @@
 "Lines starting with '%c' will be ignored, and an empty message aborts\n"
 "the commit.\n"
 msgstr ""
-"Bitte geben Sie eine Versionsbeschreibung ein um zu erklären, warum diese "
-"Zusammenführung erforderlich ist,\n"
-"insbesondere wenn es einen aktualisierten, externen Zweig mit einem Thema-"
-"Zweig zusammenführt.\n"
+"Bitte geben Sie eine Commit-Beschreibung ein um zu erklären, warum dieser\n"
+"Merge erforderlich ist, insbesondere wenn es einen aktualisierten\n"
+"Upstream-Branch mit einem Thema-Branch zusammenführt.\n"
 "\n"
-"Zeilen beginnend mit '%c' werden ignoriert, und eine leere Beschreibung "
-"bricht die Eintragung ab.\n"
+"Zeilen beginnend mit '%c' werden ignoriert, und eine leere Beschreibung\n"
+"bricht den Commit ab.\n"
 
-#: builtin/merge.c:827
+#: builtin/merge.c:841
 msgid "Empty commit message."
-msgstr "Leere Versionsbeschreibung"
+msgstr "Leere Commit-Beschreibung"
 
-#: builtin/merge.c:839
+#: builtin/merge.c:853
 #, c-format
 msgid "Wonderful.\n"
 msgstr "Wunderbar.\n"
 
-#: builtin/merge.c:904
+#: builtin/merge.c:918
 #, c-format
 msgid "Automatic merge failed; fix conflicts and then commit the result.\n"
 msgstr ""
-"Automatische Zusammenführung fehlgeschlagen; beheben Sie die Konflikte und "
-"tragen Sie dann das Ergebnis ein.\n"
+"Automatischer Merge fehlgeschlagen; beheben Sie die Konflikte und committen "
+"Sie dann das Ergebnis.\n"
 
-#: builtin/merge.c:920
+#: builtin/merge.c:934
 #, c-format
 msgid "'%s' is not a commit"
-msgstr "'%s' ist keine Version"
+msgstr "'%s' ist kein Commit"
 
-#: builtin/merge.c:961
+#: builtin/merge.c:975
 msgid "No current branch."
-msgstr "Sie befinden sich auf keinem Zweig."
+msgstr "Sie befinden sich auf keinem Branch."
 
-#: builtin/merge.c:963
+#: builtin/merge.c:977
 msgid "No remote for the current branch."
-msgstr "Kein externes Archiv für den aktuellen Zweig."
+msgstr "Kein Remote-Repository für den aktuellen Branch."
 
-#: builtin/merge.c:965
+#: builtin/merge.c:979
 msgid "No default upstream defined for the current branch."
 msgstr ""
-"Es ist kein externes Standard-Projektarchiv für den aktuellen Zweig "
-"definiert."
+"Es ist kein Standard-Upstream-Branch für den aktuellen Branch definiert."
 
-#: builtin/merge.c:970
+#: builtin/merge.c:984
 #, c-format
-msgid "No remote tracking branch for %s from %s"
-msgstr "Kein externer Übernahmezweig für %s von %s"
+msgid "No remote-tracking branch for %s from %s"
+msgstr "Kein Remote-Tracking-Branch für %s von %s"
 
-#: builtin/merge.c:1057 builtin/merge.c:1214
-#, c-format
-msgid "%s - not something we can merge"
-msgstr "%s - nichts was wir zusammenführen können"
-
-#: builtin/merge.c:1125
+#: builtin/merge.c:1140
 msgid "There is no merge to abort (MERGE_HEAD missing)."
-msgstr "Es gibt keine Zusammenführung zum Abbrechen (vermisse MERGE_HEAD)"
+msgstr "Es gibt keinen Merge zum Abbrechen (vermisse MERGE_HEAD)"
 
-#: builtin/merge.c:1141 git-pull.sh:31
+#: builtin/merge.c:1156 git-pull.sh:31
 msgid ""
 "You have not concluded your merge (MERGE_HEAD exists).\n"
 "Please, commit your changes before you can merge."
 msgstr ""
-"Sie haben Ihre Zusammenführung nicht abgeschlossen (MERGE_HEAD existiert).\n"
-"Bitte tragen Sie Ihre Änderungen ein, bevor Sie zusammenführen können."
+"Sie haben Ihren Merge nicht abgeschlossen (MERGE_HEAD existiert).\n"
+"Bitte committen Sie Ihre Änderungen, bevor Sie \"merge\" ausführen können."
 
-#: builtin/merge.c:1144 git-pull.sh:34
+#: builtin/merge.c:1159 git-pull.sh:34
 msgid "You have not concluded your merge (MERGE_HEAD exists)."
-msgstr ""
-"Sie haben Ihre Zusammenführung nicht abgeschlossen (MERGE_HEAD existiert)."
+msgstr "Sie haben Ihren Merge nicht abgeschlossen (MERGE_HEAD existiert)."
 
-#: builtin/merge.c:1148
+#: builtin/merge.c:1163
 msgid ""
 "You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists).\n"
 "Please, commit your changes before you can merge."
 msgstr ""
 "Sie haben \"cherry-pick\" nicht abgeschlossen (CHERRY_PICK_HEAD existiert).\n"
-"Bitte tragen Sie Ihre Änderungen ein, bevor Sie zusammenführen können."
+"Bitte committen Sie Ihre Änderungen, bevor Sie \"merge\" ausführen können."
 
-#: builtin/merge.c:1151
+#: builtin/merge.c:1166
 msgid "You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists)."
 msgstr ""
 "Sie haben \"cherry-pick\" nicht abgeschlossen (CHERRY_PICK_HEAD existiert)."
 
-#: builtin/merge.c:1160
+#: builtin/merge.c:1175
 msgid "You cannot combine --squash with --no-ff."
 msgstr "Sie können --squash nicht mit --no-ff kombinieren."
 
-#: builtin/merge.c:1165
-msgid "You cannot combine --no-ff with --ff-only."
-msgstr "Sie können --no-ff nicht mit --ff--only kombinieren."
-
-#: builtin/merge.c:1172
+#: builtin/merge.c:1184
 msgid "No commit specified and merge.defaultToUpstream not set."
-msgstr "Keine Version angegeben und merge.defaultToUpstream ist nicht gesetzt."
+msgstr "Kein Commit angegeben und merge.defaultToUpstream ist nicht gesetzt."
 
-#: builtin/merge.c:1204
+#: builtin/merge.c:1216
 msgid "Can merge only exactly one commit into empty head"
-msgstr "Kann nur exakt eine Version in einem leeren Zweig zusammenführen."
+msgstr "Kann nur exakt einen Commit in einem leeren Branch zusammenführen."
 
-#: builtin/merge.c:1207
+#: builtin/merge.c:1219
 msgid "Squash commit into empty head not supported yet"
-msgstr "Bin auf einem Zweig, der noch geboren wird; kann nicht quetschen."
+msgstr ""
+"Bin auf einem Commit, der noch geboren wird; kann \"squash\" nicht ausführen."
 
-#: builtin/merge.c:1209
+#: builtin/merge.c:1221
 msgid "Non-fast-forward commit does not make sense into an empty head"
 msgstr ""
-"Nicht vorzuspulende Version kann nicht in einem leeren Zweig verwendet "
+"Nicht vorzuspulender Commit kann nicht in einem leeren Branch verwendet "
 "werden."
 
-#: builtin/merge.c:1265
+#: builtin/merge.c:1226
+#, c-format
+msgid "%s - not something we can merge"
+msgstr "%s - nichts was wir zusammenführen können"
+
+#: builtin/merge.c:1277
 #, c-format
 msgid "Commit %s has an untrusted GPG signature, allegedly by %s."
-msgstr "Version %s hat eine nicht vertrauenswürdige GPG-Signatur, "
-"angeblich von %s."
+msgstr ""
+"Commit %s hat eine nicht vertrauenswürdige GPG-Signatur, angeblich von %s."
 
-#: builtin/merge.c:1268
+#: builtin/merge.c:1280
 #, c-format
 msgid "Commit %s has a bad GPG signature allegedly by %s."
-msgstr "Version %s hat eine ungültige GPG-Signatur, angeblich von %s."
+msgstr "Commit %s hat eine ungültige GPG-Signatur, angeblich von %s."
 
 #. 'N'
-#: builtin/merge.c:1271
+#: builtin/merge.c:1283
 #, c-format
 msgid "Commit %s does not have a GPG signature."
-msgstr "Version %s hat keine GPG-Signatur."
+msgstr "Commit %s hat keine GPG-Signatur."
 
-#: builtin/merge.c:1274
+#: builtin/merge.c:1286
 #, c-format
 msgid "Commit %s has a good GPG signature by %s\n"
-msgstr "Version %s hat eine gültige GPG-Signatur von %s\n"
+msgstr "Commit %s hat eine gültige GPG-Signatur von %s\n"
 
-#: builtin/merge.c:1358
+#: builtin/merge.c:1370
 #, c-format
 msgid "Updating %s..%s\n"
 msgstr "Aktualisiere %s..%s\n"
 
-#: builtin/merge.c:1397
+#: builtin/merge.c:1409
 #, c-format
 msgid "Trying really trivial in-index merge...\n"
-msgstr "Probiere wirklich triviale \"in-index\"-Zusammenführung...\n"
+msgstr "Probiere wirklich trivialen \"in-index\"-Merge...\n"
 
-#: builtin/merge.c:1404
+#: builtin/merge.c:1416
 #, c-format
 msgid "Nope.\n"
 msgstr "Nein.\n"
 
-#: builtin/merge.c:1436
+#: builtin/merge.c:1448
 msgid "Not possible to fast-forward, aborting."
 msgstr "Vorspulen nicht möglich, breche ab."
 
-#: builtin/merge.c:1459 builtin/merge.c:1538
+#: builtin/merge.c:1471 builtin/merge.c:1550
 #, c-format
 msgid "Rewinding the tree to pristine...\n"
-msgstr "Rücklauf des Zweiges bis zum Ursprung...\n"
+msgstr "Rücklauf des Verzeichnisses bis zum Ursprung...\n"
 
-#: builtin/merge.c:1463
+#: builtin/merge.c:1475
 #, c-format
 msgid "Trying merge strategy %s...\n"
-msgstr "Probiere Zusammenführungsstrategie %s...\n"
+msgstr "Probiere Merge-Strategie %s...\n"
 
-#: builtin/merge.c:1529
+#: builtin/merge.c:1541
 #, c-format
 msgid "No merge strategy handled the merge.\n"
-msgstr "Keine Zusammenführungsstrategie behandelt diese Zusammenführung.\n"
+msgstr "Keine Merge-Strategie behandelt diesen Merge.\n"
 
-#: builtin/merge.c:1531
+#: builtin/merge.c:1543
 #, c-format
 msgid "Merge with strategy %s failed.\n"
-msgstr "Zusammenführung mit Strategie %s fehlgeschlagen.\n"
+msgstr "Merge mit Strategie %s fehlgeschlagen.\n"
 
-#: builtin/merge.c:1540
+#: builtin/merge.c:1552
 #, c-format
 msgid "Using the %s to prepare resolving by hand.\n"
 msgstr "Benutzen Sie \"%s\" um die Auflösung per Hand vorzubereiten.\n"
 
-#: builtin/merge.c:1552
+#: builtin/merge.c:1564
 #, c-format
 msgid "Automatic merge went well; stopped before committing as requested\n"
 msgstr ""
-"Automatische Zusammenführung abgeschlossen; halte, wie gewünscht, vor der "
-"Eintragung an\n"
+"Automatischer Merge abgeschlossen; halte, wie gewünscht, vor dem Commit an\n"
 
 #: builtin/merge-base.c:26
 msgid "git merge-base [-a|--all] <commit> <commit>..."
-msgstr "git merge-base [-a|--all] <Version> <Version>..."
+msgstr "git merge-base [-a|--all] <Commit> <Commit>..."
 
 #: builtin/merge-base.c:27
 msgid "git merge-base [-a|--all] --octopus <commit>..."
-msgstr "git merge-base [-a|--all] --octopus <Version>..."
+msgstr "git merge-base [-a|--all] --octopus <Commit>..."
 
 #: builtin/merge-base.c:28
 msgid "git merge-base --independent <commit>..."
-msgstr "git merge-base --independent <Version>..."
+msgstr "git merge-base --independent <Commit>..."
 
 #: builtin/merge-base.c:29
 msgid "git merge-base --is-ancestor <commit> <commit>"
-msgstr "git merge-base --is-ancestor <Version> <Version>"
+msgstr "git merge-base --is-ancestor <Commit> <Commit>"
 
 #: builtin/merge-base.c:98
 msgid "output all common ancestors"
-msgstr "Ausgabe aller gemeinsamen Vorfahren"
+msgstr "Ausgabe aller gemeinsamen Vorgänger-Commits"
 
 #: builtin/merge-base.c:99
 msgid "find ancestors for a single n-way merge"
-msgstr "findet Vorfahren für eine einzelne n-Wege-Zusammenführung"
+msgstr "findet Vorgänger-Commits für einen einzelnen n-Wege-Merge"
 
 #: builtin/merge-base.c:100
 msgid "list revs not reachable from others"
-msgstr "listet Versionen auf, die nicht durch Andere erreichbar sind"
+msgstr "listet Commits auf, die nicht durch Andere erreichbar sind"
 
 #: builtin/merge-base.c:102
 msgid "is the first one ancestor of the other?"
-msgstr "ist der Erste ein Vorfahre von dem Anderen?"
+msgstr "ist der Erste ein Vorgänger-Commit von dem Anderen?"
 
 #: builtin/merge-file.c:8
 msgid ""
@@ -6531,7 +6952,7 @@
 
 #: builtin/merge-file.c:34
 msgid "use a diff3 based merge"
-msgstr "verwendet eine diff3 basierte Zusammenführung"
+msgstr "verwendet einen diff3 basierten Merge"
 
 #: builtin/merge-file.c:35
 msgid "for conflicts, use our version"
@@ -6571,7 +6992,7 @@
 
 #: builtin/mktree.c:155
 msgid "allow creation of more than one tree"
-msgstr "erlaubt die Erstellung von mehr als einem Baum"
+msgstr "erlaubt die Erstellung von mehr als einem \"Tree\"-Objekt"
 
 #: builtin/mv.c:14
 msgid "git mv [options] <source>... <destination>"
@@ -6605,7 +7026,7 @@
 #: builtin/mv.c:128
 #, c-format
 msgid "Huh? %.*s is in index?"
-msgstr "Huh? %.*s ist in der Bereitstellung?"
+msgstr "Huh? %.*s ist zum Commit vorgemerkt?"
 
 #: builtin/mv.c:140
 msgid "source directory is empty"
@@ -6647,47 +7068,51 @@
 msgid "renaming '%s' failed"
 msgstr "Umbenennung von '%s' fehlgeschlagen"
 
-#: builtin/name-rev.c:175
+#: builtin/name-rev.c:259
 msgid "git name-rev [options] <commit>..."
-msgstr "git name-rev [Optionen] <Version>..."
+msgstr "git name-rev [Optionen] <Commit>..."
 
-#: builtin/name-rev.c:176
+#: builtin/name-rev.c:260
 msgid "git name-rev [options] --all"
 msgstr "git name-rev [Optionen] --all"
 
-#: builtin/name-rev.c:177
+#: builtin/name-rev.c:261
 msgid "git name-rev [options] --stdin"
 msgstr "git name-rev [Optionen] --stdin"
 
-#: builtin/name-rev.c:229
+#: builtin/name-rev.c:313
 msgid "print only names (no SHA-1)"
 msgstr "zeigt nur Namen an (keine SHA-1)"
 
-#: builtin/name-rev.c:230
+#: builtin/name-rev.c:314
 msgid "only use tags to name the commits"
-msgstr "verwendet nur Markierungen um die Versionen zu benennen"
+msgstr "verwendet nur Tags um die Commits zu benennen"
 
-#: builtin/name-rev.c:232
+#: builtin/name-rev.c:316
 msgid "only use refs matching <pattern>"
 msgstr "verwendet nur Referenzen die <Muster> entsprechen"
 
-#: builtin/name-rev.c:234
+#: builtin/name-rev.c:318
 msgid "list all commits reachable from all refs"
-msgstr "listet alle Versionen auf, die von allen Referenzen erreichbar sind"
+msgstr "listet alle Commits auf, die von allen Referenzen erreichbar sind"
 
-#: builtin/name-rev.c:235
+#: builtin/name-rev.c:319
 msgid "read from stdin"
 msgstr "liest von der Standard-Eingabe"
 
-#: builtin/name-rev.c:236
+#: builtin/name-rev.c:320
 msgid "allow to print `undefined` names"
 msgstr "erlaubt Ausgabe von `undefinierten` Namen"
 
-#: builtin/notes.c:26
+#: builtin/name-rev.c:326
+msgid "dereference tags in the input (internal use)"
+msgstr "dereferenziert Tags in der Eingabe (interne Verwendung)"
+
+#: builtin/notes.c:24
 msgid "git notes [--ref <notes_ref>] [list [<object>]]"
 msgstr "git notes [--ref <Notiz-Referenz>] [list [<Objekt>]]"
 
-#: builtin/notes.c:27
+#: builtin/notes.c:25
 msgid ""
 "git notes [--ref <notes_ref>] add [-f] [-m <msg> | -F <file> | (-c | -C) "
 "<object>] [<object>]"
@@ -6695,12 +7120,12 @@
 "git notes [--ref <Notiz-Referenz>] add [-f] [-m <Nachricht> | -F <Datei> | (-"
 "c | -C) <Objekt>] [<Objekt>]"
 
-#: builtin/notes.c:28
+#: builtin/notes.c:26
 msgid "git notes [--ref <notes_ref>] copy [-f] <from-object> <to-object>"
 msgstr ""
 "git notes [--ref <Notiz-Referenz>] copy [-f] <von-Objekt> <nach-Objekt>"
 
-#: builtin/notes.c:29
+#: builtin/notes.c:27
 msgid ""
 "git notes [--ref <notes_ref>] append [-m <msg> | -F <file> | (-c | -C) "
 "<object>] [<object>]"
@@ -6708,223 +7133,201 @@
 "git notes [--ref <Notiz-Referenz>] append [-m <Nachricht> | -F <Datei> | (-c "
 "| -C) <Objekt>] [<Objekt>]"
 
-#: builtin/notes.c:30
+#: builtin/notes.c:28
 msgid "git notes [--ref <notes_ref>] edit [<object>]"
 msgstr "git notes [--ref <Notiz-Referenz>] edit [<Objekt>]"
 
-#: builtin/notes.c:31
+#: builtin/notes.c:29
 msgid "git notes [--ref <notes_ref>] show [<object>]"
 msgstr "git notes [--ref <Notiz-Referenz>] show [<Objekt>]"
 
-#: builtin/notes.c:32
+#: builtin/notes.c:30
 msgid ""
 "git notes [--ref <notes_ref>] merge [-v | -q] [-s <strategy> ] <notes_ref>"
 msgstr ""
 "git notes [--ref <Notiz-Referenz>] merge [-v | -q] [-s <Strategie> ] <Notiz-"
 "Referenz>"
 
-#: builtin/notes.c:33
+#: builtin/notes.c:31
 msgid "git notes merge --commit [-v | -q]"
 msgstr "git notes merge --commit [-v | -q]"
 
-#: builtin/notes.c:34
+#: builtin/notes.c:32
 msgid "git notes merge --abort [-v | -q]"
 msgstr "git notes merge --abort [-v | -q]"
 
-#: builtin/notes.c:35
+#: builtin/notes.c:33
 msgid "git notes [--ref <notes_ref>] remove [<object>...]"
 msgstr "git notes [--ref <Notiz-Referenz>] remove [<Objekt>...]"
 
-#: builtin/notes.c:36
+#: builtin/notes.c:34
 msgid "git notes [--ref <notes_ref>] prune [-n | -v]"
 msgstr "git notes [--ref <Notiz-Referenz>] prune [-n | -v]"
 
-#: builtin/notes.c:37
+#: builtin/notes.c:35
 msgid "git notes [--ref <notes_ref>] get-ref"
 msgstr "git notes [--ref <Notiz-Referenz>] get-ref"
 
-#: builtin/notes.c:42
+#: builtin/notes.c:40
 msgid "git notes [list [<object>]]"
 msgstr "git notes [list [<Objekt>]]"
 
-#: builtin/notes.c:47
+#: builtin/notes.c:45
 msgid "git notes add [<options>] [<object>]"
 msgstr "git notes add [<Optionen>] [<Objekt>]"
 
-#: builtin/notes.c:52
+#: builtin/notes.c:50
 msgid "git notes copy [<options>] <from-object> <to-object>"
 msgstr "git notes copy [<Optionen>] <von-Objekt> <nach-Objekt>"
 
-#: builtin/notes.c:53
+#: builtin/notes.c:51
 msgid "git notes copy --stdin [<from-object> <to-object>]..."
 msgstr "git notes copy --stdin [<von-Objekt> <nach-Objekt>]..."
 
-#: builtin/notes.c:58
+#: builtin/notes.c:56
 msgid "git notes append [<options>] [<object>]"
 msgstr "git notes append [<Optionen>] [<Objekt>]"
 
-#: builtin/notes.c:63
+#: builtin/notes.c:61
 msgid "git notes edit [<object>]"
 msgstr "git notes edit [<Objekt>]"
 
-#: builtin/notes.c:68
+#: builtin/notes.c:66
 msgid "git notes show [<object>]"
 msgstr "git notes show [<Objekt>]"
 
-#: builtin/notes.c:73
+#: builtin/notes.c:71
 msgid "git notes merge [<options>] <notes_ref>"
 msgstr "git notes merge [<Optionen>] <Notiz-Referenz>"
 
-#: builtin/notes.c:74
+#: builtin/notes.c:72
 msgid "git notes merge --commit [<options>]"
 msgstr "git notes merge --commit [<Optionen>]"
 
-#: builtin/notes.c:75
+#: builtin/notes.c:73
 msgid "git notes merge --abort [<options>]"
 msgstr "git notes merge --abort [<Optionen>]"
 
-#: builtin/notes.c:80
+#: builtin/notes.c:78
 msgid "git notes remove [<object>]"
 msgstr "git notes remove [<Objekt>]"
 
-#: builtin/notes.c:85
+#: builtin/notes.c:83
 msgid "git notes prune [<options>]"
 msgstr "git notes prune [<Optionen>]"
 
-#: builtin/notes.c:90
+#: builtin/notes.c:88
 msgid "git notes get-ref"
 msgstr "git notes get-ref"
 
-#: builtin/notes.c:139
+#: builtin/notes.c:137
 #, c-format
 msgid "unable to start 'show' for object '%s'"
 msgstr "konnte 'show' für Objekt '%s' nicht starten"
 
-#: builtin/notes.c:143
+#: builtin/notes.c:141
 msgid "could not read 'show' output"
 msgstr "Konnte Ausgabe von 'show' nicht lesen."
 
-#: builtin/notes.c:151
+#: builtin/notes.c:149
 #, c-format
 msgid "failed to finish 'show' for object '%s'"
 msgstr "konnte 'show' für Objekt '%s' nicht abschließen"
 
-#: builtin/notes.c:169 builtin/tag.c:341
+#: builtin/notes.c:167 builtin/tag.c:341
 #, c-format
 msgid "could not create file '%s'"
 msgstr "konnte Datei '%s' nicht erstellen"
 
-#: builtin/notes.c:188
+#: builtin/notes.c:186
 msgid "Please supply the note contents using either -m or -F option"
 msgstr ""
 "Bitte liefern Sie den Notiz-Inhalt unter Verwendung der Option -m oder -F."
 
-#: builtin/notes.c:209 builtin/notes.c:972
+#: builtin/notes.c:207 builtin/notes.c:844
 #, c-format
 msgid "Removing note for object %s\n"
 msgstr "Entferne Notiz für Objekt %s\n"
 
-#: builtin/notes.c:214
+#: builtin/notes.c:212
 msgid "unable to write note object"
 msgstr "Konnte Notiz-Objekt nicht schreiben"
 
-#: builtin/notes.c:216
+#: builtin/notes.c:214
 #, c-format
 msgid "The note contents has been left in %s"
 msgstr "Die Notiz-Inhalte wurden in %s belassen"
 
-#: builtin/notes.c:250 builtin/tag.c:540
+#: builtin/notes.c:248 builtin/tag.c:540
 #, c-format
 msgid "cannot read '%s'"
 msgstr "kann '%s' nicht lesen"
 
-#: builtin/notes.c:252 builtin/tag.c:543
+#: builtin/notes.c:250 builtin/tag.c:543
 #, c-format
 msgid "could not open or read '%s'"
 msgstr "konnte '%s' nicht öffnen oder lesen"
 
-#: builtin/notes.c:271 builtin/notes.c:444 builtin/notes.c:446
-#: builtin/notes.c:506 builtin/notes.c:560 builtin/notes.c:643
-#: builtin/notes.c:648 builtin/notes.c:723 builtin/notes.c:765
-#: builtin/notes.c:967 builtin/tag.c:556
+#: builtin/notes.c:269 builtin/notes.c:316 builtin/notes.c:318
+#: builtin/notes.c:378 builtin/notes.c:432 builtin/notes.c:515
+#: builtin/notes.c:520 builtin/notes.c:595 builtin/notes.c:637
+#: builtin/notes.c:839 builtin/tag.c:556
 #, c-format
 msgid "Failed to resolve '%s' as a valid ref."
 msgstr "Konnte '%s' nicht als gültige Referenz auflösen."
 
-#: builtin/notes.c:274
+#: builtin/notes.c:272
 #, c-format
 msgid "Failed to read object '%s'."
 msgstr "Fehler beim Lesen des Objektes '%s'."
 
-#: builtin/notes.c:298
-msgid "Cannot commit uninitialized/unreferenced notes tree"
-msgstr "Kann uninitialisierten/unreferenzierten Notiz-Baum nicht eintragen."
-
-#: builtin/notes.c:339
-#, c-format
-msgid "Bad notes.rewriteMode value: '%s'"
-msgstr "Ungültiger notes.rewriteMode Wert: '%s'"
-
-#: builtin/notes.c:349
-#, c-format
-msgid "Refusing to rewrite notes in %s (outside of refs/notes/)"
-msgstr ""
-"Umschreiben der Notizen in %s zurückgewiesen (außerhalb von refs/notes/)"
-
-#. TRANSLATORS: The first %s is the name of the
-#. environment variable, the second %s is its value
-#: builtin/notes.c:376
-#, c-format
-msgid "Bad %s value: '%s'"
-msgstr "Ungültiger %s Wert: '%s'"
-
-#: builtin/notes.c:440
+#: builtin/notes.c:312
 #, c-format
 msgid "Malformed input line: '%s'."
 msgstr "Fehlerhafte Eingabezeile: '%s'."
 
-#: builtin/notes.c:455
+#: builtin/notes.c:327
 #, c-format
 msgid "Failed to copy notes from '%s' to '%s'"
 msgstr "Fehler beim Kopieren der Notizen von '%s' nach '%s'"
 
-#: builtin/notes.c:499 builtin/notes.c:553 builtin/notes.c:626
-#: builtin/notes.c:638 builtin/notes.c:711 builtin/notes.c:758
-#: builtin/notes.c:1032
+#: builtin/notes.c:371 builtin/notes.c:425 builtin/notes.c:498
+#: builtin/notes.c:510 builtin/notes.c:583 builtin/notes.c:630
+#: builtin/notes.c:904
 msgid "too many parameters"
 msgstr "zu viele Parameter"
 
-#: builtin/notes.c:512 builtin/notes.c:771
+#: builtin/notes.c:384 builtin/notes.c:643
 #, c-format
 msgid "No note found for object %s."
 msgstr "Kein Notiz für Objekt %s gefunden."
 
-#: builtin/notes.c:534 builtin/notes.c:691
+#: builtin/notes.c:406 builtin/notes.c:563
 msgid "note contents as a string"
 msgstr "Notizinhalte als Zeichenkette"
 
-#: builtin/notes.c:537 builtin/notes.c:694
+#: builtin/notes.c:409 builtin/notes.c:566
 msgid "note contents in a file"
 msgstr "Notizinhalte in einer Datei"
 
-#: builtin/notes.c:539 builtin/notes.c:542 builtin/notes.c:696
-#: builtin/notes.c:699 builtin/tag.c:474
+#: builtin/notes.c:411 builtin/notes.c:414 builtin/notes.c:568
+#: builtin/notes.c:571 builtin/tag.c:474
 msgid "object"
 msgstr "Objekt"
 
-#: builtin/notes.c:540 builtin/notes.c:697
+#: builtin/notes.c:412 builtin/notes.c:569
 msgid "reuse and edit specified note object"
 msgstr "Wiederverwendung und Bearbeitung des angegebenen Notiz-Objektes"
 
-#: builtin/notes.c:543 builtin/notes.c:700
+#: builtin/notes.c:415 builtin/notes.c:572
 msgid "reuse specified note object"
 msgstr "Wiederverwendung des angegebenen Notiz-Objektes"
 
-#: builtin/notes.c:545 builtin/notes.c:613
+#: builtin/notes.c:417 builtin/notes.c:485
 msgid "replace existing notes"
 msgstr "ersetzt existierende Notizen"
 
-#: builtin/notes.c:579
+#: builtin/notes.c:451
 #, c-format
 msgid ""
 "Cannot add notes. Found existing notes for object %s. Use '-f' to overwrite "
@@ -6933,26 +7336,26 @@
 "Konnte Notizen nicht hinzufügen. Existierende Notizen für Objekt %s "
 "gefunden. Verwenden Sie '-f' um die existierenden Notizen zu überschreiben."
 
-#: builtin/notes.c:584 builtin/notes.c:661
+#: builtin/notes.c:456 builtin/notes.c:533
 #, c-format
 msgid "Overwriting existing notes for object %s\n"
 msgstr "Überschreibe existierende Notizen für Objekt %s\n"
 
-#: builtin/notes.c:614
+#: builtin/notes.c:486
 msgid "read objects from stdin"
 msgstr "liest Objekte von der Standard-Eingabe"
 
-#: builtin/notes.c:616
+#: builtin/notes.c:488
 msgid "load rewriting config for <command> (implies --stdin)"
 msgstr ""
 "lädt Konfiguration für <Kommando> beim Umschreiben von Versionen (impliziert "
 "--stdin)"
 
-#: builtin/notes.c:634
+#: builtin/notes.c:506
 msgid "too few parameters"
 msgstr "zu wenig Parameter"
 
-#: builtin/notes.c:655
+#: builtin/notes.c:527
 #, c-format
 msgid ""
 "Cannot copy notes. Found existing notes for object %s. Use '-f' to overwrite "
@@ -6961,12 +7364,12 @@
 "Kann Notizen nicht kopieren. Existierende Notizen für Objekt %s gefunden. "
 "Verwenden Sie '-f' um die existierenden Notizen zu überschreiben."
 
-#: builtin/notes.c:667
+#: builtin/notes.c:539
 #, c-format
 msgid "Missing notes on source object %s. Cannot copy."
 msgstr "Keine Notizen für Quell-Objekt %s. Kopie nicht möglich."
 
-#: builtin/notes.c:716
+#: builtin/notes.c:588
 #, c-format
 msgid ""
 "The -m/-F/-c/-C options have been deprecated for the 'edit' subcommand.\n"
@@ -6975,15 +7378,15 @@
 "Die Optionen -m/-F/-c/-C sind für das Unterkommando 'edit' veraltet.\n"
 "Bitte benutzen Sie stattdessen 'git notes add -f -m/-F/-c/-C'.\n"
 
-#: builtin/notes.c:863
+#: builtin/notes.c:735
 msgid "General options"
 msgstr "Allgemeine Optionen"
 
-#: builtin/notes.c:865
+#: builtin/notes.c:737
 msgid "Merge options"
-msgstr "Optionen für Zusammenführung"
+msgstr "Merge-Optionen"
 
-#: builtin/notes.c:867
+#: builtin/notes.c:739
 msgid ""
 "resolve notes conflicts using the given strategy (manual/ours/theirs/union/"
 "cat_sort_uniq)"
@@ -6991,46 +7394,46 @@
 "löst Konflikte bei Notizen mit der angegebenen Strategie auf (manual/ours/"
 "theirs/union/cat_sort_uniq)"
 
-#: builtin/notes.c:869
+#: builtin/notes.c:741
 msgid "Committing unmerged notes"
 msgstr "trägt nicht zusammengeführte Notizen ein"
 
-#: builtin/notes.c:871
+#: builtin/notes.c:743
 msgid "finalize notes merge by committing unmerged notes"
 msgstr ""
-"schließt Zusammenführung von Notizen ab, in dem nicht zusammengeführte "
-"Notizen eingetragen werden"
+"schließt Merge von Notizen ab, in dem nicht zusammengeführte Notizen "
+"committet werden"
 
-#: builtin/notes.c:873
+#: builtin/notes.c:745
 msgid "Aborting notes merge resolution"
-msgstr "bricht Konfliktauflösung bei Zusammenführung von Notizen ab"
+msgstr "bricht Konfliktauflösung beim Merge von Notizen ab"
 
-#: builtin/notes.c:875
+#: builtin/notes.c:747
 msgid "abort notes merge"
-msgstr "bricht Zusammenführung von Notizen ab"
+msgstr "bricht Merge von Notizen ab"
 
-#: builtin/notes.c:970
+#: builtin/notes.c:842
 #, c-format
 msgid "Object %s has no note\n"
 msgstr "Objekt %s hat keine Notiz\n"
 
-#: builtin/notes.c:982
+#: builtin/notes.c:854
 msgid "attempt to remove non-existent note is not an error"
 msgstr "der Versuch, eine nicht existierende Notiz zu löschen, ist kein Fehler"
 
-#: builtin/notes.c:985
+#: builtin/notes.c:857
 msgid "read object names from the standard input"
 msgstr "liest Objektnamen von der Standard-Eingabe"
 
-#: builtin/notes.c:1066
+#: builtin/notes.c:938
 msgid "notes_ref"
 msgstr "Notiz-Referenz"
 
-#: builtin/notes.c:1067
+#: builtin/notes.c:939
 msgid "use notes from <notes_ref>"
 msgstr "verwendet Notizen von <Notiz-Referenz>"
 
-#: builtin/notes.c:1102 builtin/remote.c:1598
+#: builtin/notes.c:974 builtin/remote.c:1598
 #, c-format
 msgid "Unknown subcommand: %s"
 msgstr "Unbekanntes Unterkommando: %s"
@@ -7053,12 +7456,12 @@
 #: builtin/pack-objects.c:2397
 #, c-format
 msgid "unsupported index version %s"
-msgstr "Nicht unterstützte Bereitstellungsversion %s"
+msgstr "Nicht unterstützte Staging-Area-Version %s"
 
 #: builtin/pack-objects.c:2401
 #, c-format
 msgid "bad index version '%s'"
-msgstr "Ungültige Bereitstellungsversion '%s'"
+msgstr "Ungültige Staging-Area-Version '%s'"
 
 #: builtin/pack-objects.c:2424
 #, c-format
@@ -7144,7 +7547,7 @@
 
 #: builtin/pack-objects.c:2481
 msgid "read revision arguments from standard input"
-msgstr "liest Argumente bezüglich Revisionen von der Standard-Eingabe"
+msgstr "liest Argumente bezüglich Commits von der Standard-Eingabe"
 
 #: builtin/pack-objects.c:2483
 msgid "limit the objects to those that are not yet packed"
@@ -7157,8 +7560,7 @@
 #: builtin/pack-objects.c:2489
 msgid "include objects referred by reflog entries"
 msgstr ""
-"schließt Objekte ein, die von Einträgen des Referenzprotokolls referenziert "
-"werden"
+"schließt Objekte ein, die von Einträgen des Reflogs referenziert werden"
 
 #: builtin/pack-objects.c:2492
 msgid "output pack to stdout"
@@ -7166,8 +7568,7 @@
 
 #: builtin/pack-objects.c:2494
 msgid "include tag objects that refer to objects to be packed"
-msgstr ""
-"schließt Markierungsobjekte ein, die auf gepackte Objekte referenzieren"
+msgstr "schließt Tag-Objekte ein, die auf gepackte Objekte referenzieren"
 
 #: builtin/pack-objects.c:2496
 msgid "keep unreachable objects"
@@ -7195,7 +7596,7 @@
 
 #: builtin/pack-objects.c:2507
 msgid "do not hide commits by grafts"
-msgstr "verbirgt keine Versionen mit künstlichen Vorgängern (\"grafts\")"
+msgstr "verbirgt keine Commits mit künstlichen Vorgängern (\"grafts\")"
 
 #: builtin/pack-refs.c:6
 msgid "git pack-refs [options]"
@@ -7215,7 +7616,7 @@
 
 #: builtin/prune.c:12
 msgid "git prune [-n] [-v] [--expire <time>] [--] [<head>...]"
-msgstr "git prune [-n] [-v] [--expire <Zeit>] [--] [<Zweigspitze>...]"
+msgstr "git prune [-n] [-v] [--expire <Zeit>] [--] [<head>...]"
 
 #: builtin/prune.c:132
 msgid "do not remove, show only"
@@ -7231,11 +7632,11 @@
 
 #: builtin/push.c:14
 msgid "git push [<options>] [<repository> [<refspec>...]]"
-msgstr "git push [<Optionen>] [<Projektarchiv> [<Referenzspezifikation>...]]"
+msgstr "git push [<Optionen>] [<Repository> [<Refspec>...]]"
 
 #: builtin/push.c:45
 msgid "tag shorthand without <tag>"
-msgstr "Kurzschrift für Markierung ohne <Markierung>"
+msgstr "Kurzschrift für Tag ohne <Tag>"
 
 #: builtin/push.c:64
 msgid "--delete only accepts plain target ref names"
@@ -7264,19 +7665,19 @@
 "    git push %s %s\n"
 "%s"
 msgstr ""
-"Der Name des externen Übernahmezweiges stimmt nicht mit dem Namen Ihres\n"
-"aktuellen Zweiges überein. Um auf den Übernahmezweig in dem externen\n"
-"Projektarchiv zu versenden, benutzen Sie:\n"
+"Der Name des Upstream-Branches stimmt nicht mit dem Namen Ihres\n"
+"aktuellen Branches überein. Um auf den Upstream-Branch in dem Remote-\n"
+"Repository zu versenden, benutzen Sie:\n"
 "\n"
 "    git push %s HEAD:%s\n"
 "\n"
-"Um auf den Zweig mit dem selben Namen in dem externen Projekarchiv\n"
-"zu versenden, benutzen Sie:\n"
+"Um auf den Branch mit dem selben Namen im Remote-Repository zu versenden,\n"
+"benutzen Sie:\n"
 "\n"
 "    git push %s %s\n"
 "%s"
 
-#: builtin/push.c:121
+#: builtin/push.c:117
 #, c-format
 msgid ""
 "You are not currently on a branch.\n"
@@ -7285,13 +7686,13 @@
 "\n"
 "    git push %s HEAD:<name-of-remote-branch>\n"
 msgstr ""
-"Sie befinden sich im Moment auf keinem Zweig.\n"
-"Um die Historie, führend zum aktuellen (freistehende Zweigspitze (HEAD))\n"
+"Sie befinden sich im Moment auf keinem Branch.\n"
+"Um die Historie, führend zum aktuellen (losgelöster HEAD)\n"
 "Status zu versenden, benutzen Sie\n"
 "\n"
-"    git push %s HEAD:<Name-des-externen-Zweiges>\n"
+"    git push %s HEAD:<Name-des-Remote-Branches>\n"
 
-#: builtin/push.c:128
+#: builtin/push.c:131
 #, c-format
 msgid ""
 "The current branch %s has no upstream branch.\n"
@@ -7299,29 +7700,30 @@
 "\n"
 "    git push --set-upstream %s %s\n"
 msgstr ""
-"Der aktuelle Zweig %s hat keinen Zweig im externen Projektarchiv.\n"
-"Um den aktuellen Zweig zu versenden und das Fernarchiv als externes\n"
-"Projektarchiv zu verwenden, benutzen Sie\n"
+"Der aktuelle Branch %s hat keinen Upstream-Branch.\n"
+"Um den aktuellen Branch zu versenden und den Remote-Branch\n"
+"als Upstream-Branch zu setzen, benutzen Sie\n"
 "\n"
 "    git push --set-upstream %s %s\n"
 
-#: builtin/push.c:136
+#: builtin/push.c:139
 #, c-format
 msgid "The current branch %s has multiple upstream branches, refusing to push."
-msgstr "Der aktuelle Zweig %s hat mehrere externe Zweige, Versand verweigert."
+msgstr ""
+"Der aktuelle Branch %s hat mehrere Upstream-Branches, \"push\" verweigert."
 
-#: builtin/push.c:139
+#: builtin/push.c:142
 #, c-format
 msgid ""
 "You are pushing to remote '%s', which is not the upstream of\n"
 "your current branch '%s', without telling me what to push\n"
 "to update which remote branch."
 msgstr ""
-"Sie versenden nach '%s', welches kein externes Projektarchiv Ihres\n"
-"aktuellen Zweiges '%s' ist, ohne mir mitzuteilen, was ich versenden\n"
-"soll, um welchen externen Zweig zu aktualisieren."
+"Sie versenden nach '%s', welches kein Upstream-Repository Ihres aktuellen\n"
+"Branches '%s' ist, ohne mir mitzuteilen, was ich versenden soll, um welchen\n"
+"Remote-Branch zu aktualisieren."
 
-#: builtin/push.c:151
+#: builtin/push.c:165
 msgid ""
 "push.default is unset; its implicit value is changing in\n"
 "Git 2.0 from 'matching' to 'simple'. To squelch this message\n"
@@ -7342,6 +7744,7 @@
 "wird in Git 2.0 von 'matching' nach 'simple' geändert. Um diese Meldung zu\n"
 "unterdrücken und das aktuelle Verhalten nach Änderung des Standardwertes\n"
 "beizubehalten, benutzen Sie:\n"
+"\n"
 "  git config --global push.default matching\n"
 "\n"
 "Um diese Meldung zu unterdrücken und das neue Verhalten jetzt zu übernehmen, "
@@ -7355,28 +7758,28 @@
 "Modus 'current' anstatt 'simple', falls Sie gelegentlich ältere Versionen "
 "von Git benutzen.)"
 
-#: builtin/push.c:199
+#: builtin/push.c:225
 msgid ""
 "You didn't specify any refspecs to push, and push.default is \"nothing\"."
 msgstr ""
-"Sie haben keine Referenzspezifikationen zum Versenden angegeben, und push."
-"default ist \"nothing\"."
+"Sie haben keine Refspec für \"push\" angegeben, und push.default ist "
+"\"nothing\"."
 
-#: builtin/push.c:206
+#: builtin/push.c:232
 msgid ""
 "Updates were rejected because the tip of your current branch is behind\n"
-"its remote counterpart. Merge the remote changes (e.g. 'git pull')\n"
-"before pushing again.\n"
+"its remote counterpart. Integrate the remote changes (e.g.\n"
+"'git pull ...') before pushing again.\n"
 "See the 'Note about fast-forwards' in 'git push --help' for details."
 msgstr ""
 "Aktualisierungen wurden zurückgewiesen, weil die Spitze Ihres aktuellen\n"
-"Zweiges hinter seinem externen Gegenstück zurückgefallen ist. Führen Sie\n"
-"die externen Änderungen zusammen (z.B. 'git pull') bevor Sie erneut\n"
-"versenden.\n"
+"Branches hinter seinem externen Gegenstück zurückgefallen ist. Führen Sie\n"
+"die externen Änderungen zusammen (z.B. 'git pull ...') bevor Sie \"push\"\n"
+"erneut ausführen.\n"
 "Siehe auch die Sektion 'Note about fast-forwards' in 'git push --help'\n"
 "für weitere Details."
 
-#: builtin/push.c:212
+#: builtin/push.c:238
 msgid ""
 "Updates were rejected because a pushed branch tip is behind its remote\n"
 "counterpart. If you did not intend to push that branch, you may want to\n"
@@ -7384,80 +7787,79 @@
 "to 'simple', 'current' or 'upstream' to push only the current branch."
 msgstr ""
 "Aktualisierungen wurden zurückgewiesen, weil die Spitze eines versendeten\n"
-"Zweiges hinter seinem externen Gegenstück zurückgefallen ist. Wenn Sie "
+"Branches hinter seinem externen Gegenstück zurückgefallen ist. Wenn Sie "
 "nicht\n"
-"beabsichtigt haben, diesen Zweig zu versenden, können Sie auch den zu "
+"beabsichtigt haben, diesen Branch zu versenden, können Sie auch den zu "
 "versendenden\n"
-"Zweig spezifizieren oder die Konfigurationsvariable 'push.default' zu "
+"Branch spezifizieren oder die Konfigurationsvariable 'push.default' zu "
 "'simple', 'current'\n"
-"oder 'upstream' setzen, um nur den aktuellen Zweig zu versenden."
+"oder 'upstream' setzen, um nur den aktuellen Branch zu versenden."
 
-#: builtin/push.c:218
+#: builtin/push.c:244
 msgid ""
 "Updates were rejected because a pushed branch tip is behind its remote\n"
-"counterpart. Check out this branch and merge the remote changes\n"
-"(e.g. 'git pull') before pushing again.\n"
+"counterpart. Check out this branch and integrate the remote changes\n"
+"(e.g. 'git pull ...') before pushing again.\n"
 "See the 'Note about fast-forwards' in 'git push --help' for details."
 msgstr ""
 "Aktualisierungen wurden zurückgewiesen, weil die Spitze eines versendeten\n"
-"Zweiges hinter seinem externen Gegenstück zurückgefallen ist. Checken Sie\n"
-"diesen Zweig aus und führen Sie die externen Änderungen zusammen\n"
-"(z.B. 'git pull') bevor Sie erneut versenden.\n"
+"Branches hinter seinem externen Gegenstück zurückgefallen ist. Checken Sie\n"
+"diesen Branch aus und führen Sie die externen Änderungen zusammen\n"
+"(z.B. 'git pull ...') bevor Sie erneut \"push\" ausführen.\n"
 "Siehe auch die Sektion 'Note about fast-forwards' in 'git push --help'\n"
 "für weitere Details."
 
-#: builtin/push.c:224
+#: builtin/push.c:250
 msgid ""
 "Updates were rejected because the remote contains work that you do\n"
 "not have locally. This is usually caused by another repository pushing\n"
-"to the same ref. You may want to first merge the remote changes (e.g.,\n"
-"'git pull') before pushing again.\n"
+"to the same ref. You may want to first integrate the remote changes\n"
+"(e.g., 'git pull ...') before pushing again.\n"
 "See the 'Note about fast-forwards' in 'git push --help' for details."
 msgstr ""
-"Aktualisierungen wurden zurückgewiesen, weil das Fernarchiv Versionen "
+"Aktualisierungen wurden zurückgewiesen, weil das Remote-Repository Commits "
 "enthält,\n"
-"die lokal nicht vorhanden sind. Das wird üblicherweise durch das Versenden "
+"die lokal nicht vorhanden sind. Das wird üblicherweise durch einen \"push\" "
 "von\n"
-"Versionen auf dieselbe Referenz von einem anderen Projektarchiv aus "
-"verursacht.\n"
+"Commits auf dieselbe Referenz von einem anderen Repository aus verursacht.\n"
 "Vielleicht müssen Sie die externen Änderungen zusammenzuführen (z.B. 'git "
-"pull')\n"
-"bevor Sie erneut versenden.\n"
+"pull ...')\n"
+"bevor Sie erneut \"push\" ausführen.\n"
 "Siehe auch die Sektion 'Note about fast-forwards' in 'git push --help'\n"
 "für weitere Details."
 
-#: builtin/push.c:231
+#: builtin/push.c:257
 msgid "Updates were rejected because the tag already exists in the remote."
 msgstr ""
-"Aktualisierungen wurden zurückgewiesen, weil die Markierung bereits\n"
-"im Fernarchiv existiert."
+"Aktualisierungen wurden zurückgewiesen, weil das Tag bereits\n"
+"im Remote-Repository existiert."
 
-#: builtin/push.c:234
+#: builtin/push.c:260
 msgid ""
 "You cannot update a remote ref that points at a non-commit object,\n"
 "or update a remote ref to make it point at a non-commit object,\n"
 "without using the '--force' option.\n"
 msgstr ""
-"Sie können keine externe Referenz aktualisieren, die auf ein Objekt zeigt,\n"
-"das keine Version ist, oder es auf ein solches Objekt zeigen lassen, ohne\n"
+"Sie können keine Remote-Referenz aktualisieren, die auf ein Objekt zeigt,\n"
+"das kein Commit ist, oder es auf ein solches Objekt zeigen lassen, ohne\n"
 "die Option '--force' zu verwenden.\n"
 
-#: builtin/push.c:294
+#: builtin/push.c:320
 #, c-format
 msgid "Pushing to %s\n"
 msgstr "Versende nach %s\n"
 
-#: builtin/push.c:298
+#: builtin/push.c:324
 #, c-format
 msgid "failed to push some refs to '%s'"
 msgstr "Fehler beim Versenden einiger Referenzen nach '%s'"
 
-#: builtin/push.c:331
+#: builtin/push.c:357
 #, c-format
 msgid "bad repository '%s'"
-msgstr "ungültiges Projektarchiv '%s'"
+msgstr "ungültiges Repository '%s'"
 
-#: builtin/push.c:332
+#: builtin/push.c:358
 msgid ""
 "No configured push destination.\n"
 "Either specify the URL from the command-line or configure a remote "
@@ -7469,100 +7871,97 @@
 "\n"
 "    git push <name>\n"
 msgstr ""
-"Kein Ziel zum Versenden konfiguriert.\n"
+"Kein Ziel für \"push\" konfiguriert.\n"
 "Entweder spezifizieren Sie die URL von der Kommandozeile oder konfigurieren "
-"ein externes Projektarchiv unter Benutzung von\n"
+"ein Remote-Repository unter Benutzung von\n"
 "\n"
 "    git remote add <Name> <URL>\n"
 "\n"
-"und versenden dann unter Benutzung dieses Namens\n"
+"und führen \"push\" dann unter Benutzung dieses Namens aus\n"
 "\n"
 "    git push <Name>\n"
 
-#: builtin/push.c:347
+#: builtin/push.c:373
 msgid "--all and --tags are incompatible"
 msgstr "Die Optionen --all und --tags sind inkompatibel."
 
-#: builtin/push.c:348
+#: builtin/push.c:374
 msgid "--all can't be combined with refspecs"
-msgstr ""
-"Die Option --all kann nicht mit Referenzspezifikationen kombiniert werden."
+msgstr "Die Option --all kann nicht mit Refspecs kombiniert werden."
 
-#: builtin/push.c:353
+#: builtin/push.c:379
 msgid "--mirror and --tags are incompatible"
 msgstr "Die Optionen --mirror und --tags sind inkompatibel."
 
-#: builtin/push.c:354
+#: builtin/push.c:380
 msgid "--mirror can't be combined with refspecs"
-msgstr ""
-"Die Option --mirror kann nicht mit Referenzspezifikationen kombiniert werden."
+msgstr "Die Option --mirror kann nicht mit Refspecs kombiniert werden."
 
-#: builtin/push.c:359
+#: builtin/push.c:385
 msgid "--all and --mirror are incompatible"
 msgstr "Die Optionen --all und --mirror sind inkompatibel."
 
-#: builtin/push.c:419
+#: builtin/push.c:445
 msgid "repository"
-msgstr "Projektarchiv"
+msgstr "Repository"
 
-#: builtin/push.c:420
+#: builtin/push.c:446
 msgid "push all refs"
 msgstr "versendet alle Referenzen"
 
-#: builtin/push.c:421
+#: builtin/push.c:447
 msgid "mirror all refs"
 msgstr "spiegelt alle Referenzen"
 
-#: builtin/push.c:423
+#: builtin/push.c:449
 msgid "delete refs"
 msgstr "löscht Referenzen"
 
-#: builtin/push.c:424
+#: builtin/push.c:450
 msgid "push tags (can't be used with --all or --mirror)"
-msgstr ""
-"versendet Markierungen (kann nicht mit --all oder --mirror verwendet werden)"
+msgstr "versendet Tags (kann nicht mit --all oder --mirror verwendet werden)"
 
-#: builtin/push.c:427
+#: builtin/push.c:453
 msgid "force updates"
 msgstr "erzwingt Aktualisierung"
 
-#: builtin/push.c:428
+#: builtin/push.c:454
 msgid "check"
 msgstr ""
 
-#: builtin/push.c:429
+#: builtin/push.c:455
 msgid "control recursive pushing of submodules"
-msgstr "steuert rekursives Versenden von Unterprojekten"
+msgstr "steuert rekursiven \"push\" von Submodulen"
 
-#: builtin/push.c:431
+#: builtin/push.c:457
 msgid "use thin pack"
 msgstr "verwendet kleinere Pakete"
 
-#: builtin/push.c:432 builtin/push.c:433
+#: builtin/push.c:458 builtin/push.c:459
 msgid "receive pack program"
 msgstr "'receive pack' Programm"
 
-#: builtin/push.c:434
+#: builtin/push.c:460
 msgid "set upstream for git pull/status"
-msgstr "setzt externes Projektarchiv für \"git pull/status\""
+msgstr "setzt Upstream für \"git pull/status\""
 
-#: builtin/push.c:437
+#: builtin/push.c:463
 msgid "prune locally removed refs"
 msgstr "entfernt lokal gelöschte Referenzen"
 
-#: builtin/push.c:439
+#: builtin/push.c:465
 msgid "bypass pre-push hook"
 msgstr "umgeht \"pre-push hook\""
 
-#: builtin/push.c:440
+#: builtin/push.c:466
 msgid "push missing but relevant tags"
-msgstr "versendet fehlende, aber relevante Markierungen"
+msgstr "versendet fehlende, aber relevante Tags"
 
-#: builtin/push.c:450
+#: builtin/push.c:476
 msgid "--delete is incompatible with --all, --mirror and --tags"
 msgstr "Die Option --delete ist inkompatibel mit --all, --mirror und --tags."
 
-#: builtin/push.c:452
+#: builtin/push.c:478
 msgid "--delete doesn't make sense without any refs"
 msgstr "Die Option --delete kann nur mit Referenzen verwendet werden."
 
@@ -7574,76 +7973,83 @@
 msgstr ""
 "git read-tree [[-m [--trivial] [--aggressive] | --reset | --prefix=<Prefix>] "
 "[-u [--exclude-per-directory=<gitignore>] | -i]] [--no-sparse-checkout] [--"
-"index-output=<Datei>] (--empty | <Versionsreferenz1> [<Versionsreferenz2> "
-"[<Versionsreferenz3>]])"
+"index-output=<Datei>] (--empty | <Commit-Referenz1> [<Commit-Referenz2> "
+"[<Commit-Referenz3>]])"
 
-#: builtin/read-tree.c:108
+#: builtin/read-tree.c:109
 msgid "write resulting index to <file>"
-msgstr "schreibt resultierende Bereitstellung nach <Datei>"
+msgstr "schreibt resultierende Staging-Area nach <Datei>"
 
-#: builtin/read-tree.c:111
+#: builtin/read-tree.c:112
 msgid "only empty the index"
-msgstr "leert die Bereitstellung"
+msgstr "leert die Staging-Area"
 
-#: builtin/read-tree.c:113
+#: builtin/read-tree.c:114
 msgid "Merging"
-msgstr "Zusammenführung"
+msgstr "Merge"
 
-#: builtin/read-tree.c:115
+#: builtin/read-tree.c:116
 msgid "perform a merge in addition to a read"
-msgstr "führt eine Zusammenführung zusätzlich zum Lesen aus"
+msgstr "führt einen Merge zusätzlich zum Lesen aus"
 
-#: builtin/read-tree.c:117
+#: builtin/read-tree.c:118
 msgid "3-way merge if no file level merging required"
-msgstr ""
-"3-Wege-Zusammenführung, wenn keine Zusammenführung auf Dateiebene "
-"erforderlich ist"
+msgstr "3-Wege-Merge, wenn kein Merge auf Dateiebene erforderlich ist"
 
-#: builtin/read-tree.c:119
+#: builtin/read-tree.c:120
 msgid "3-way merge in presence of adds and removes"
-msgstr ""
-"3-Wege-Zusammenführung bei Vorhandensein von hinzugefügten/entfernten Zeilen"
+msgstr "3-Wege-Merge bei Vorhandensein von hinzugefügten/entfernten Zeilen"
 
-#: builtin/read-tree.c:121
+#: builtin/read-tree.c:122
 msgid "same as -m, but discard unmerged entries"
 msgstr "genau wie -m, verwirft aber nicht zusammengeführte Einträge"
 
-#: builtin/read-tree.c:122
+#: builtin/read-tree.c:123
 msgid "<subdirectory>/"
 msgstr "<Unterverzeichnis>/"
 
-#: builtin/read-tree.c:123
+#: builtin/read-tree.c:124
 msgid "read the tree into the index under <subdirectory>/"
-msgstr "liest den Baum in die Bereitstellung unter <Unterverzeichnis>/"
+msgstr "liest das Verzeichnis in die Staging-Area unter <Unterverzeichnis>/"
 
-#: builtin/read-tree.c:126
+#: builtin/read-tree.c:127
 msgid "update working tree with merge result"
-msgstr "aktualisiert Arbeitsbaum mit Ergebnis der Zusammenführung"
+msgstr "aktualisiert Arbeitsverzeichnis mit dem Ergebnis des Merges"
 
-#: builtin/read-tree.c:128
+#: builtin/read-tree.c:129
 msgid "gitignore"
 msgstr "gitignore"
 
-#: builtin/read-tree.c:129
+#: builtin/read-tree.c:130
 msgid "allow explicitly ignored files to be overwritten"
 msgstr "erlaubt explizit ignorierte Dateien zu überschreiben"
 
-#: builtin/read-tree.c:132
-msgid "don't check the working tree after merging"
-msgstr "prüft nicht den Arbeitsbaum nach der Zusammenführung"
-
 #: builtin/read-tree.c:133
-msgid "don't update the index or the work tree"
-msgstr "aktualisiert weder die Bereitstellung, noch den Arbeitsbaum"
+msgid "don't check the working tree after merging"
+msgstr "prüft nicht das Arbeitsverzeichnis nach dem Merge"
 
-#: builtin/read-tree.c:135
+#: builtin/read-tree.c:134
+msgid "don't update the index or the work tree"
+msgstr "aktualisiert weder die Staging-Area, noch das Arbeitsverzeichnis"
+
+#: builtin/read-tree.c:136
 msgid "skip applying sparse checkout filter"
 msgstr "überspringt Anwendung des Filters für spärliches Auschecken"
 
-#: builtin/read-tree.c:137
+#: builtin/read-tree.c:138
 msgid "debug unpack-trees"
 msgstr "protokolliert Entpacken der Bäume"
 
+#: builtin/reflog.c:500
+#, c-format
+msgid "%s' for '%s' is not a valid timestamp"
+msgstr "'%s' für '%s' ist kein gültiger Zeitstempel"
+
+#: builtin/reflog.c:616 builtin/reflog.c:621
+#, c-format
+msgid "'%s' is not a valid timestamp"
+msgstr "'%s' ist kein gültiger Zeitstempel"
+
 #: builtin/remote.c:11
 msgid "git remote [-v | --verbose]"
 msgstr "git remote [-v | --verbose]"
@@ -7653,7 +8059,7 @@
 "git remote add [-t <branch>] [-m <master>] [-f] [--tags|--no-tags] [--"
 "mirror=<fetch|push>] <name> <url>"
 msgstr ""
-"git remote add [-t <Zweig>] [-m <master>] [-f] [--tags|--no-tags] [--"
+"git remote add [-t <Branch>] [-m <master>] [-f] [--tags|--no-tags] [--"
 "mirror=<fetch|push>] <Name> <URL>"
 
 #: builtin/remote.c:13 builtin/remote.c:32
@@ -7666,7 +8072,7 @@
 
 #: builtin/remote.c:15 builtin/remote.c:42
 msgid "git remote set-head <name> (-a | -d | <branch>)"
-msgstr "git remote set-head <Name> (-a | -d | <Zweig>)"
+msgstr "git remote set-head <Name> (-a | -d | <Branch>)"
 
 #: builtin/remote.c:16
 msgid "git remote [-v | --verbose] show [-n] <name>"
@@ -7680,12 +8086,11 @@
 msgid ""
 "git remote [-v | --verbose] update [-p | --prune] [(<group> | <remote>)...]"
 msgstr ""
-"git remote [-v | --verbose] update [-p | --prune] [(<Gruppe> | "
-"<externesProjektarchiv>)...]"
+"git remote [-v | --verbose] update [-p | --prune] [(<Gruppe> | <Remote>)...]"
 
 #: builtin/remote.c:19
 msgid "git remote set-branches [--add] <name> <branch>..."
-msgstr "git remote set-branches [--add] <Name> <Zweig>..."
+msgstr "git remote set-branches [--add] <Name> <Branch>..."
 
 #: builtin/remote.c:20 builtin/remote.c:68
 msgid "git remote set-url [--push] <name> <newurl> [<oldurl>]"
@@ -7705,11 +8110,11 @@
 
 #: builtin/remote.c:47
 msgid "git remote set-branches <name> <branch>..."
-msgstr "git remote set-branches <Name> <Zweig>..."
+msgstr "git remote set-branches <Name> <Branch>..."
 
 #: builtin/remote.c:48
 msgid "git remote set-branches --add <name> <branch>..."
-msgstr "git remote set-branches --add <Name> <Zweig>..."
+msgstr "git remote set-branches --add <Name> <Branch>..."
 
 #: builtin/remote.c:53
 msgid "git remote show [<options>] <name>"
@@ -7721,7 +8126,7 @@
 
 #: builtin/remote.c:63
 msgid "git remote update [<options>] [<group> | <remote>]..."
-msgstr "git remote update [<Optionen>] [<Gruppe> | <externesProjektarchiv>]..."
+msgstr "git remote update [<Optionen>] [<Gruppe> | <externesRepository>]..."
 
 #: builtin/remote.c:98
 #, c-format
@@ -7743,11 +8148,11 @@
 
 #: builtin/remote.c:163
 msgid "fetch the remote branches"
-msgstr "fordert die externen Zweige an"
+msgstr "fordert die Remote-Branches an"
 
 #: builtin/remote.c:165
 msgid "import all tags and associated objects when fetching"
-msgstr "importiert alle Markierungen und verbundene Objekte beim Anfordern"
+msgstr "importiert alle Tags und verbundene Objekte beim Anfordern"
 
 #: builtin/remote.c:168
 msgid "or do not fetch any tag at all (--no-tags)"
@@ -7755,11 +8160,11 @@
 
 #: builtin/remote.c:170
 msgid "branch(es) to track"
-msgstr "Zweige zur Übernahme"
+msgstr "Branch(es) zur Übernahme"
 
 #: builtin/remote.c:171
 msgid "master branch"
-msgstr "Hauptzweig"
+msgstr "Hauptbranch"
 
 #: builtin/remote.c:172
 msgid "push|fetch"
@@ -7768,34 +8173,35 @@
 #: builtin/remote.c:173
 msgid "set up remote as a mirror to push to or fetch from"
 msgstr ""
-"Aufsetzen des Fernarchivs als Spiegelarchiv zum Versenden und Anfordern"
+"Aufsetzen des Remote-Repositories als Spiegel-Repository für \"push\" und "
+"\"fetch\""
 
 #: builtin/remote.c:185
 msgid "specifying a master branch makes no sense with --mirror"
 msgstr ""
-"Die Option --mirror kann nicht mit der Angabe eines Hauptzweiges verwendet "
+"Die Option --mirror kann nicht mit der Angabe eines Hauptbranches verwendet "
 "werden."
 
 #: builtin/remote.c:187
 msgid "specifying branches to track makes sense only with fetch mirrors"
 msgstr ""
-"Die Angabe von zu folgenden Zweigen kann nur mit dem Anfordern von "
+"Die Angabe von zu folgenden Branches kann nur mit dem Anfordern von "
 "Spiegelarchiven verwendet werden."
 
 #: builtin/remote.c:195 builtin/remote.c:646
 #, c-format
 msgid "remote %s already exists."
-msgstr "externes Projektarchiv %s existiert bereits"
+msgstr "externes Repository %s existiert bereits"
 
 #: builtin/remote.c:199 builtin/remote.c:650
 #, c-format
 msgid "'%s' is not a valid remote name"
-msgstr "'%s' ist kein gültiger Name für ein externes Projektarchiv"
+msgstr "'%s' ist kein gültiger Name für ein Remote-Repository"
 
 #: builtin/remote.c:243
 #, c-format
 msgid "Could not setup master '%s'"
-msgstr "Konnte symbolische Referenz für Hauptzweig von '%s' nicht einrichten"
+msgstr "Konnte symbolische Referenz für Hauptbranch von '%s' nicht einrichten"
 
 #: builtin/remote.c:299
 #, c-format
@@ -7805,7 +8211,7 @@
 #: builtin/remote.c:339
 #, c-format
 msgid "Could not get fetch map for refspec %s"
-msgstr "Konnte Abholungszuordnung für Referenzspezifikation %s nicht bekommen"
+msgstr "Konnte Fetch-Map für Refspec %s nicht bekommen"
 
 #: builtin/remote.c:440 builtin/remote.c:448
 msgid "(matching)"
@@ -7823,7 +8229,7 @@
 #: builtin/remote.c:639 builtin/remote.c:792 builtin/remote.c:890
 #, c-format
 msgid "No such remote: %s"
-msgstr "Kein solches externes Archiv: %s"
+msgstr "Kein solches Remote-Repository: %s"
 
 #: builtin/remote.c:656
 #, c-format
@@ -7842,8 +8248,7 @@
 "\t%s\n"
 "\tPlease update the configuration manually if necessary."
 msgstr ""
-"Keine Aktualisierung der nicht standardmäßigen Referenzspezifikation zum "
-"Abholen\n"
+"Keine Aktualisierung der nicht standardmäßigen Refspec für \"fetch\"\n"
 "\t%s\n"
 "\tBitte aktualisieren Sie, falls notwendig, die Konfiguration manuell."
 
@@ -7870,7 +8275,7 @@
 #: builtin/remote.c:764
 #, c-format
 msgid "Could not remove branch %s"
-msgstr "Konnte Zweig %s nicht löschen"
+msgstr "Konnte Branch %s nicht löschen"
 
 #: builtin/remote.c:834
 msgid ""
@@ -7880,18 +8285,18 @@
 "Note: Some branches outside the refs/remotes/ hierarchy were not removed;\n"
 "to delete them, use:"
 msgstr[0] ""
-"Hinweis: Ein Zweig außerhalb der /refs/remotes/ Hierachie wurde nicht "
+"Hinweis: Ein Branch außerhalb der refs/remotes/ Hierachie wurde nicht "
 "gelöscht;\n"
 "um diesen zu löschen, benutzen Sie:"
 msgstr[1] ""
-"Hinweis: Einige Zweige außer der /refs/remotes/ Hierarchie wurden nicht "
+"Hinweis: Einige Branches außer der refs/remotes/ Hierarchie wurden nicht "
 "entfernt;\n"
 "um diese zu entfernen, benutzen Sie:"
 
 #: builtin/remote.c:943
 #, c-format
 msgid " new (next fetch will store in remotes/%s)"
-msgstr " neu (wird bei nächster Abholung in remotes/%s gespeichert)"
+msgstr " neu (wird bei nächstem \"fetch\" in remotes/%s gespeichert)"
 
 #: builtin/remote.c:946
 msgid " tracked"
@@ -7908,30 +8313,30 @@
 #: builtin/remote.c:991
 #, c-format
 msgid "invalid branch.%s.merge; cannot rebase onto > 1 branch"
-msgstr "ungültiges branch.%s.merge; kann nicht auf > 1 Zweig neu aufbauen"
+msgstr "ungültiges branch.%s.merge; kann Rebase nicht auf > 1 Branch ausführen"
 
 #: builtin/remote.c:998
 #, c-format
 msgid "rebases onto remote %s"
-msgstr "baut neu auf externen Zweig %s auf"
+msgstr "Rebase auf Remote-Branch %s"
 
 #: builtin/remote.c:1001
 #, c-format
 msgid " merges with remote %s"
-msgstr " führt mit externem Zweig %s zusammen"
+msgstr " führt mit Remote-Branch %s zusammen"
 
 #: builtin/remote.c:1002
 msgid "    and with remote"
-msgstr "    und mit externem Zweig"
+msgstr "    und mit Remote-Branch"
 
 #: builtin/remote.c:1004
 #, c-format
 msgid "merges with remote %s"
-msgstr "führt mit externem Zweig %s zusammen"
+msgstr "führt mit Remote-Branch %s zusammen"
 
 #: builtin/remote.c:1005
 msgid "   and with remote"
-msgstr "   und mit externem Zweig"
+msgstr "   und mit Remote-Branch"
 
 #: builtin/remote.c:1051
 msgid "create"
@@ -7975,12 +8380,12 @@
 
 #: builtin/remote.c:1091
 msgid "do not query remotes"
-msgstr "keine Abfrage von Fernarchiven"
+msgstr "keine Abfrage von Remote-Repositories"
 
 #: builtin/remote.c:1118
 #, c-format
 msgid "* remote %s"
-msgstr "* externes Projektarchiv %s"
+msgstr "* Remote-Repository %s"
 
 #: builtin/remote.c:1119
 #, c-format
@@ -7999,22 +8404,22 @@
 #: builtin/remote.c:1133 builtin/remote.c:1135 builtin/remote.c:1137
 #, c-format
 msgid "  HEAD branch: %s"
-msgstr "  Hauptzweig: %s"
+msgstr "  Hauptbranch: %s"
 
 #: builtin/remote.c:1139
 #, c-format
 msgid ""
 "  HEAD branch (remote HEAD is ambiguous, may be one of the following):\n"
 msgstr ""
-"  Hauptzweig (externer Hauptzweig ist mehrdeutig, könnte einer der folgenden "
+"  Hauptbranch (externer HEAD ist mehrdeutig, könnte einer der folgenden "
 "sein):\n"
 
 #: builtin/remote.c:1151
 #, c-format
 msgid "  Remote branch:%s"
 msgid_plural "  Remote branches:%s"
-msgstr[0] "  externer Zweig:%s"
-msgstr[1] "  externe Zweige:%s"
+msgstr[0] "  Remote-Branch:%s"
+msgstr[1] "  Remote-Branches:%s"
 
 #: builtin/remote.c:1154 builtin/remote.c:1181
 msgid " (status not queried)"
@@ -8023,8 +8428,8 @@
 #: builtin/remote.c:1163
 msgid "  Local branch configured for 'git pull':"
 msgid_plural "  Local branches configured for 'git pull':"
-msgstr[0] "  Lokaler Zweig konfiguriert für 'git pull':"
-msgstr[1] "  Lokale Zweige konfiguriert für 'git pull':"
+msgstr[0] "  Lokaler Branch konfiguriert für 'git pull':"
+msgstr[1] "  Lokale Branches konfiguriert für 'git pull':"
 
 #: builtin/remote.c:1171
 msgid "  Local refs will be mirrored by 'git push'"
@@ -8039,7 +8444,7 @@
 
 #: builtin/remote.c:1199
 msgid "set refs/remotes/<name>/HEAD according to remote"
-msgstr "setzt refs/remotes/<Name>/HEAD gemäß dem Fernarchiv"
+msgstr "setzt refs/remotes/<Name>/HEAD gemäß dem Remote-Repository"
 
 #: builtin/remote.c:1201
 msgid "delete refs/remotes/<name>/HEAD"
@@ -8047,13 +8452,13 @@
 
 #: builtin/remote.c:1216
 msgid "Cannot determine remote HEAD"
-msgstr "Kann Hauptzweig des externen Projektarchivs nicht bestimmen"
+msgstr "Kann HEAD des Remote-Repositories nicht bestimmen"
 
 #: builtin/remote.c:1218
 msgid "Multiple remote HEAD branches. Please choose one explicitly with:"
 msgstr ""
-"Mehrere Hauptzweige im externen Projektarchiv. Bitte wählen Sie explizit "
-"einen aus mit:"
+"Mehrere Hauptbranches im Remote-Repository. Bitte wählen Sie explizit einen "
+"aus mit:"
 
 #: builtin/remote.c:1228
 #, c-format
@@ -8083,7 +8488,7 @@
 #: builtin/remote.c:1281
 #, c-format
 msgid "Pruning %s"
-msgstr "entferne veraltete Zweige von %s"
+msgstr "entferne veraltete Branches von %s"
 
 #: builtin/remote.c:1282
 #, c-format
@@ -8093,33 +8498,33 @@
 #: builtin/remote.c:1295
 #, c-format
 msgid " * [would prune] %s"
-msgstr " * [würde veralteten Zweig entfernen] %s"
+msgstr " * [würde veralteten Branch entfernen] %s"
 
 #: builtin/remote.c:1298
 #, c-format
 msgid " * [pruned] %s"
-msgstr "* [veralteten Zweig entfernt] %s"
+msgstr "* [veralteten Branch entfernt] %s"
 
 #: builtin/remote.c:1321
 msgid "prune remotes after fetching"
-msgstr "entfernt veraltete Zweige im Fernarchiv nach dem Abholen"
+msgstr "entfernt veraltete Branches im Remote-Repository nach \"fetch\""
 
 #: builtin/remote.c:1387 builtin/remote.c:1461
 #, c-format
 msgid "No such remote '%s'"
-msgstr "Kein solches externes Projektarchiv '%s'"
+msgstr "Kein solches Remote-Repository '%s'"
 
 #: builtin/remote.c:1407
 msgid "add branch"
-msgstr "fügt Zweig hinzu"
+msgstr "fügt Branch hinzu"
 
 #: builtin/remote.c:1414
 msgid "no remote specified"
-msgstr "kein externes Projektarchiv angegeben"
+msgstr "kein Remote-Repository angegeben"
 
 #: builtin/remote.c:1436
 msgid "manipulate push URLs"
-msgstr "manipuliert URLs zum Versenden"
+msgstr "manipuliert URLs für \"push\""
 
 #: builtin/remote.c:1438
 msgid "add URL"
@@ -8146,7 +8551,7 @@
 
 #: builtin/remote.c:1497
 msgid "Will not delete all non-push URLs"
-msgstr "Werde keine URLs entfernen, die nicht für den Versand bestimmt sind"
+msgstr "Werde keine URLs entfernen, die nicht für \"push\" bestimmt sind"
 
 #: builtin/remote.c:1569
 msgid "be verbose; must be placed before a subcommand"
@@ -8182,21 +8587,21 @@
 
 #: builtin/rerere.c:56
 msgid "register clean resolutions in index"
-msgstr "registriert saubere Auflösungen in der Bereitstellung"
+msgstr "registriert saubere Auflösungen in der Staging-Area"
 
 #: builtin/reset.c:25
 msgid ""
 "git reset [--mixed | --soft | --hard | --merge | --keep] [-q] [<commit>]"
 msgstr ""
-"git reset [--mixed | --soft | --hard | --merge | --keep] [-q] [<Version>]"
+"git reset [--mixed | --soft | --hard | --merge | --keep] [-q] [<Commit>]"
 
 #: builtin/reset.c:26
 msgid "git reset [-q] <tree-ish> [--] <paths>..."
-msgstr "git reset [-q] <Versionsreferenz> [--] <Pfade>..."
+msgstr "git reset [-q] <Commit-Referenz> [--] <Pfade>..."
 
 #: builtin/reset.c:27
 msgid "git reset --patch [<tree-ish>] [--] [<paths>...]"
-msgstr "git reset --patch [<Versionsreferenz>] [--] [<Pfade>...]"
+msgstr "git reset --patch [<Commit-Referenz>] [--] [<Pfade>...]"
 
 #: builtin/reset.c:33
 msgid "mixed"
@@ -8220,110 +8625,108 @@
 
 #: builtin/reset.c:73
 msgid "You do not have a valid HEAD."
-msgstr "Sie haben keine gültige Zweigspitze (HEAD)."
+msgstr "Sie haben keinen gültigen HEAD."
 
 #: builtin/reset.c:75
 msgid "Failed to find tree of HEAD."
-msgstr "Fehler beim Finden des Baumes der Zweigspitze (HEAD)."
+msgstr "Fehler beim Finden des \"Tree\"-Objektes von HEAD."
 
 #: builtin/reset.c:81
 #, c-format
 msgid "Failed to find tree of %s."
-msgstr "Fehler beim Finden des Baumes von %s."
+msgstr "Fehler beim Finden des \"Tree\"-Objektes von %s."
 
-#: builtin/reset.c:98
+#: builtin/reset.c:99
 #, c-format
 msgid "HEAD is now at %s"
-msgstr "Zweigspitze (HEAD) ist jetzt bei %s"
+msgstr "HEAD ist jetzt bei %s"
 
-#: builtin/reset.c:169
+#: builtin/reset.c:172
 #, c-format
 msgid "Cannot do a %s reset in the middle of a merge."
-msgstr ""
-"Kann keine '%s' Zurücksetzung durchführen, während eine Zusammenführung im "
-"Gange ist."
+msgstr "Kann keinen '%s'-Reset durchführen, während ein Merge im Gange ist."
 
-#: builtin/reset.c:248
+#: builtin/reset.c:251
 msgid "be quiet, only report errors"
 msgstr "weniger Ausgaben, meldet nur Fehler"
 
-#: builtin/reset.c:250
+#: builtin/reset.c:253
 msgid "reset HEAD and index"
-msgstr "setzt Zweigspitze (HEAD) und Bereitstellung neu"
+msgstr "setzt HEAD und Staging-Area um"
 
-#: builtin/reset.c:251
+#: builtin/reset.c:254
 msgid "reset only HEAD"
-msgstr "setzt nur Zweigspitze (HEAD) neu"
+msgstr "setzt nur HEAD um"
 
-#: builtin/reset.c:253 builtin/reset.c:255
+#: builtin/reset.c:256 builtin/reset.c:258
 msgid "reset HEAD, index and working tree"
-msgstr "setzt Zweigspitze (HEAD), Bereitstellung und Arbeitsbaum neu"
+msgstr "setzt HEAD, Staging-Area und Arbeitsverzeichnis um"
 
-#: builtin/reset.c:257
+#: builtin/reset.c:260
 msgid "reset HEAD but keep local changes"
-msgstr "setzt Zweigspitze (HEAD) neu, behält aber lokale Änderungen"
+msgstr "setzt HEAD um, behält aber lokale Änderungen"
 
-#: builtin/reset.c:275
+#: builtin/reset.c:278
 #, c-format
 msgid "Failed to resolve '%s' as a valid revision."
-msgstr "Konnte '%s' nicht als gültige Revision auflösen."
+msgstr "Konnte '%s' nicht als gültigen Commit auflösen."
 
-#: builtin/reset.c:278 builtin/reset.c:286
+#: builtin/reset.c:281 builtin/reset.c:289
 #, c-format
 msgid "Could not parse object '%s'."
 msgstr "Konnte Objekt '%s' nicht parsen."
 
-#: builtin/reset.c:283
+#: builtin/reset.c:286
 #, c-format
 msgid "Failed to resolve '%s' as a valid tree."
-msgstr "Konnte '%s' nicht als gültigen Baum auflösen."
+msgstr "Konnte '%s' nicht als gültiges \"Tree\"-Objekt auflösen."
 
-#: builtin/reset.c:292
+#: builtin/reset.c:295
 msgid "--patch is incompatible with --{hard,mixed,soft}"
 msgstr "--patch ist inkompatibel mit --{hard,mixed,soft}"
 
-#: builtin/reset.c:301
+#: builtin/reset.c:304
 msgid "--mixed with paths is deprecated; use 'git reset -- <paths>' instead."
 msgstr ""
 "--mixed mit Pfaden ist veraltet; benutzen Sie stattdessen 'git reset -- "
 "<Pfade>'."
 
-#: builtin/reset.c:303
+#: builtin/reset.c:306
 #, c-format
 msgid "Cannot do %s reset with paths."
-msgstr "Eine '%s' Zurücksetzung mit Pfaden ist nicht möglich."
+msgstr "Ein '%s'-Reset mit Pfaden ist nicht möglich."
 
-#: builtin/reset.c:313
+#: builtin/reset.c:316
 #, c-format
 msgid "%s reset is not allowed in a bare repository"
-msgstr "'%s' Zurücksetzung ist in einem bloßen Projektarchiv nicht erlaubt"
+msgstr "'%s'-Reset ist in einem Bare-Repository nicht erlaubt"
 
-#: builtin/reset.c:333
+#: builtin/reset.c:336
 #, c-format
 msgid "Could not reset index file to revision '%s'."
-msgstr "Konnte Bereitstellungsdatei nicht zu Revision '%s' setzen."
+msgstr "Konnte Staging-Area-Datei nicht zu Commit '%s' setzen."
 
-#: builtin/reset.c:339
+#: builtin/reset.c:342
 msgid "Unstaged changes after reset:"
-msgstr "Nicht bereitgestellte Änderungen nach Zurücksetzung:"
+msgstr "Nicht zum Commit vorgemerkte Änderungen nach Zurücksetzung:"
 
-#: builtin/reset.c:344
+#: builtin/reset.c:347
 msgid "Could not write new index file."
-msgstr "Konnte neue Bereitstellungsdatei nicht schreiben."
+msgstr "Konnte neue Staging-Area-Datei nicht schreiben."
 
-#: builtin/rev-parse.c:339
+#: builtin/rev-parse.c:345
 msgid "git rev-parse --parseopt [options] -- [<args>...]"
 msgstr "git rev-parse --parseopt [Optionen] -- [<Argumente>...]"
 
-#: builtin/rev-parse.c:344
+#: builtin/rev-parse.c:350
 msgid "keep the `--` passed as an arg"
 msgstr "lässt `--` als Argument"
 
-#: builtin/rev-parse.c:346
+#: builtin/rev-parse.c:352
 msgid "stop parsing after the first non-option argument"
 msgstr "stoppt das Parsen nach dem ersten Argument was keine Option ist"
 
-#: builtin/rev-parse.c:464
+#: builtin/rev-parse.c:470
 msgid ""
 "git rev-parse --parseopt [options] -- [<args>...]\n"
 "   or: git rev-parse --sq-quote [<arg>...]\n"
@@ -8339,196 +8742,221 @@
 "erster Verwendung aus."
 
 #: builtin/revert.c:22
-msgid "git revert [options] <commit-ish>"
-msgstr "git revert [options] <Versionsangabe>"
+msgid "git revert [options] <commit-ish>..."
+msgstr "git revert [Optionen] <Commit-Angabe>..."
 
 #: builtin/revert.c:23
 msgid "git revert <subcommand>"
 msgstr "git revert <Unterkommando>"
 
 #: builtin/revert.c:28
-msgid "git cherry-pick [options] <commit-ish>"
-msgstr "git cherry-pick [Optionen] <Versionsangabe>"
+msgid "git cherry-pick [options] <commit-ish>..."
+msgstr "git cherry-pick [Optionen] <Commit-Angabe>..."
 
 #: builtin/revert.c:29
 msgid "git cherry-pick <subcommand>"
 msgstr "git cherry-pick <Unterkommando>"
 
-#: builtin/revert.c:70 builtin/revert.c:92
+#: builtin/revert.c:71 builtin/revert.c:94
 #, c-format
 msgid "%s: %s cannot be used with %s"
 msgstr "%s: %s kann nicht mit %s verwendet werden"
 
-#: builtin/revert.c:103
+#: builtin/revert.c:105
 msgid "end revert or cherry-pick sequence"
 msgstr "beendet \"revert\" oder \"cherry-pick\" Ablauf"
 
-#: builtin/revert.c:104
+#: builtin/revert.c:106
 msgid "resume revert or cherry-pick sequence"
 msgstr "setzt \"revert\" oder \"cherry-pick\" Ablauf fort"
 
-#: builtin/revert.c:105
+#: builtin/revert.c:107
 msgid "cancel revert or cherry-pick sequence"
 msgstr "bricht \"revert\" oder \"cherry-pick\" Ablauf ab"
 
-#: builtin/revert.c:106
+#: builtin/revert.c:108
 msgid "don't automatically commit"
-msgstr "trägt nicht automatisch ein"
+msgstr "committet nicht automatisch"
 
-#: builtin/revert.c:107
+#: builtin/revert.c:109
 msgid "edit the commit message"
-msgstr "Bearbeitung der Versionsbeschreibung"
+msgstr "Bearbeitung der Commit-Beschreibung"
 
-#: builtin/revert.c:110
+#: builtin/revert.c:112
 msgid "parent number"
 msgstr "Nummer des Elternteils"
 
-#: builtin/revert.c:112
+#: builtin/revert.c:114
 msgid "merge strategy"
-msgstr "Zusammenführungsstrategie"
+msgstr "Merge-Strategie"
 
-#: builtin/revert.c:113
+#: builtin/revert.c:115
 msgid "option"
 msgstr "Option"
 
-#: builtin/revert.c:114
+#: builtin/revert.c:116
 msgid "option for merge strategy"
-msgstr "Option für Zusammenführungsstrategie"
+msgstr "Option für Merge-Strategie"
 
-#: builtin/revert.c:125
+#: builtin/revert.c:127
 msgid "append commit name"
-msgstr "hängt Versionsnamen an"
+msgstr "hängt Commit-Namen an"
 
-#: builtin/revert.c:126
+#: builtin/revert.c:128
 msgid "allow fast-forward"
 msgstr "erlaubt Vorspulen"
 
-#: builtin/revert.c:127
-msgid "preserve initially empty commits"
-msgstr "erhält ursprüngliche, leere Versionen"
-
-#: builtin/revert.c:128
-msgid "allow commits with empty messages"
-msgstr "erlaubt Version mit leerer Beschreibung"
-
 #: builtin/revert.c:129
-msgid "keep redundant, empty commits"
-msgstr "behält redundante, leere Versionen"
+msgid "preserve initially empty commits"
+msgstr "erhält ursprüngliche, leere Commits"
 
-#: builtin/revert.c:133
+#: builtin/revert.c:130
+msgid "allow commits with empty messages"
+msgstr "erlaubt Commits mit leerer Beschreibung"
+
+#: builtin/revert.c:131
+msgid "keep redundant, empty commits"
+msgstr "behält redundante, leere Commits"
+
+#: builtin/revert.c:135
 msgid "program error"
 msgstr "Programmfehler"
 
-#: builtin/revert.c:223
+#: builtin/revert.c:225
 msgid "revert failed"
 msgstr "\"revert\" fehlgeschlagen"
 
-#: builtin/revert.c:238
+#: builtin/revert.c:240
 msgid "cherry-pick failed"
 msgstr "\"cherry-pick\" fehlgeschlagen"
 
-#: builtin/rm.c:15
+#: builtin/rm.c:16
 msgid "git rm [options] [--] <file>..."
 msgstr "git rm [Optionen] [--] [<Datei>...]"
 
-#: builtin/rm.c:64 builtin/rm.c:186
-#, c-format
+#: builtin/rm.c:64
 msgid ""
-"submodule '%s' (or one of its nested submodules) uses a .git directory\n"
+"the following submodule (or one of its nested submodules)\n"
+"uses a .git directory:"
+msgid_plural ""
+"the following submodules (or one of its nested submodules)\n"
+"use a .git directory:"
+msgstr[0] ""
+"das folgende Submodul (oder ein geschachteltes Submodul hiervon)\n"
+"benutzt ein .git-Verzeichnis:"
+msgstr[1] ""
+"die folgenden Submodule (oder ein geschachteltes Submodul hiervon)\n"
+"benutzen ein .git-Verzeichnis:"
+
+#: builtin/rm.c:70
+msgid ""
+"\n"
 "(use 'rm -rf' if you really want to remove it including all of its history)"
 msgstr ""
-"Unterprojekt '%s' (oder ein geschachteltes Unterprojekt hiervon) verwendet\n"
-"ein .git-Verzeichnis (benutzen Sie 'rm -rf' wenn Sie dieses wirklich "
-"mitsamt\n"
+"\n"
+"(benutzen Sie 'rm -rf' wenn Sie dieses Submodul wirklich mitsamt\n"
 "seiner Historie löschen möchten)"
 
-#: builtin/rm.c:174
-#, c-format
+#: builtin/rm.c:230
 msgid ""
-"'%s' has staged content different from both the file and the HEAD\n"
+"the following file has staged content different from both the\n"
+"file and the HEAD:"
+msgid_plural ""
+"the following files have staged content different from both the\n"
+"file and the HEAD:"
+msgstr[0] ""
+"die folgende Datei hat zum Commit vorgemerkte Änderungen unterschiedlich\n"
+"zu der Datei und HEAD:"
+msgstr[1] ""
+"die folgenden Dateien haben zum Commit vorgemerkte Änderungen "
+"unterschiedlich\n"
+"zu der Datei und HEAD:"
+
+#: builtin/rm.c:235
+msgid ""
+"\n"
 "(use -f to force removal)"
 msgstr ""
-"'%s' hat bereitgestellten Inhalt unterschiedlich zu der Datei und der\n"
-"Zweigspitze (HEAD) (benutzen Sie -f um die Entfernung zu erzwingen)"
+"\n"
+"(benutzen Sie -f um die Löschung zu erzwingen)"
 
-#: builtin/rm.c:180
-#, c-format
+#: builtin/rm.c:239
+msgid "the following file has changes staged in the index:"
+msgid_plural "the following files have changes staged in the index:"
+msgstr[0] "die folgende Datei hat zum Commit vorgemerkte Änderungen:"
+msgstr[1] "die folgenden Dateien haben zum Commit vorgemerkte Änderungen:"
+
+#: builtin/rm.c:243 builtin/rm.c:254
 msgid ""
-"'%s' has changes staged in the index\n"
+"\n"
 "(use --cached to keep the file, or -f to force removal)"
 msgstr ""
-"'%s' hat Änderungen in der Bereitstellung\n"
+"\n"
 "(benutzen Sie --cached um die Datei zu behalten, oder -f um die Entfernung "
 "zu erzwingen)"
 
-#: builtin/rm.c:191
-#, c-format
-msgid ""
-"'%s' has local modifications\n"
-"(use --cached to keep the file, or -f to force removal)"
-msgstr ""
-"'%s' hat lokale Modifikationen\n"
-"(benutzen Sie --cached um die Datei zu behalten, oder -f um die Entfernung "
-"zu erzwingen)"
+#: builtin/rm.c:251
+msgid "the following file has local modifications:"
+msgid_plural "the following files have local modifications:"
+msgstr[0] "die folgende Datei hat lokale Änderungen:"
+msgstr[1] "die folgenden Dateien haben lokale Änderungen:"
 
-#: builtin/rm.c:207
+#: builtin/rm.c:269
 msgid "do not list removed files"
 msgstr "listet keine gelöschten Dateien auf"
 
-#: builtin/rm.c:208
+#: builtin/rm.c:270
 msgid "only remove from the index"
-msgstr "entfernt nur aus der Bereitstellung"
+msgstr "entfernt nur aus der Staging-Area"
 
-#: builtin/rm.c:209
+#: builtin/rm.c:271
 msgid "override the up-to-date check"
 msgstr "überschreibt die \"up-to-date\" Prüfung"
 
-#: builtin/rm.c:210
+#: builtin/rm.c:272
 msgid "allow recursive removal"
 msgstr "erlaubt rekursive Entfernung"
 
-#: builtin/rm.c:212
+#: builtin/rm.c:274
 msgid "exit with a zero status even if nothing matched"
 msgstr "beendet mit Rückgabewert 0, wenn keine Übereinstimmung gefunden wurde"
 
-#: builtin/rm.c:283
+#: builtin/rm.c:345
 #, c-format
 msgid "not removing '%s' recursively without -r"
 msgstr "'%s' wird nicht ohne -r rekursiv entfernt"
 
-#: builtin/rm.c:322
+#: builtin/rm.c:384
 #, c-format
 msgid "git rm: unable to remove %s"
 msgstr "git rm: konnte %s nicht löschen"
 
 #: builtin/shortlog.c:13
-msgid "git shortlog [-n] [-s] [-e] [-w] [rev-opts] [--] [<commit-id>... ]"
-msgstr ""
-"git shortlog [-n] [-s] [-e] [-w] [rev-opts] [--] "
-"[<Versionsidentifikation>... ]"
+msgid "git shortlog [<options>] [<revision range>] [[--] [<path>...]]"
+msgstr "git shortlog [<Optionen>] [Commitbereich] [[--] <Pfad>...]"
 
-#: builtin/shortlog.c:133
+#: builtin/shortlog.c:131
 #, c-format
 msgid "Missing author: %s"
 msgstr "fehlender Autor: %s"
 
-#: builtin/shortlog.c:229
+#: builtin/shortlog.c:228
 msgid "sort output according to the number of commits per author"
-msgstr "sortiert die Ausgabe entsprechend der Anzahl von Versionen pro Autor"
+msgstr "sortiert die Ausgabe entsprechend der Anzahl von Commits pro Autor"
 
-#: builtin/shortlog.c:231
+#: builtin/shortlog.c:230
 msgid "Suppress commit descriptions, only provides commit count"
-msgstr "Unterdrückt Versionsbeschreibungen, liefert nur Anzahl der Versionen"
+msgstr "Unterdrückt Commit-Beschreibungen, liefert nur Anzahl der Commits"
 
-#: builtin/shortlog.c:233
+#: builtin/shortlog.c:232
 msgid "Show the email address of each author"
 msgstr "Zeigt die Email-Adresse von jedem Autor"
 
-#: builtin/shortlog.c:234
+#: builtin/shortlog.c:233
 msgid "w[,i1[,i2]]"
 msgstr "w[,i1[,i2]]"
 
-#: builtin/shortlog.c:235
+#: builtin/shortlog.c:234
 msgid "Linewrap output"
 msgstr "Ausgabe mit Zeilenumbrüchen"
 
@@ -8541,78 +8969,76 @@
 msgstr ""
 "git show-branch [-a|--all] [-r|--remotes] [--topo-order | --date-order] [--"
 "current] [--color[=<Wann>] | --no-color] [--sparse] [--more=<n> | --list | --"
-"independent | --merge-base] [--no-name | --sha1-name] [--topics] "
-"[(<Revision> | <glob>)...]"
+"independent | --merge-base] [--no-name | --sha1-name] [--topics] [(<Commit> "
+"| <glob>)...]"
 
 #: builtin/show-branch.c:10
 msgid "git show-branch (-g|--reflog)[=<n>[,<base>]] [--list] [<ref>]"
 msgstr "git show-branch (-g|--reflog)[=<n>[,<Basis>]] [--list] [<Referenz>]"
 
-#: builtin/show-branch.c:651
+#: builtin/show-branch.c:650
 msgid "show remote-tracking and local branches"
-msgstr "zeigt externe Übernahmezweige und lokale Zweige an"
+msgstr "zeigt Remote-Tracking und lokale Branches an"
 
-#: builtin/show-branch.c:653
+#: builtin/show-branch.c:652
 msgid "show remote-tracking branches"
-msgstr "zeigt externe Übernahmezweige an"
+msgstr "zeigt Remote-Tracking-Branches an"
 
-#: builtin/show-branch.c:655
+#: builtin/show-branch.c:654
 msgid "color '*!+-' corresponding to the branch"
-msgstr "färbt '*!+-' entsprechend des Zweiges ein"
+msgstr "färbt '*!+-' entsprechend des Branches ein"
 
-#: builtin/show-branch.c:657
+#: builtin/show-branch.c:656
 msgid "show <n> more commits after the common ancestor"
-msgstr "zeigt <n> weitere Versionen nach dem gemeinsamen Vorfahren"
+msgstr "zeigt <n> weitere Commits nach dem gemeinsamen Vorgänger-Commit"
 
-#: builtin/show-branch.c:659
+#: builtin/show-branch.c:658
 msgid "synonym to more=-1"
 msgstr "Synonym für more=-1"
 
-#: builtin/show-branch.c:660
+#: builtin/show-branch.c:659
 msgid "suppress naming strings"
 msgstr "unterdrückt Namen"
 
-#: builtin/show-branch.c:662
+#: builtin/show-branch.c:661
 msgid "include the current branch"
-msgstr "bezieht den aktuellen Zweig ein"
+msgstr "bezieht den aktuellen Branch ein"
 
-#: builtin/show-branch.c:664
+#: builtin/show-branch.c:663
 msgid "name commits with their object names"
-msgstr "benennt Versionen nach ihren Objektnamen"
+msgstr "benennt Commits nach ihren Objektnamen"
 
-#: builtin/show-branch.c:666
+#: builtin/show-branch.c:665
 msgid "show possible merge bases"
-msgstr "zeigt mögliche Basen für Zusammenführung"
+msgstr "zeigt mögliche Merge-Basen an"
 
-#: builtin/show-branch.c:668
+#: builtin/show-branch.c:667
 msgid "show refs unreachable from any other ref"
 msgstr "zeigt Referenzen die unerreichbar von allen anderen Referenzen sind"
 
-#: builtin/show-branch.c:670
+#: builtin/show-branch.c:669
 msgid "show commits in topological order"
-msgstr "zeigt Versionen in topologischer Ordnung"
+msgstr "zeigt Commits in topologischer Ordnung"
 
 #: builtin/show-branch.c:672
 msgid "show only commits not on the first branch"
-msgstr "zeigt nur Versionen, die sich nicht im ersten Zweig befinden"
+msgstr "zeigt nur Commits, die sich nicht im ersten Branch befinden"
 
 #: builtin/show-branch.c:674
 msgid "show merges reachable from only one tip"
-msgstr ""
-"zeigt Zusammenführungen, die nur von einer Zweigspitze aus erreichbar sind"
+msgstr "zeigt Merges, die nur von einem Branch aus erreichbar sind"
 
 #: builtin/show-branch.c:676
-msgid "show commits where no parent comes before its children"
-msgstr "zeigt Versionen, wo kein Elternteil vor seinem Kind kommt"
+msgid "topologically sort, maintaining date order where possible"
+msgstr "topologische Sortierung, Beibehaltung Datumsordnung wo möglich"
 
-#: builtin/show-branch.c:678
+#: builtin/show-branch.c:679
 msgid "<n>[,<base>]"
 msgstr "<n>[,<Basis>]"
 
-#: builtin/show-branch.c:679
+#: builtin/show-branch.c:680
 msgid "show <n> most recent ref-log entries starting at base"
-msgstr ""
-"zeigt die <n> jüngsten Einträge im Referenzprotokoll beginnend an der Basis"
+msgstr "zeigt die <n> jüngsten Einträge im Reflog beginnend an der Basis"
 
 #: builtin/show-ref.c:10
 msgid ""
@@ -8626,40 +9052,40 @@
 msgid "git show-ref --exclude-existing[=pattern] < ref-list"
 msgstr "git show-ref --exclude-existing[=Muster] < ref-list"
 
-#: builtin/show-ref.c:165
+#: builtin/show-ref.c:168
 msgid "only show tags (can be combined with heads)"
-msgstr "zeigt nur Markierungen (kann mit \"heads\" kombiniert werden)"
+msgstr "zeigt nur Tags (kann mit \"heads\" kombiniert werden)"
 
-#: builtin/show-ref.c:166
+#: builtin/show-ref.c:169
 msgid "only show heads (can be combined with tags)"
-msgstr "zeigt nur Zweigspitzen (kann mit \"tags\" kombiniert werden)"
+msgstr "zeigt nur Branches (kann mit \"tags\" kombiniert werden)"
 
-#: builtin/show-ref.c:167
+#: builtin/show-ref.c:170
 msgid "stricter reference checking, requires exact ref path"
 msgstr "strengere Referenzprüfung, erfordert exakten Referenzpfad"
 
-#: builtin/show-ref.c:170 builtin/show-ref.c:172
-msgid "show the HEAD reference"
-msgstr "zeigt Referenz der Zweigspitze (HEAD)"
+#: builtin/show-ref.c:173 builtin/show-ref.c:176
+msgid "show the HEAD reference, even if it would be filtered out"
+msgstr "zeigt die HEAD-Referenz, selbst wenn diese ausgefiltert werden würde"
 
-#: builtin/show-ref.c:174
+#: builtin/show-ref.c:178
 msgid "dereference tags into object IDs"
-msgstr "dereferenziert Markierungen in Objekt-Identifikationen"
+msgstr "dereferenziert Tags in Objekt-Identifikationen"
 
-#: builtin/show-ref.c:176
+#: builtin/show-ref.c:180
 msgid "only show SHA1 hash using <n> digits"
 msgstr "zeigt nur SHA1 Hash mit <n> Ziffern"
 
-#: builtin/show-ref.c:180
+#: builtin/show-ref.c:184
 msgid "do not print results to stdout (useful with --verify)"
 msgstr ""
 "keine Ausgabe der Ergebnisse in die Standard-Ausgabe (nützlich mit --verify)"
 
-#: builtin/show-ref.c:182
+#: builtin/show-ref.c:186
 msgid "show refs from stdin that aren't in local repository"
 msgstr ""
 "zeigt Referenzen von der Standard-Eingabe, die sich nicht im lokalen "
-"Projektarchiv befinden, an"
+"Repository befinden, an"
 
 #: builtin/symbolic-ref.c:7
 msgid "git symbolic-ref [options] name [ref]"
@@ -8694,24 +9120,24 @@
 msgid ""
 "git tag [-a|-s|-u <key-id>] [-f] [-m <msg>|-F <file>] <tagname> [<head>]"
 msgstr ""
-"git tag [-a|-s|-u <Schlüssel-id>] [-f] [-m <Nachricht>|-F <Datei>] "
-"<Markierungsname> [<Zweig>]"
+"git tag [-a|-s|-u <Schlüssel-id>] [-f] [-m <Nachricht>|-F <Datei>] <Tagname> "
+"[<Commit>]"
 
 #: builtin/tag.c:23
 msgid "git tag -d <tagname>..."
-msgstr "git tag -d <Markierungsname>..."
+msgstr "git tag -d <Tagname>..."
 
 #: builtin/tag.c:24
 msgid ""
 "git tag -l [-n[<num>]] [--contains <commit>] [--points-at <object>] \n"
 "\t\t[<pattern>...]"
 msgstr ""
-"git tag -l [-n[<Nummer>]] [--contains <Version>] [--points-at <Objekt>] \n"
+"git tag -l [-n[<Nummer>]] [--contains <Commit>] [--points-at <Objekt>] \n"
 "\t\t[<Muster>...]"
 
 #: builtin/tag.c:26
 msgid "git tag -v <tagname>..."
-msgstr "git tag -v <Markierungsname>..."
+msgstr "git tag -v <Tagname>..."
 
 #: builtin/tag.c:60
 #, c-format
@@ -8721,22 +9147,22 @@
 #: builtin/tag.c:207
 #, c-format
 msgid "tag name too long: %.*s..."
-msgstr "Markierungsname zu lang: %.*s..."
+msgstr "Tagname zu lang: %.*s..."
 
 #: builtin/tag.c:212
 #, c-format
 msgid "tag '%s' not found."
-msgstr "Markierung '%s' nicht gefunden."
+msgstr "Tag '%s' nicht gefunden."
 
 #: builtin/tag.c:227
 #, c-format
 msgid "Deleted tag '%s' (was %s)\n"
-msgstr "Gelöschte Markierung '%s' (war %s)\n"
+msgstr "Tag '%s' gelöscht (war %s)\n"
 
 #: builtin/tag.c:239
 #, c-format
 msgid "could not verify the tag '%s'"
-msgstr "Konnte Markierung '%s' nicht verifizieren"
+msgstr "Konnte Tag '%s' nicht verifizieren"
 
 #: builtin/tag.c:249
 #, c-format
@@ -8746,7 +9172,7 @@
 "Lines starting with '%c' will be ignored.\n"
 msgstr ""
 "\n"
-"Geben Sie eine Markierungsbeschreibung ein.\n"
+"Geben Sie eine Tag-Beschreibung ein.\n"
 "Zeilen, die mit '%c' beginnen, werden ignoriert.\n"
 
 #: builtin/tag.c:253
@@ -8758,17 +9184,17 @@
 "want to.\n"
 msgstr ""
 "\n"
-"Geben Sie eine Markierungsbeschreibung ein.\n"
+"Geben Sie eine Tag-Beschreibung ein.\n"
 "Zeilen, die mit '%c' beginnen, werden behalten; Sie dürfen diese\n"
 "selbst entfernen wenn Sie möchten.\n"
 
 #: builtin/tag.c:292
 msgid "unable to sign the tag"
-msgstr "konnte Markierung nicht signieren"
+msgstr "konnte Tag nicht signieren"
 
 #: builtin/tag.c:294
 msgid "unable to write tag file"
-msgstr "konnte Markierungsdatei nicht schreiben"
+msgstr "konnte Tag-Datei nicht schreiben"
 
 #: builtin/tag.c:319
 msgid "bad object type."
@@ -8776,16 +9202,16 @@
 
 #: builtin/tag.c:332
 msgid "tag header too big."
-msgstr "Markierungskopf zu groß."
+msgstr "Tag-Kopf zu groß."
 
 #: builtin/tag.c:368
 msgid "no tag message?"
-msgstr "keine Markierungsbeschreibung?"
+msgstr "keine Tag-Beschreibung?"
 
 #: builtin/tag.c:374
 #, c-format
 msgid "The tag message has been left in %s\n"
-msgstr "Die Markierungsbeschreibung wurde gelassen in %s\n"
+msgstr "Die Tag-Beschreibung wurde gelassen in %s\n"
 
 #: builtin/tag.c:423
 msgid "switch 'points-at' requires an object"
@@ -8798,59 +9224,59 @@
 
 #: builtin/tag.c:445
 msgid "list tag names"
-msgstr "listet Markierungsnamen auf"
+msgstr "listet Tagnamen auf"
 
 #: builtin/tag.c:447
 msgid "print <n> lines of each tag message"
-msgstr "zeigt <n> Zeilen jeder Markierungsbeschreibung"
+msgstr "zeigt <n> Zeilen jeder Tag-Beschreibung"
 
 #: builtin/tag.c:449
 msgid "delete tags"
-msgstr "löscht Markierungen"
+msgstr "löscht Tags"
 
 #: builtin/tag.c:450
 msgid "verify tags"
-msgstr "überprüft Markierungen"
+msgstr "überprüft Tags"
 
 #: builtin/tag.c:452
 msgid "Tag creation options"
-msgstr "Optionen für Erstellung von Markierungen"
+msgstr "Optionen für Erstellung von Tags"
 
 #: builtin/tag.c:454
 msgid "annotated tag, needs a message"
-msgstr "annotierte Markierung, benötigt eine Beschreibung"
+msgstr "annotiertes Tag, benötigt eine Beschreibung"
 
 #: builtin/tag.c:456
 msgid "tag message"
-msgstr "Markierungsbeschreibung"
+msgstr "Tag-Beschreibung"
 
 #: builtin/tag.c:458
 msgid "annotated and GPG-signed tag"
-msgstr "annotierte und GPG-signierte Markierung"
+msgstr "annotiertes und GPG-signiertes Tag"
 
 #: builtin/tag.c:462
 msgid "use another key to sign the tag"
-msgstr "verwendet einen anderen Schlüssel um die Markierung zu signieren"
+msgstr "verwendet einen anderen Schlüssel um das Tag zu signieren"
 
 #: builtin/tag.c:463
 msgid "replace the tag if exists"
-msgstr "ersetzt die Markierung, wenn sie existiert"
+msgstr "ersetzt das Tag, wenn es existiert"
 
 #: builtin/tag.c:464
 msgid "show tag list in columns"
-msgstr "zeigt Liste der Markierungen in Spalten"
+msgstr "zeigt Liste der Tags in Spalten"
 
 #: builtin/tag.c:466
 msgid "Tag listing options"
-msgstr "Optionen für Auflistung der Markierungen"
+msgstr "Optionen für Auflistung der Tags"
 
 #: builtin/tag.c:469
 msgid "print only tags that contain the commit"
-msgstr "gibt nur Markierungen aus, die diese Version beinhalten"
+msgstr "gibt nur Tags aus, die diesen Commit beinhalten"
 
 #: builtin/tag.c:475
 msgid "print only tags of the object"
-msgstr "gibt nur Markierungen von dem Objekt aus"
+msgstr "gibt nur Tags von dem Objekt aus"
 
 #: builtin/tag.c:504
 msgid "--column and -n are incompatible"
@@ -8879,12 +9305,12 @@
 #: builtin/tag.c:559
 #, c-format
 msgid "'%s' is not a valid tag name."
-msgstr "'%s' ist kein gültiger Markierungsname."
+msgstr "'%s' ist kein gültiger Tagname."
 
 #: builtin/tag.c:564
 #, c-format
 msgid "tag '%s' already exists"
-msgstr "Markierung '%s' existiert bereits"
+msgstr "Tag '%s' existiert bereits"
 
 #: builtin/tag.c:582
 #, c-format
@@ -8899,7 +9325,7 @@
 #: builtin/tag.c:586
 #, c-format
 msgid "Updated tag '%s' (was %s)\n"
-msgstr "Aktualisierte Markierung '%s' (war %s)\n"
+msgstr "Tag '%s' aktualisiert (war %s)\n"
 
 #: builtin/update-index.c:401
 msgid "git update-index [options] [--] [<file>...]"
@@ -8908,12 +9334,12 @@
 #: builtin/update-index.c:718
 msgid "continue refresh even when index needs update"
 msgstr ""
-"Aktualisierung fortsetzen, auch wenn die Bereitstellung aktualisiert werden "
+"Aktualisierung fortsetzen, auch wenn die Staging-Area aktualisiert werden "
 "muss"
 
 #: builtin/update-index.c:721
 msgid "refresh: ignore submodules"
-msgstr "Aktualisierung: ignoriert Unterprojekte"
+msgstr "Aktualisierung: ignoriert Submodule"
 
 #: builtin/update-index.c:724
 msgid "do not ignore new files"
@@ -8925,12 +9351,12 @@
 
 #: builtin/update-index.c:728
 msgid "notice files missing from worktree"
-msgstr "beachtet fehlende Dateien im Arbeitsbaum"
+msgstr "beachtet fehlende Dateien im Arbeitsverzeichnis"
 
 #: builtin/update-index.c:730
 msgid "refresh even if index contains unmerged entries"
 msgstr ""
-"aktualisiert, auch wenn die Bereitstellung nicht zusammengeführte Einträge "
+"aktualisiert, auch wenn die Staging-Area nicht zusammengeführte Einträge "
 "beinhaltet"
 
 #: builtin/update-index.c:733
@@ -8947,7 +9373,7 @@
 
 #: builtin/update-index.c:742
 msgid "add the specified entry to the index"
-msgstr "stellt den angegebenen Eintrag zur Eintragung bereit"
+msgstr "merkt den angegebenen Eintrag zum Commit vor"
 
 #: builtin/update-index.c:746
 msgid "(+/-)x"
@@ -8976,12 +9402,13 @@
 #: builtin/update-index.c:763
 msgid "add to index only; do not add content to object database"
 msgstr ""
-"fügt nur der Bereitstellung hinzu; Inhalt wird nicht der Objekt-Datenbank "
-"hinzugefügt"
+"merkt die Änderungen nur zum Commit vor; Inhalt wird nicht der Objekt-"
+"Datenbank hinzugefügt"
 
 #: builtin/update-index.c:765
 msgid "remove named paths even if present in worktree"
-msgstr "löscht benannte Pfade, auch wenn sie sich im Arbeitsbaum befinden"
+msgstr ""
+"löscht benannte Pfade, auch wenn sie sich im Arbeitsverzeichnis befinden"
 
 #: builtin/update-index.c:767
 msgid "with --stdin: input lines are terminated by null bytes"
@@ -8993,7 +9420,7 @@
 
 #: builtin/update-index.c:773
 msgid "add entries from standard input to the index"
-msgstr "fügt Einträge von der Standard-Eingabe der Bereitstellung hinzu"
+msgstr "merkt Einträge von der Standard-Eingabe zum Commit vor"
 
 #: builtin/update-index.c:777
 msgid "repopulate stages #2 and #3 for the listed paths"
@@ -9002,12 +9429,11 @@
 
 #: builtin/update-index.c:781
 msgid "only update entries that differ from HEAD"
-msgstr ""
-"aktualisiert nur Einträge, die unterschiedlich zur Zweigspitze (HEAD) sind"
+msgstr "aktualisiert nur Einträge, die unterschiedlich zu HEAD sind"
 
 #: builtin/update-index.c:785
 msgid "ignore files missing from worktree"
-msgstr "ignoriert fehlende Dateien im Arbeitsbaum"
+msgstr "ignoriert fehlende Dateien im Arbeitsverzeichnis"
 
 #: builtin/update-index.c:788
 msgid "report actions to standard output"
@@ -9019,7 +9445,7 @@
 
 #: builtin/update-index.c:794
 msgid "write index in this format"
-msgstr "schreibt Bereitstellungsdatei in diesem Format"
+msgstr "schreibt Staging-Area-Datei in diesem Format"
 
 #: builtin/update-ref.c:7
 msgid "git update-ref [options] -d <refname> [<oldval>]"
@@ -9059,11 +9485,11 @@
 
 #: builtin/verify-tag.c:17
 msgid "git verify-tag [-v|--verbose] <tag>..."
-msgstr "git verify-tag [-v|--verbose] <Markierung>..."
+msgstr "git verify-tag [-v|--verbose] <Tag>..."
 
 #: builtin/verify-tag.c:73
 msgid "print tag contents"
-msgstr "gibt Markierungsinhalte aus"
+msgstr "gibt Tag-Inhalte aus"
 
 #: builtin/write-tree.c:13
 msgid "git write-tree [--missing-ok] [--prefix=<prefix>/]"
@@ -9075,37 +9501,46 @@
 
 #: builtin/write-tree.c:27
 msgid "write tree object for a subdirectory <prefix>"
-msgstr "schreibt das Baumobjekt für ein Unterverzeichnis <Prefix>"
+msgstr "schreibt das \"Tree\"-Objekt für ein Unterverzeichnis <Prefix>"
 
 #: builtin/write-tree.c:30
 msgid "only useful for debugging"
 msgstr "nur nützlich für Fehlersuche"
 
-#: git.c:16
-msgid "See 'git help <command>' for more information on a specific command."
+#: git.c:17
+msgid ""
+"'git help -a' and 'git help -g' lists available subcommands and some\n"
+"concept guides. See 'git help <command>' or 'git help <concept>'\n"
+"to read about a specific subcommand or concept."
 msgstr ""
-"Siehe 'git help <Kommando>' für weitere Informationen zu einem spezifischen "
-"Kommando"
+"'git help -a' und 'git help -g' listet verfügbare Unterkommandos und\n"
+"einige Anleitungen zu Git-Konzepten auf. Benutzen Sie 'git help <Kommando>'\n"
+"oder 'git help <Konzept>' um mehr über ein spezifisches Kommando oder\n"
+"Konzept zu erfahren."
 
-#: parse-options.h:156
+#: parse-options.h:144
+msgid "expiry date"
+msgstr "Verfallsdatum"
+
+#: parse-options.h:159
 msgid "no-op (backward compatibility)"
 msgstr "Kein Effekt (Rückwärtskompatibilität)"
 
-#: parse-options.h:232
+#: parse-options.h:236
 msgid "be more verbose"
 msgstr "erweiterte Ausgaben"
 
-#: parse-options.h:234
+#: parse-options.h:238
 msgid "be more quiet"
 msgstr "weniger Ausgaben"
 
-#: parse-options.h:240
+#: parse-options.h:244
 msgid "use <n> digits to display SHA-1s"
 msgstr "benutze <n> Ziffern zur Anzeige von SHA-1s"
 
 #: common-cmds.h:8
 msgid "Add file contents to the index"
-msgstr "stellt Dateiinhalte zur Eintragung bereit"
+msgstr "merkt Dateiinhalte zum Commit vor"
 
 #: common-cmds.h:9
 msgid "Find by binary search the change that introduced a bug"
@@ -9114,27 +9549,28 @@
 
 #: common-cmds.h:10
 msgid "List, create, or delete branches"
-msgstr "Zeigt an, erstellt oder entfernt Zweige"
+msgstr "Zeigt an, erstellt oder entfernt Branches"
 
 #: common-cmds.h:11
 msgid "Checkout a branch or paths to the working tree"
-msgstr "Checkt Zweige oder Pfade im Arbeitszweig aus"
+msgstr "Checkt Branches oder Pfade im Arbeitsverzeichnis aus"
 
 #: common-cmds.h:12
 msgid "Clone a repository into a new directory"
-msgstr "Klont ein Projektarchiv in einem neuen Verzeichnis"
+msgstr "Klont ein Repository in einem neuen Verzeichnis"
 
 #: common-cmds.h:13
 msgid "Record changes to the repository"
-msgstr "Trägt Änderungen in das Projektarchiv ein"
+msgstr "Trägt Änderungen in das Repository ein"
 
 #: common-cmds.h:14
 msgid "Show changes between commits, commit and working tree, etc"
-msgstr "Zeigt Änderungen zwischen Versionen, Version und Arbeitszweig, etc. an"
+msgstr ""
+"Zeigt Änderungen zwischen Commits, Commit und Arbeitsverzeichnis, etc. an"
 
 #: common-cmds.h:15
 msgid "Download objects and refs from another repository"
-msgstr "Lädt Objekte und Referenzen von einem anderen Projektarchiv herunter"
+msgstr "Lädt Objekte und Referenzen von einem anderen Repository herunter"
 
 #: common-cmds.h:16
 msgid "Print lines matching a pattern"
@@ -9143,11 +9579,11 @@
 #: common-cmds.h:17
 msgid "Create an empty Git repository or reinitialize an existing one"
 msgstr ""
-"Erstellt ein leeres Git-Projektarchiv oder initialisiert ein bestehendes neu"
+"Erstellt ein leeres Git-Repository oder initialisiert ein bestehendes neu"
 
 #: common-cmds.h:18
 msgid "Show commit logs"
-msgstr "Zeigt Versionshistorie an"
+msgstr "Zeigt Commit-Historie an"
 
 #: common-cmds.h:19
 msgid "Join two or more development histories together"
@@ -9156,30 +9592,30 @@
 #: common-cmds.h:20
 msgid "Move or rename a file, a directory, or a symlink"
 msgstr ""
-"Verschiebt oder benennt eine Datei, ein Verzeichnis, oder eine symbolische "
-"Verknüpfung um"
+"Verschiebt oder benennt eine Datei, ein Verzeichnis, oder einen symbolischen "
+"Verweis um"
 
 #: common-cmds.h:21
-msgid "Fetch from and merge with another repository or a local branch"
+msgid "Fetch from and integrate with another repository or a local branch"
 msgstr ""
-"Fordert Objekte von einem externen Projektarchiv an und führt sie mit einem "
-"anderen Projektarchiv oder einem lokalen Zweig zusammen"
+"Fordert Objekte von einem externen Repository an und führt sie mit einem "
+"anderen Repository oder einem lokalen Branch zusammen"
 
 #: common-cmds.h:22
 msgid "Update remote refs along with associated objects"
-msgstr "Aktualisiert externe Referenzen mitsamt den verbundenen Objekten"
+msgstr "Aktualisiert Remote-Referenzen mitsamt den verbundenen Objekten"
 
 #: common-cmds.h:23
 msgid "Forward-port local commits to the updated upstream head"
-msgstr "Baut lokale Versionen auf einem aktuellerem externen Zweig neu auf"
+msgstr "Baut lokale Commits auf einem aktuellerem Upstream-Branch neu auf"
 
 #: common-cmds.h:24
 msgid "Reset current HEAD to the specified state"
-msgstr "Setzt die aktuelle Zweigspitze (HEAD) zu einem spezifizierten Zustand"
+msgstr "Setzt aktuellen HEAD zu einem spezifizierten Zustand"
 
 #: common-cmds.h:25
 msgid "Remove files from the working tree and from the index"
-msgstr "Löscht Dateien im Arbeitszweig und von der Bereitstellung"
+msgstr "Löscht Dateien im Arbeitsverzeichnis und von der Staging-Area"
 
 #: common-cmds.h:26
 msgid "Show various types of objects"
@@ -9187,54 +9623,53 @@
 
 #: common-cmds.h:27
 msgid "Show the working tree status"
-msgstr "Zeigt den Zustand des Arbeitszweiges an"
+msgstr "Zeigt den Zustand des Arbeitsverzeichnisses an"
 
 #: common-cmds.h:28
 msgid "Create, list, delete or verify a tag object signed with GPG"
 msgstr ""
-"Erzeugt, listet auf, löscht oder verifiziert ein mit GPG signiertes "
-"Markierungsobjekt"
+"Erzeugt, listet auf, löscht oder verifiziert ein mit GPG signiertes Tag-"
+"Objekt"
 
 #: git-am.sh:50
 msgid "You need to set your committer info first"
-msgstr "Sie müssen zuerst die Informationen des Eintragenden setzen."
+msgstr "Sie müssen zuerst die Informationen zum Commit-Ersteller setzen."
 
 #: git-am.sh:95
 msgid ""
 "You seem to have moved HEAD since the last 'am' failure.\n"
 "Not rewinding to ORIG_HEAD"
 msgstr ""
-"Sie scheinen seit dem letzten gescheiterten 'am' die Zweigspitze (HEAD)\n"
-"geändert zu haben.\n"
+"Sie scheinen seit dem letzten gescheiterten 'am' HEAD geändert zu haben.\n"
 "Keine Zurücksetzung zu ORIG_HEAD."
 
 #: git-am.sh:105
 #, sh-format
 msgid ""
-"When you have resolved this problem, run \"$cmdline --resolved\".\n"
+"When you have resolved this problem, run \"$cmdline --continue\".\n"
 "If you prefer to skip this patch, run \"$cmdline --skip\" instead.\n"
 "To restore the original branch and stop patching, run \"$cmdline --abort\"."
 msgstr ""
-"Wenn Sie das Problem gelöst haben, führen Sie \"$cmdline --resolved\" aus.\n"
+"Wenn Sie das Problem gelöst haben, führen Sie \"$cmdline --continue\" aus.\n"
 "Falls Sie diesen Patch auslassen möchten, führen Sie stattdessen\n"
 "\"$cmdline --skip\" aus.\n"
-"Um den ursprünglichen Zweig wiederherzustellen und die Anwendung der\n"
+"Um den ursprünglichen Branch wiederherzustellen und die Anwendung der\n"
 "Patches abzubrechen, führen Sie \"$cmdline --abort\" aus."
 
 #: git-am.sh:121
 msgid "Cannot fall back to three-way merge."
-msgstr "Kann nicht zu 3-Wege-Zusammenführung zurückfallen."
+msgstr "Kann nicht zu 3-Wege-Merge zurückfallen."
 
 #: git-am.sh:137
 msgid "Repository lacks necessary blobs to fall back on 3-way merge."
 msgstr ""
-"Dem Projektarchiv fehlen notwendige Blobs um auf eine 3-Wege-Zusammenführung "
+"Dem Repository fehlen notwendige Blobs um auf einen 3-Wege-Merge "
 "zurückzufallen."
 
 #: git-am.sh:139
 msgid "Using index info to reconstruct a base tree..."
 msgstr ""
-"Verwende Informationen aus der Bereitstellung um einen Basisbaum "
+"Verwende Informationen aus der Staging-Area um einen Basisverzeichnis "
 "nachzustellen"
 
 #: git-am.sh:154
@@ -9247,11 +9682,11 @@
 
 #: git-am.sh:163
 msgid "Falling back to patching base and 3-way merge..."
-msgstr "Falle zurück zum Patchen der Basis und der 3-Wege-Zusammenführung..."
+msgstr "Falle zurück zum Patchen der Basis und des 3-Wege-Merges..."
 
 #: git-am.sh:179
 msgid "Failed to merge in the changes."
-msgstr "Zusammenführung der Änderungen fehlgeschlagen"
+msgstr "Merge der Änderungen fehlgeschlagen"
 
 #: git-am.sh:274
 msgid "Only one StGIT patch series can be applied at once"
@@ -9274,28 +9709,35 @@
 "Die -b/--binary Option hat seit Langem keinen Effekt und wird\n"
 "entfernt. Bitte nicht mehr verwenden."
 
-#: git-am.sh:477
+#: git-am.sh:479
 #, sh-format
 msgid "previous rebase directory $dotest still exists but mbox given."
 msgstr ""
-"Vorheriges Verzeichnis des Neuaufbaus $dotest existiert noch, aber mbox "
-"gegeben."
+"Vorheriges Rebase-Verzeichnis $dotest existiert noch, aber mbox gegeben."
 
-#: git-am.sh:482
+#: git-am.sh:484
 msgid "Please make up your mind. --skip or --abort?"
 msgstr "Bitte werden Sie sich klar. --skip oder --abort?"
 
-#: git-am.sh:509
+#: git-am.sh:520
+#, sh-format
+msgid ""
+"Stray $dotest directory found.\n"
+"Use \"git am --abort\" to remove it."
+msgstr ""
+"Stray $dotest Verzeichnis gefunden.\n"
+"Benutzen Sie \"git am --abort\" um es zu entfernen."
+
+#: git-am.sh:528
 msgid "Resolve operation not in progress, we are not resuming."
 msgstr "Es ist keine Auflösung im Gange, es wird nicht fortgesetzt."
 
-#: git-am.sh:575
+#: git-am.sh:594
 #, sh-format
 msgid "Dirty index: cannot apply patches (dirty: $files)"
-msgstr ""
-"Unsaubere Bereitstellung: kann Patches nicht anwenden (unsauber: $files)"
+msgstr "Geänderte Staging-Area: kann Patches nicht anwenden (geändert: $files)"
 
-#: git-am.sh:679
+#: git-am.sh:698
 #, sh-format
 msgid ""
 "Patch is empty.  Was it split wrong?\n"
@@ -9305,65 +9747,65 @@
 "Patch ist leer. Wurde er falsch aufgeteilt?\n"
 "Wenn Sie diesen Patch auslassen möchten, führen Sie stattdessen\n"
 "\"$cmdline --skip\" aus.\n"
-"Um den ursprünglichen Zweig wiederherzustellen und die Anwendung der "
+"Um den ursprünglichen Branch wiederherzustellen und die Anwendung der "
 "Patches\n"
 "abzubrechen, führen Sie \"$cmdline --abort\" aus."
 
-#: git-am.sh:706
+#: git-am.sh:725
 msgid "Patch does not have a valid e-mail address."
 msgstr "Patch enthält keine gültige Email-Adresse."
 
-#: git-am.sh:753
+#: git-am.sh:772
 msgid "cannot be interactive without stdin connected to a terminal."
 msgstr ""
 "Kann nicht interaktiv sein, ohne dass die Standard-Eingabe mit einem "
 "Terminal verbunden ist."
 
-#: git-am.sh:757
+#: git-am.sh:776
 msgid "Commit Body is:"
-msgstr "Beschreibung der Eintragung ist:"
+msgstr "Commit-Beschreibung ist:"
 
 #. TRANSLATORS: Make sure to include [y], [n], [e], [v] and [a]
 #. in your translation. The program will only accept English
 #. input at this point.
-#: git-am.sh:764
+#: git-am.sh:783
 msgid "Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all "
 msgstr "Anwenden? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all "
 
-#: git-am.sh:800
+#: git-am.sh:819
 #, sh-format
 msgid "Applying: $FIRSTLINE"
 msgstr "Wende an: $FIRSTLINE"
 
-#: git-am.sh:821
+#: git-am.sh:840
 msgid ""
 "No changes - did you forget to use 'git add'?\n"
 "If there is nothing left to stage, chances are that something else\n"
 "already introduced the same changes; you might want to skip this patch."
 msgstr ""
 "Keine Änderungen - haben Sie vergessen 'git add' zu benutzen?\n"
-"Wenn keine Änderungen mehr zum Bereitstellen vorhanden sind, könnten\n"
+"Wenn keine Änderungen mehr zum Commit vorzumerken sind, könnten\n"
 "diese bereits anderweitig eingefügt worden sein; Sie könnten diesen Patch\n"
 "auslassen."
 
-#: git-am.sh:829
+#: git-am.sh:848
 msgid ""
 "You still have unmerged paths in your index\n"
 "did you forget to use 'git add'?"
 msgstr ""
-"Sie haben immer noch nicht zusammengeführte Pfade in der Bereitstellung.\n"
+"Sie haben immer noch nicht zusammengeführte Pfade in der Staging-Area.\n"
 "Haben Sie vergessen 'git add' zu benutzen?"
 
-#: git-am.sh:845
+#: git-am.sh:864
 msgid "No changes -- Patch already applied."
 msgstr "Keine Änderungen -- Patches bereits angewendet."
 
-#: git-am.sh:855
+#: git-am.sh:874
 #, sh-format
 msgid "Patch failed at $msgnum $FIRSTLINE"
 msgstr "Anwendung des Patches fehlgeschlagen bei $msgnum $FIRSTLINE"
 
-#: git-am.sh:858
+#: git-am.sh:877
 #, sh-format
 msgid ""
 "The copy of the patch that failed is found in:\n"
@@ -9372,7 +9814,7 @@
 "Die Kopie des fehlgeschlagenen Patches befindet sich in:\n"
 "   $dotest/patch"
 
-#: git-am.sh:876
+#: git-am.sh:895
 msgid "applying to an empty history"
 msgstr "wende zu leerer Historie an"
 
@@ -9395,11 +9837,11 @@
 #: git-bisect.sh:99
 #, sh-format
 msgid "'$arg' does not appear to be a valid revision"
-msgstr "'$arg' scheint keine gültige Revision zu sein"
+msgstr "'$arg' scheint kein gültiger Commit zu sein"
 
 #: git-bisect.sh:117
 msgid "Bad HEAD - I need a HEAD"
-msgstr "Ungültige Zweigspitze (HEAD) - Zweigspitze (HEAD) wird benötigt"
+msgstr "Ungültiger HEAD - HEAD wird benötigt"
 
 #: git-bisect.sh:130
 #, sh-format
@@ -9407,15 +9849,15 @@
 "Checking out '$start_head' failed. Try 'git bisect reset <validbranch>'."
 msgstr ""
 "Auschecken von '$start_head' fehlgeschlagen. Versuchen Sie 'git bisect reset "
-"<gueltigerzweig>'."
+"<gueltigerbranch>'."
 
 #: git-bisect.sh:140
 msgid "won't bisect on seeked tree"
-msgstr "binäre Suche auf gesuchtem Zweig nicht möglich"
+msgstr "binäre Suche auf gesuchtem Branch nicht möglich"
 
 #: git-bisect.sh:144
 msgid "Bad HEAD - strange symbolic ref"
-msgstr "Ungültige Zweigspitze (HEAD) - merkwürdige symbolische Referenz"
+msgstr "Ungültiger HEAD - merkwürdige symbolische Referenz"
 
 #: git-bisect.sh:189
 #, sh-format
@@ -9444,7 +9886,7 @@
 #. this is less optimum.
 #: git-bisect.sh:273
 msgid "Warning: bisecting only with a bad commit."
-msgstr "Warnung: binäre Suche nur mit einer fehlerhaften Version"
+msgstr "Warnung: binäre Suche nur mit einem fehlerhaften Commit"
 
 #. TRANSLATORS: Make sure to include [Y] and [n] in your
 #. translation. The program will only accept English input
@@ -9458,7 +9900,8 @@
 "You need to give me at least one good and one bad revisions.\n"
 "(You can use \"git bisect bad\" and \"git bisect good\" for that.)"
 msgstr ""
-"Sie müssen mindestens eine korrekte und eine fehlerhafte Revision angeben.\n"
+"Sie müssen mindestens einen korrekten und einen fehlerhaften Commit "
+"angeben.\n"
 "(Sie können dafür \"git bisect bad\" und \"git bisect good\" benutzen.)"
 
 #: git-bisect.sh:292
@@ -9468,47 +9911,47 @@
 "(You can use \"git bisect bad\" and \"git bisect good\" for that.)"
 msgstr ""
 "Sie müssen mit \"git bisect start\" beginnen.\n"
-"Danach müssen Sie mindestens eine korrekte und eine fehlerhafte Revision "
+"Danach müssen Sie mindestens einen korrekten und einen fehlerhaften Commit "
 "angeben.\n"
 "(Sie können dafür \"git bisect bad\" und \"git bisect good\" benutzen.)"
 
-#: git-bisect.sh:347 git-bisect.sh:474
+#: git-bisect.sh:363 git-bisect.sh:490
 msgid "We are not bisecting."
 msgstr "keine binäre Suche im Gange"
 
-#: git-bisect.sh:354
+#: git-bisect.sh:370
 #, sh-format
 msgid "'$invalid' is not a valid commit"
-msgstr "'$invalid' ist keine gültige Version"
+msgstr "'$invalid' ist kein gültiger Commit"
 
-#: git-bisect.sh:363
+#: git-bisect.sh:379
 #, sh-format
 msgid ""
 "Could not check out original HEAD '$branch'.\n"
 "Try 'git bisect reset <commit>'."
 msgstr ""
-"Konnte die ursprüngliche Zweigspitze (HEAD) '$branch' nicht auschecken.\n"
-"Versuchen Sie 'git bisect reset <Version>'."
+"Konnte den ursprünglichen HEAD '$branch' nicht auschecken.\n"
+"Versuchen Sie 'git bisect reset <Commit>'."
 
-#: git-bisect.sh:390
+#: git-bisect.sh:406
 msgid "No logfile given"
 msgstr "Keine Log-Datei gegeben"
 
-#: git-bisect.sh:391
+#: git-bisect.sh:407
 #, sh-format
 msgid "cannot read $file for replaying"
 msgstr "kann $file nicht für das Abspielen lesen"
 
-#: git-bisect.sh:408
+#: git-bisect.sh:424
 msgid "?? what are you talking about?"
 msgstr "?? Was reden Sie da?"
 
-#: git-bisect.sh:420
+#: git-bisect.sh:436
 #, sh-format
 msgid "running $command"
 msgstr "führe $command aus"
 
-#: git-bisect.sh:427
+#: git-bisect.sh:443
 #, sh-format
 msgid ""
 "bisect run failed:\n"
@@ -9517,11 +9960,11 @@
 "'bisect run' fehlgeschlagen:\n"
 "Rückkehrwert $res von '$command' ist < 0 oder >= 128"
 
-#: git-bisect.sh:453
+#: git-bisect.sh:469
 msgid "bisect run cannot continue any more"
 msgstr "'bisect run' kann nicht mehr fortgesetzt werden"
 
-#: git-bisect.sh:459
+#: git-bisect.sh:475
 #, sh-format
 msgid ""
 "bisect run failed:\n"
@@ -9530,7 +9973,7 @@
 "'bisect run' fehlgeschlagen:\n"
 "'bisect_state $state' wurde mit Fehlerwert $res beendet"
 
-#: git-bisect.sh:466
+#: git-bisect.sh:482
 msgid "bisect run success"
 msgstr "'bisect run' erfolgreich ausgeführt"
 
@@ -9541,10 +9984,9 @@
 "as appropriate to mark resolution, or use 'git commit -a'."
 msgstr ""
 "\"pull\" ist nicht möglich, weil Sie nicht zusammengeführte Dateien haben.\n"
-"Bitte korrigieren Sie dies im Arbeitsbaum und benutzen Sie dann 'git add/rm "
-"<Datei>'\n"
-"um die Auflösung entsprechend zu markieren, oder benutzen Sie 'git commit -"
-"a'."
+"Bitte korrigieren Sie dies im Arbeitsverzeichnis und benutzen Sie dann \n"
+"'git add/rm <Datei>' um die Auflösung entsprechend zu markieren, oder\n"
+"benutzen Sie 'git commit -a'."
 
 #: git-pull.sh:25
 msgid "Pull is not possible because you have unmerged files."
@@ -9554,8 +9996,8 @@
 #: git-pull.sh:203
 msgid "updating an unborn branch with changes added to the index"
 msgstr ""
-"Aktualisiere eine ungeborenen Zweig mit Änderungen, die zur Bereitstellung "
-"hinzugefügt wurden"
+"Aktualisiere einen ungeborenen Branch mit Änderungen, die zum Commit "
+"vorgemerkt sind"
 
 #. The fetch involved updating the current branch.
 #. The working tree and the index file is still based on the
@@ -9568,18 +10010,18 @@
 "Warning: fast-forwarding your working tree from\n"
 "Warning: commit $orig_head."
 msgstr ""
-"Warnung: Die Anforderung aktualisierte die Spitze des aktuellen Zweiges.\n"
-"Warnung: Spule Ihren Arbeitszweig von Version $orig_head vor."
+"Warnung: \"fetch\" aktualisierte die Spitze des aktuellen Branches.\n"
+"Warnung: Spule Ihr Arbeitsverzeichnis von Commit $orig_head vor."
 
 #: git-pull.sh:260
 msgid "Cannot merge multiple branches into empty head"
-msgstr "Kann nicht mehrere Zweige in einen ungeborenen Zweig zusammenführen"
+msgstr "Kann nicht mehrere Branches in einen ungeborenen Branch zusammenführen"
 
 #: git-pull.sh:264
 msgid "Cannot rebase onto multiple branches"
-msgstr "kann nicht auf mehrere Zweige neu aufbauen"
+msgstr "kann Rebase nicht auf mehrere Branches ausführen"
 
-#: git-rebase.sh:53
+#: git-rebase.sh:54
 msgid ""
 "When you have resolved this problem, run \"git rebase --continue\".\n"
 "If you prefer to skip this patch, run \"git rebase --skip\" instead.\n"
@@ -9590,50 +10032,68 @@
 "aus.\n"
 "Falls Sie diesen Patch auslassen möchten, führen Sie stattdessen \"git "
 "rebase --skip\" aus.\n"
-"Um den ursprünglichen Zweig wiederherzustellen und den Neuaufbau "
-"abzubrechen,\n"
+"Um den ursprünglichen Branch wiederherzustellen und den Rebase abzubrechen,\n"
 "führen Sie \"git rebase --abort\" aus."
 
+#: git-rebase.sh:156
+msgid "Applied autostash."
+msgstr "\"autostash\" angewendet."
+
+#: git-rebase.sh:159
+#, sh-format
+msgid "Cannot store $stash_sha1"
+msgstr "Kann $stash_sha1 nicht speichern."
+
 #: git-rebase.sh:160
+msgid ""
+"Applying autostash resulted in conflicts.\n"
+"Your changes are safe in the stash.\n"
+"You can run \"git stash pop\" or \"git stash drop\" at any time.\n"
+msgstr ""
+"Anwendung von \"autostash\" resultierte in Konflikten.\n"
+"Ihre Änderungen sind im Stash sicher.\n"
+"Sie können jederzeit \"git stash pop\" oder \"git stash drop\" ausführen.\n"
+
+#: git-rebase.sh:190
 msgid "The pre-rebase hook refused to rebase."
-msgstr "Der \"pre-rebase hook\" hat den Neuaufbau zurückgewiesen."
+msgstr "Der \"pre-rebase hook\" hat den Rebase zurückgewiesen."
 
-#: git-rebase.sh:165
+#: git-rebase.sh:195
 msgid "It looks like git-am is in progress. Cannot rebase."
-msgstr "\"git-am\" scheint im Gange zu sein. Kann nicht neu aufbauen."
+msgstr "\"git-am\" scheint im Gange zu sein. Kann Rebase nicht durchführen."
 
-#: git-rebase.sh:296
+#: git-rebase.sh:329
 msgid "The --exec option must be used with the --interactive option"
 msgstr "Die Option --exec muss mit --interactive verwendet werden."
 
-#: git-rebase.sh:301
+#: git-rebase.sh:334
 msgid "No rebase in progress?"
-msgstr "Kein Neuaufbau im Gange?"
+msgstr "Kein Rebase im Gange?"
 
-#: git-rebase.sh:312
+#: git-rebase.sh:345
 msgid "The --edit-todo action can only be used during interactive rebase."
 msgstr ""
-"Die --edit-todo Aktion kann nur während eines interaktiven Neuaufbaus "
-"verwendet werden."
+"Die --edit-todo Aktion kann nur während eines interaktiven Rebase verwendet "
+"werden."
 
-#: git-rebase.sh:319
+#: git-rebase.sh:352
 msgid "Cannot read HEAD"
-msgstr "Kann Zweigspitze (HEAD) nicht lesen"
+msgstr "Kann HEAD nicht lesen"
 
-#: git-rebase.sh:322
+#: git-rebase.sh:355
 msgid ""
 "You must edit all merge conflicts and then\n"
 "mark them as resolved using git add"
 msgstr ""
-"Sie müssen alle Zusammenführungskonflikte editieren und diese dann\n"
+"Sie müssen alle Merge-Konflikte editieren und diese dann\n"
 "mittels \"git add\" als aufgelöst markieren"
 
-#: git-rebase.sh:340
+#: git-rebase.sh:373
 #, sh-format
 msgid "Could not move back to $head_name"
 msgstr "Konnte nicht zu $head_name zurückgehen"
 
-#: git-rebase.sh:359
+#: git-rebase.sh:392
 #, sh-format
 msgid ""
 "It seems that there is already a $state_dir_base directory, and\n"
@@ -9646,7 +10106,7 @@
 "valuable there."
 msgstr ""
 "Es sieht so aus, als ob es das Verzeichnis $state_dir_base bereits gibt\n"
-"und es könnte ein anderer Neuaufbau im Gange sein. Wenn das der Fall ist,\n"
+"und es könnte ein anderer Rebase im Gange sein. Wenn das der Fall ist,\n"
 "probieren Sie bitte\n"
 "\t$cmd_live_rebase\n"
 "Wenn das nicht der Fall ist, probieren Sie bitte\n"
@@ -9654,59 +10114,68 @@
 "und führen Sie dieses Kommando nochmal aus. Es wird angehalten, falls noch\n"
 "etwas Schützenswertes vorhanden ist."
 
-#: git-rebase.sh:404
+#: git-rebase.sh:437
 #, sh-format
 msgid "invalid upstream $upstream_name"
-msgstr "ungültiger Übernahmezweig $upstream_name"
+msgstr "ungültiger Upstream-Branch $upstream_name"
 
-#: git-rebase.sh:428
+#: git-rebase.sh:461
 #, sh-format
 msgid "$onto_name: there are more than one merge bases"
-msgstr "$onto_name: es gibt mehr als eine Zusammenführungsbasis"
+msgstr "$onto_name: es gibt mehr als eine Merge-Basis"
 
-#: git-rebase.sh:431 git-rebase.sh:435
+#: git-rebase.sh:464 git-rebase.sh:468
 #, sh-format
 msgid "$onto_name: there is no merge base"
-msgstr "$onto_name: es gibt keine Zusammenführungsbasis"
+msgstr "$onto_name: es gibt keine Merge-Basis"
 
-#: git-rebase.sh:440
+#: git-rebase.sh:473
 #, sh-format
 msgid "Does not point to a valid commit: $onto_name"
-msgstr "$onto_name zeigt auf keine gültige Version"
+msgstr "$onto_name zeigt auf keinen gültigen Commit"
 
-#: git-rebase.sh:463
+#: git-rebase.sh:496
 #, sh-format
 msgid "fatal: no such branch: $branch_name"
-msgstr "fatal: Zweig $branch_name nicht gefunden"
+msgstr "fatal: Branch $branch_name nicht gefunden"
 
-#: git-rebase.sh:483
+#: git-rebase.sh:519
+msgid "Cannot autostash"
+msgstr "Kann \"autostash\" nicht ausführen."
+
+#: git-rebase.sh:524
+#, sh-format
+msgid "Created autostash: $stash_abbrev"
+msgstr "\"autostash\" erzeugt: $stash_abbrev"
+
+#: git-rebase.sh:528
 msgid "Please commit or stash them."
-msgstr "Bitte tragen Sie die Änderungen ein oder benutzen Sie \"stash\"."
+msgstr "Bitte committen Sie die Änderungen oder benutzen Sie \"stash\"."
 
-#: git-rebase.sh:501
+#: git-rebase.sh:548
 #, sh-format
 msgid "Current branch $branch_name is up to date."
-msgstr "Aktueller Zweig $branch_name ist auf dem neusten Stand."
+msgstr "Aktueller Branch $branch_name ist auf dem neusten Stand."
 
-#: git-rebase.sh:504
+#: git-rebase.sh:552
 #, sh-format
 msgid "Current branch $branch_name is up to date, rebase forced."
 msgstr ""
-"Aktueller Zweig $branch_name ist auf dem neusten Stand, Neuaufbau erzwungen."
+"Aktueller Branch $branch_name ist auf dem neusten Stand, Rebase erzwungen."
 
-#: git-rebase.sh:515
+#: git-rebase.sh:563
 #, sh-format
 msgid "Changes from $mb to $onto:"
 msgstr "Änderungen von $mb zu $onto:"
 
 #. Detach HEAD and reset the tree
-#: git-rebase.sh:524
+#: git-rebase.sh:572
 msgid "First, rewinding head to replay your work on top of it..."
 msgstr ""
-"Zunächst wird die Zweigspitze zurückgespult, um Ihre Änderungen\n"
+"Zunächst wird der Branch zurückgespult, um Ihre Änderungen\n"
 "darauf neu anzuwenden..."
 
-#: git-rebase.sh:532
+#: git-rebase.sh:582
 #, sh-format
 msgid "Fast-forwarded $branch_name to $onto_name."
 msgstr "$branch_name zu $onto_name vorgespult."
@@ -9717,15 +10186,15 @@
 
 #: git-stash.sh:74
 msgid "You do not have the initial commit yet"
-msgstr "Sie haben bisher noch keine initiale Version"
+msgstr "Sie haben bisher noch keinen initialen Commit"
 
 #: git-stash.sh:89
 msgid "Cannot save the current index state"
-msgstr "Kann den aktuellen Zustand der Bereitstellung nicht speichern"
+msgstr "Kann den aktuellen Zustand der Staging-Area nicht speichern"
 
 #: git-stash.sh:123 git-stash.sh:136
 msgid "Cannot save the current worktree state"
-msgstr "Kann den aktuellen Zustand des Arbeitsbaumes nicht speichern"
+msgstr "Kann den aktuellen Zustand des Arbeitsverzeichnisses nicht speichern"
 
 #: git-stash.sh:140
 msgid "No changes selected"
@@ -9733,11 +10202,16 @@
 
 #: git-stash.sh:143
 msgid "Cannot remove temporary index (can't happen)"
-msgstr "Kann temporäre Bereitstellung nicht löschen (kann nicht passieren)"
+msgstr "Kann temporäre Staging-Area nicht löschen (kann nicht passieren)"
 
 #: git-stash.sh:156
 msgid "Cannot record working tree state"
-msgstr "Kann Zustand des Arbeitsbaumes nicht aufzeichnen"
+msgstr "Kann Zustand des Arbeitsverzeichnisses nicht aufzeichnen"
+
+#: git-stash.sh:190
+#, sh-format
+msgid "Cannot update $ref_stash with $w_commit"
+msgstr "Kann $ref_stash nicht mit $w_commit aktualisieren."
 
 #. TRANSLATORS: $option is an invalid option, like
 #. `--blah-blah'. The 7 spaces at the beginning of the
@@ -9749,7 +10223,7 @@
 #. $ git stash save --blah-blah 2>&1 | head -n 2
 #. error: unknown option for 'stash save': --blah-blah
 #. To provide a message, use git stash save -- '--blah-blah'
-#: git-stash.sh:202
+#: git-stash.sh:241
 #, sh-format
 msgid ""
 "error: unknown option for 'stash save': $option\n"
@@ -9759,122 +10233,140 @@
 "        Um eine Beschreibung anzugeben, benutzen Sie \"git stash save -- "
 "'$option'\""
 
-#: git-stash.sh:223
+#: git-stash.sh:262
 msgid "No local changes to save"
 msgstr "Keine lokalen Änderungen zum Speichern"
 
-#: git-stash.sh:227
+#: git-stash.sh:268
+msgid ""
+"The following untracked files would NOT be saved but need to be removed by "
+"stash save:"
+msgstr ""
+"Die folgenden unbeobachteten Dateien würden NICHT gespeichert werden,\n"
+"müssen aber durch \"stash save\" entfernt werden:"
+
+#: git-stash.sh:270
+msgid ""
+"Aborting. Consider using either the --force or --include-untracked option."
+msgstr ""
+"Abgebrochen. Benutzen Sie entweder die Option --force oder --include-"
+"untracked."
+
+#: git-stash.sh:274
 msgid "Cannot initialize stash"
 msgstr "Kann \"stash\" nicht initialisieren"
 
-#: git-stash.sh:235
+#: git-stash.sh:278
 msgid "Cannot save the current status"
 msgstr "Kann den aktuellen Status nicht speichern"
 
-#: git-stash.sh:253
+#: git-stash.sh:296
 msgid "Cannot remove worktree changes"
-msgstr "Kann Änderungen am Arbeitsbaum nicht löschen"
+msgstr "Kann Änderungen im Arbeitsverzeichnis nicht löschen"
 
-#: git-stash.sh:352
+#: git-stash.sh:395
 msgid "No stash found."
 msgstr "Kein \"stash\" gefunden."
 
-#: git-stash.sh:359
+#: git-stash.sh:402
 #, sh-format
 msgid "Too many revisions specified: $REV"
-msgstr "Zu viele Revisionen angegeben: $REV"
+msgstr "Zu viele Commits angegeben: $REV"
 
-#: git-stash.sh:365
+#: git-stash.sh:408
 #, sh-format
 msgid "$reference is not valid reference"
 msgstr "$reference ist keine gültige Referenz"
 
-#: git-stash.sh:393
+#: git-stash.sh:436
 #, sh-format
 msgid "'$args' is not a stash-like commit"
-msgstr "'$args' ist keine \"stash\"-artige Version"
+msgstr "'$args' ist kein \"stash\"-artiger Commit"
 
-#: git-stash.sh:404
+#: git-stash.sh:447
 #, sh-format
 msgid "'$args' is not a stash reference"
 msgstr "'$args' ist keine \"stash\"-Referenz"
 
-#: git-stash.sh:412
+#: git-stash.sh:455
 msgid "unable to refresh index"
-msgstr "unfähig die Bereitstellung zu aktualisieren"
+msgstr "unfähig die Staging-Area zu aktualisieren"
 
-#: git-stash.sh:416
+#: git-stash.sh:459
 msgid "Cannot apply a stash in the middle of a merge"
-msgstr ""
-"Kann \"stash\" nicht anwenden, solang eine Zusammenführung im Gange ist"
+msgstr "Kann \"stash\" nicht anwenden, solang ein Merge im Gange ist"
 
-#: git-stash.sh:424
+#: git-stash.sh:467
 msgid "Conflicts in index. Try without --index."
-msgstr "Konflikte in der Bereitstellung. Versuchen Sie es ohne --index."
+msgstr "Konflikte in der Staging-Area. Versuchen Sie es ohne --index."
 
-#: git-stash.sh:426
+#: git-stash.sh:469
 msgid "Could not save index tree"
-msgstr "Konnte Bereitstellungsbaum nicht speichern"
+msgstr "Konnte Staging-Area-Verzeichnis nicht speichern"
 
-#: git-stash.sh:460
+#: git-stash.sh:503
 msgid "Cannot unstage modified files"
-msgstr "Kann geänderte Dateien nicht aus der Bereitstellung herausnehmen"
+msgstr "Kann geänderte Dateien nicht aus der Staging-Area entfernen"
 
-#: git-stash.sh:475
+#: git-stash.sh:518
 msgid "Index was not unstashed."
-msgstr "Bereitstellung wurde nicht ausgelagert."
+msgstr "Staging-Area wurde nicht aus dem Stash zurückgeladen."
 
-#: git-stash.sh:492
+#: git-stash.sh:535
 #, sh-format
 msgid "Dropped ${REV} ($s)"
 msgstr "Gelöscht ${REV} ($s)"
 
-#: git-stash.sh:493
+#: git-stash.sh:536
 #, sh-format
 msgid "${REV}: Could not drop stash entry"
 msgstr "${REV}: Konnte \"stash\"-Eintrag nicht löschen"
 
-#: git-stash.sh:500
+#: git-stash.sh:543
 msgid "No branch name specified"
-msgstr "Kein Zweigname spezifiziert"
+msgstr "Kein Branchname spezifiziert"
 
-#: git-stash.sh:571
+#: git-stash.sh:615
 msgid "(To restore them type \"git stash apply\")"
 msgstr "(Zur Wiederherstellung geben Sie \"git stash apply\" ein)"
 
-#: git-submodule.sh:91
+#: git-submodule.sh:95
 #, sh-format
 msgid "cannot strip one component off url '$remoteurl'"
 msgstr "Kann eine Komponente von URL '$remoteurl' nicht extrahieren"
 
-#: git-submodule.sh:196
+#: git-submodule.sh:237
 #, sh-format
 msgid "No submodule mapping found in .gitmodules for path '$sm_path'"
-msgstr ""
-"Keine Unterprojekt-Zuordnung in .gitmodules für Pfad '$sm_path' gefunden"
+msgstr "Keine Submodul-Zuordnung in .gitmodules für Pfad '$sm_path' gefunden"
 
-#: git-submodule.sh:239
+#: git-submodule.sh:281
 #, sh-format
 msgid "Clone of '$url' into submodule path '$sm_path' failed"
-msgstr "Klonen von '$url' in Unterprojekt-Pfad '$sm_path' fehlgeschlagen"
+msgstr "Klonen von '$url' in Submodul-Pfad '$sm_path' fehlgeschlagen"
 
-#: git-submodule.sh:251
+#: git-submodule.sh:293
 #, sh-format
 msgid "Gitdir '$a' is part of the submodule path '$b' or vice versa"
-msgstr ""
-"Git-Verzeichnis '$a' ist Teil des Unterprojekt-Pfades '$b', oder umgekehrt"
+msgstr "Git-Verzeichnis '$a' ist Teil des Submodul-Pfades '$b', oder umgekehrt"
 
-#: git-submodule.sh:349
+#: git-submodule.sh:403
+msgid "Relative path can only be used from the toplevel of the working tree"
+msgstr ""
+"Relative Pfade können nur von der obersten Ebene des Arbeitsverzeichnisses "
+"benutzt werden."
+
+#: git-submodule.sh:413
 #, sh-format
 msgid "repo URL: '$repo' must be absolute or begin with ./|../"
 msgstr "repo URL: '$repo' muss absolut sein oder mit ./|../ beginnen"
 
-#: git-submodule.sh:366
+#: git-submodule.sh:430
 #, sh-format
 msgid "'$sm_path' already exists in the index"
-msgstr "'$sm_path' existiert bereits in der Bereitstellung"
+msgstr "'$sm_path' ist bereits zum Commit vorgemerkt"
 
-#: git-submodule.sh:370
+#: git-submodule.sh:434
 #, sh-format
 msgid ""
 "The following path is ignored by one of your .gitignore files:\n"
@@ -9885,25 +10377,24 @@
 "$sm_path\n"
 "Benutzen Sie -f wenn Sie diesen wirklich hinzufügen möchten."
 
-#: git-submodule.sh:388
+#: git-submodule.sh:452
 #, sh-format
 msgid "Adding existing repo at '$sm_path' to the index"
-msgstr ""
-"Füge existierendes Projektarchiv in '$sm_path' der Bereitstellung hinzu."
+msgstr "Füge existierendes Repository in '$sm_path' der Staging-Area hinzu."
 
-#: git-submodule.sh:390
+#: git-submodule.sh:454
 #, sh-format
 msgid "'$sm_path' already exists and is not a valid git repo"
-msgstr "'$sm_path' existiert bereits und ist kein gültiges Git-Projektarchiv"
+msgstr "'$sm_path' existiert bereits und ist kein gültiges Git-Repository"
 
-#: git-submodule.sh:398
+#: git-submodule.sh:462
 #, sh-format
 msgid "A git directory for '$sm_name' is found locally with remote(s):"
 msgstr ""
-"Ein Git-Verzeichnis für '$sm_name' wurde lokal gefunden mit den Fernarchiv"
-"(en):"
+"Ein Git-Verzeichnis für '$sm_name' wurde lokal gefunden mit den Remote-"
+"Repositories:"
 
-#: git-submodule.sh:400
+#: git-submodule.sh:464
 #, sh-format
 msgid ""
 "If you want to reuse this local git directory instead of cloning again from"
@@ -9911,15 +10402,15 @@
 "Wenn Sie dieses lokale Git-Verzeichnis wiederverwenden möchtest, anstatt "
 "erneut zu klonen"
 
-#: git-submodule.sh:402
+#: git-submodule.sh:466
 #, sh-format
 msgid ""
 "use the '--force' option. If the local git directory is not the correct repo"
 msgstr ""
 "benutzen Sie die Option '--force'. Wenn das lokale Git-Verzeichnis nicht das "
-"korrekte Projektarchiv ist"
+"korrekte Repository ist"
 
-#: git-submodule.sh:403
+#: git-submodule.sh:467
 #, sh-format
 msgid ""
 "or you are unsure what this means choose another name with the '--name' "
@@ -9928,216 +10419,303 @@
 "oder Sie sich unsicher sind, was das bedeutet, wählen Sie einen anderen "
 "Namenmit der Option '--name'."
 
-#: git-submodule.sh:405
+#: git-submodule.sh:469
 #, sh-format
 msgid "Reactivating local git directory for submodule '$sm_name'."
-msgstr "Reaktiviere lokales Git-Verzeichnis für Unterprojekt '$sm_name'."
+msgstr "Reaktiviere lokales Git-Verzeichnis für Submodul '$sm_name'."
 
-#: git-submodule.sh:417
+#: git-submodule.sh:481
 #, sh-format
 msgid "Unable to checkout submodule '$sm_path'"
-msgstr "Unfähig Unterprojekt '$sm_path' auszuchecken"
+msgstr "Unfähig Submodul '$sm_path' auszuchecken"
 
-#: git-submodule.sh:422
+#: git-submodule.sh:486
 #, sh-format
 msgid "Failed to add submodule '$sm_path'"
-msgstr "Hinzufügen von Unterprojekt '$sm_path' fehlgeschlagen"
+msgstr "Hinzufügen von Submodul '$sm_path' fehlgeschlagen"
 
-#: git-submodule.sh:431
+#: git-submodule.sh:495
 #, sh-format
 msgid "Failed to register submodule '$sm_path'"
-msgstr "Fehler beim Eintragen von Unterprojekt '$sm_path' in die Konfiguration."
+msgstr "Fehler beim Eintragen von Submodul '$sm_path' in die Konfiguration."
 
-#: git-submodule.sh:474
+#: git-submodule.sh:539
 #, sh-format
-msgid "Entering '$prefix$sm_path'"
-msgstr "Betrete '$prefix$sm_path'"
+msgid "Entering '$prefix$displaypath'"
+msgstr "Betrete '$prefix$displaypath'"
 
-#: git-submodule.sh:488
+#: git-submodule.sh:554
 #, sh-format
-msgid "Stopping at '$sm_path'; script returned non-zero status."
-msgstr "Stoppe bei '$sm_path'; Skript gab nicht-Null Status zurück."
+msgid "Stopping at '$prefix$displaypath'; script returned non-zero status."
+msgstr "Stoppe bei '$prefix$displaypath'; Skript gab nicht-Null Status zurück."
 
-#: git-submodule.sh:532
+#: git-submodule.sh:600
 #, sh-format
-msgid "No url found for submodule path '$sm_path' in .gitmodules"
-msgstr "Keine URL für Unterprojekt-Pfad '$sm_path' in .gitmodules gefunden"
+msgid "No url found for submodule path '$displaypath' in .gitmodules"
+msgstr "Keine URL für Submodul-Pfad '$displaypath' in .gitmodules gefunden"
 
-#: git-submodule.sh:541
+#: git-submodule.sh:609
 #, sh-format
-msgid "Failed to register url for submodule path '$sm_path'"
-msgstr "Fehler beim Eintragen der URL für Unterprojekt-Pfad '$sm_path' in die"
-" Konfiguration."
+msgid "Failed to register url for submodule path '$displaypath'"
+msgstr ""
+"Fehler beim Eintragen der URL für Submodul-Pfad '$displaypath' in die "
+"Konfiguration."
 
-#: git-submodule.sh:543
+#: git-submodule.sh:611
 #, sh-format
-msgid "Submodule '$name' ($url) registered for path '$sm_path'"
-msgstr "Unterprojekt '$name' ($url) für Pfad '$sm_path' in die Konfiguration "
-"eingetragen"
+msgid "Submodule '$name' ($url) registered for path '$displaypath'"
+msgstr ""
+"Submodul '$name' ($url) für Pfad '$displaypath' in die Konfiguration "
+"eingetragen."
 
-#: git-submodule.sh:551
+#: git-submodule.sh:619
 #, sh-format
-msgid "Failed to register update mode for submodule path '$sm_path'"
-msgstr "Fehler bei Änderung des Aktualisierungsmodus für Unterprojekt-Pfad "
-"'$sm_path' in der Konfiguration."
+msgid "Failed to register update mode for submodule path '$displaypath'"
+msgstr ""
+"Fehler bei Änderung des Aktualisierungsmodus für Submodul-Pfad "
+"'$displaypath' in der Konfiguration."
 
-#: git-submodule.sh:588
+#: git-submodule.sh:656
 #, sh-format
 msgid "Use '.' if you really want to deinitialize all submodules"
-msgstr "Verwenden Sie '.' wenn Sie wirklich alle Unterprojekte\n"
+msgstr ""
+"Verwenden Sie '.' wenn Sie wirklich alle Submodule\n"
 "deinitialisieren möchten."
 
-#: git-submodule.sh:603
+#: git-submodule.sh:673
 #, sh-format
-msgid "Submodule work tree '$sm_path' contains a .git directory"
-msgstr "Arbeitsbaum des Unterprojekts in '$sm_path' enthält ein .git-Verzeichnis"
+msgid "Submodule work tree '$displaypath' contains a .git directory"
+msgstr ""
+"Arbeitsverzeichnis des Submoduls in '$displaypath' enthält ein .git-"
+"Verzeichnis"
 
-#: git-submodule.sh:604
+#: git-submodule.sh:674
 #, sh-format
 msgid ""
 "(use 'rm -rf' if you really want to remove it including all of its history)"
 msgstr ""
-"(benutzen Sie 'rm -rf' wenn Sie dieses Unterprojekt wirklich mitsamt\n"
+"(benutzen Sie 'rm -rf' wenn Sie dieses Submodul wirklich mitsamt\n"
 "seiner Historie löschen möchten)"
 
-#: git-submodule.sh:610
+#: git-submodule.sh:680
 #, sh-format
 msgid ""
-"Submodule work tree '$sm_path' contains local modifications; use '-f' to "
+"Submodule work tree '$displaypath' contains local modifications; use '-f' to "
 "discard them"
 msgstr ""
-"Arbeitsbaum von Unterprojekt in '$sm_path' enthält lokale Änderungen; "
+"Arbeitsverzeichnis von Submodul in '$displaypath' enthält lokale Änderungen; "
 "verwenden Sie '-f' um diese zu verwerfen"
 
-#: git-submodule.sh:613
+#: git-submodule.sh:683
 #, sh-format
-msgid "Cleared directory '$sm_path'"
-msgstr "Verzeichnis '$sm_path' bereinigt."
+msgid "Cleared directory '$displaypath'"
+msgstr "Verzeichnis '$displaypath' bereinigt."
 
-#: git-submodule.sh:614
+#: git-submodule.sh:684
 #, sh-format
-msgid "Could not remove submodule work tree '$sm_path'"
-msgstr "Konnte Arbeitsbaum des Unterprojektes in '$sm_path' nicht löschen."
+msgid "Could not remove submodule work tree '$displaypath'"
+msgstr ""
+"Konnte Arbeitsverzeichnis des Submoduls in '$displaypath' nicht löschen."
 
-#: git-submodule.sh:617
+#: git-submodule.sh:687
 #, sh-format
-msgid "Could not create empty submodule directory '$sm_path'"
-msgstr "Konnte kein leeres Verzeichnis für Unterprojekt in '$sm_path' erstellen."
+msgid "Could not create empty submodule directory '$displaypath'"
+msgstr ""
+"Konnte kein leeres Verzeichnis für Submodul in '$displaypath' erstellen."
 
-#: git-submodule.sh:626
+#: git-submodule.sh:696
 #, sh-format
-msgid "Submodule '$name' ($url) unregistered for path '$sm_path'"
-msgstr "Unterprojekt '$name' ($url) für Pfad '$sm_path' wurde aus der "
-"Konfiguration entfernt."
+msgid "Submodule '$name' ($url) unregistered for path '$displaypath'"
+msgstr ""
+"Submodul '$name' ($url) für Pfad '$displaypath' wurde aus der Konfiguration "
+"entfernt."
 
-#: git-submodule.sh:731
+#: git-submodule.sh:811
 #, sh-format
 msgid ""
-"Submodule path '$prefix$sm_path' not initialized\n"
+"Submodule path '$displaypath' not initialized\n"
 "Maybe you want to use 'update --init'?"
 msgstr ""
-"Unterprojekt-Pfad '$prefix$sm_path' ist nicht initialisiert.\n"
+"Submodul-Pfad '$displaypath' ist nicht initialisiert.\n"
 "Vielleicht möchten Sie 'update --init' benutzen?"
 
-#: git-submodule.sh:744
+#: git-submodule.sh:824
 #, sh-format
-msgid "Unable to find current revision in submodule path '$prefix$sm_path'"
-msgstr "Konnte aktuelle Revision in Unterprojekt-Pfad '$prefix$sm_path' nicht finden."
+msgid "Unable to find current revision in submodule path '$displaypath'"
+msgstr "Konnte aktuellen Commit in Submodul-Pfad '$displaypath' nicht finden."
 
-#: git-submodule.sh:753
+#: git-submodule.sh:833
 #, sh-format
 msgid "Unable to fetch in submodule path '$sm_path'"
-msgstr "Konnte in Unterprojekt-Pfad '$sm_path' nicht anfordern"
+msgstr "Konnte \"fetch\" in Submodul-Pfad '$sm_path' nicht ausführen"
 
-#: git-submodule.sh:777
+#: git-submodule.sh:857
 #, sh-format
-msgid "Unable to fetch in submodule path '$prefix$sm_path'"
-msgstr "Konnte in Unterprojekt-Pfad '$prefix$sm_path' nicht anfordern"
+msgid "Unable to fetch in submodule path '$displaypath'"
+msgstr "Konnte \"fetch\" in Submodul-Pfad '$displaypath' nicht ausführen"
 
-#: git-submodule.sh:791
+#: git-submodule.sh:871
 #, sh-format
-msgid "Unable to rebase '$sha1' in submodule path '$prefix$sm_path'"
-msgstr "Neuaufbau von '$sha1' in Unterprojekt-Pfad '$prefix$sm_path' nicht möglich"
+msgid "Unable to rebase '$sha1' in submodule path '$displaypath'"
+msgstr "Rebase auf '$sha1' in Submodul-Pfad '$displaypath' nicht möglich"
 
-#: git-submodule.sh:792
+#: git-submodule.sh:872
 #, sh-format
-msgid "Submodule path '$prefix$sm_path': rebased into '$sha1'"
-msgstr "Unterprojekt-Pfad '$prefix$sm_path': neu aufgebaut in '$sha1'"
+msgid "Submodule path '$displaypath': rebased into '$sha1'"
+msgstr "Submodul-Pfad '$displaypath': Rebase auf '$sha1'"
 
-#: git-submodule.sh:797
+#: git-submodule.sh:877
 #, sh-format
-msgid "Unable to merge '$sha1' in submodule path '$prefix$sm_path'"
+msgid "Unable to merge '$sha1' in submodule path '$displaypath'"
+msgstr "Merge von '$sha1' in Submodul-Pfad '$displaypath' fehlgeschlagen"
+
+#: git-submodule.sh:878
+#, sh-format
+msgid "Submodule path '$displaypath': merged in '$sha1'"
+msgstr "Submodul-Pfad '$displaypath': zusammengeführt in '$sha1'"
+
+#: git-submodule.sh:883
+#, sh-format
+msgid ""
+"Execution of '$command $sha1' failed in submodule  path '$prefix$sm_path'"
 msgstr ""
-"Zusammenführung von '$sha1' in Unterprojekt-Pfad '$prefix$sm_path' fehlgeschlagen"
+"Ausführung von '$command $sha1' in Submodul-Pfad '$prefix$sm_path' "
+"fehlgeschlagen"
 
-#: git-submodule.sh:798
+#: git-submodule.sh:884
 #, sh-format
-msgid "Submodule path '$prefix$sm_path': merged in '$sha1'"
-msgstr "Unterprojekt-Pfad '$prefix$sm_path': zusammengeführt in '$sha1'"
+msgid "Submodule path '$prefix$sm_path': '$command $sha1'"
+msgstr "Submodul-Pfad '$prefix$sm_path': '$command $sha1'"
 
-#: git-submodule.sh:803
+#: git-submodule.sh:889
 #, sh-format
-msgid "Unable to checkout '$sha1' in submodule path '$prefix$sm_path'"
-msgstr "Konnte '$sha1' in Unterprojekt-Pfad '$prefix$sm_path' nicht auschecken."
+msgid "Unable to checkout '$sha1' in submodule path '$displaypath'"
+msgstr "Konnte '$sha1' in Submodul-Pfad '$displaypath' nicht auschecken."
 
-#: git-submodule.sh:804
+#: git-submodule.sh:890
 #, sh-format
-msgid "Submodule path '$prefix$sm_path': checked out '$sha1'"
-msgstr "Unterprojekt-Pfad: '$prefix$sm_path': '$sha1' ausgecheckt"
+msgid "Submodule path '$displaypath': checked out '$sha1'"
+msgstr "Submodul-Pfad: '$displaypath': '$sha1' ausgecheckt"
 
-#: git-submodule.sh:831
+#: git-submodule.sh:917
 #, sh-format
-msgid "Failed to recurse into submodule path '$prefix$sm_path'"
-msgstr "Fehler bei Rekursion in Unterprojekt-Pfad '$prefix$sm_path'"
+msgid "Failed to recurse into submodule path '$displaypath'"
+msgstr "Fehler bei Rekursion in Submodul-Pfad '$displaypath'"
 
-#: git-submodule.sh:939
+#: git-submodule.sh:1025
 msgid "The --cached option cannot be used with the --files option"
 msgstr ""
 "Die Optionen --cached und --files können nicht gemeinsam verwendet werden."
 
 #. unexpected type
-#: git-submodule.sh:979
+#: git-submodule.sh:1066
 #, sh-format
 msgid "unexpected mode $mod_dst"
 msgstr "unerwarteter Modus $mod_dst"
 
-#: git-submodule.sh:997
+#: git-submodule.sh:1086
 #, sh-format
-msgid "  Warn: $name doesn't contain commit $sha1_src"
-msgstr "  Warnung: $name beinhaltet nicht Version $sha1_src"
+msgid "  Warn: $display_name doesn't contain commit $sha1_src"
+msgstr "  Warnung: $display_name beinhaltet nicht Commit $sha1_src"
 
-#: git-submodule.sh:1000
+#: git-submodule.sh:1089
 #, sh-format
-msgid "  Warn: $name doesn't contain commit $sha1_dst"
-msgstr "  Warnung: $name beinhaltet nicht Version $sha1_dst"
+msgid "  Warn: $display_name doesn't contain commit $sha1_dst"
+msgstr "  Warnung: $display_name beinhaltet nicht Commit $sha1_dst"
 
-#: git-submodule.sh:1003
+#: git-submodule.sh:1092
 #, sh-format
-msgid "  Warn: $name doesn't contain commits $sha1_src and $sha1_dst"
+msgid "  Warn: $display_name doesn't contain commits $sha1_src and $sha1_dst"
 msgstr ""
-"  Warnung: $name beinhaltet nicht die Versionen $sha1_src und $sha1_dst"
+"  Warnung: $display_name beinhaltet nicht die Commits $sha1_src und $sha1_dst"
 
-#: git-submodule.sh:1028
+#: git-submodule.sh:1117
 msgid "blob"
 msgstr "Blob"
 
-#: git-submodule.sh:1066
+#: git-submodule.sh:1155
 msgid "Submodules changed but not updated:"
-msgstr "Unterprojekte geändert, aber nicht aktualisiert:"
+msgstr "Submodule geändert, aber nicht aktualisiert:"
 
-#: git-submodule.sh:1068
+#: git-submodule.sh:1157
 msgid "Submodule changes to be committed:"
-msgstr "Änderungen in Unterprojekt zum Eintragen:"
+msgstr "Änderungen in Submodul zum Committen:"
 
-#: git-submodule.sh:1153
+#: git-submodule.sh:1242
 #, sh-format
 msgid "Failed to recurse into submodule path '$sm_path'"
-msgstr "Fehler bei Rekursion in Unterprojekt-Pfad '$sm_path'"
+msgstr "Fehler bei Rekursion in Submodul-Pfad '$sm_path'"
 
-#: git-submodule.sh:1216
+#: git-submodule.sh:1306
 #, sh-format
-msgid "Synchronizing submodule url for '$prefix$sm_path'"
-msgstr "Synchronisiere Unterprojekt-URL für '$prefix$sm_path'"
+msgid "Synchronizing submodule url for '$displaypath'"
+msgstr "Synchronisiere Submodul-URL für '$displaypath'"
+
+#~ msgid "  (fix conflicts and then run \"git am --resolved\")"
+#~ msgstr ""
+#~ "  (beheben Sie die Konflikte und führen Sie dann \"git am --resolved\" "
+#~ "aus)"
+
+#~ msgid "  (all conflicts fixed: run \"git commit\")"
+#~ msgstr "  (alle Konflikte behoben: führen Sie \"git commit\" aus)"
+
+#~ msgid "more than %d trees given: '%s'"
+#~ msgstr "Mehr als %d \"Tree\"-Objekte angegeben: '%s'"
+
+#~ msgid "You cannot combine --no-ff with --ff-only."
+#~ msgstr "Sie können --no-ff nicht mit --ff--only kombinieren."
+
+#~ msgid ""
+#~ "submodule '%s' (or one of its nested submodules) uses a .git directory\n"
+#~ "(use 'rm -rf' if you really want to remove it including all of its "
+#~ "history)"
+#~ msgstr ""
+#~ "Submodul '%s' (oder ein geschachteltes Submodul hiervon) verwendet\n"
+#~ "ein .git-Verzeichnis (benutzen Sie 'rm -rf' wenn Sie dieses wirklich "
+#~ "mitsamt\n"
+#~ "seiner Historie löschen möchten)"
+
+#~ msgid ""
+#~ "'%s' has changes staged in the index\n"
+#~ "(use --cached to keep the file, or -f to force removal)"
+#~ msgstr ""
+#~ "'%s' hat zum Commit vorgemerkte Änderungen\n"
+#~ "(benutzen Sie --cached um die Datei zu behalten, oder -f um die "
+#~ "Entfernung zu erzwingen)"
+
+#~ msgid "show commits where no parent comes before its children"
+#~ msgstr ""
+#~ "zeigt Commits, bei denen kein Eltern-Commit vor seinem Kind-Commit kommt"
+
+#~ msgid "show the HEAD reference"
+#~ msgstr "zeigt Referenz von HEAD"
+
+#~ msgid "Unable to fetch in submodule path '$prefix$sm_path'"
+#~ msgstr "Konnte \"fetch\" in Submodul-Pfad '$prefix$sm_path' nicht ausführen"
+
+#~ msgid "Failed to recurse into submodule path '$prefix$sm_path'"
+#~ msgstr "Fehler bei Rekursion in Submodul-Pfad '$prefix$sm_path'"
+
+#~ msgid "It took %.2f seconds to enumerate untracked files.  'status -uno'"
+#~ msgstr ""
+#~ "Es dauerte %.2f Sekunden die unbeobachteten Dateien zu bestimmen.'status -"
+#~ "uno'"
+
+#~ msgid "may speed it up, but you have to be careful not to forget to add"
+#~ msgstr "könnte das beschleunigen, aber Sie müssen darauf achten, neue"
+
+#~ msgid "new files yourself (see 'git help status')."
+#~ msgstr "Dateien selbstständig hinzuzufügen (siehe 'git help status')."
+
+#~ msgid "git shortlog [-n] [-s] [-e] [-w] [rev-opts] [--] [<commit-id>... ]"
+#~ msgstr ""
+#~ "git shortlog [-n] [-s] [-e] [-w] [rev-opts] [--] "
+#~ "[<Versionsidentifikation>... ]"
+
+#~ msgid "See 'git help <command>' for more information on a specific command."
+#~ msgstr ""
+#~ "Siehe 'git help <Kommando>' für weitere Informationen zu einem "
+#~ "spezifischen Kommando"
 
 #~ msgid "use any ref in .git/refs"
 #~ msgstr "verwendet alle Referenzen in .git/refs"
diff --git a/po/fr.po b/po/fr.po
new file mode 100644
index 0000000..2cdb6f9
--- /dev/null
+++ b/po/fr.po
@@ -0,0 +1,9823 @@
+# French translations for Git.
+# Copyright (C) 2013 Jean-Noël Avila <jn.avila@free.fr>
+# This file is distributed under the same license as the Git package.
+# Jean-Noël Avila <jn.avila@free.fr>, 2013.
+# Sébastien Helleu <flashcode@flashtux.org>, 2013.
+#
+# French translations of common Git words used in this file:
+#
+#   English          |  French
+#   -----------------+---------------------------------
+#   #NN              |  n°NN
+#   a commit         |  un commit
+#   backward         |
+#     compatibility  |  rétrocompatibilité
+#   bare repository  |  dépôt nu
+#   bisect           |  bissection
+#   blob             |  blob
+#   bug              |  bogue
+#   bundle           |  colis
+#   cherry-pick      |  picorer
+#   dangling         |  en suspens
+#   debugging        |  débogage
+#   fast-forward     |  avance rapide
+#   fast-forwarded   |  mis à jour en avance rapide
+#   glob             |  glob
+#   hash             |  hachage
+#   HEAD             |  HEAD (genre féminin)
+#   hook             |  hook
+#   hunk             |  section
+#   merge            |  fusion
+#   pattern          |  motif
+#   repository       |  dépôt
+#   remote           |  distante (ou serveur distant)
+#   revision         |  révision
+#   stash            |  remisage
+#   tag              |  étiquette
+#   template         |  modèle
+#   to checkout      |  extraire
+#   to commit        |  valider
+#   to fetch         |  rapatrier
+#   to prune         |  élaguer
+#   to push          |  pousser
+#   to rebase        |  rebaser
+#   to stash         |  remiser
+#   to track         |  suivre
+#   to unstage       |  désindexer
+#   tree-ish         |  arbre
+#   upstream         |  amont
+#   worktree /       |
+#   work(ing) tree   |  copie de travail
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: git\n"
+"Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
+"POT-Creation-Date: 2013-04-30 08:25+0800\n"
+"PO-Revision-Date: 2013-08-27 19:43+0200\n"
+"Last-Translator: Sébastien Helleu <flashcode@flashtux.org>\n"
+"Language-Team: Jean-Noël Avila <jn.avila@free.fr>\n"
+"Language: fr\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n<=1 ?0 : 1;\n"
+"X-Generator: Poedit 1.5.4\n"
+
+#: advice.c:53
+#, c-format
+msgid "hint: %.*s\n"
+msgstr "astuce: %.*s\n"
+
+#.
+#. * Message used both when 'git commit' fails and when
+#. * other commands doing a merge do.
+#.
+#: advice.c:83
+msgid ""
+"Fix them up in the work tree,\n"
+"and then use 'git add/rm <file>' as\n"
+"appropriate to mark resolution and make a commit,\n"
+"or use 'git commit -a'."
+msgstr ""
+"Corrigez-les dans la copie de travail,\n"
+"et utilisez 'git add/rm <fichier>' si\n"
+"nécessaire pour marquer la résolution et valider,\n"
+"ou utilisez 'git commit -a'."
+
+#: archive.c:10
+msgid "git archive [options] <tree-ish> [<path>...]"
+msgstr "git archive [options] <arbre> [<chemin>...]"
+
+#: archive.c:11
+msgid "git archive --list"
+msgstr "git archive --list"
+
+#: archive.c:12
+msgid ""
+"git archive --remote <repo> [--exec <cmd>] [options] <tree-ish> [<path>...]"
+msgstr "git archive --remote <dépôt> [--exec <commande>] [options] <arbre> [<chemin>...]"
+
+#: archive.c:13
+msgid "git archive --remote <repo> [--exec <cmd>] --list"
+msgstr "git archive --remote <dépôt> [--exec <commande>] --list"
+
+#: archive.c:323
+msgid "fmt"
+msgstr "fmt"
+
+#: archive.c:323
+msgid "archive format"
+msgstr "format d'archive"
+
+#: archive.c:324 builtin/log.c:1126
+msgid "prefix"
+msgstr "préfixe"
+
+#: archive.c:325
+msgid "prepend prefix to each pathname in the archive"
+msgstr "préfixer chaque chemin de fichier dans l'archive"
+
+#: archive.c:326 builtin/archive.c:88 builtin/blame.c:2371
+#: builtin/blame.c:2372 builtin/config.c:55 builtin/fast-export.c:665
+#: builtin/fast-export.c:667 builtin/grep.c:715 builtin/hash-object.c:77
+#: builtin/ls-files.c:490 builtin/ls-files.c:493 builtin/notes.c:536
+#: builtin/notes.c:693 builtin/read-tree.c:107 parse-options.h:149
+msgid "file"
+msgstr "fichier"
+
+#: archive.c:327 builtin/archive.c:89
+msgid "write the archive to this file"
+msgstr "écrire l'archive dans ce fichier"
+
+#: archive.c:329
+msgid "read .gitattributes in working directory"
+msgstr "lire .gitattributes dans le répertoire de travail"
+
+#: archive.c:330
+msgid "report archived files on stderr"
+msgstr "afficher les fichiers archivés sur stderr"
+
+#: archive.c:331
+msgid "store only"
+msgstr "stockage seulement"
+
+#: archive.c:332
+msgid "compress faster"
+msgstr "compression rapide"
+
+#: archive.c:340
+msgid "compress better"
+msgstr "compression efficace"
+
+#: archive.c:343
+msgid "list supported archive formats"
+msgstr "lister les formats d'archive supportés"
+
+#: archive.c:345 builtin/archive.c:90 builtin/clone.c:86
+msgid "repo"
+msgstr "dépôt"
+
+#: archive.c:346 builtin/archive.c:91
+msgid "retrieve the archive from remote repository <repo>"
+msgstr "récupérer l'archive depuis le dépôt distant <dépôt>"
+
+#: archive.c:347 builtin/archive.c:92 builtin/notes.c:615
+msgid "command"
+msgstr "commande"
+
+#: archive.c:348 builtin/archive.c:93
+msgid "path to the remote git-upload-archive command"
+msgstr "chemin vers la commande distante git-upload-archive"
+
+#: attr.c:259
+msgid ""
+"Negative patterns are ignored in git attributes\n"
+"Use '\\!' for literal leading exclamation."
+msgstr ""
+"Les motifs de négation sont ignorés dans les attributs git\n"
+"Utilisez '\\!' pour un point d'exclamation littéral."
+
+#: branch.c:60
+#, c-format
+msgid "Not setting branch %s as its own upstream."
+msgstr "La branche %s ne peut pas être sa propre branche amont."
+
+#: branch.c:82
+#, c-format
+msgid "Branch %s set up to track remote branch %s from %s by rebasing."
+msgstr "La branche %s est paramétrée pour suivre la branche distante %s de %s en rebasant."
+
+#: branch.c:83
+#, c-format
+msgid "Branch %s set up to track remote branch %s from %s."
+msgstr "La branche %s est paramétrée pour suivre la branche distante %s depuis %s."
+
+#: branch.c:87
+#, c-format
+msgid "Branch %s set up to track local branch %s by rebasing."
+msgstr "La branche %s est paramétrée pour suivre la branche locale %s en rebasant."
+
+#: branch.c:88
+#, c-format
+msgid "Branch %s set up to track local branch %s."
+msgstr "La branche %s est paramétrée pour suivre la branche locale %s."
+
+#: branch.c:92
+#, c-format
+msgid "Branch %s set up to track remote ref %s by rebasing."
+msgstr "La branche %s est paramétrée pour suivre la référence distante %s en rebasant."
+
+#: branch.c:93
+#, c-format
+msgid "Branch %s set up to track remote ref %s."
+msgstr "La branche %s est paramétrée pour suivre la référence distante %s."
+
+#: branch.c:97
+#, c-format
+msgid "Branch %s set up to track local ref %s by rebasing."
+msgstr "La branche %s est paramétrée pour suivre la référence locale %s en rebasant."
+
+#: branch.c:98
+#, c-format
+msgid "Branch %s set up to track local ref %s."
+msgstr "La branche %s est paramétrée pour suivre la référence locale %s."
+
+#: branch.c:118
+#, c-format
+msgid "Tracking not set up: name too long: %s"
+msgstr "Suivi de branche non paramétré : le nom est trop long : %s"
+
+#: branch.c:137
+#, c-format
+msgid "Not tracking: ambiguous information for ref %s"
+msgstr "Pas de suivi : information ambiguë pour la référence %s"
+
+#: branch.c:182
+#, c-format
+msgid "'%s' is not a valid branch name."
+msgstr "'%s' n'est pas un nom de branche valide."
+
+#: branch.c:187
+#, c-format
+msgid "A branch named '%s' already exists."
+msgstr "Une branche nommée '%s' existe déjà."
+
+#: branch.c:195
+msgid "Cannot force update the current branch."
+msgstr "Impossible de forcer la mise à jour de la branche courante."
+
+#: branch.c:201
+#, c-format
+msgid "Cannot setup tracking information; starting point '%s' is not a branch."
+msgstr "Impossible de paramétrer le suivi de branche ; le point de départ '%s' n'est pas une branche."
+
+#: branch.c:203
+#, c-format
+msgid "the requested upstream branch '%s' does not exist"
+msgstr "la branche amont demandée '%s' n'existe pas"
+
+#: branch.c:205
+msgid ""
+"\n"
+"If you are planning on basing your work on an upstream\n"
+"branch that already exists at the remote, you may need to\n"
+"run \"git fetch\" to retrieve it.\n"
+"\n"
+"If you are planning to push out a new local branch that\n"
+"will track its remote counterpart, you may want to use\n"
+"\"git push -u\" to set the upstream config as you push."
+msgstr ""
+"\n"
+"Si vous comptez baser votre travail sur une branche\n"
+"amont qui existe déjà sur le serveur distant, vous pourriez\n"
+"devoir lancer \"git fetch\" pour la récupérer.\n"
+"\n"
+"Si vous comptez pousser une nouvelle branche locale qui suivra\n"
+"sa jumelle distante, vous souhaiterez utiliser \"git push -u\"\n"
+"pour paramétrer le suivi distant en même temps que vous poussez."
+
+#: branch.c:250
+#, c-format
+msgid "Not a valid object name: '%s'."
+msgstr "Nom d'objet invalide : '%s'."
+
+#: branch.c:270
+#, c-format
+msgid "Ambiguous object name: '%s'."
+msgstr "Nom d'objet ambigu : '%s'."
+
+#: branch.c:275
+#, c-format
+msgid "Not a valid branch point: '%s'."
+msgstr "Point d'embranchement invalide : '%s'."
+
+#: branch.c:281
+msgid "Failed to lock ref for update"
+msgstr "Échec du verrouillage de la référence pour mise à jour"
+
+#: branch.c:299
+msgid "Failed to write ref"
+msgstr "Échec de l'écriture de la référence"
+
+#: bundle.c:36
+#, c-format
+msgid "'%s' does not look like a v2 bundle file"
+msgstr "'%s' ne semble pas être un fichier bundle v2"
+
+#: bundle.c:63
+#, c-format
+msgid "unrecognized header: %s%s (%d)"
+msgstr "en-tête non reconnu : %s%s (%d)"
+
+#: bundle.c:89 builtin/commit.c:676
+#, c-format
+msgid "could not open '%s'"
+msgstr "impossible d'ouvrir '%s'"
+
+#: bundle.c:140
+msgid "Repository lacks these prerequisite commits:"
+msgstr "Le dépôt ne dispose pas des commits prérequis :"
+
+#: bundle.c:164 sequencer.c:651 sequencer.c:1101 builtin/log.c:300
+#: builtin/log.c:770 builtin/log.c:1344 builtin/log.c:1570 builtin/merge.c:349
+#: builtin/shortlog.c:155
+msgid "revision walk setup failed"
+msgstr "échec de la préparation du parcours des révisions"
+
+#: bundle.c:186
+#, c-format
+msgid "The bundle contains this ref:"
+msgid_plural "The bundle contains these %d refs:"
+msgstr[0] "Le colis contient cette référence :"
+msgstr[1] "Le colis contient ces %d références :"
+
+#: bundle.c:193
+msgid "The bundle records a complete history."
+msgstr "Le colis enregistre l'historique complet."
+
+#: bundle.c:195
+#, c-format
+msgid "The bundle requires this ref:"
+msgid_plural "The bundle requires these %d refs:"
+msgstr[0] "Le colis exige cette référence :"
+msgstr[1] "Le colis exige ces %d références :"
+
+#: bundle.c:294
+msgid "rev-list died"
+msgstr "rev-list a disparu"
+
+#: bundle.c:300 builtin/log.c:1255 builtin/shortlog.c:258
+#, c-format
+msgid "unrecognized argument: %s"
+msgstr "argument non reconnu : %s"
+
+#: bundle.c:335
+#, c-format
+msgid "ref '%s' is excluded by the rev-list options"
+msgstr "la référence '%s' est exclue par les options de rev-list"
+
+#: bundle.c:380
+msgid "Refusing to create empty bundle."
+msgstr "Refus de créer un colis vide."
+
+#: bundle.c:398
+msgid "Could not spawn pack-objects"
+msgstr "Impossible de créer des objets groupés"
+
+#: bundle.c:416
+msgid "pack-objects died"
+msgstr "les objets groupés ont disparu"
+
+#: bundle.c:419
+#, c-format
+msgid "cannot create '%s'"
+msgstr "impossible de créer '%s'"
+
+#: bundle.c:441
+msgid "index-pack died"
+msgstr "l'index de groupe a disparu"
+
+#: commit.c:50
+#, c-format
+msgid "could not parse %s"
+msgstr "impossible d'analyser %s"
+
+#: commit.c:52
+#, c-format
+msgid "%s %s is not a commit!"
+msgstr "%s %s n'est pas un commit !"
+
+#: compat/obstack.c:406 compat/obstack.c:408
+msgid "memory exhausted"
+msgstr "plus de mémoire"
+
+#: connected.c:39
+msgid "Could not run 'git rev-list'"
+msgstr "Impossible de lancer 'git rev-list'"
+
+#: connected.c:48
+#, c-format
+msgid "failed write to rev-list: %s"
+msgstr "impossible d'écrire dans la rev-list : %s"
+
+#: connected.c:56
+#, c-format
+msgid "failed to close rev-list's stdin: %s"
+msgstr "impossible de fermer le stdin du rev-list : %s"
+
+#: date.c:95
+msgid "in the future"
+msgstr "dans le futur"
+
+#: date.c:101
+#, c-format
+msgid "%lu second ago"
+msgid_plural "%lu seconds ago"
+msgstr[0] "il y a %lu seconde"
+msgstr[1] "il y a %lu secondes"
+
+#: date.c:108
+#, c-format
+msgid "%lu minute ago"
+msgid_plural "%lu minutes ago"
+msgstr[0] "il y a %lu minute"
+msgstr[1] "il y a %lu minutes"
+
+#: date.c:115
+#, c-format
+msgid "%lu hour ago"
+msgid_plural "%lu hours ago"
+msgstr[0] "il y a %lu heure"
+msgstr[1] "il y a %lu heures"
+
+#: date.c:122
+#, c-format
+msgid "%lu day ago"
+msgid_plural "%lu days ago"
+msgstr[0] "il y a %lu jour"
+msgstr[1] "il y a %lu jours"
+
+#: date.c:128
+#, c-format
+msgid "%lu week ago"
+msgid_plural "%lu weeks ago"
+msgstr[0] "il y a %lu semaine"
+msgstr[1] "il y a %lu semaines"
+
+#: date.c:135
+#, c-format
+msgid "%lu month ago"
+msgid_plural "%lu months ago"
+msgstr[0] "il y a %lu mois"
+msgstr[1] "il y a %lu mois"
+
+#: date.c:146
+#, c-format
+msgid "%lu year"
+msgid_plural "%lu years"
+msgstr[0] "%lu an"
+msgstr[1] "%lu ans"
+
+#: date.c:149
+#, c-format
+msgid "%s, %lu month ago"
+msgid_plural "%s, %lu months ago"
+msgstr[0] "il y a %s et %lu mois"
+msgstr[1] "il y a %s et %lu mois"
+
+#: date.c:154 date.c:159
+#, c-format
+msgid "%lu year ago"
+msgid_plural "%lu years ago"
+msgstr[0] "il y a %lu an"
+msgstr[1] "il y a %lu ans"
+
+#: diff.c:112
+#, c-format
+msgid "  Failed to parse dirstat cut-off percentage '%s'\n"
+msgstr "  Impossible d'analyser le pourcentage de modification de dirstat '%s'\n"
+
+#: diff.c:117
+#, c-format
+msgid "  Unknown dirstat parameter '%s'\n"
+msgstr "  Paramètre dirstat inconnu '%s'\n"
+
+#: diff.c:210
+#, c-format
+msgid "Unknown value for 'diff.submodule' config variable: '%s'"
+msgstr "Valeur inconnue pour la variable de configuration 'diff.submodule' : '%s'"
+
+#: diff.c:260
+#, c-format
+msgid ""
+"Found errors in 'diff.dirstat' config variable:\n"
+"%s"
+msgstr "Erreurs dans la variable de configuration 'diff.dirstat' :\n"
+"%s"
+
+#: diff.c:3481
+#, c-format
+msgid ""
+"Failed to parse --dirstat/-X option parameter:\n"
+"%s"
+msgstr "Impossible d'analyser le paramètre de l'option --dirstat/-X :\n"
+"%s"
+
+#: diff.c:3495
+#, c-format
+msgid "Failed to parse --submodule option parameter: '%s'"
+msgstr "Impossible d'analyser le paramètre de l'option --submodule : '%s'"
+
+#: gpg-interface.c:59 gpg-interface.c:131
+msgid "could not run gpg."
+msgstr "impossible de lancer gpg."
+
+#: gpg-interface.c:71
+msgid "gpg did not accept the data"
+msgstr "gpg n'a pas accepté les données"
+
+#: gpg-interface.c:82
+msgid "gpg failed to sign the data"
+msgstr "gpg n'a pas pu signer les données"
+
+#: gpg-interface.c:115
+#, c-format
+msgid "could not create temporary file '%s': %s"
+msgstr "impossible de créer un fichier temporaire '%s' : %s"
+
+#: gpg-interface.c:118
+#, c-format
+msgid "failed writing detached signature to '%s': %s"
+msgstr "impossible d'écrire la signature détachée dans '%s' : %s"
+
+#: grep.c:1623
+#, c-format
+msgid "'%s': unable to read %s"
+msgstr "'%s' : lecture de %s impossible"
+
+#: grep.c:1640
+#, c-format
+msgid "'%s': %s"
+msgstr "'%s' : %s"
+
+#: grep.c:1651
+#, c-format
+msgid "'%s': short read %s"
+msgstr "'%s' : lecture tronquée %s"
+
+#: help.c:212
+#, c-format
+msgid "available git commands in '%s'"
+msgstr "commandes git disponibles dans '%s'"
+
+#: help.c:219
+msgid "git commands available from elsewhere on your $PATH"
+msgstr "commandes git disponibles depuis un autre endroit de votre $PATH"
+
+#: help.c:235
+msgid "The most commonly used git commands are:"
+msgstr "Les commandes git les plus utilisées sont :"
+
+#: help.c:292
+#, c-format
+msgid ""
+"'%s' appears to be a git command, but we were not\n"
+"able to execute it. Maybe git-%s is broken?"
+msgstr ""
+"'%s' semble être une commande git, mais elle n'a pas pu\n"
+"être exécutée. Peut-être git-%s est-elle cassée ?"
+
+#: help.c:349
+msgid "Uh oh. Your system reports no Git commands at all."
+msgstr "Ahem. Votre système n'indique aucune commande Git."
+
+#: help.c:371
+#, c-format
+msgid ""
+"WARNING: You called a Git command named '%s', which does not exist.\n"
+"Continuing under the assumption that you meant '%s'"
+msgstr "ATTENTION : vous avez invoqué une commande Git nommée '%s' qui n'existe pas.\n"
+"Poursuite en supposant que vous avez voulu dire '%s'"
+
+#: help.c:376
+#, c-format
+msgid "in %0.1f seconds automatically..."
+msgstr "dans %0.1f secondes automatiquement..."
+
+#: help.c:383
+#, c-format
+msgid "git: '%s' is not a git command. See 'git --help'."
+msgstr "git : '%s' n'est pas une commande git. Voir 'git --help'."
+
+#: help.c:387
+msgid ""
+"\n"
+"Did you mean this?"
+msgid_plural ""
+"\n"
+"Did you mean one of these?"
+msgstr[0] "\n"
+"Vouliez-vous dire cela ?"
+msgstr[1] "\nVouliez-vous dire un de ceux-là ?"
+
+#: merge.c:56
+msgid "failed to read the cache"
+msgstr "impossible de lire le cache"
+
+#: merge.c:110 builtin/checkout.c:365 builtin/checkout.c:566
+#: builtin/clone.c:645
+msgid "unable to write new index file"
+msgstr "impossible d'écrire le nouveau fichier d'index"
+
+#: merge-recursive.c:190
+#, c-format
+msgid "(bad commit)\n"
+msgstr "(mauvais commit)\n"
+
+#: merge-recursive.c:206
+#, c-format
+msgid "addinfo_cache failed for path '%s'"
+msgstr "échec de addinfo_cache pour le chemin '%s'"
+
+#: merge-recursive.c:268
+msgid "error building trees"
+msgstr "erreur de construction des arbres"
+
+#: merge-recursive.c:672
+#, c-format
+msgid "failed to create path '%s'%s"
+msgstr "impossible de créer le chemin '%s' %s"
+
+#: merge-recursive.c:683
+#, c-format
+msgid "Removing %s to make room for subdirectory\n"
+msgstr "Suppression de %s pour faire de la place pour le sous-répertoire\n"
+
+#. something else exists
+#. .. but not some other error (who really cares what?)
+#: merge-recursive.c:697 merge-recursive.c:718
+msgid ": perhaps a D/F conflict?"
+msgstr ": peut-être un conflit D/F ?"
+
+#: merge-recursive.c:708
+#, c-format
+msgid "refusing to lose untracked file at '%s'"
+msgstr "refus de perdre le fichier non suivi '%s'"
+
+#: merge-recursive.c:748
+#, c-format
+msgid "cannot read object %s '%s'"
+msgstr "impossible de lire l'objet %s '%s'"
+
+#: merge-recursive.c:750
+#, c-format
+msgid "blob expected for %s '%s'"
+msgstr "blob attendu pour %s '%s'"
+
+#: merge-recursive.c:773 builtin/clone.c:313
+#, c-format
+msgid "failed to open '%s'"
+msgstr "échec à l'ouverture de '%s'"
+
+#: merge-recursive.c:781
+#, c-format
+msgid "failed to symlink '%s'"
+msgstr "échec à la création du lien symbolique '%s'"
+
+#: merge-recursive.c:784
+#, c-format
+msgid "do not know what to do with %06o %s '%s'"
+msgstr "ne sait pas traiter %06o %s '%s'"
+
+#: merge-recursive.c:922
+msgid "Failed to execute internal merge"
+msgstr "Échec à l'exécution de la fusion interne"
+
+#: merge-recursive.c:926
+#, c-format
+msgid "Unable to add %s to database"
+msgstr "Impossible d'ajouter %s à la base de données"
+
+#: merge-recursive.c:942
+msgid "unsupported object type in the tree"
+msgstr "type d'objet non supporté dans l'arbre"
+
+#: merge-recursive.c:1021 merge-recursive.c:1035
+#, c-format
+msgid ""
+"CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s left "
+"in tree."
+msgstr "CONFLIT (%s/suppression) : %s supprimé dans %s et %s dans %s. Version %s de %s laissée dans l'arbre."
+
+#: merge-recursive.c:1027 merge-recursive.c:1040
+#, c-format
+msgid ""
+"CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s left "
+"in tree at %s."
+msgstr "CONFLIT (%s/suppression) : %s supprimé dans %s et %s dans %s. Version %s de %s laissée dans l'arbre dans le fichier %s."
+
+#: merge-recursive.c:1081
+msgid "rename"
+msgstr "renommage"
+
+#: merge-recursive.c:1081
+msgid "renamed"
+msgstr "renommé"
+
+#: merge-recursive.c:1137
+#, c-format
+msgid "%s is a directory in %s adding as %s instead"
+msgstr "%s est un répertoire dans %s ajouté plutôt comme %s"
+
+#: merge-recursive.c:1159
+#, c-format
+msgid ""
+"CONFLICT (rename/rename): Rename \"%s\"->\"%s\" in branch \"%s\" rename \"%s"
+"\"->\"%s\" in \"%s\"%s"
+msgstr "CONFLIT (renommage/renommage) : Renommage de \"%s\"->\"%s\" dans la branche \"%s\" et renommage \"%s\"->\"%s\" dans \"%s\"%s"
+
+#: merge-recursive.c:1164
+msgid " (left unresolved)"
+msgstr " (laissé non résolu)"
+
+#: merge-recursive.c:1218
+#, c-format
+msgid "CONFLICT (rename/rename): Rename %s->%s in %s. Rename %s->%s in %s"
+msgstr "CONFLIT (renommage/renommage) : renommage '%s'->'%s' dans %s. Renommage '%s'->'%s' dans %s"
+
+#: merge-recursive.c:1248
+#, c-format
+msgid "Renaming %s to %s and %s to %s instead"
+msgstr "Renommage de %s en %s et de %s en %s à la place"
+
+#: merge-recursive.c:1447
+#, c-format
+msgid "CONFLICT (rename/add): Rename %s->%s in %s. %s added in %s"
+msgstr "CONFLIT (renommage/ajout) : Renommage de %s->%s dans %s. %s ajouté dans %s"
+
+#: merge-recursive.c:1457
+#, c-format
+msgid "Adding merged %s"
+msgstr "Ajout de %s fusionné"
+
+#: merge-recursive.c:1462 merge-recursive.c:1660
+#, c-format
+msgid "Adding as %s instead"
+msgstr "Ajout plutôt comme %s"
+
+#: merge-recursive.c:1513
+#, c-format
+msgid "cannot read object %s"
+msgstr "impossible de lire l'objet %s"
+
+#: merge-recursive.c:1516
+#, c-format
+msgid "object %s is not a blob"
+msgstr "l'objet %s n'est pas un blob"
+
+#: merge-recursive.c:1564
+msgid "modify"
+msgstr "modification"
+
+#: merge-recursive.c:1564
+msgid "modified"
+msgstr "modifié"
+
+#: merge-recursive.c:1574
+msgid "content"
+msgstr "contenu"
+
+#: merge-recursive.c:1581
+msgid "add/add"
+msgstr "ajout/ajout"
+
+#: merge-recursive.c:1615
+#, c-format
+msgid "Skipped %s (merged same as existing)"
+msgstr "%s ignoré (fusion identique à l'existant)"
+
+#: merge-recursive.c:1629
+#, c-format
+msgid "Auto-merging %s"
+msgstr "Fusion automatique de %s"
+
+#: merge-recursive.c:1633 git-submodule.sh:1029
+msgid "submodule"
+msgstr "sous-module"
+
+#: merge-recursive.c:1634
+#, c-format
+msgid "CONFLICT (%s): Merge conflict in %s"
+msgstr "CONFLIT (%s) : Conflit de fusion dans %s"
+
+#: merge-recursive.c:1724
+#, c-format
+msgid "Removing %s"
+msgstr "Suppression de %s"
+
+#: merge-recursive.c:1749
+msgid "file/directory"
+msgstr "fichier/répertoire"
+
+#: merge-recursive.c:1755
+msgid "directory/file"
+msgstr "répertoire/fichier"
+
+#: merge-recursive.c:1760
+#, c-format
+msgid "CONFLICT (%s): There is a directory with name %s in %s. Adding %s as %s"
+msgstr "CONFLIT (%s) : Il y a un répertoire nommé %s dans %s. Ajout de %s comme %s"
+
+#: merge-recursive.c:1770
+#, c-format
+msgid "Adding %s"
+msgstr "Ajout de %s"
+
+#: merge-recursive.c:1787
+msgid "Fatal merge failure, shouldn't happen."
+msgstr "Échec fatal de fusion, qui ne devrait jamais arriver."
+
+#: merge-recursive.c:1806
+msgid "Already up-to-date!"
+msgstr "Déjà à jour !"
+
+#: merge-recursive.c:1815
+#, c-format
+msgid "merging of trees %s and %s failed"
+msgstr "échec de fusion des arbres %s et %s"
+
+#: merge-recursive.c:1845
+#, c-format
+msgid "Unprocessed path??? %s"
+msgstr "Chemin non traité ??? %s"
+
+#: merge-recursive.c:1890
+msgid "Merging:"
+msgstr "Fusion :"
+
+#: merge-recursive.c:1903
+#, c-format
+msgid "found %u common ancestor:"
+msgid_plural "found %u common ancestors:"
+msgstr[0] "%u ancêtre commun trouvé :"
+msgstr[1] "%u ancêtres communs trouvés :"
+
+#: merge-recursive.c:1940
+msgid "merge returned no commit"
+msgstr "la fusion n'a pas retourné de commit"
+
+#: merge-recursive.c:1997
+#, c-format
+msgid "Could not parse object '%s'"
+msgstr "Impossible d'analyser l'objet '%s'"
+
+#: merge-recursive.c:2009 builtin/merge.c:658
+msgid "Unable to write index."
+msgstr "Impossible d'écrire l'index."
+
+#: object.c:195
+#, c-format
+msgid "unable to parse object: %s"
+msgstr "impossible d'analyser l'objet : %s"
+
+#: parse-options.c:489
+msgid "..."
+msgstr "..."
+
+#: parse-options.c:507
+#, c-format
+msgid "usage: %s"
+msgstr "usage : %s"
+
+#. TRANSLATORS: the colon here should align with the
+#. one in "usage: %s" translation
+#: parse-options.c:511
+#, c-format
+msgid "   or: %s"
+msgstr "   ou : %s"
+
+#: parse-options.c:514
+#, c-format
+msgid "    %s"
+msgstr "    %s"
+
+#: parse-options.c:548
+msgid "-NUM"
+msgstr "-NUM"
+
+#: pathspec.c:83
+#, c-format
+msgid "Path '%s' is in submodule '%.*s'"
+msgstr "Le chemin '%s' est dans le sous-module '%.*s'"
+
+#: pathspec.c:99
+#, c-format
+msgid "'%s' is beyond a symbolic link"
+msgstr "'%s' est au delà d'un lien symbolique"
+
+#: remote.c:1781
+#, c-format
+msgid "Your branch is ahead of '%s' by %d commit.\n"
+msgid_plural "Your branch is ahead of '%s' by %d commits.\n"
+msgstr[0] "Votre branche est en avance sur '%s' de %d commit.\n"
+msgstr[1] "Votre branche est en avance sur '%s' de %d commits.\n"
+
+#: remote.c:1787
+msgid "  (use \"git push\" to publish your local commits)\n"
+msgstr "  (utilisez \"git push\" pour publier vos commits locaux)\n"
+
+#: remote.c:1790
+#, c-format
+msgid "Your branch is behind '%s' by %d commit, and can be fast-forwarded.\n"
+msgid_plural ""
+"Your branch is behind '%s' by %d commits, and can be fast-forwarded.\n"
+msgstr[0] "Votre branche est en retard sur '%s' de %d commit, et peut être mise à jour en avance rapide.\n"
+msgstr[1] "Votre branche est en retard sur '%s' de %d commits, et peut être mise à jour en avance rapide.\n"
+
+#: remote.c:1798
+msgid "  (use \"git pull\" to update your local branch)\n"
+msgstr "  (utilisez \"git pull\" pour mettre à jour votre branche locale)\n"
+
+#: remote.c:1801
+#, c-format
+msgid ""
+"Your branch and '%s' have diverged,\n"
+"and have %d and %d different commit each, respectively.\n"
+msgid_plural ""
+"Your branch and '%s' have diverged,\n"
+"and have %d and %d different commits each, respectively.\n"
+msgstr[0] "Votre branche et '%s' ont divergé,\n"
+"et ont %d et %d commit différent chacune respectivement.\n"
+msgstr[1] "Votre branche et '%s' ont divergé,\n"
+"et ont %d et %d commits différents chacune respectivement.\n"
+
+#: remote.c:1811
+msgid "  (use \"git pull\" to merge the remote branch into yours)\n"
+msgstr "  (utilisez \"git pull\" pour fusionner la branche distante dans la vôtre)\n"
+
+#: sequencer.c:206 builtin/merge.c:776 builtin/merge.c:889 builtin/merge.c:999
+#: builtin/merge.c:1009
+#, c-format
+msgid "Could not open '%s' for writing"
+msgstr "Impossible d'ouvrir '%s' en écriture"
+
+#: sequencer.c:208 builtin/merge.c:335 builtin/merge.c:779
+#: builtin/merge.c:1001 builtin/merge.c:1014
+#, c-format
+msgid "Could not write to '%s'"
+msgstr "Impossible d'écrire dans '%s'"
+
+#: sequencer.c:229
+msgid ""
+"after resolving the conflicts, mark the corrected paths\n"
+"with 'git add <paths>' or 'git rm <paths>'"
+msgstr "après résolution des conflits, marquez les chemins corrigés\n"
+"avec 'git add <chemins>' ou 'git rm <chemins>'"
+
+#: sequencer.c:232
+msgid ""
+"after resolving the conflicts, mark the corrected paths\n"
+"with 'git add <paths>' or 'git rm <paths>'\n"
+"and commit the result with 'git commit'"
+msgstr ""
+"après résolution des conflits, marquez les chemins corrigés\n"
+"avec 'git add <chemins>' ou 'git rm <chemins>'\n"
+"puis validez le résultat avec 'git commit'"
+
+#: sequencer.c:245 sequencer.c:859 sequencer.c:942
+#, c-format
+msgid "Could not write to %s"
+msgstr "Impossible d'écrire dans %s"
+
+#: sequencer.c:248
+#, c-format
+msgid "Error wrapping up %s"
+msgstr "Erreur à l'emballage de %s"
+
+#: sequencer.c:263
+msgid "Your local changes would be overwritten by cherry-pick."
+msgstr "Vos modifications locales seraient écrasées par cherry-pick."
+
+#: sequencer.c:265
+msgid "Your local changes would be overwritten by revert."
+msgstr "Vos modifications locales seraient écrasées par revert."
+
+#: sequencer.c:268
+msgid "Commit your changes or stash them to proceed."
+msgstr "Validez vos modifications ou remisez-les pour continuer."
+
+#. TRANSLATORS: %s will be "revert" or "cherry-pick"
+#: sequencer.c:319
+#, c-format
+msgid "%s: Unable to write new index file"
+msgstr "%s: Impossible d'écrire le nouveau fichier index"
+
+#: sequencer.c:350
+msgid "Could not resolve HEAD commit\n"
+msgstr "Impossible de résoudre le commit HEAD\n"
+
+#: sequencer.c:371
+msgid "Unable to update cache tree\n"
+msgstr "Impossible de mettre à jour l'arbre de cache\n"
+
+#: sequencer.c:416
+#, c-format
+msgid "Could not parse commit %s\n"
+msgstr "Impossible d'analyser le commit %s\n"
+
+#: sequencer.c:421
+#, c-format
+msgid "Could not parse parent commit %s\n"
+msgstr "Impossible d'analyser le commit parent %s\n"
+
+#: sequencer.c:487
+msgid "Your index file is unmerged."
+msgstr "Votre fichier d'index n'est pas fusionné."
+
+#: sequencer.c:506
+#, c-format
+msgid "Commit %s is a merge but no -m option was given."
+msgstr "Le commit %s est une fusion mais l'option -m n'a pas été spécifiée."
+
+#: sequencer.c:514
+#, c-format
+msgid "Commit %s does not have parent %d"
+msgstr "Le commit %s n'a pas le parent %d"
+
+#: sequencer.c:518
+#, c-format
+msgid "Mainline was specified but commit %s is not a merge."
+msgstr "Une branche principale a été spécifiée mais le commit %s n'est pas une fusion."
+
+#. TRANSLATORS: The first %s will be "revert" or
+#. "cherry-pick", the second %s a SHA1
+#: sequencer.c:531
+#, c-format
+msgid "%s: cannot parse parent commit %s"
+msgstr "%s : impossible d'analyser le commit parent %s"
+
+#: sequencer.c:535
+#, c-format
+msgid "Cannot get commit message for %s"
+msgstr "Impossible d'obtenir un message de validation pour %s"
+
+#: sequencer.c:621
+#, c-format
+msgid "could not revert %s... %s"
+msgstr "impossible d'annuler %s... %s"
+
+#: sequencer.c:622
+#, c-format
+msgid "could not apply %s... %s"
+msgstr "impossible d'appliquer %s... %s"
+
+#: sequencer.c:654
+msgid "empty commit set passed"
+msgstr "l'ensemble de commits spéficifié est vide"
+
+#: sequencer.c:662
+#, c-format
+msgid "git %s: failed to read the index"
+msgstr "git %s : échec à la lecture de l'index"
+
+#: sequencer.c:667
+#, c-format
+msgid "git %s: failed to refresh the index"
+msgstr "git %s : échec du raffraîchissement de l'index"
+
+#: sequencer.c:725
+#, c-format
+msgid "Cannot %s during a %s"
+msgstr "Impossible de %s pendant un %s"
+
+#: sequencer.c:747
+#, c-format
+msgid "Could not parse line %d."
+msgstr "Impossible d'analyser la ligne %d."
+
+#: sequencer.c:752
+msgid "No commits parsed."
+msgstr "Aucun commit analysé."
+
+#: sequencer.c:765
+#, c-format
+msgid "Could not open %s"
+msgstr "Impossible d'ouvrir %s"
+
+#: sequencer.c:769
+#, c-format
+msgid "Could not read %s."
+msgstr "Impossible de lire %s."
+
+#: sequencer.c:776
+#, c-format
+msgid "Unusable instruction sheet: %s"
+msgstr "Feuille d'instruction inutilisable : %s"
+
+#: sequencer.c:804
+#, c-format
+msgid "Invalid key: %s"
+msgstr "Clé invalide: %s"
+
+#: sequencer.c:807
+#, c-format
+msgid "Invalid value for %s: %s"
+msgstr "Valeur invalide pour %s : %s"
+
+#: sequencer.c:819
+#, c-format
+msgid "Malformed options sheet: %s"
+msgstr "Feuille d'options malformée : %s"
+
+#: sequencer.c:840
+msgid "a cherry-pick or revert is already in progress"
+msgstr "un picorage ou un retour est déjà en cours"
+
+#: sequencer.c:841
+msgid "try \"git cherry-pick (--continue | --quit | --abort)\""
+msgstr "essayez \"git cherry-pick (--continue|--quit|-- abort)\""
+
+#: sequencer.c:845
+#, c-format
+msgid "Could not create sequencer directory %s"
+msgstr "Impossible de créer le répertoire de séquenceur %s"
+
+#: sequencer.c:861 sequencer.c:946
+#, c-format
+msgid "Error wrapping up %s."
+msgstr "Erreur lors de l'emballage de %s."
+
+#: sequencer.c:880 sequencer.c:1014
+msgid "no cherry-pick or revert in progress"
+msgstr "aucun picorage ou retour en cours"
+
+#: sequencer.c:882
+msgid "cannot resolve HEAD"
+msgstr "impossible de résoudre HEAD"
+
+#: sequencer.c:884
+msgid "cannot abort from a branch yet to be born"
+msgstr "impossible d'abandonner depuis une branche non encore créée"
+
+#: sequencer.c:906 builtin/apply.c:4060
+#, c-format
+msgid "cannot open %s: %s"
+msgstr "impossible d'ouvrir %s : %s"
+
+#: sequencer.c:909
+#, c-format
+msgid "cannot read %s: %s"
+msgstr "impossible de lire %s : %s"
+
+#: sequencer.c:910
+msgid "unexpected end of file"
+msgstr "fin de fichier inattendue"
+
+#: sequencer.c:916
+#, c-format
+msgid "stored pre-cherry-pick HEAD file '%s' is corrupt"
+msgstr "le fichier HEAD de préparation de picorage '%s' est corrompu"
+
+#: sequencer.c:939
+#, c-format
+msgid "Could not format %s."
+msgstr "Impossible de formater %s."
+
+#: sequencer.c:1083
+#, c-format
+msgid "%s: can't cherry-pick a %s"
+msgstr "%s : impossible de picorer un %s"
+
+#: sequencer.c:1085
+#, c-format
+msgid "%s: bad revision"
+msgstr "%s : mauvaise révision"
+
+#: sequencer.c:1119
+msgid "Can't revert as initial commit"
+msgstr "Impossible d'annuler en tant que commit initial"
+
+#: sequencer.c:1120
+msgid "Can't cherry-pick into empty head"
+msgstr "Impossible de picorer vers une HEAD vide"
+
+#: sha1_name.c:1036
+msgid "HEAD does not point to a branch"
+msgstr "HEAD ne pointe pas sur une branche"
+
+#: sha1_name.c:1039
+#, c-format
+msgid "No such branch: '%s'"
+msgstr "Branche inconnue : '%s'"
+
+#: sha1_name.c:1041
+#, c-format
+msgid "No upstream configured for branch '%s'"
+msgstr "Aucune branche amont configurée pour la branche '%s'"
+
+#: sha1_name.c:1044
+#, c-format
+msgid "Upstream branch '%s' not stored as a remote-tracking branch"
+msgstr "La branche amont '%s' n'est pas stockée comme branche de suivi"
+
+#: wrapper.c:408
+#, c-format
+msgid "unable to access '%s': %s"
+msgstr "impossible d'accéder à '%s' : %s"
+
+#: wrapper.c:423
+#, c-format
+msgid "unable to access '%s'"
+msgstr "impossible d'accéder à '%s'"
+
+#: wrapper.c:434
+#, c-format
+msgid "unable to look up current user in the passwd file: %s"
+msgstr "impossible de rechercher l'utilisateur actuel dans le fichier de mots de passe : %s"
+
+#: wrapper.c:435
+msgid "no such user"
+msgstr "utilisateur inconnu"
+
+#: wt-status.c:140
+msgid "Unmerged paths:"
+msgstr "Chemins non fusionnés :"
+
+#: wt-status.c:167 wt-status.c:194
+#, c-format
+msgid "  (use \"git reset %s <file>...\" to unstage)"
+msgstr "  (utilisez \"git reset %s <fichier>...\" pour désindexer)"
+
+#: wt-status.c:169 wt-status.c:196
+msgid "  (use \"git rm --cached <file>...\" to unstage)"
+msgstr "  (utilisez \"git rm --cached <fichier>...\" pour désindexer)"
+
+#: wt-status.c:173
+msgid "  (use \"git add <file>...\" to mark resolution)"
+msgstr "  (utilisez \"git add <fichier>...\" pour marquer comme résolu)"
+
+#: wt-status.c:175 wt-status.c:179
+msgid "  (use \"git add/rm <file>...\" as appropriate to mark resolution)"
+msgstr "  (utilisez \"git add/rm <fichier>...\" si nécessaire pour marquer comme résolu)"
+
+#: wt-status.c:177
+msgid "  (use \"git rm <file>...\" to mark resolution)"
+msgstr "  (utilisez \"git rm <fichier>...\" pour marquer comme résolu)"
+
+#: wt-status.c:188
+msgid "Changes to be committed:"
+msgstr "Modifications qui seront validées :"
+
+#: wt-status.c:206
+msgid "Changes not staged for commit:"
+msgstr "Modifications qui ne seront pas validées :"
+
+#: wt-status.c:210
+msgid "  (use \"git add <file>...\" to update what will be committed)"
+msgstr "  (utilisez \"git add <fichier>...\" pour mettre à jour ce qui sera validé)"
+
+#: wt-status.c:212
+msgid "  (use \"git add/rm <file>...\" to update what will be committed)"
+msgstr "  (utilisez \"git add/rm <fichier>...\" pour mettre à jour ce qui sera validé)"
+
+#: wt-status.c:213
+msgid ""
+"  (use \"git checkout -- <file>...\" to discard changes in working directory)"
+msgstr "  (utilisez \"git checkout -- <fichier>...\" pour annuler les modifications dans la copie de travail)"
+
+#: wt-status.c:215
+msgid "  (commit or discard the untracked or modified content in submodules)"
+msgstr "  (valider ou annuler le contenu non suivi ou modifié dans les sous-modules)"
+
+#: wt-status.c:227
+#, c-format
+msgid "  (use \"git %s <file>...\" to include in what will be committed)"
+msgstr "  (utilisez \"git %s <fichier>...\" pour inclure dans ce qui sera validé)"
+
+#: wt-status.c:244
+msgid "bug"
+msgstr "bogue"
+
+#: wt-status.c:249
+msgid "both deleted:"
+msgstr "supprimé des deux côtés :"
+
+#: wt-status.c:250
+msgid "added by us:"
+msgstr "ajouté par nous :"
+
+#: wt-status.c:251
+msgid "deleted by them:"
+msgstr "supprimé par eux :"
+
+#: wt-status.c:252
+msgid "added by them:"
+msgstr "ajouté par eux :"
+
+#: wt-status.c:253
+msgid "deleted by us:"
+msgstr "supprimé par nous :"
+
+#: wt-status.c:254
+msgid "both added:"
+msgstr "ajouté de deux côtés :"
+
+#: wt-status.c:255
+msgid "both modified:"
+msgstr "modifié des deux côtés :"
+
+#: wt-status.c:285
+msgid "new commits, "
+msgstr "nouveaux commits, "
+
+#: wt-status.c:287
+msgid "modified content, "
+msgstr "contenu modifié, "
+
+#: wt-status.c:289
+msgid "untracked content, "
+msgstr "contenu non suivi, "
+
+#: wt-status.c:306
+#, c-format
+msgid "new file:   %s"
+msgstr "nouveau :   %s"
+
+#: wt-status.c:309
+#, c-format
+msgid "copied:     %s -> %s"
+msgstr "copié :     %s -> %s"
+
+#: wt-status.c:312
+#, c-format
+msgid "deleted:    %s"
+msgstr "supprimé :  %s"
+
+#: wt-status.c:315
+#, c-format
+msgid "modified:   %s"
+msgstr "modifié :   %s"
+
+#: wt-status.c:318
+#, c-format
+msgid "renamed:    %s -> %s"
+msgstr "renommé :   %s -> %s"
+
+#: wt-status.c:321
+#, c-format
+msgid "typechange: %s"
+msgstr "nv type :   %s"
+
+#: wt-status.c:324
+#, c-format
+msgid "unknown:    %s"
+msgstr "inconnu :   %s"
+
+#: wt-status.c:327
+#, c-format
+msgid "unmerged:   %s"
+msgstr "non fus. :  %s"
+
+#: wt-status.c:330
+#, c-format
+msgid "bug: unhandled diff status %c"
+msgstr "bogue : état de diff non géré %c"
+
+#: wt-status.c:803
+msgid "You have unmerged paths."
+msgstr "Vous avez des chemins non fusionnés."
+
+#: wt-status.c:806 wt-status.c:958
+msgid "  (fix conflicts and run \"git commit\")"
+msgstr "  (réglez les conflits et lancez \"git commit\")"
+
+#: wt-status.c:809
+msgid "All conflicts fixed but you are still merging."
+msgstr "Tous les conflits sont réglés mais la fusion n'est pas terminée."
+
+#: wt-status.c:812
+msgid "  (use \"git commit\" to conclude merge)"
+msgstr "  (utilisez \"git commit\" pour terminer la fusion)"
+
+#: wt-status.c:822
+msgid "You are in the middle of an am session."
+msgstr "Vous êtes au milieu d'une session am."
+
+#: wt-status.c:825
+msgid "The current patch is empty."
+msgstr "Le patch actuel est vide."
+
+#: wt-status.c:829
+msgid "  (fix conflicts and then run \"git am --resolved\")"
+msgstr "  (réglez les conflits puis lancez \"git am --resolved\")"
+
+#: wt-status.c:831
+msgid "  (use \"git am --skip\" to skip this patch)"
+msgstr "  (utilisez \"git am --skip\" pour sauter ce patch)"
+
+#: wt-status.c:833
+msgid "  (use \"git am --abort\" to restore the original branch)"
+msgstr "  (utilisez \"git am --abort\" pour restaurer la branche d'origine)"
+
+#: wt-status.c:893 wt-status.c:910
+#, c-format
+msgid "You are currently rebasing branch '%s' on '%s'."
+msgstr "Vous êtes en train de rebaser la branche '%s' sur '%s'."
+
+#: wt-status.c:898 wt-status.c:915
+msgid "You are currently rebasing."
+msgstr "Vous êtes en train de rebaser."
+
+#: wt-status.c:901
+msgid "  (fix conflicts and then run \"git rebase --continue\")"
+msgstr "  (résolvez les conflits puis lancez \"git rebase --continue\")"
+
+#: wt-status.c:903
+msgid "  (use \"git rebase --skip\" to skip this patch)"
+msgstr "  (utilisez \"git rebase --skip\" pour sauter ce patch)"
+
+#: wt-status.c:905
+msgid "  (use \"git rebase --abort\" to check out the original branch)"
+msgstr "  (utilisez \"git rebase --abort\" pour extraire la branche d'origine)"
+
+#: wt-status.c:918
+msgid "  (all conflicts fixed: run \"git rebase --continue\")"
+msgstr "  (tous les conflits sont résolus : lancez \"git rebase --continue\")"
+
+#: wt-status.c:922
+#, c-format
+msgid ""
+"You are currently splitting a commit while rebasing branch '%s' on '%s'."
+msgstr "Vous êtes actuellement en train de fractionner un commit pendant un rebasage de la branche '%s' sur '%s'."
+
+#: wt-status.c:927
+msgid "You are currently splitting a commit during a rebase."
+msgstr "Vous êtes actuellement en train de fractionner un commit pendant un rebasage."
+
+#: wt-status.c:930
+msgid "  (Once your working directory is clean, run \"git rebase --continue\")"
+msgstr "  (Une fois la copie de travail nettoyée, lancez \"git rebase --continue\")"
+
+#: wt-status.c:934
+#, c-format
+msgid "You are currently editing a commit while rebasing branch '%s' on '%s'."
+msgstr "Vous êtes actuellement en train d'éditer un commit pendant un rebasage de la branche '%s' sur '%s'."
+
+#: wt-status.c:939
+msgid "You are currently editing a commit during a rebase."
+msgstr "Vous êtes actuellement en train d'éditer un commit pendant un rebasage."
+
+#: wt-status.c:942
+msgid "  (use \"git commit --amend\" to amend the current commit)"
+msgstr "  (utilisez \"git commit --amend\" pour corriger le commit actuel)"
+
+#: wt-status.c:944
+msgid ""
+"  (use \"git rebase --continue\" once you are satisfied with your changes)"
+msgstr "  (utilisez \"git rebase --continue\" quand vous êtes satisfait de vos modifications)"
+
+#: wt-status.c:954
+msgid "You are currently cherry-picking."
+msgstr "Vous êtes actuellement en train de picorer."
+
+#: wt-status.c:961
+msgid "  (all conflicts fixed: run \"git commit\")"
+msgstr "  (tous les conflits sont résolus : lancez \"git commit\")"
+
+#: wt-status.c:970
+#, c-format
+msgid "You are currently reverting commit %s."
+msgstr "Vous êtes actuellement en train de rétablir le commit %s."
+
+#: wt-status.c:975
+msgid "  (fix conflicts and run \"git revert --continue\")"
+msgstr "  (résolvez les conflits et lancez \"git revert --continue\")"
+
+#: wt-status.c:978
+msgid "  (all conflicts fixed: run \"git revert --continue\")"
+msgstr "  (tous les conflits sont résolus : lancez \"git revert --continue\")"
+
+#: wt-status.c:980
+msgid "  (use \"git revert --abort\" to cancel the revert operation)"
+msgstr "  (utilisez \"git revert --abort\" pour annuler le rétablissement)"
+
+#: wt-status.c:991
+#, c-format
+msgid "You are currently bisecting, started from branch '%s'."
+msgstr "Vous êtes en cours de bissection, depuis la branche '%s'."
+
+#: wt-status.c:995
+msgid "You are currently bisecting."
+msgstr "Vous êtes en cours de bissection."
+
+#: wt-status.c:998
+msgid "  (use \"git bisect reset\" to get back to the original branch)"
+msgstr "  (utilisez \"git bisect reset\" pour revenir à la branche d'origine)"
+
+#: wt-status.c:1173
+msgid "On branch "
+msgstr "Sur la branche "
+
+#: wt-status.c:1184
+msgid "HEAD detached at "
+msgstr "HEAD détachée sur "
+
+#: wt-status.c:1186
+msgid "HEAD detached from "
+msgstr "HEAD détachée depuis "
+
+#: wt-status.c:1189
+msgid "Not currently on any branch."
+msgstr "Actuellement sur aucun branche."
+
+#: wt-status.c:1206
+msgid "Initial commit"
+msgstr "Validation initiale"
+
+#: wt-status.c:1220
+msgid "Untracked files"
+msgstr "Fichiers non suivis"
+
+#: wt-status.c:1222
+msgid "Ignored files"
+msgstr "Fichiers ignorés"
+
+#: wt-status.c:1226
+#, c-format
+msgid ""
+"It took %.2f seconds to enumerate untracked files. 'status -uno'\n"
+"may speed it up, but you have to be careful not to forget to add\n"
+"new files yourself (see 'git help status')."
+msgstr "L'énumération des fichiers non suivis a duré %.2f secondes. 'status -uno'\n"
+"peut l'accélerer, mais vous devez alors faire attention à ne pas\n"
+"oublier d'ajouter les nouveaux fichiers par vous-même (voir 'git help status')."
+
+#: wt-status.c:1232
+#, c-format
+msgid "Untracked files not listed%s"
+msgstr "Fichiers non suivis non listés%s"
+
+#: wt-status.c:1234
+msgid " (use -u option to show untracked files)"
+msgstr " (utilisez -u pour afficher les fichiers non suivis)"
+
+#: wt-status.c:1240
+msgid "No changes"
+msgstr "Aucune modification"
+
+#: wt-status.c:1245
+#, c-format
+msgid "no changes added to commit (use \"git add\" and/or \"git commit -a\")\n"
+msgstr "aucune modification n'a été ajoutée à la validation (utilisez \"git add\" ou \"git commit -a\")\n"
+
+#: wt-status.c:1248
+#, c-format
+msgid "no changes added to commit\n"
+msgstr "aucune modification ajoutée à la validation\n"
+
+#: wt-status.c:1251
+#, c-format
+msgid ""
+"nothing added to commit but untracked files present (use \"git add\" to "
+"track)\n"
+msgstr "aucune modification ajoutée à la validation mais des fichiers non suivis sont présents (utilisez \"git add\" pour les suivre)\n"
+
+#: wt-status.c:1254
+#, c-format
+msgid "nothing added to commit but untracked files present\n"
+msgstr "aucune modification ajoutée à la validation mais des fichiers non suivis sont présents\n"
+
+#: wt-status.c:1257
+#, c-format
+msgid "nothing to commit (create/copy files and use \"git add\" to track)\n"
+msgstr "rien à valider (créez/copiez des fichiers et utilisez \"git add\" pour les suivre)\n"
+
+#: wt-status.c:1260 wt-status.c:1265
+#, c-format
+msgid "nothing to commit\n"
+msgstr "rien à valider\n"
+
+#: wt-status.c:1263
+#, c-format
+msgid "nothing to commit (use -u to show untracked files)\n"
+msgstr "rien à valider (utilisez -u pour afficher les fichiers non suivis)\n"
+
+#: wt-status.c:1267
+#, c-format
+msgid "nothing to commit, working directory clean\n"
+msgstr "rien à valider, la copie de travail est propre\n"
+
+#: wt-status.c:1375
+msgid "HEAD (no branch)"
+msgstr "HEAD (aucune branche)"
+
+#: wt-status.c:1381
+msgid "Initial commit on "
+msgstr "Validation initiale sur "
+
+#: wt-status.c:1396
+msgid "behind "
+msgstr "derrière "
+
+#: wt-status.c:1399 wt-status.c:1402
+msgid "ahead "
+msgstr "devant "
+
+#: wt-status.c:1404
+msgid ", behind "
+msgstr ", derrière "
+
+#: compat/precompose_utf8.c:58 builtin/clone.c:352
+#, c-format
+msgid "failed to unlink '%s'"
+msgstr "echec lors de l'unlink de '%s'"
+
+#: builtin/add.c:20
+msgid "git add [options] [--] <pathspec>..."
+msgstr "git add [options] [--] <chemin>..."
+
+#.
+#. * To be consistent with "git add -p" and most Git
+#. * commands, we should default to being tree-wide, but
+#. * this is not the original behavior and can't be
+#. * changed until users trained themselves not to type
+#. * "git add -u" or "git add -A". For now, we warn and
+#. * keep the old behavior. Later, the behavior can be changed
+#. * to tree-wide, keeping the warning for a while, and
+#. * eventually we can drop the warning.
+#.
+#: builtin/add.c:58
+#, c-format
+msgid ""
+"The behavior of 'git add %s (or %s)' with no path argument from a\n"
+"subdirectory of the tree will change in Git 2.0 and should not be used "
+"anymore.\n"
+"To add content for the whole tree, run:\n"
+"\n"
+"  git add %s :/\n"
+"  (or git add %s :/)\n"
+"\n"
+"To restrict the command to the current directory, run:\n"
+"\n"
+"  git add %s .\n"
+"  (or git add %s .)\n"
+"\n"
+"With the current Git version, the command is restricted to the current "
+"directory.\n"
+msgstr ""
+"Le comportement de 'git add %s (ou %s)' sans argument de chemin depuis un\n"
+"sous-répertoire du projet va changer dans Git 2.0 et ne doit plus être utilisé.\n"
+"Pour ajouter le contenu de toute l'arborescence, lancez :\n"
+"\n"
+"  git add %s :/\n"
+"  (ou git add %s :/)\n"
+"\n"
+"Pour restreindre la commande au répertoire courant, lancez :\n"
+"\n"
+"  git add %s .\n"
+"  (ou git add %s .)\n"
+"\n"
+"Avec la version actuelle de Git, la commande est restreinte au répertoire courant.\n"
+
+#: builtin/add.c:100
+#, c-format
+msgid ""
+"You ran 'git add' with neither '-A (--all)' or '--ignore-removal',\n"
+"whose behaviour will change in Git 2.0 with respect to paths you removed.\n"
+"Paths like '%s' that are\n"
+"removed from your working tree are ignored with this version of Git.\n"
+"\n"
+"* 'git add --ignore-removal <pathspec>', which is the current default,\n"
+"  ignores paths you removed from your working tree.\n"
+"\n"
+"* 'git add --all <pathspec>' will let you also record the removals.\n"
+"\n"
+"Run 'git status' to check the paths you removed from your working tree.\n"
+msgstr ""
+"Vous avez lancé 'git add' sans '-A (--all)' ni '--ignore-removal',\n"
+"dont le comportement va changer dans Git 2.0 avec le respect des chemins que vous supprimez.\n"
+"Les chemins tels que '%s' qui ont été\n"
+"retirés de votre copie de travail sont ignorés avec cette version de Git.\n"
+"\n"
+"* 'git add --ignore-removal <chemin>', qui est l'option par défaut actuelle,\n"
+"  ignore les chemins que vous avez supprimés de votre copie de travail.\n"
+"\n"
+"* 'git add --all <chemin>' permet d'enregistrer aussi les suppressions.\n"
+"\n"
+"Lancez 'git status' pour vérifier les chemins que vous avez supprimés de votre copie de travail.\n"
+
+#: builtin/add.c:144
+#, c-format
+msgid "unexpected diff status %c"
+msgstr "status de diff inattendu %c"
+
+#: builtin/add.c:149 builtin/commit.c:233
+msgid "updating files failed"
+msgstr "échec de la mise à jour des fichiers"
+
+#: builtin/add.c:163
+#, c-format
+msgid "remove '%s'\n"
+msgstr "suppression de '%s'\n"
+
+#: builtin/add.c:253
+msgid "Unstaged changes after refreshing the index:"
+msgstr "Modifications non indexées après rafraîchissement de l'index :"
+
+#: builtin/add.c:256 builtin/add.c:572 builtin/rm.c:275
+#, c-format
+msgid "pathspec '%s' did not match any files"
+msgstr "le chemin '%s' ne correspond à aucun fichier"
+
+#: builtin/add.c:339
+msgid "Could not read the index"
+msgstr "Impossible de lire l'index"
+
+#: builtin/add.c:349
+#, c-format
+msgid "Could not open '%s' for writing."
+msgstr "Impossible d'ouvrir '%s' en écriture."
+
+#: builtin/add.c:353
+msgid "Could not write patch"
+msgstr "Impossible d'écrire le patch"
+
+#: builtin/add.c:358
+#, c-format
+msgid "Could not stat '%s'"
+msgstr "Stat de '%s' impossible"
+
+#: builtin/add.c:360
+msgid "Empty patch. Aborted."
+msgstr "Patch vide. Abandon."
+
+#: builtin/add.c:366
+#, c-format
+msgid "Could not apply '%s'"
+msgstr "Impossible d'appliquer '%s'"
+
+#: builtin/add.c:376
+msgid "The following paths are ignored by one of your .gitignore files:\n"
+msgstr "Les chemins suivants sont ignorés par un de vos fichiers .gitignore :\n"
+
+#: builtin/add.c:393 builtin/clean.c:161 builtin/fetch.c:78 builtin/mv.c:63
+#: builtin/prune-packed.c:76 builtin/push.c:425 builtin/remote.c:1253
+#: builtin/rm.c:206
+msgid "dry run"
+msgstr "à vide"
+
+#: builtin/add.c:394 builtin/apply.c:4409 builtin/check-ignore.c:19
+#: builtin/commit.c:1152 builtin/count-objects.c:95 builtin/fsck.c:613
+#: builtin/log.c:1518 builtin/mv.c:62 builtin/read-tree.c:112
+msgid "be verbose"
+msgstr "mode verbeux"
+
+#: builtin/add.c:396
+msgid "interactive picking"
+msgstr "sélection interactive"
+
+#: builtin/add.c:397 builtin/checkout.c:1063 builtin/reset.c:258
+msgid "select hunks interactively"
+msgstr "sélection interactive des sections"
+
+#: builtin/add.c:398
+msgid "edit current diff and apply"
+msgstr "édition du diff actuel et application"
+
+#: builtin/add.c:399
+msgid "allow adding otherwise ignored files"
+msgstr "permettre l'ajout de fichiers ignorés"
+
+#: builtin/add.c:400
+msgid "update tracked files"
+msgstr "mettre à jour les fichiers suivis"
+
+#: builtin/add.c:401
+msgid "record only the fact that the path will be added later"
+msgstr "enregistrer seulement le fait que le chemin sera ajouté plus tard"
+
+#: builtin/add.c:402
+msgid "add changes from all tracked and untracked files"
+msgstr "ajouter les modifications de tous les fichiers suivis et non suivis"
+
+#. takes no arguments
+#: builtin/add.c:405
+msgid "ignore paths removed in the working tree (same as --no-all)"
+msgstr "ignorer les chemins effacés dans la copie de travail (identique à --no-all)"
+
+#: builtin/add.c:407
+msgid "don't add, only refresh the index"
+msgstr "ne pas ajouter, juste rafraîchir l'index"
+
+#: builtin/add.c:408
+msgid "just skip files which cannot be added because of errors"
+msgstr "sauter seulement les fichiers qui ne peuvent pas être ajoutés du fait d'erreurs"
+
+#: builtin/add.c:409
+msgid "check if - even missing - files are ignored in dry run"
+msgstr "vérifier si des fichiers - même manquants - sont ignorés, à vide"
+
+#: builtin/add.c:431
+#, c-format
+msgid "Use -f if you really want to add them.\n"
+msgstr "Utilisez -f si vous voulez réellement les ajouter.\n"
+
+#: builtin/add.c:432
+msgid "no files added"
+msgstr "aucun fichier ajouté"
+
+#: builtin/add.c:438
+msgid "adding files failed"
+msgstr "échec de l'ajout de fichiers"
+
+#: builtin/add.c:477
+msgid "-A and -u are mutually incompatible"
+msgstr "-A et -u sont mutuellement incompatibles"
+
+#: builtin/add.c:495
+msgid "Option --ignore-missing can only be used together with --dry-run"
+msgstr "L'option --ignore-missing ne peut être utilisée qu'en complément de --dry-run"
+
+#: builtin/add.c:525
+#, c-format
+msgid "Nothing specified, nothing added.\n"
+msgstr "Rien de spécifié, rien n'a été ajouté.\n"
+
+#: builtin/add.c:526
+#, c-format
+msgid "Maybe you wanted to say 'git add .'?\n"
+msgstr "Vous vouliez sûrement dire 'git add .' ?\n"
+
+#: builtin/add.c:532 builtin/check-ignore.c:66 builtin/clean.c:204
+#: builtin/commit.c:293 builtin/mv.c:82 builtin/rm.c:235
+msgid "index file corrupt"
+msgstr "fichier d'index corrompu"
+
+#: builtin/add.c:604 builtin/apply.c:4505 builtin/mv.c:229 builtin/rm.c:370
+msgid "Unable to write new index file"
+msgstr "Impossible d'écrire le nouveau fichier d'index"
+
+#: builtin/apply.c:57
+msgid "git apply [options] [<patch>...]"
+msgstr "git apply [options] [<patch>...]"
+
+#: builtin/apply.c:110
+#, c-format
+msgid "unrecognized whitespace option '%s'"
+msgstr "option d'espace non reconnue '%s'"
+
+#: builtin/apply.c:125
+#, c-format
+msgid "unrecognized whitespace ignore option '%s'"
+msgstr "option d'ignorance d'espce non reconnue '%s'"
+
+#: builtin/apply.c:823
+#, c-format
+msgid "Cannot prepare timestamp regexp %s"
+msgstr "Impossible de préparer la regexp d'horodatage %s"
+
+#: builtin/apply.c:832
+#, c-format
+msgid "regexec returned %d for input: %s"
+msgstr "regexec a retourné %d pour l'entrée : %s"
+
+#: builtin/apply.c:913
+#, c-format
+msgid "unable to find filename in patch at line %d"
+msgstr "nom de fichier du patch introuvable à la ligne %d"
+
+#: builtin/apply.c:945
+#, c-format
+msgid "git apply: bad git-diff - expected /dev/null, got %s on line %d"
+msgstr "git apply : mauvais format de git-diff - /dev/null attendu, %s trouvé à la ligne %d"
+
+#: builtin/apply.c:949
+#, c-format
+msgid "git apply: bad git-diff - inconsistent new filename on line %d"
+msgstr "git apply : mauvais format de git-diff - nouveau nom de fichier inconsistant à la ligne %d"
+
+#: builtin/apply.c:950
+#, c-format
+msgid "git apply: bad git-diff - inconsistent old filename on line %d"
+msgstr "git apply : mauvais format de git-diff - ancien nom de fichier inconsistant à la ligne %d"
+
+#: builtin/apply.c:957
+#, c-format
+msgid "git apply: bad git-diff - expected /dev/null on line %d"
+msgstr "git apply : mauvais format de git-diff - /dev/null attendu à la ligne %d"
+
+#: builtin/apply.c:1422
+#, c-format
+msgid "recount: unexpected line: %.*s"
+msgstr "recount : ligne inattendue : %.*s"
+
+#: builtin/apply.c:1479
+#, c-format
+msgid "patch fragment without header at line %d: %.*s"
+msgstr "fragment de patch sans en-tête à la ligne %d : %.*s"
+
+#: builtin/apply.c:1496
+#, c-format
+msgid ""
+"git diff header lacks filename information when removing %d leading pathname "
+"component (line %d)"
+msgid_plural ""
+"git diff header lacks filename information when removing %d leading pathname "
+"components (line %d)"
+msgstr[0] "information de nom de fichier manquante dans l'en-tête de git diff lors de la suppression de %d composant de préfixe de chemin (ligne %d)"
+msgstr[1] "information de nom de fichier manquante dans l'en-tête de git diff lors de la suppression de %d composants de préfixe de chemin (ligne %d)"
+
+#: builtin/apply.c:1656
+msgid "new file depends on old contents"
+msgstr "le nouveau fichier dépend de contenus anciens"
+
+#: builtin/apply.c:1658
+msgid "deleted file still has contents"
+msgstr "le fichier supprimé a encore du contenu"
+
+#: builtin/apply.c:1684
+#, c-format
+msgid "corrupt patch at line %d"
+msgstr "patch corrompu à la ligne %d"
+
+#: builtin/apply.c:1720
+#, c-format
+msgid "new file %s depends on old contents"
+msgstr "le nouveau fichier %s dépend de contenus anciens"
+
+#: builtin/apply.c:1722
+#, c-format
+msgid "deleted file %s still has contents"
+msgstr "le fichier supprimé %s a encore du contenu"
+
+#: builtin/apply.c:1725
+#, c-format
+msgid "** warning: file %s becomes empty but is not deleted"
+msgstr "** attention : le fichier %s devient vide mais n'est pas supprimé"
+
+#: builtin/apply.c:1871
+#, c-format
+msgid "corrupt binary patch at line %d: %.*s"
+msgstr "patch binaire corrompu à la ligne %d : %.*s"
+
+#. there has to be one hunk (forward hunk)
+#: builtin/apply.c:1900
+#, c-format
+msgid "unrecognized binary patch at line %d"
+msgstr "patch binaire non reconnu à la ligne %d"
+
+#: builtin/apply.c:1986
+#, c-format
+msgid "patch with only garbage at line %d"
+msgstr "patch totalement incompréhensible à la ligne %d"
+
+#: builtin/apply.c:2076
+#, c-format
+msgid "unable to read symlink %s"
+msgstr "lecture du lien symbolique %s impossible"
+
+#: builtin/apply.c:2080
+#, c-format
+msgid "unable to open or read %s"
+msgstr "ouverture ou lecture de %s impossible"
+
+#: builtin/apply.c:2688
+#, c-format
+msgid "invalid start of line: '%c'"
+msgstr "début de ligne invalide : '%c'"
+
+#: builtin/apply.c:2806
+#, c-format
+msgid "Hunk #%d succeeded at %d (offset %d line)."
+msgid_plural "Hunk #%d succeeded at %d (offset %d lines)."
+msgstr[0] "La section n°%d a réussi à la ligne %d (offset %d ligne)."
+msgstr[1] "La section n°%d a réussi à la ligne %d (offset %d lignes)."
+
+#: builtin/apply.c:2818
+#, c-format
+msgid "Context reduced to (%ld/%ld) to apply fragment at %d"
+msgstr "Contexte réduit à (%ld/%ld) pour appliquer le fragment à la ligne %d"
+
+#: builtin/apply.c:2824
+#, c-format
+msgid ""
+"while searching for:\n"
+"%.*s"
+msgstr "pendant la recherche de :\n"
+"%.*s"
+
+#: builtin/apply.c:2843
+#, c-format
+msgid "missing binary patch data for '%s'"
+msgstr "données de patch binaire manquantes pour '%s'"
+
+#: builtin/apply.c:2946
+#, c-format
+msgid "binary patch does not apply to '%s'"
+msgstr "le patch binaire ne s'applique par correctement à '%s'"
+
+#: builtin/apply.c:2952
+#, c-format
+msgid "binary patch to '%s' creates incorrect result (expecting %s, got %s)"
+msgstr "le patch binaire sur '%s' crée un résultat incorrect (%s attendu, mais %s trouvé)"
+
+#: builtin/apply.c:2973
+#, c-format
+msgid "patch failed: %s:%ld"
+msgstr "le patch a échoué : %s:%ld"
+
+#: builtin/apply.c:3095
+#, c-format
+msgid "cannot checkout %s"
+msgstr "extraction de %s impossible"
+
+#: builtin/apply.c:3140 builtin/apply.c:3149 builtin/apply.c:3193
+#, c-format
+msgid "read of %s failed"
+msgstr "echec de la lecture de %s"
+
+#: builtin/apply.c:3173 builtin/apply.c:3395
+#, c-format
+msgid "path %s has been renamed/deleted"
+msgstr "le chemin %s a été renommé/supprimé"
+
+#: builtin/apply.c:3254 builtin/apply.c:3409
+#, c-format
+msgid "%s: does not exist in index"
+msgstr "%s : n'existe pas dans l'index"
+
+#: builtin/apply.c:3258 builtin/apply.c:3401 builtin/apply.c:3423
+#, c-format
+msgid "%s: %s"
+msgstr "%s : %s"
+
+#: builtin/apply.c:3263 builtin/apply.c:3417
+#, c-format
+msgid "%s: does not match index"
+msgstr "%s : ne correspond pas à l'index"
+
+#: builtin/apply.c:3365
+msgid "removal patch leaves file contents"
+msgstr "le patch de suppression laisse un contenu dans le fichier"
+
+#: builtin/apply.c:3434
+#, c-format
+msgid "%s: wrong type"
+msgstr "%s : type erroné"
+
+#: builtin/apply.c:3436
+#, c-format
+msgid "%s has type %o, expected %o"
+msgstr "%s est de type %o, mais %o attendu"
+
+#: builtin/apply.c:3537
+#, c-format
+msgid "%s: already exists in index"
+msgstr "%s : existe déjà dans l'index"
+
+#: builtin/apply.c:3540
+#, c-format
+msgid "%s: already exists in working directory"
+msgstr "%s : existe déjà dans la copie de travail"
+
+#: builtin/apply.c:3560
+#, c-format
+msgid "new mode (%o) of %s does not match old mode (%o)"
+msgstr "le nouveau mode (%o) de %s ne correspond pas à l'ancien mode (%o)"
+
+#: builtin/apply.c:3565
+#, c-format
+msgid "new mode (%o) of %s does not match old mode (%o) of %s"
+msgstr "le nouveau mode (%o) de %s ne correspond pas à l'ancien mode (%o) de %s"
+
+#: builtin/apply.c:3573
+#, c-format
+msgid "%s: patch does not apply"
+msgstr "%s : le patch ne s'applique pas"
+
+#: builtin/apply.c:3586
+#, c-format
+msgid "Checking patch %s..."
+msgstr "Vérification du patch %s..."
+
+#: builtin/apply.c:3679 builtin/checkout.c:216 builtin/reset.c:124
+#, c-format
+msgid "make_cache_entry failed for path '%s'"
+msgstr "echec de make_cache_entry pour le chemin '%s'"
+
+#: builtin/apply.c:3822
+#, c-format
+msgid "unable to remove %s from index"
+msgstr "suppression de %s dans l'index impossible"
+
+#: builtin/apply.c:3850
+#, c-format
+msgid "corrupt patch for subproject %s"
+msgstr "patch corrompu pour le sous-projet %s"
+
+#: builtin/apply.c:3854
+#, c-format
+msgid "unable to stat newly created file '%s'"
+msgstr "stat du fichier nouvellement créé '%s' impossible"
+
+#: builtin/apply.c:3859
+#, c-format
+msgid "unable to create backing store for newly created file %s"
+msgstr "création du magasin de stockage pour le fichier nouvellement créé %s impossible"
+
+#: builtin/apply.c:3862 builtin/apply.c:3970
+#, c-format
+msgid "unable to add cache entry for %s"
+msgstr "ajout de l'entrée de cache %s impossible"
+
+#: builtin/apply.c:3895
+#, c-format
+msgid "closing file '%s'"
+msgstr "fermeture du fichier '%s'"
+
+#: builtin/apply.c:3944
+#, c-format
+msgid "unable to write file '%s' mode %o"
+msgstr "écriture du fichier '%s' mode %o impossible"
+
+#: builtin/apply.c:4031
+#, c-format
+msgid "Applied patch %s cleanly."
+msgstr "Patch %s appliqué proprement."
+
+#: builtin/apply.c:4039
+msgid "internal error"
+msgstr "erreur interne"
+
+#. Say this even without --verbose
+#: builtin/apply.c:4042
+#, c-format
+msgid "Applying patch %%s with %d reject..."
+msgid_plural "Applying patch %%s with %d rejects..."
+msgstr[0] "Application du patch %%s avec %d rejet..."
+msgstr[1] "Application du patch %%s avec %d rejets..."
+
+#: builtin/apply.c:4052
+#, c-format
+msgid "truncating .rej filename to %.*s.rej"
+msgstr "troncature du nom de fichier .rej en %.*s.rej"
+
+#: builtin/apply.c:4073
+#, c-format
+msgid "Hunk #%d applied cleanly."
+msgstr "Section n°%d appliquée proprement."
+
+#: builtin/apply.c:4076
+#, c-format
+msgid "Rejected hunk #%d."
+msgstr "Section n°%d rejetée."
+
+#: builtin/apply.c:4226
+msgid "unrecognized input"
+msgstr "entrée non reconnue"
+
+#: builtin/apply.c:4237
+msgid "unable to read index file"
+msgstr "lecture du fichier d'index impossible"
+
+#: builtin/apply.c:4356 builtin/apply.c:4359 builtin/clone.c:92
+#: builtin/fetch.c:63
+msgid "path"
+msgstr "chemin"
+
+#: builtin/apply.c:4357
+msgid "don't apply changes matching the given path"
+msgstr "ne pas appliquer les modifications qui correspondent au chemin donné"
+
+#: builtin/apply.c:4360
+msgid "apply changes matching the given path"
+msgstr "appliquer les modifications qui correspondent au chemin donné"
+
+#: builtin/apply.c:4362
+msgid "num"
+msgstr "num"
+
+#: builtin/apply.c:4363
+msgid "remove <num> leading slashes from traditional diff paths"
+msgstr "supprimer <num> barres obliques des chemins traditionnels de diff"
+
+#: builtin/apply.c:4366
+msgid "ignore additions made by the patch"
+msgstr "ignorer les additions réalisées par le patch"
+
+#: builtin/apply.c:4368
+msgid "instead of applying the patch, output diffstat for the input"
+msgstr "au lieu d'appliquer le patch, afficher le diffstat de l'entrée"
+
+#: builtin/apply.c:4372
+msgid "show number of added and deleted lines in decimal notation"
+msgstr "afficher le nombre de lignes ajoutées et supprimées en notation décimale"
+
+#: builtin/apply.c:4374
+msgid "instead of applying the patch, output a summary for the input"
+msgstr "au lieu d'appliquer le patch, afficher un résumer de l'entrée"
+
+#: builtin/apply.c:4376
+msgid "instead of applying the patch, see if the patch is applicable"
+msgstr "au lieu d'appliquer le patch, voir si le patch est applicable"
+
+#: builtin/apply.c:4378
+msgid "make sure the patch is applicable to the current index"
+msgstr "s'assurer que le patch est applicable sur l'index actuel"
+
+#: builtin/apply.c:4380
+msgid "apply a patch without touching the working tree"
+msgstr "appliquer les patch sans toucher à la copie de travail"
+
+#: builtin/apply.c:4382
+msgid "also apply the patch (use with --stat/--summary/--check)"
+msgstr "appliquer aussi le patch (à utiliser avec ---stat/--summary/--check)"
+
+#: builtin/apply.c:4384
+msgid "attempt three-way merge if a patch does not apply"
+msgstr "tenter une fusion à 3 points si le patch ne s'applique pas proprement"
+
+#: builtin/apply.c:4386
+msgid "build a temporary index based on embedded index information"
+msgstr "construire un index temporaire fondé sur l'information de l'index embarqué"
+
+#: builtin/apply.c:4388 builtin/checkout-index.c:197 builtin/ls-files.c:456
+msgid "paths are separated with NUL character"
+msgstr "les chemins sont séparés par un caractère NUL"
+
+#: builtin/apply.c:4391
+msgid "ensure at least <n> lines of context match"
+msgstr "s'assurer d'au moins <n> lignes de correspondance de contexte"
+
+#: builtin/apply.c:4392
+msgid "action"
+msgstr "action"
+
+#: builtin/apply.c:4393
+msgid "detect new or modified lines that have whitespace errors"
+msgstr "détecter des lignes nouvelles ou modifiées qui contiennent des erreurs d'espace"
+
+#: builtin/apply.c:4396 builtin/apply.c:4399
+msgid "ignore changes in whitespace when finding context"
+msgstr "ignorer des modifications d'espace lors de la recherche de contexte"
+
+#: builtin/apply.c:4402
+msgid "apply the patch in reverse"
+msgstr "appliquer le patch en sens inverse"
+
+#: builtin/apply.c:4404
+msgid "don't expect at least one line of context"
+msgstr "ne pas s'attendre à au moins une ligne de contexte"
+
+#: builtin/apply.c:4406
+msgid "leave the rejected hunks in corresponding *.rej files"
+msgstr "laisser les sections rejetées dans les fichiers *.rej correspondants"
+
+#: builtin/apply.c:4408
+msgid "allow overlapping hunks"
+msgstr "accepter les recouvrements de sections"
+
+#: builtin/apply.c:4411
+msgid "tolerate incorrectly detected missing new-line at the end of file"
+msgstr "tolérer des erreurs de détection de retours chariot manquants en fin de fichier"
+
+#: builtin/apply.c:4414
+msgid "do not trust the line counts in the hunk headers"
+msgstr "ne pas se fier au compte de lignes dans les en-têtes de section"
+
+#: builtin/apply.c:4416
+msgid "root"
+msgstr "racine"
+
+#: builtin/apply.c:4417
+msgid "prepend <root> to all filenames"
+msgstr "préfixer tous les noms de fichier avec <root>"
+
+#: builtin/apply.c:4439
+msgid "--3way outside a repository"
+msgstr "--3way hors d'un dépôt"
+
+#: builtin/apply.c:4447
+msgid "--index outside a repository"
+msgstr "--index hors d'un dépôt"
+
+#: builtin/apply.c:4450
+msgid "--cached outside a repository"
+msgstr "--cached hors d'un dépôt"
+
+#: builtin/apply.c:4466
+#, c-format
+msgid "can't open patch '%s'"
+msgstr "ouverture impossible du patch '%s'"
+
+#: builtin/apply.c:4480
+#, c-format
+msgid "squelched %d whitespace error"
+msgid_plural "squelched %d whitespace errors"
+msgstr[0] "%d erreur d'espace ignorée"
+msgstr[1] "%d erreurs d'espace ignorées"
+
+#: builtin/apply.c:4486 builtin/apply.c:4496
+#, c-format
+msgid "%d line adds whitespace errors."
+msgid_plural "%d lines add whitespace errors."
+msgstr[0] "%d ligne a ajouté des erreurs d'espace."
+msgstr[1] "%d lignes ont ajouté des erreurs d'espace."
+
+#: builtin/archive.c:17
+#, c-format
+msgid "could not create archive file '%s'"
+msgstr "création impossible du fichier d'archive '%s'"
+
+#: builtin/archive.c:20
+msgid "could not redirect output"
+msgstr "impossible de rediriger la sortie"
+
+#: builtin/archive.c:37
+msgid "git archive: Remote with no URL"
+msgstr "git archive : Dépôt distant sans URL"
+
+#: builtin/archive.c:58
+msgid "git archive: expected ACK/NAK, got EOF"
+msgstr "git archive : ACK/NACK attendu, EOF reçu"
+
+#: builtin/archive.c:61
+#, c-format
+msgid "git archive: NACK %s"
+msgstr "git archive : NACK %s"
+
+#: builtin/archive.c:63
+#, c-format
+msgid "remote error: %s"
+msgstr "erreur distante : %s"
+
+#: builtin/archive.c:64
+msgid "git archive: protocol error"
+msgstr "git archive : erreur de protocole"
+
+#: builtin/archive.c:68
+msgid "git archive: expected a flush"
+msgstr "git archive : vidage attendu"
+
+#: builtin/bisect--helper.c:7
+msgid "git bisect--helper --next-all [--no-checkout]"
+msgstr "git bisect --helper --next-all [--no-checkout]"
+
+#: builtin/bisect--helper.c:17
+msgid "perform 'git bisect next'"
+msgstr "effectuer 'git bisect next'"
+
+#: builtin/bisect--helper.c:19
+msgid "update BISECT_HEAD instead of checking out the current commit"
+msgstr "mettre à jour BISECT_HEAD au lieu d'extraire le commit actuel"
+
+#: builtin/blame.c:25
+msgid "git blame [options] [rev-opts] [rev] [--] file"
+msgstr "git blame [options] [options-de-révision] [rev] [--] fichier"
+
+#: builtin/blame.c:30
+msgid "[rev-opts] are documented in git-rev-list(1)"
+msgstr "[options-de-révision] sont documentés dans git-rev-list(1)"
+
+#: builtin/blame.c:2355
+msgid "Show blame entries as we find them, incrementally"
+msgstr "Montrer les entrée de blâme au fur et à mesure de leur découverte, de manière incrémentale"
+
+#: builtin/blame.c:2356
+msgid "Show blank SHA-1 for boundary commits (Default: off)"
+msgstr "Montrer un SHA-1 blanc pour les commits de limite (Défaut : désactivé)"
+
+#: builtin/blame.c:2357
+msgid "Do not treat root commits as boundaries (Default: off)"
+msgstr "Ne pas traiter les commits racine comme des limites (Défaut : désactivé)"
+
+#: builtin/blame.c:2358
+msgid "Show work cost statistics"
+msgstr "Montrer les statistiques de coût d'activité"
+
+#: builtin/blame.c:2359
+msgid "Show output score for blame entries"
+msgstr "Montrer le score de sortie pour les entrées de blâme"
+
+#: builtin/blame.c:2360
+msgid "Show original filename (Default: auto)"
+msgstr "Montrer les noms de fichier originaux (Défaut : auto)"
+
+#: builtin/blame.c:2361
+msgid "Show original linenumber (Default: off)"
+msgstr "Montrer les numéros de lignes originaux (Défaut : désactivé)"
+
+#: builtin/blame.c:2362
+msgid "Show in a format designed for machine consumption"
+msgstr "Afficher dans un format propice à la consommation par machine"
+
+#: builtin/blame.c:2363
+msgid "Show porcelain format with per-line commit information"
+msgstr "Afficher en format porcelaine avec l'information de commit par ligne"
+
+#: builtin/blame.c:2364
+msgid "Use the same output mode as git-annotate (Default: off)"
+msgstr "Utiliser le même mode de sortie que git-annotate (Défaut : désactivé)"
+
+#: builtin/blame.c:2365
+msgid "Show raw timestamp (Default: off)"
+msgstr "Afficher les horodatages bruts (Défaut: désactivé)"
+
+#: builtin/blame.c:2366
+msgid "Show long commit SHA1 (Default: off)"
+msgstr "Afficher les longs SHA1 de commits (Défaut : désactivé)"
+
+#: builtin/blame.c:2367
+msgid "Suppress author name and timestamp (Default: off)"
+msgstr "Supprimer le nom de l'auteur et l'horodatage (Défaut : désactivé)"
+
+#: builtin/blame.c:2368
+msgid "Show author email instead of name (Default: off)"
+msgstr "Afficher l'e-mail de l'auteur au lieu du nom (Défaut : désactivé)"
+
+#: builtin/blame.c:2369
+msgid "Ignore whitespace differences"
+msgstr "Ignorer les différences d'espace"
+
+#: builtin/blame.c:2370
+msgid "Spend extra cycles to find better match"
+msgstr "Dépenser des cycles supplémentaires pour trouver une meilleure correspondance"
+
+#: builtin/blame.c:2371
+msgid "Use revisions from <file> instead of calling git-rev-list"
+msgstr "Utiliser les révisions du fichier <fichier> au lieu d'appeler git-rev-list"
+
+#: builtin/blame.c:2372
+msgid "Use <file>'s contents as the final image"
+msgstr "Utiliser le contenu de <fichier> comme image finale"
+
+#: builtin/blame.c:2373 builtin/blame.c:2374
+msgid "score"
+msgstr "score"
+
+#: builtin/blame.c:2373
+msgid "Find line copies within and across files"
+msgstr "Trouver les copies de ligne dans et entre les fichiers"
+
+#: builtin/blame.c:2374
+msgid "Find line movements within and across files"
+msgstr "Trouver les mouvements de ligne dans et entre les fichiers"
+
+#: builtin/blame.c:2375
+msgid "n,m"
+msgstr "n,m"
+
+#: builtin/blame.c:2375
+msgid "Process only line range n,m, counting from 1"
+msgstr "Traiter seulement l'intervalle de ligne n,m en commençant le compte à 1"
+
+#: builtin/branch.c:24
+msgid "git branch [options] [-r | -a] [--merged | --no-merged]"
+msgstr "git branch [options] [-r | -a] [--merged | --no-merged]"
+
+#: builtin/branch.c:25
+msgid "git branch [options] [-l] [-f] <branchname> [<start-point>]"
+msgstr "git branch [options] [-l] [-f] <nomdebranch> [<point-de-départ>]"
+
+#: builtin/branch.c:26
+msgid "git branch [options] [-r] (-d | -D) <branchname>..."
+msgstr "git branch [options] [-r] (-d | -D) <nomdebranche>..."
+
+#: builtin/branch.c:27
+msgid "git branch [options] (-m | -M) [<oldbranch>] <newbranch>"
+msgstr "git branch [options] (-m | -M) [<anciennebranche>] <nouvellebranche>"
+
+#: builtin/branch.c:150
+#, c-format
+msgid ""
+"deleting branch '%s' that has been merged to\n"
+"         '%s', but not yet merged to HEAD."
+msgstr ""
+"suppression de la branche '%s' qui a été fusionnée dans\n"
+"         '%s', mais pas dans HEAD."
+
+#: builtin/branch.c:154
+#, c-format
+msgid ""
+"not deleting branch '%s' that is not yet merged to\n"
+"         '%s', even though it is merged to HEAD."
+msgstr ""
+"branche '%s' non supprimée car elle n'a pas été fusionnée dans\n"
+"         '%s', même si elle est fusionnée dans HEAD."
+
+#: builtin/branch.c:168
+#, c-format
+msgid "Couldn't look up commit object for '%s'"
+msgstr "Impossible de rechercher l'objet commit pour '%s'"
+
+#: builtin/branch.c:172
+#, c-format
+msgid ""
+"The branch '%s' is not fully merged.\n"
+"If you are sure you want to delete it, run 'git branch -D %s'."
+msgstr ""
+"La branche '%s' n'est pas totalement fusionnée.\n"
+"Si vous êtes sur que vous voulez la supprimer, lancez 'git branch -D %s'."
+
+#: builtin/branch.c:185
+msgid "Update of config-file failed"
+msgstr "Échec de la mise à jour du fichier de config"
+
+#: builtin/branch.c:213
+msgid "cannot use -a with -d"
+msgstr "impossible d'utiliser -a avec -d"
+
+#: builtin/branch.c:219
+msgid "Couldn't look up commit object for HEAD"
+msgstr "Impossible de rechercher l'objet commit pour HEAD"
+
+#: builtin/branch.c:227
+#, c-format
+msgid "Cannot delete the branch '%s' which you are currently on."
+msgstr "Impossible de supprimer la branche '%s' sur laquelle vous êtes."
+
+#: builtin/branch.c:240
+#, c-format
+msgid "remote branch '%s' not found."
+msgstr "branche distante %s' non trouvée."
+
+#: builtin/branch.c:241
+#, c-format
+msgid "branch '%s' not found."
+msgstr "branche '%s' non trouvée."
+
+#: builtin/branch.c:255
+#, c-format
+msgid "Error deleting remote branch '%s'"
+msgstr "Erreur lors de la suppression de la branche distante '%s'"
+
+#: builtin/branch.c:256
+#, c-format
+msgid "Error deleting branch '%s'"
+msgstr "Erreur lors de la suppression de la branche '%s'"
+
+#: builtin/branch.c:263
+#, c-format
+msgid "Deleted remote branch %s (was %s).\n"
+msgstr "Branche distante %s supprimée (précédemment %s).\n"
+
+#: builtin/branch.c:264
+#, c-format
+msgid "Deleted branch %s (was %s).\n"
+msgstr "Branche %s supprimée (précédemment %s).\n"
+
+#: builtin/branch.c:366
+#, c-format
+msgid "branch '%s' does not point at a commit"
+msgstr "la branche '%s' ne pointe pas sur un commit"
+
+#: builtin/branch.c:453
+#, c-format
+msgid "[%s: behind %d]"
+msgstr "[%s: en retard de %d]"
+
+#: builtin/branch.c:455
+#, c-format
+msgid "[behind %d]"
+msgstr "[en retard de %d]"
+
+#: builtin/branch.c:459
+#, c-format
+msgid "[%s: ahead %d]"
+msgstr "[%s : en avance de %d]"
+
+#: builtin/branch.c:461
+#, c-format
+msgid "[ahead %d]"
+msgstr "[en avance de %d]"
+
+#: builtin/branch.c:464
+#, c-format
+msgid "[%s: ahead %d, behind %d]"
+msgstr "[%s : en avance de %d, en retard de %d]"
+
+#: builtin/branch.c:467
+#, c-format
+msgid "[ahead %d, behind %d]"
+msgstr "[en avance de %d, en retard de %d]"
+
+#: builtin/branch.c:490
+msgid " **** invalid ref ****"
+msgstr " **** référence invalide ****"
+
+#: builtin/branch.c:582
+#, c-format
+msgid "(no branch, rebasing %s)"
+msgstr "(aucune branche, rebasage de %s)"
+
+#: builtin/branch.c:585
+#, c-format
+msgid "(no branch, bisect started on %s)"
+msgstr "(aucune branche, bisect a démarré sur %s)"
+
+#: builtin/branch.c:588
+#, c-format
+msgid "(detached from %s)"
+msgstr "(détaché de %s)"
+
+#: builtin/branch.c:591
+msgid "(no branch)"
+msgstr "(aucune branche)"
+
+#: builtin/branch.c:637
+#, c-format
+msgid "object '%s' does not point to a commit"
+msgstr "l'objet '%s' ne pointe pas sur un commit"
+
+#: builtin/branch.c:669
+msgid "some refs could not be read"
+msgstr "des références n'ont pas pu être lues"
+
+#: builtin/branch.c:682
+msgid "cannot rename the current branch while not on any."
+msgstr "impossible de renommer la branche actuelle, il n'y en a pas."
+
+#: builtin/branch.c:692
+#, c-format
+msgid "Invalid branch name: '%s'"
+msgstr "Nom de branche invalide : '%s'"
+
+#: builtin/branch.c:707
+msgid "Branch rename failed"
+msgstr "Echec de renommage de la branche"
+
+#: builtin/branch.c:711
+#, c-format
+msgid "Renamed a misnamed branch '%s' away"
+msgstr "Renommage d'un branche mal nommée '%s'"
+
+#: builtin/branch.c:715
+#, c-format
+msgid "Branch renamed to %s, but HEAD is not updated!"
+msgstr "La branche a été renommée en %s, mais HEAD n'est pas mise à jour !"
+
+#: builtin/branch.c:722
+msgid "Branch is renamed, but update of config-file failed"
+msgstr "La branche est renommée, mais la mise à jour du fichier de config a échoué"
+
+#: builtin/branch.c:737
+#, c-format
+msgid "malformed object name %s"
+msgstr "nom d'objet malformé %s"
+
+#: builtin/branch.c:761
+#, c-format
+msgid "could not write branch description template: %s"
+msgstr "impossible d'écrire le modèle de description de branche : %s"
+
+#: builtin/branch.c:791
+msgid "Generic options"
+msgstr "Options génériques"
+
+#: builtin/branch.c:793
+msgid "show hash and subject, give twice for upstream branch"
+msgstr "afficher le hachage et le sujet, doublé pour la branche amont"
+
+#: builtin/branch.c:794
+msgid "suppress informational messages"
+msgstr "supprimer les messages d'information"
+
+#: builtin/branch.c:795
+msgid "set up tracking mode (see git-pull(1))"
+msgstr "régler le mode de suivi (voir git-pull(1))"
+
+#: builtin/branch.c:797
+msgid "change upstream info"
+msgstr "modifier l'information amont"
+
+#: builtin/branch.c:801
+msgid "use colored output"
+msgstr "utiliser la coloration dans la sortie"
+
+#: builtin/branch.c:802
+msgid "act on remote-tracking branches"
+msgstr "agir sur les branches de suivi distantes"
+
+#: builtin/branch.c:805 builtin/branch.c:811 builtin/branch.c:832
+#: builtin/branch.c:838 builtin/commit.c:1368 builtin/commit.c:1369
+#: builtin/commit.c:1370 builtin/commit.c:1371 builtin/tag.c:468
+msgid "commit"
+msgstr "valider"
+
+#: builtin/branch.c:806 builtin/branch.c:812
+msgid "print only branches that contain the commit"
+msgstr "afficher seulement les branches qui contiennent le commit"
+
+#: builtin/branch.c:818
+msgid "Specific git-branch actions:"
+msgstr "Actions spécifiques à git-branch :"
+
+#: builtin/branch.c:819
+msgid "list both remote-tracking and local branches"
+msgstr "afficher à la fois les branches de suivi et les branches locales"
+
+#: builtin/branch.c:821
+msgid "delete fully merged branch"
+msgstr "supprimer une branche totalement fusionnée"
+
+#: builtin/branch.c:822
+msgid "delete branch (even if not merged)"
+msgstr "supprimer une branche (même non fusionnée)"
+
+#: builtin/branch.c:823
+msgid "move/rename a branch and its reflog"
+msgstr "déplacer/renommer une branche et son reflog"
+
+#: builtin/branch.c:824
+msgid "move/rename a branch, even if target exists"
+msgstr "déplacer/renommer une branche, même si la cible existe"
+
+#: builtin/branch.c:825
+msgid "list branch names"
+msgstr "afficher les noms des branches"
+
+#: builtin/branch.c:826
+msgid "create the branch's reflog"
+msgstr "créer le reflog de la branche"
+
+#: builtin/branch.c:828
+msgid "edit the description for the branch"
+msgstr "éditer la description de la branche"
+
+#: builtin/branch.c:829
+msgid "force creation (when already exists)"
+msgstr "forcer la création (même si la cible existe)"
+
+#: builtin/branch.c:832
+msgid "print only not merged branches"
+msgstr "afficher seulement les branches non fusionnées"
+
+#: builtin/branch.c:838
+msgid "print only merged branches"
+msgstr "afficher seulement les branches fusionnées"
+
+#: builtin/branch.c:842
+msgid "list branches in columns"
+msgstr "afficher les branches en colonnes"
+
+#: builtin/branch.c:855
+msgid "Failed to resolve HEAD as a valid ref."
+msgstr "Échec de résolution de HEAD comme référence valide."
+
+#: builtin/branch.c:860 builtin/clone.c:619
+msgid "HEAD not found below refs/heads!"
+msgstr "HEAD non trouvée sous refs/heads !"
+
+#: builtin/branch.c:883
+msgid "--column and --verbose are incompatible"
+msgstr "--column et --verbose sont incompatibles"
+
+#: builtin/branch.c:889 builtin/branch.c:928
+msgid "branch name required"
+msgstr "le nom de branche est requis"
+
+#: builtin/branch.c:904
+msgid "Cannot give description to detached HEAD"
+msgstr "Impossible de décrire une HEAD détachée"
+
+#: builtin/branch.c:909
+msgid "cannot edit description of more than one branch"
+msgstr "impossible d'éditer la description de plus d'une branche"
+
+#: builtin/branch.c:916
+#, c-format
+msgid "No commit on branch '%s' yet."
+msgstr "Aucun commit sur la branche '%s'."
+
+#: builtin/branch.c:919
+#, c-format
+msgid "No branch named '%s'."
+msgstr "Aucune branche nommée '%s'."
+
+#: builtin/branch.c:934
+msgid "too many branches for a rename operation"
+msgstr "trop de branches pour une opération de renommage"
+
+#: builtin/branch.c:939
+msgid "too many branches to set new upstream"
+msgstr "trop de branches pour spécifier une branche amont"
+
+#: builtin/branch.c:943
+#, c-format
+msgid ""
+"could not set upstream of HEAD to %s when it does not point to any branch."
+msgstr "impossible de spécifier une branche amont de HEAD par %s qui ne pointe sur aucune branche."
+
+#: builtin/branch.c:946 builtin/branch.c:968 builtin/branch.c:990
+#, c-format
+msgid "no such branch '%s'"
+msgstr "pas de branche '%s'"
+
+#: builtin/branch.c:950
+#, c-format
+msgid "branch '%s' does not exist"
+msgstr "la branche '%s' n'existe pas"
+
+#: builtin/branch.c:962
+msgid "too many branches to unset upstream"
+msgstr "trop de branches pour désactiver un amont"
+
+#: builtin/branch.c:966
+msgid "could not unset upstream of HEAD when it does not point to any branch."
+msgstr "impossible de désactiver une branche amont de HEAD quand elle ne pointe sur aucune branche."
+
+#: builtin/branch.c:972
+#, c-format
+msgid "Branch '%s' has no upstream information"
+msgstr "La branche '%s' n'a aucune information de branche amont"
+
+#: builtin/branch.c:987
+msgid "it does not make sense to create 'HEAD' manually"
+msgstr "créer manuellement 'HEAD' n'a aucun sens"
+
+#: builtin/branch.c:993
+msgid "-a and -r options to 'git branch' do not make sense with a branch name"
+msgstr "les options -a et -r de 'git branch' n'ont pas de sens avec un nom de branche"
+
+#: builtin/branch.c:996
+#, c-format
+msgid ""
+"The --set-upstream flag is deprecated and will be removed. Consider using --"
+"track or --set-upstream-to\n"
+msgstr "l'option --set-upstream est obsolète et va disparaître. Utilisez plutôt --track ou --set-upstream-to\n"
+
+#: builtin/branch.c:1013
+#, c-format
+msgid ""
+"\n"
+"If you wanted to make '%s' track '%s', do this:\n"
+"\n"
+msgstr "\n"
+"Si vous vouliez que '%s' suive '%s', faîtes ceci :\n"
+"\n"
+
+#: builtin/branch.c:1014
+#, c-format
+msgid "    git branch -d %s\n"
+msgstr "    git branch -d %s\n"
+
+#: builtin/branch.c:1015
+#, c-format
+msgid "    git branch --set-upstream-to %s\n"
+msgstr "    git branch -set-upstream-to %s\n"
+
+#: builtin/bundle.c:47
+#, c-format
+msgid "%s is okay\n"
+msgstr "%s est correct\n"
+
+#: builtin/bundle.c:56
+msgid "Need a repository to create a bundle."
+msgstr "La création d'un colis requiert un dépôt."
+
+#: builtin/bundle.c:60
+msgid "Need a repository to unbundle."
+msgstr "Le dépaquetage d'un colis requiert un dépôt."
+
+#: builtin/cat-file.c:176
+msgid "git cat-file (-t|-s|-e|-p|<type>|--textconv) <object>"
+msgstr "git cat-file (-t|-s|-e|-p|<type>|--textconv) <objet>"
+
+#: builtin/cat-file.c:177
+msgid "git cat-file (--batch|--batch-check) < <list_of_objects>"
+msgstr "git cat-file (--batch|--batch-check) < <liste_d_objets>"
+
+#: builtin/cat-file.c:195
+msgid "<type> can be one of: blob, tree, commit, tag"
+msgstr "<type> peut être : blob, tree, commit ou tag"
+
+#: builtin/cat-file.c:196
+msgid "show object type"
+msgstr "afficher le type de l'objet"
+
+#: builtin/cat-file.c:197
+msgid "show object size"
+msgstr "afficher la taille de l'objet"
+
+#: builtin/cat-file.c:199
+msgid "exit with zero when there's no error"
+msgstr "sortir avec un code d'erreur nul quand il n'y a aucune erreur"
+
+#: builtin/cat-file.c:200
+msgid "pretty-print object's content"
+msgstr "afficher avec mise en forme le contenu de l'objet"
+
+#: builtin/cat-file.c:202
+msgid "for blob objects, run textconv on object's content"
+msgstr "pour les objets blob, lancer textconv sur le contenu de l'objet"
+
+#: builtin/cat-file.c:204
+msgid "show info and content of objects fed from the standard input"
+msgstr "afficher l'information et le contenu des objets passés en entrée standard"
+
+#: builtin/cat-file.c:207
+msgid "show info about objects fed from the standard input"
+msgstr "afficher l'information des objets passés en entrée standard"
+
+#: builtin/check-attr.c:11
+msgid "git check-attr [-a | --all | attr...] [--] pathname..."
+msgstr "git check-attr [-a | --all | attr...] [--] chemin..."
+
+#: builtin/check-attr.c:12
+msgid "git check-attr --stdin [-z] [-a | --all | attr...] < <list-of-paths>"
+msgstr "git check-attr --stdin [-z] [-a | --all | attr...] < <liste-de-chemins>"
+
+#: builtin/check-attr.c:19
+msgid "report all attributes set on file"
+msgstr "afficher tous les attributs associés au fichier"
+
+#: builtin/check-attr.c:20
+msgid "use .gitattributes only from the index"
+msgstr "utiliser .gitattributes seulement depuis l'index"
+
+#: builtin/check-attr.c:21 builtin/check-ignore.c:22 builtin/hash-object.c:75
+msgid "read file names from stdin"
+msgstr "lire les noms de fichier depuis stdin"
+
+#: builtin/check-attr.c:23 builtin/check-ignore.c:24
+msgid "input paths are terminated by a null character"
+msgstr "les chemins en entrée sont terminés par le caractère nul"
+
+#: builtin/check-ignore.c:18 builtin/checkout.c:1044 builtin/gc.c:177
+msgid "suppress progress reporting"
+msgstr "supprimer l'état d'avancement"
+
+#: builtin/check-ignore.c:146
+msgid "cannot specify pathnames with --stdin"
+msgstr "impossible de spécifier les chemins avec --stdin"
+
+#: builtin/check-ignore.c:149
+msgid "-z only makes sense with --stdin"
+msgstr "-z n'a de sens qu'avec l'option --stdin"
+
+#: builtin/check-ignore.c:151
+msgid "no path specified"
+msgstr "aucun chemin spécifié"
+
+#: builtin/check-ignore.c:155
+msgid "--quiet is only valid with a single pathname"
+msgstr "--quiet n'est valide qu'avec un seul chemin"
+
+#: builtin/check-ignore.c:157
+msgid "cannot have both --quiet and --verbose"
+msgstr "impossible d'avoir --quiet et --verbose"
+
+#: builtin/checkout-index.c:126
+msgid "git checkout-index [options] [--] [<file>...]"
+msgstr "git checkout-index [options] [--] [<fichier>...]"
+
+#: builtin/checkout-index.c:187
+msgid "check out all files in the index"
+msgstr "extraire tous les fichiers présents dans l'index"
+
+#: builtin/checkout-index.c:188
+msgid "force overwrite of existing files"
+msgstr "forcer l'écrasement des fichiers existants"
+
+#: builtin/checkout-index.c:190
+msgid "no warning for existing files and files not in index"
+msgstr "pas d'avertissement pour les fichiers existants et les fichiers absents de l'index"
+
+#: builtin/checkout-index.c:192
+msgid "don't checkout new files"
+msgstr "ne pas extraire les nouveaux fichiers"
+
+#: builtin/checkout-index.c:194
+msgid "update stat information in the index file"
+msgstr "mettre à jour l'information de stat dans le fichier d'index"
+
+#: builtin/checkout-index.c:200
+msgid "read list of paths from the standard input"
+msgstr "lire la liste des chemins depuis l'entrée standard"
+
+#: builtin/checkout-index.c:202
+msgid "write the content to temporary files"
+msgstr "écrire le contenu dans des fichiers temporaires"
+
+#: builtin/checkout-index.c:203 builtin/column.c:30
+msgid "string"
+msgstr "chaîne"
+
+#: builtin/checkout-index.c:204
+msgid "when creating files, prepend <string>"
+msgstr "lors de la création de fichiers, préfixer par <chaîne>"
+
+#: builtin/checkout-index.c:207
+msgid "copy out the files from named stage"
+msgstr "copier les fichiers depuis l'index nommé"
+
+#: builtin/checkout.c:25
+msgid "git checkout [options] <branch>"
+msgstr "git checkout [options] <branche>"
+
+#: builtin/checkout.c:26
+msgid "git checkout [options] [<branch>] -- <file>..."
+msgstr "git checkout [options] [<branche>] -- <fichier>..."
+
+#: builtin/checkout.c:117 builtin/checkout.c:150
+#, c-format
+msgid "path '%s' does not have our version"
+msgstr "le chemin '%s' n'a pas notre version"
+
+#: builtin/checkout.c:119 builtin/checkout.c:152
+#, c-format
+msgid "path '%s' does not have their version"
+msgstr "le chemin '%s' n'a pas leur version"
+
+#: builtin/checkout.c:135
+#, c-format
+msgid "path '%s' does not have all necessary versions"
+msgstr "le chemin '%s' n'a aucune des versions nécessaires"
+
+#: builtin/checkout.c:179
+#, c-format
+msgid "path '%s' does not have necessary versions"
+msgstr "le chemin '%s' n'a pas les versions nécessaires"
+
+#: builtin/checkout.c:196
+#, c-format
+msgid "path '%s': cannot merge"
+msgstr "chemin '%s' : impossible de fusionner"
+
+#: builtin/checkout.c:213
+#, c-format
+msgid "Unable to add merge result for '%s'"
+msgstr "Impossible d'ajouter le résultat de fusion pour '%s'"
+
+#: builtin/checkout.c:237 builtin/checkout.c:240 builtin/checkout.c:243
+#: builtin/checkout.c:246
+#, c-format
+msgid "'%s' cannot be used with updating paths"
+msgstr "'%s' ne peut pas être utilisé avec des mises à jour de chemins"
+
+#: builtin/checkout.c:249 builtin/checkout.c:252
+#, c-format
+msgid "'%s' cannot be used with %s"
+msgstr "'%s' ne peut pas être utilisé avec %s"
+
+#: builtin/checkout.c:255
+#, c-format
+msgid "Cannot update paths and switch to branch '%s' at the same time."
+msgstr "Impossible de mettre à jour les chemins et basculer sur la branche '%s' en même temps."
+
+#: builtin/checkout.c:266 builtin/checkout.c:458
+msgid "corrupt index file"
+msgstr "fichier d'index corrompu"
+
+#: builtin/checkout.c:329 builtin/checkout.c:336
+#, c-format
+msgid "path '%s' is unmerged"
+msgstr "le chemin '%s' n'est pas fusionné"
+
+#: builtin/checkout.c:480
+msgid "you need to resolve your current index first"
+msgstr "vous devez d'abord résoudre votre index courant"
+
+#: builtin/checkout.c:601
+#, c-format
+msgid "Can not do reflog for '%s'\n"
+msgstr "Impossible de faire un reflog pour '%s'\n"
+
+#: builtin/checkout.c:634
+msgid "HEAD is now at"
+msgstr "HEAD est maintenant sur"
+
+#: builtin/checkout.c:641
+#, c-format
+msgid "Reset branch '%s'\n"
+msgstr "Remise à zéro de la branche '%s'\n"
+
+#: builtin/checkout.c:644
+#, c-format
+msgid "Already on '%s'\n"
+msgstr "Déjà sur '%s'\n"
+
+#: builtin/checkout.c:648
+#, c-format
+msgid "Switched to and reset branch '%s'\n"
+msgstr "Basculement et remise à zéro de la branche '%s'\n"
+
+#: builtin/checkout.c:650 builtin/checkout.c:987
+#, c-format
+msgid "Switched to a new branch '%s'\n"
+msgstr "Basculement sur la nouvelle branche '%s'\n"
+
+#: builtin/checkout.c:652
+#, c-format
+msgid "Switched to branch '%s'\n"
+msgstr "Basculement sur la branche '%s'\n"
+
+#: builtin/checkout.c:708
+#, c-format
+msgid " ... and %d more.\n"
+msgstr " ... et %d en plus.\n"
+
+#. The singular version
+#: builtin/checkout.c:714
+#, c-format
+msgid ""
+"Warning: you are leaving %d commit behind, not connected to\n"
+"any of your branches:\n"
+"\n"
+"%s\n"
+msgid_plural ""
+"Warning: you are leaving %d commits behind, not connected to\n"
+"any of your branches:\n"
+"\n"
+"%s\n"
+msgstr[0] ""
+"Attention : vous laissez %d commit en retard, non connectés à\n"
+"une branche :\n"
+"\n"
+"%s\n"
+msgstr[1] ""
+"Attention : vous laissez %d commits en retard, non connectés à\n"
+"une branche :\n"
+"\n"
+"%s\n"
+
+#: builtin/checkout.c:732
+#, c-format
+msgid ""
+"If you want to keep them by creating a new branch, this may be a good time\n"
+"to do so with:\n"
+"\n"
+" git branch new_branch_name %s\n"
+"\n"
+msgstr ""
+"Si vous souhaitez les garder en créant une nouvelle branche, c'est le bon moment\n"
+"de le faire avec :\n"
+"\n"
+"git branche nouvelle_branche %s\n"
+"\n"
+
+#: builtin/checkout.c:762
+msgid "internal error in revision walk"
+msgstr "erreur interne lors du parcours des révisions"
+
+#: builtin/checkout.c:766
+msgid "Previous HEAD position was"
+msgstr "La position précédente de HEAD était"
+
+#: builtin/checkout.c:793 builtin/checkout.c:982
+msgid "You are on a branch yet to be born"
+msgstr "Vous êtes sur une branche qui doit encore naître"
+
+#. case (1)
+#: builtin/checkout.c:918
+#, c-format
+msgid "invalid reference: %s"
+msgstr "référence invalide : %s"
+
+#. case (1): want a tree
+#: builtin/checkout.c:957
+#, c-format
+msgid "reference is not a tree: %s"
+msgstr "la référence n'est pas un arbre : %s"
+
+#: builtin/checkout.c:996
+msgid "paths cannot be used with switching branches"
+msgstr "impossible d'utiliser des chemins avec un basculement de branches"
+
+#: builtin/checkout.c:999 builtin/checkout.c:1003
+#, c-format
+msgid "'%s' cannot be used with switching branches"
+msgstr "'%s' ne peut pas être utilisé avec un basculement de branches"
+
+#: builtin/checkout.c:1007 builtin/checkout.c:1010 builtin/checkout.c:1015
+#: builtin/checkout.c:1018
+#, c-format
+msgid "'%s' cannot be used with '%s'"
+msgstr "'%s' ne peut pas être utilisé avec '%s'"
+
+#: builtin/checkout.c:1023
+#, c-format
+msgid "Cannot switch branch to a non-commit '%s'"
+msgstr "Impossible de basculer de branche vers '%s' qui n'est pas un commit"
+
+#: builtin/checkout.c:1045 builtin/checkout.c:1047 builtin/clone.c:90
+#: builtin/remote.c:169 builtin/remote.c:171
+msgid "branch"
+msgstr "branche"
+
+#: builtin/checkout.c:1046
+msgid "create and checkout a new branch"
+msgstr "créer et extraire une nouvelle branche"
+
+#: builtin/checkout.c:1048
+msgid "create/reset and checkout a branch"
+msgstr "créer/réinitialiser et extraire une branche"
+
+#: builtin/checkout.c:1049
+msgid "create reflog for new branch"
+msgstr "créer un refog pour une nouvelle branche"
+
+#: builtin/checkout.c:1050
+msgid "detach the HEAD at named commit"
+msgstr "détacher la HEAD à la validation nommée"
+
+#: builtin/checkout.c:1051
+msgid "set upstream info for new branch"
+msgstr "paramétrer l'information de branche amont pour une nouvelle branche"
+
+#: builtin/checkout.c:1053
+msgid "new branch"
+msgstr "nouvelle branche"
+
+#: builtin/checkout.c:1053
+msgid "new unparented branch"
+msgstr "nouvelle branche sans parent"
+
+#: builtin/checkout.c:1054
+msgid "checkout our version for unmerged files"
+msgstr "extraire notre version pour les fichiers non fusionnés"
+
+#: builtin/checkout.c:1056
+msgid "checkout their version for unmerged files"
+msgstr "extraire leur version pour les fichiers non fusionnés"
+
+#: builtin/checkout.c:1058
+msgid "force checkout (throw away local modifications)"
+msgstr "forcer l'extraction (laisser tomber les modifications locales)"
+
+#: builtin/checkout.c:1059
+msgid "perform a 3-way merge with the new branch"
+msgstr "réaliser une fusion à 3 points avec la nouvelle branche"
+
+#: builtin/checkout.c:1060 builtin/merge.c:217
+msgid "update ignored files (default)"
+msgstr "mettre à jour les fichiers ignorés (par défaut)"
+
+#: builtin/checkout.c:1061 builtin/log.c:1158 parse-options.h:245
+msgid "style"
+msgstr "style"
+
+#: builtin/checkout.c:1062
+msgid "conflict style (merge or diff3)"
+msgstr "style de conflit (fusion ou diff3)"
+
+#: builtin/checkout.c:1065
+msgid "do not limit pathspecs to sparse entries only"
+msgstr "ne pas limiter les spécificateurs de chemins aux seules entrées creuses"
+
+#: builtin/checkout.c:1067
+msgid "second guess 'git checkout no-such-branch'"
+msgstr "deuxième chance 'git checkout branche-inexistante'"
+
+#: builtin/checkout.c:1091
+msgid "-b, -B and --orphan are mutually exclusive"
+msgstr "-b, -B et --orphan sont mutuellement exclusifs"
+
+#: builtin/checkout.c:1108
+msgid "--track needs a branch name"
+msgstr "--track requiert un nom de branche"
+
+#: builtin/checkout.c:1115
+msgid "Missing branch name; try -b"
+msgstr "Nom de branche manquant ; essayez -b"
+
+#: builtin/checkout.c:1150
+msgid "invalid path specification"
+msgstr "spécification de chemin invalide"
+
+#: builtin/checkout.c:1157
+#, c-format
+msgid ""
+"Cannot update paths and switch to branch '%s' at the same time.\n"
+"Did you intend to checkout '%s' which can not be resolved as commit?"
+msgstr ""
+"Impossible de mettre à jour les chemins et de basculer sur la branche '%s' en même temps.\n"
+"Souhaitiez-vous extraire '%s' qui ne peut être résolu comme commit ?"
+
+#: builtin/checkout.c:1162
+#, c-format
+msgid "git checkout: --detach does not take a path argument '%s'"
+msgstr "git checkout: --detach n'accepte pas un argument de chemin '%s'"
+
+#: builtin/checkout.c:1166
+msgid ""
+"git checkout: --ours/--theirs, --force and --merge are incompatible when\n"
+"checking out of the index."
+msgstr ""
+"git checkout: --ours/--theirs, --force et --merge sont incompatibles lors\n"
+"de l'extraction de l'index."
+
+#: builtin/clean.c:20
+msgid "git clean [-d] [-f] [-n] [-q] [-e <pattern>] [-x | -X] [--] <paths>..."
+msgstr "git clean [-d] [-f] [-n] [-q] [-e <motif>] [-x | -X] [--] <chemins>..."
+
+#: builtin/clean.c:24
+#, c-format
+msgid "Removing %s\n"
+msgstr "Suppression de %s\n"
+
+#: builtin/clean.c:25
+#, c-format
+msgid "Would remove %s\n"
+msgstr "Supprimerait %s\n"
+
+#: builtin/clean.c:26
+#, c-format
+msgid "Skipping repository %s\n"
+msgstr "Ignore le dépôt %s\n"
+
+#: builtin/clean.c:27
+#, c-format
+msgid "Would skip repository %s\n"
+msgstr "Ignorerait le dépôt %s\n"
+
+#: builtin/clean.c:28
+#, c-format
+msgid "failed to remove %s"
+msgstr "échec de la suppression de %s"
+
+#: builtin/clean.c:160
+msgid "do not print names of files removed"
+msgstr "ne pas afficher les noms des fichiers supprimés"
+
+#: builtin/clean.c:162
+msgid "force"
+msgstr "forcer"
+
+#: builtin/clean.c:164
+msgid "remove whole directories"
+msgstr "supprimer les répertoires entiers"
+
+#: builtin/clean.c:165 builtin/describe.c:412 builtin/grep.c:717
+#: builtin/ls-files.c:487 builtin/name-rev.c:231 builtin/show-ref.c:182
+msgid "pattern"
+msgstr "motif"
+
+#: builtin/clean.c:166
+msgid "add <pattern> to ignore rules"
+msgstr "ajouter <motif> aux règles ignore"
+
+#: builtin/clean.c:167
+msgid "remove ignored files, too"
+msgstr "supprimer les fichiers ignorés, aussi"
+
+#: builtin/clean.c:169
+msgid "remove only ignored files"
+msgstr "supprimer seulement les fichiers ignorés"
+
+#: builtin/clean.c:187
+msgid "-x and -X cannot be used together"
+msgstr "-x et -X ne peuvent pas être utilisés ensemble"
+
+#: builtin/clean.c:191
+msgid ""
+"clean.requireForce set to true and neither -n nor -f given; refusing to clean"
+msgstr "clean.requireForce positionné à true et ni -n ni -f fourni ; refus de nettoyer"
+
+#: builtin/clean.c:194
+msgid ""
+"clean.requireForce defaults to true and neither -n nor -f given; refusing to "
+"clean"
+msgstr "clean.requireForce à true par défaut et ni -n ni -f fourni ; refus de nettoyer"
+
+#: builtin/clone.c:37
+msgid "git clone [options] [--] <repo> [<dir>]"
+msgstr "git clone [options] [--] <dépôt> [<répertoire>]"
+
+#: builtin/clone.c:65 builtin/fetch.c:82 builtin/merge.c:214
+#: builtin/push.c:436
+msgid "force progress reporting"
+msgstr "forcer l'état d'avancement"
+
+#: builtin/clone.c:67
+msgid "don't create a checkout"
+msgstr "ne pas créer d'extraction"
+
+#: builtin/clone.c:68 builtin/clone.c:70 builtin/init-db.c:488
+msgid "create a bare repository"
+msgstr "créer un dépôt nu"
+
+#: builtin/clone.c:73
+msgid "create a mirror repository (implies bare)"
+msgstr "créer un dépôt miroir (implique dépôt nu)"
+
+#: builtin/clone.c:75
+msgid "to clone from a local repository"
+msgstr "pour cloner depuis un dépôt local"
+
+#: builtin/clone.c:77
+msgid "don't use local hardlinks, always copy"
+msgstr "ne pas utiliser de liens durs locaux, toujours copier"
+
+#: builtin/clone.c:79
+msgid "setup as shared repository"
+msgstr "régler comme dépôt partagé"
+
+#: builtin/clone.c:81 builtin/clone.c:83
+msgid "initialize submodules in the clone"
+msgstr "initialiser les sous-modules dans le clone"
+
+#: builtin/clone.c:84 builtin/init-db.c:485
+msgid "template-directory"
+msgstr "répertoire-modèle"
+
+#: builtin/clone.c:85 builtin/init-db.c:486
+msgid "directory from which templates will be used"
+msgstr "répertoire depuis lequel les modèles vont être utilisés"
+
+#: builtin/clone.c:87
+msgid "reference repository"
+msgstr "dépôt de référence"
+
+#: builtin/clone.c:88 builtin/column.c:26 builtin/merge-file.c:44
+msgid "name"
+msgstr "nom"
+
+#: builtin/clone.c:89
+msgid "use <name> instead of 'origin' to track upstream"
+msgstr "utiliser <nom> au lieu de 'origin' pour suivre la branche amont"
+
+#: builtin/clone.c:91
+msgid "checkout <branch> instead of the remote's HEAD"
+msgstr "extraire <branche> au lieu de la HEAD du répertoire distant"
+
+#: builtin/clone.c:93
+msgid "path to git-upload-pack on the remote"
+msgstr "chemin vers git-upload-pack sur le serveur distant"
+
+#: builtin/clone.c:94 builtin/fetch.c:83 builtin/grep.c:662
+msgid "depth"
+msgstr "profondeur"
+
+#: builtin/clone.c:95
+msgid "create a shallow clone of that depth"
+msgstr "créer un clone superficiel de cette profondeur"
+
+#: builtin/clone.c:97
+msgid "clone only one branch, HEAD or --branch"
+msgstr "cloner seulement une branche, HEAD ou --branch"
+
+#: builtin/clone.c:98 builtin/init-db.c:494
+msgid "gitdir"
+msgstr "gitdir"
+
+#: builtin/clone.c:99 builtin/init-db.c:495
+msgid "separate git dir from working tree"
+msgstr "séparer le répertoire git de la copie de travail"
+
+#: builtin/clone.c:100
+msgid "key=value"
+msgstr "clé=valeur"
+
+#: builtin/clone.c:101
+msgid "set config inside the new repository"
+msgstr "régler la configuration dans le nouveau dépôt"
+
+#: builtin/clone.c:254
+#, c-format
+msgid "reference repository '%s' is not a local repository."
+msgstr "le dépôt de référence '%s' n'est pas un dépôt local."
+
+#: builtin/clone.c:317
+#, c-format
+msgid "failed to create directory '%s'"
+msgstr "échec de la création du répertoire '%s'"
+
+#: builtin/clone.c:319 builtin/diff.c:77
+#, c-format
+msgid "failed to stat '%s'"
+msgstr "échec du stat de '%s'"
+
+#: builtin/clone.c:321
+#, c-format
+msgid "%s exists and is not a directory"
+msgstr "%s existe et n'est pas un répertoire"
+
+#: builtin/clone.c:335
+#, c-format
+msgid "failed to stat %s\n"
+msgstr "échec du stat de %s\n"
+
+#: builtin/clone.c:357
+#, c-format
+msgid "failed to create link '%s'"
+msgstr "échec de la création du lien '%s'"
+
+#: builtin/clone.c:361
+#, c-format
+msgid "failed to copy file to '%s'"
+msgstr "échec de la copie vers '%s'"
+
+#: builtin/clone.c:384
+#, c-format
+msgid "done.\n"
+msgstr "fait.\n"
+
+#: builtin/clone.c:397
+msgid ""
+"Clone succeeded, but checkout failed.\n"
+"You can inspect what was checked out with 'git status'\n"
+"and retry the checkout with 'git checkout -f HEAD'\n"
+msgstr "Le clone a réussi, mais l'extraction a échoué.\n"
+"Vous pouvez inspecter ce qui a été extrait avec 'git status'\n"
+"et réessayer l'extraction avec 'git checkout -f HEAD'\n"
+
+#: builtin/clone.c:476
+#, c-format
+msgid "Could not find remote branch %s to clone."
+msgstr "Impossible de trouver la branche distante '%s' à cloner."
+
+#: builtin/clone.c:550
+msgid "remote did not send all necessary objects"
+msgstr "le serveur distant n'a pas envoyé tous les objets nécessaires"
+
+#: builtin/clone.c:610
+msgid "remote HEAD refers to nonexistent ref, unable to checkout.\n"
+msgstr "la HEAD distante réfère à une référence non existante, impossible de l'extraire.\n"
+
+#: builtin/clone.c:641
+msgid "unable to checkout working tree"
+msgstr "inpossible d'extraire la copie de travail"
+
+#: builtin/clone.c:749
+msgid "Too many arguments."
+msgstr "Trop d'arguments."
+
+#: builtin/clone.c:753
+msgid "You must specify a repository to clone."
+msgstr "Vous devez spécifier un dépôt à cloner."
+
+#: builtin/clone.c:764
+#, c-format
+msgid "--bare and --origin %s options are incompatible."
+msgstr "les options --bare et --origin %s sont incompatibles."
+
+#: builtin/clone.c:767
+msgid "--bare and --separate-git-dir are incompatible."
+msgstr "--bare et --separate-git-dir sont incompatibles."
+
+#: builtin/clone.c:780
+#, c-format
+msgid "repository '%s' does not exist"
+msgstr "le dépôt '%s' n'existe pas"
+
+#: builtin/clone.c:785
+msgid "--depth is ignored in local clones; use file:// instead."
+msgstr "--depth est ignoré dans les clones locaux : utilisez plutôt \"file://\"."
+
+#: builtin/clone.c:795
+#, c-format
+msgid "destination path '%s' already exists and is not an empty directory."
+msgstr "le chemin de destination '%s' existe déjà et n'est pas un répertoire vide."
+
+#: builtin/clone.c:805
+#, c-format
+msgid "working tree '%s' already exists."
+msgstr "la copie de travail '%s' existe déjà."
+
+#: builtin/clone.c:818 builtin/clone.c:830
+#, c-format
+msgid "could not create leading directories of '%s'"
+msgstr "impossible de créer les répertoires de premier niveau dans '%s'"
+
+#: builtin/clone.c:821
+#, c-format
+msgid "could not create work tree dir '%s'."
+msgstr "impossible de créer le répertoire de la copie de travail '%s'."
+
+#: builtin/clone.c:840
+#, c-format
+msgid "Cloning into bare repository '%s'...\n"
+msgstr "Clonage dans le dépôt nu '%s'\n"
+
+#: builtin/clone.c:842
+#, c-format
+msgid "Cloning into '%s'...\n"
+msgstr "Clonage dans '%s'...\n"
+
+#: builtin/clone.c:877
+#, c-format
+msgid "Don't know how to clone %s"
+msgstr "Je ne sais pas cloner %s"
+
+#: builtin/clone.c:926
+#, c-format
+msgid "Remote branch %s not found in upstream %s"
+msgstr "La branche distante %s n'a pas été trouvée dans le dépôt amont %s"
+
+#: builtin/clone.c:933
+msgid "You appear to have cloned an empty repository."
+msgstr "Vous semblez avoir cloné un dépôt vide."
+
+#: builtin/column.c:9
+msgid "git column [options]"
+msgstr "git column [options]"
+
+#: builtin/column.c:26
+msgid "lookup config vars"
+msgstr "rechercher les variables de configuration"
+
+#: builtin/column.c:27 builtin/column.c:28
+msgid "layout to use"
+msgstr "mise en page à utiliser"
+
+#: builtin/column.c:29
+msgid "Maximum width"
+msgstr "Largeur maximale"
+
+#: builtin/column.c:30
+msgid "Padding space on left border"
+msgstr "Remplissage d'espace sur la bordure gauche"
+
+#: builtin/column.c:31
+msgid "Padding space on right border"
+msgstr "Remplissage d'espace sur le côté droit"
+
+#: builtin/column.c:32
+msgid "Padding space between columns"
+msgstr "Remplissage d'espace entre les colonnes"
+
+#: builtin/column.c:51
+msgid "--command must be the first argument"
+msgstr "--command doit être le premier argument"
+
+#: builtin/commit.c:34
+msgid "git commit [options] [--] <pathspec>..."
+msgstr "git commit [options] [--] <spécification-de-chemin>..."
+
+#: builtin/commit.c:39
+msgid "git status [options] [--] <pathspec>..."
+msgstr "git status [options] [--] <spécification-de-chemin>..."
+
+#: builtin/commit.c:44
+msgid ""
+"Your name and email address were configured automatically based\n"
+"on your username and hostname. Please check that they are accurate.\n"
+"You can suppress this message by setting them explicitly:\n"
+"\n"
+"    git config --global user.name \"Your Name\"\n"
+"    git config --global user.email you@example.com\n"
+"\n"
+"After doing this, you may fix the identity used for this commit with:\n"
+"\n"
+"    git commit --amend --reset-author\n"
+msgstr ""
+"Votre nom et votre adresse e-mail ont été configurés automatiquement en se fondant\n"
+"sur votre nom d'utilisateur et votre nom d'ordinateur. Veuillez vérifier qu'ils sont corrects.\n"
+"Vous pouvez supprimer ce message en les paramétrant explicitement :\n"
+"\n"
+"    git config --global user.name \"Votre Nom\"\n"
+"    git config --global user.email vous@exemple.com\n"
+"\n"
+"Après ceci, vous pouvez corriger l'identité utilisée pour ce commit avec :\n"
+"\n"
+"    git commit --amend --reset-author\n"
+
+#: builtin/commit.c:56
+msgid ""
+"You asked to amend the most recent commit, but doing so would make\n"
+"it empty. You can repeat your command with --allow-empty, or you can\n"
+"remove the commit entirely with \"git reset HEAD^\".\n"
+msgstr "Vous avez demandé de corriger le commit le plus récent, mais le faire le rendrait\n"
+"vide. Vous pouvez répéter votre commande avec --allow-empty, ou vous pouvez\n"
+"supprimer complètement le commit avec \"git reset HEAD^\".\n"
+
+#: builtin/commit.c:61
+msgid ""
+"The previous cherry-pick is now empty, possibly due to conflict resolution.\n"
+"If you wish to commit it anyway, use:\n"
+"\n"
+"    git commit --allow-empty\n"
+"\n"
+"Otherwise, please use 'git reset'\n"
+msgstr ""
+"Le picorage précédent est à présent vide, vraisemblablement dû à une résolution de conflit.\n"
+"Si vous souhaitez tout de même le valider, utilisez :\n"
+"\n"
+"    git commit --allow-empty\n"
+"\n"
+"Sinon, utilisez 'git reset'\n"
+
+#: builtin/commit.c:260
+msgid "failed to unpack HEAD tree object"
+msgstr "échec du dépaquetage de l'objet arbre HEAD"
+
+#: builtin/commit.c:302
+msgid "unable to create temporary index"
+msgstr "impossible de créer l'index temporaire"
+
+#: builtin/commit.c:308
+msgid "interactive add failed"
+msgstr "échec de l'ajout interactif"
+
+#: builtin/commit.c:341 builtin/commit.c:362 builtin/commit.c:412
+msgid "unable to write new_index file"
+msgstr "impossible d'écrire le fichier new_index"
+
+#: builtin/commit.c:393
+msgid "cannot do a partial commit during a merge."
+msgstr "impossible de faire une validation partielle pendant une fusion."
+
+#: builtin/commit.c:395
+msgid "cannot do a partial commit during a cherry-pick."
+msgstr "impossible de faire une validation partielle pendant un picorage."
+
+#: builtin/commit.c:405
+msgid "cannot read the index"
+msgstr "impossible de lire l'index"
+
+#: builtin/commit.c:425
+msgid "unable to write temporary index file"
+msgstr "impossible d'écrire le fichier d'index temporaire"
+
+#: builtin/commit.c:513 builtin/commit.c:519
+#, c-format
+msgid "invalid commit: %s"
+msgstr "commit invalide : %s"
+
+#: builtin/commit.c:542
+msgid "malformed --author parameter"
+msgstr "paramètre --author mal formé"
+
+#: builtin/commit.c:562
+#, c-format
+msgid "Malformed ident string: '%s'"
+msgstr "Chaîne ident mal formée : '%s'"
+
+#: builtin/commit.c:600 builtin/commit.c:633 builtin/commit.c:956
+#, c-format
+msgid "could not lookup commit %s"
+msgstr "impossible de rechercher le commit %s"
+
+#: builtin/commit.c:612 builtin/shortlog.c:270
+#, c-format
+msgid "(reading log message from standard input)\n"
+msgstr "(lecture du message de journal depuis l'entrée standard)\n"
+
+#: builtin/commit.c:614
+msgid "could not read log from standard input"
+msgstr "impossible de lire le journal depuis l'entrée standard"
+
+#: builtin/commit.c:618
+#, c-format
+msgid "could not read log file '%s'"
+msgstr "impossible de lire le fichier de journal '%s'"
+
+#: builtin/commit.c:624
+msgid "commit has empty message"
+msgstr "le commit a un message vide"
+
+#: builtin/commit.c:640
+msgid "could not read MERGE_MSG"
+msgstr "impossible de lire MERGE_MSG"
+
+#: builtin/commit.c:644
+msgid "could not read SQUASH_MSG"
+msgstr "impossible de lire SQUASH_MSG"
+
+#: builtin/commit.c:648
+#, c-format
+msgid "could not read '%s'"
+msgstr "impossible de lire '%s'"
+
+#: builtin/commit.c:709
+msgid "could not write commit template"
+msgstr "impossible d'écrire le modèle de commit"
+
+#: builtin/commit.c:720
+#, c-format
+msgid ""
+"\n"
+"It looks like you may be committing a merge.\n"
+"If this is not correct, please remove the file\n"
+"\t%s\n"
+"and try again.\n"
+msgstr ""
+"\n"
+"Il semble que vous validiez une fusion.\n"
+"Si ce n'est pas le cas, veuillez supprimer le fichier\n"
+"\t%s\n"
+"et essayez à nouveau.\n"
+
+#: builtin/commit.c:725
+#, c-format
+msgid ""
+"\n"
+"It looks like you may be committing a cherry-pick.\n"
+"If this is not correct, please remove the file\n"
+"\t%s\n"
+"and try again.\n"
+msgstr ""
+"\n"
+"Il semble que vous validiez un picorage.\n"
+"Si ce n'est pas le cas, veuillez supprimer le fichier\n"
+"\t%s\n"
+"et essayez à nouveau.\n"
+
+#: builtin/commit.c:737
+#, c-format
+msgid ""
+"Please enter the commit message for your changes. Lines starting\n"
+"with '%c' will be ignored, and an empty message aborts the commit.\n"
+msgstr ""
+"Veuillez saisir le message de validation pour vos modifications. Les lignes\n"
+"commençant par '%c' seront ignorées, et un message vide abandonne la validation.\n"
+
+#: builtin/commit.c:742
+#, c-format
+msgid ""
+"Please enter the commit message for your changes. Lines starting\n"
+"with '%c' will be kept; you may remove them yourself if you want to.\n"
+"An empty message aborts the commit.\n"
+msgstr ""
+"Veuillez saisir le message de validation pour vos modifications. Les lignes\n"
+"commençant par '%c' seront conservées ; vous pouvez les supprimer vous-même\n"
+"si vous le souhaitez. Un message vide abandonne la validation.\n"
+
+#: builtin/commit.c:755
+#, c-format
+msgid "%sAuthor:    %s"
+msgstr "%sAuteur :     %s"
+
+#: builtin/commit.c:762
+#, c-format
+msgid "%sCommitter: %s"
+msgstr "%sValidateur : %s"
+
+#: builtin/commit.c:782
+msgid "Cannot read index"
+msgstr "Impossible de lire l'index"
+
+#: builtin/commit.c:819
+msgid "Error building trees"
+msgstr "Erreur lors de la construction des arbres"
+
+#: builtin/commit.c:834 builtin/tag.c:359
+#, c-format
+msgid "Please supply the message using either -m or -F option.\n"
+msgstr "Veuillez fournir le message en utilisant l'option -m ou -F.\n"
+
+#: builtin/commit.c:931
+#, c-format
+msgid "No existing author found with '%s'"
+msgstr "Aucun auteur existant trouvé avec '%s'"
+
+#: builtin/commit.c:946 builtin/commit.c:1140
+#, c-format
+msgid "Invalid untracked files mode '%s'"
+msgstr "Mode de fichier non suivi invalide '%s'"
+
+#: builtin/commit.c:976
+msgid "Using both --reset-author and --author does not make sense"
+msgstr "L'utilisation simultanée de --reset-author et --author n'a pas de sens"
+
+#: builtin/commit.c:987
+msgid "You have nothing to amend."
+msgstr "Il n'y a rien à corriger."
+
+#: builtin/commit.c:990
+msgid "You are in the middle of a merge -- cannot amend."
+msgstr "Vous êtes en pleine fusion -- impossible de corriger (amend)."
+
+#: builtin/commit.c:992
+msgid "You are in the middle of a cherry-pick -- cannot amend."
+msgstr "Vous êtes en plein picorage -- impossible de corriger (amend)."
+
+#: builtin/commit.c:995
+msgid "Options --squash and --fixup cannot be used together"
+msgstr "Les options --squash et --fixup ne peuvent pas être utilisées ensemble"
+
+#: builtin/commit.c:1005
+msgid "Only one of -c/-C/-F/--fixup can be used."
+msgstr "Une seule option parmi -c/-C/-F/--fixup peut être utilisée."
+
+#: builtin/commit.c:1007
+msgid "Option -m cannot be combined with -c/-C/-F/--fixup."
+msgstr "L'option -m ne peut pas être combinée avec -c/-C/-F/--fixup."
+
+#: builtin/commit.c:1015
+msgid "--reset-author can be used only with -C, -c or --amend."
+msgstr "--reset-author ne peut être utilisé qu'avec -C, -c ou --amend."
+
+#: builtin/commit.c:1032
+msgid "Only one of --include/--only/--all/--interactive/--patch can be used."
+msgstr "Une seule option parmi --include/--only/--all/--interactive/--patch peut être utilisée."
+
+#: builtin/commit.c:1034
+msgid "No paths with --include/--only does not make sense."
+msgstr "Aucun chemin avec les options --include/--only n'a pas de sens."
+
+#: builtin/commit.c:1036
+msgid "Clever... amending the last one with dirty index."
+msgstr "Malin... correction du dernier avec un index sale."
+
+#: builtin/commit.c:1038
+msgid "Explicit paths specified without -i nor -o; assuming --only paths..."
+msgstr ""
+
+#: builtin/commit.c:1048 builtin/tag.c:575
+#, c-format
+msgid "Invalid cleanup mode %s"
+msgstr ""
+
+#: builtin/commit.c:1053
+msgid "Paths with -a does not make sense."
+msgstr ""
+
+#: builtin/commit.c:1059 builtin/commit.c:1194
+msgid "--long and -z are incompatible"
+msgstr ""
+
+#: builtin/commit.c:1154 builtin/commit.c:1390
+msgid "show status concisely"
+msgstr ""
+
+#: builtin/commit.c:1156 builtin/commit.c:1392
+msgid "show branch information"
+msgstr ""
+
+#: builtin/commit.c:1158 builtin/commit.c:1394 builtin/push.c:426
+msgid "machine-readable output"
+msgstr ""
+
+#: builtin/commit.c:1161 builtin/commit.c:1396
+msgid "show status in long format (default)"
+msgstr ""
+
+#: builtin/commit.c:1164 builtin/commit.c:1399
+msgid "terminate entries with NUL"
+msgstr ""
+
+#: builtin/commit.c:1166 builtin/commit.c:1402 builtin/fast-export.c:659
+#: builtin/fast-export.c:662 builtin/tag.c:459
+msgid "mode"
+msgstr ""
+
+#: builtin/commit.c:1167 builtin/commit.c:1402
+msgid "show untracked files, optional modes: all, normal, no. (Default: all)"
+msgstr ""
+
+#: builtin/commit.c:1170
+msgid "show ignored files"
+msgstr ""
+
+#: builtin/commit.c:1171 parse-options.h:151
+msgid "when"
+msgstr ""
+
+#: builtin/commit.c:1172
+msgid ""
+"ignore changes to submodules, optional when: all, dirty, untracked. "
+"(Default: all)"
+msgstr ""
+
+#: builtin/commit.c:1174
+msgid "list untracked files in columns"
+msgstr ""
+
+#: builtin/commit.c:1248
+msgid "couldn't look up newly created commit"
+msgstr ""
+
+#: builtin/commit.c:1250
+msgid "could not parse newly created commit"
+msgstr ""
+
+#: builtin/commit.c:1291
+msgid "detached HEAD"
+msgstr ""
+
+#: builtin/commit.c:1293
+msgid " (root-commit)"
+msgstr ""
+
+#: builtin/commit.c:1360
+msgid "suppress summary after successful commit"
+msgstr ""
+
+#: builtin/commit.c:1361
+msgid "show diff in commit message template"
+msgstr ""
+
+#: builtin/commit.c:1363
+msgid "Commit message options"
+msgstr ""
+
+#: builtin/commit.c:1364 builtin/tag.c:457
+msgid "read message from file"
+msgstr ""
+
+#: builtin/commit.c:1365
+msgid "author"
+msgstr ""
+
+#: builtin/commit.c:1365
+msgid "override author for commit"
+msgstr ""
+
+#: builtin/commit.c:1366 builtin/gc.c:178
+msgid "date"
+msgstr ""
+
+#: builtin/commit.c:1366
+msgid "override date for commit"
+msgstr ""
+
+#: builtin/commit.c:1367 builtin/merge.c:208 builtin/notes.c:533
+#: builtin/notes.c:690 builtin/tag.c:455
+msgid "message"
+msgstr ""
+
+#: builtin/commit.c:1367
+msgid "commit message"
+msgstr ""
+
+#: builtin/commit.c:1368
+msgid "reuse and edit message from specified commit"
+msgstr ""
+
+#: builtin/commit.c:1369
+msgid "reuse message from specified commit"
+msgstr ""
+
+#: builtin/commit.c:1370
+msgid "use autosquash formatted message to fixup specified commit"
+msgstr ""
+
+#: builtin/commit.c:1371
+msgid "use autosquash formatted message to squash specified commit"
+msgstr ""
+
+#: builtin/commit.c:1372
+msgid "the commit is authored by me now (used with -C/-c/--amend)"
+msgstr ""
+
+#: builtin/commit.c:1373 builtin/log.c:1113 builtin/revert.c:109
+msgid "add Signed-off-by:"
+msgstr ""
+
+#: builtin/commit.c:1374
+msgid "use specified template file"
+msgstr ""
+
+#: builtin/commit.c:1375
+msgid "force edit of commit"
+msgstr ""
+
+#: builtin/commit.c:1376
+msgid "default"
+msgstr ""
+
+#: builtin/commit.c:1376 builtin/tag.c:460
+msgid "how to strip spaces and #comments from message"
+msgstr ""
+
+#: builtin/commit.c:1377
+msgid "include status in commit message template"
+msgstr ""
+
+#: builtin/commit.c:1378 builtin/merge.c:215 builtin/tag.c:461
+msgid "key id"
+msgstr ""
+
+#: builtin/commit.c:1379 builtin/merge.c:216
+msgid "GPG sign commit"
+msgstr ""
+
+#. end commit message options
+#: builtin/commit.c:1382
+msgid "Commit contents options"
+msgstr ""
+
+#: builtin/commit.c:1383
+msgid "commit all changed files"
+msgstr ""
+
+#: builtin/commit.c:1384
+msgid "add specified files to index for commit"
+msgstr ""
+
+#: builtin/commit.c:1385
+msgid "interactively add files"
+msgstr ""
+
+#: builtin/commit.c:1386
+msgid "interactively add changes"
+msgstr ""
+
+#: builtin/commit.c:1387
+msgid "commit only specified files"
+msgstr ""
+
+#: builtin/commit.c:1388
+msgid "bypass pre-commit hook"
+msgstr ""
+
+#: builtin/commit.c:1389
+msgid "show what would be committed"
+msgstr ""
+
+#: builtin/commit.c:1400
+msgid "amend previous commit"
+msgstr ""
+
+#: builtin/commit.c:1401
+msgid "bypass post-rewrite hook"
+msgstr ""
+
+#: builtin/commit.c:1406
+msgid "ok to record an empty change"
+msgstr ""
+
+#: builtin/commit.c:1409
+msgid "ok to record a change with an empty message"
+msgstr ""
+
+#: builtin/commit.c:1441
+msgid "could not parse HEAD commit"
+msgstr ""
+
+#: builtin/commit.c:1479 builtin/merge.c:510
+#, c-format
+msgid "could not open '%s' for reading"
+msgstr ""
+
+#: builtin/commit.c:1486
+#, c-format
+msgid "Corrupt MERGE_HEAD file (%s)"
+msgstr ""
+
+#: builtin/commit.c:1493
+msgid "could not read MERGE_MODE"
+msgstr ""
+
+#: builtin/commit.c:1512
+#, c-format
+msgid "could not read commit message: %s"
+msgstr ""
+
+#: builtin/commit.c:1526
+#, c-format
+msgid "Aborting commit; you did not edit the message.\n"
+msgstr ""
+
+#: builtin/commit.c:1531
+#, c-format
+msgid "Aborting commit due to empty commit message.\n"
+msgstr ""
+
+#: builtin/commit.c:1546 builtin/merge.c:847 builtin/merge.c:872
+msgid "failed to write commit object"
+msgstr ""
+
+#: builtin/commit.c:1567
+msgid "cannot lock HEAD ref"
+msgstr ""
+
+#: builtin/commit.c:1571
+msgid "cannot update HEAD ref"
+msgstr ""
+
+#: builtin/commit.c:1582
+msgid ""
+"Repository has been updated, but unable to write\n"
+"new_index file. Check that disk is not full or quota is\n"
+"not exceeded, and then \"git reset HEAD\" to recover."
+msgstr ""
+
+#: builtin/config.c:7
+msgid "git config [options]"
+msgstr ""
+
+#: builtin/config.c:51
+msgid "Config file location"
+msgstr ""
+
+#: builtin/config.c:52
+msgid "use global config file"
+msgstr ""
+
+#: builtin/config.c:53
+msgid "use system config file"
+msgstr ""
+
+#: builtin/config.c:54
+msgid "use repository config file"
+msgstr ""
+
+#: builtin/config.c:55
+msgid "use given config file"
+msgstr ""
+
+#: builtin/config.c:56
+msgid "Action"
+msgstr ""
+
+#: builtin/config.c:57
+msgid "get value: name [value-regex]"
+msgstr ""
+
+#: builtin/config.c:58
+msgid "get all values: key [value-regex]"
+msgstr ""
+
+#: builtin/config.c:59
+msgid "get values for regexp: name-regex [value-regex]"
+msgstr ""
+
+#: builtin/config.c:60
+msgid "replace all matching variables: name value [value_regex]"
+msgstr ""
+
+#: builtin/config.c:61
+msgid "add a new variable: name value"
+msgstr ""
+
+#: builtin/config.c:62
+msgid "remove a variable: name [value-regex]"
+msgstr ""
+
+#: builtin/config.c:63
+msgid "remove all matches: name [value-regex]"
+msgstr ""
+
+#: builtin/config.c:64
+msgid "rename section: old-name new-name"
+msgstr ""
+
+#: builtin/config.c:65
+msgid "remove a section: name"
+msgstr ""
+
+#: builtin/config.c:66
+msgid "list all"
+msgstr ""
+
+#: builtin/config.c:67
+msgid "open an editor"
+msgstr ""
+
+#: builtin/config.c:68 builtin/config.c:69
+msgid "slot"
+msgstr ""
+
+#: builtin/config.c:68
+msgid "find the color configured: [default]"
+msgstr ""
+
+#: builtin/config.c:69
+msgid "find the color setting: [stdout-is-tty]"
+msgstr ""
+
+#: builtin/config.c:70
+msgid "Type"
+msgstr ""
+
+#: builtin/config.c:71
+msgid "value is \"true\" or \"false\""
+msgstr ""
+
+#: builtin/config.c:72
+msgid "value is decimal number"
+msgstr ""
+
+#: builtin/config.c:73
+msgid "value is --bool or --int"
+msgstr ""
+
+#: builtin/config.c:74
+msgid "value is a path (file or directory name)"
+msgstr ""
+
+#: builtin/config.c:75
+msgid "Other"
+msgstr ""
+
+#: builtin/config.c:76
+msgid "terminate values with NUL byte"
+msgstr ""
+
+#: builtin/config.c:77
+msgid "respect include directives on lookup"
+msgstr ""
+
+#: builtin/count-objects.c:82
+msgid "git count-objects [-v] [-H | --human-readable]"
+msgstr ""
+
+#: builtin/count-objects.c:97
+msgid "print sizes in human readable format"
+msgstr ""
+
+#: builtin/describe.c:15
+msgid "git describe [options] <committish>*"
+msgstr ""
+
+#: builtin/describe.c:16
+msgid "git describe [options] --dirty"
+msgstr ""
+
+#: builtin/describe.c:233
+#, c-format
+msgid "annotated tag %s not available"
+msgstr ""
+
+#: builtin/describe.c:237
+#, c-format
+msgid "annotated tag %s has no embedded name"
+msgstr ""
+
+#: builtin/describe.c:239
+#, c-format
+msgid "tag '%s' is really '%s' here"
+msgstr ""
+
+#: builtin/describe.c:266
+#, c-format
+msgid "Not a valid object name %s"
+msgstr ""
+
+#: builtin/describe.c:269
+#, c-format
+msgid "%s is not a valid '%s' object"
+msgstr "%s n'est pas un objet '%s' valide"
+
+#: builtin/describe.c:286
+#, c-format
+msgid "no tag exactly matches '%s'"
+msgstr ""
+
+#: builtin/describe.c:288
+#, c-format
+msgid "searching to describe %s\n"
+msgstr ""
+
+#: builtin/describe.c:328
+#, c-format
+msgid "finished search at %s\n"
+msgstr ""
+
+#: builtin/describe.c:352
+#, c-format
+msgid ""
+"No annotated tags can describe '%s'.\n"
+"However, there were unannotated tags: try --tags."
+msgstr ""
+
+#: builtin/describe.c:356
+#, c-format
+msgid ""
+"No tags can describe '%s'.\n"
+"Try --always, or create some tags."
+msgstr ""
+
+#: builtin/describe.c:377
+#, c-format
+msgid "traversed %lu commits\n"
+msgstr ""
+
+#: builtin/describe.c:380
+#, c-format
+msgid ""
+"more than %i tags found; listed %i most recent\n"
+"gave up search at %s\n"
+msgstr ""
+
+#: builtin/describe.c:402
+msgid "find the tag that comes after the commit"
+msgstr ""
+
+#: builtin/describe.c:403
+msgid "debug search strategy on stderr"
+msgstr ""
+
+#: builtin/describe.c:404
+msgid "use any ref"
+msgstr ""
+
+#: builtin/describe.c:405
+msgid "use any tag, even unannotated"
+msgstr ""
+
+#: builtin/describe.c:406
+msgid "always use long format"
+msgstr ""
+
+#: builtin/describe.c:409
+msgid "only output exact matches"
+msgstr ""
+
+#: builtin/describe.c:411
+msgid "consider <n> most recent tags (default: 10)"
+msgstr ""
+
+#: builtin/describe.c:413
+msgid "only consider tags matching <pattern>"
+msgstr ""
+
+#: builtin/describe.c:415 builtin/name-rev.c:238
+msgid "show abbreviated commit object as fallback"
+msgstr ""
+
+#: builtin/describe.c:416
+msgid "mark"
+msgstr ""
+
+#: builtin/describe.c:417
+msgid "append <mark> on dirty working tree (default: \"-dirty\")"
+msgstr ""
+
+#: builtin/describe.c:435
+msgid "--long is incompatible with --abbrev=0"
+msgstr ""
+
+#: builtin/describe.c:461
+msgid "No names found, cannot describe anything."
+msgstr ""
+
+#: builtin/describe.c:481
+msgid "--dirty is incompatible with committishes"
+msgstr ""
+
+#: builtin/diff.c:79
+#, c-format
+msgid "'%s': not a regular file or symlink"
+msgstr ""
+
+#: builtin/diff.c:228
+#, c-format
+msgid "invalid option: %s"
+msgstr ""
+
+#: builtin/diff.c:305
+msgid "Not a git repository"
+msgstr ""
+
+#: builtin/diff.c:348
+#, c-format
+msgid "invalid object '%s' given."
+msgstr ""
+
+#: builtin/diff.c:353
+#, c-format
+msgid "more than %d trees given: '%s'"
+msgstr ""
+
+#: builtin/diff.c:363
+#, c-format
+msgid "more than two blobs given: '%s'"
+msgstr ""
+
+#: builtin/diff.c:371
+#, c-format
+msgid "unhandled object '%s' given."
+msgstr ""
+
+#: builtin/fast-export.c:22
+msgid "git fast-export [rev-list-opts]"
+msgstr ""
+
+#: builtin/fast-export.c:658
+msgid "show progress after <n> objects"
+msgstr ""
+
+#: builtin/fast-export.c:660
+msgid "select handling of signed tags"
+msgstr ""
+
+#: builtin/fast-export.c:663
+msgid "select handling of tags that tag filtered objects"
+msgstr ""
+
+#: builtin/fast-export.c:666
+msgid "Dump marks to this file"
+msgstr ""
+
+#: builtin/fast-export.c:668
+msgid "Import marks from this file"
+msgstr ""
+
+#: builtin/fast-export.c:670
+msgid "Fake a tagger when tags lack one"
+msgstr ""
+
+#: builtin/fast-export.c:672
+msgid "Output full tree for each commit"
+msgstr ""
+
+#: builtin/fast-export.c:674
+msgid "Use the done feature to terminate the stream"
+msgstr ""
+
+#: builtin/fast-export.c:675
+msgid "Skip output of blob data"
+msgstr ""
+
+#: builtin/fetch.c:20
+msgid "git fetch [<options>] [<repository> [<refspec>...]]"
+msgstr ""
+
+#: builtin/fetch.c:21
+msgid "git fetch [<options>] <group>"
+msgstr ""
+
+#: builtin/fetch.c:22
+msgid "git fetch --multiple [<options>] [(<repository> | <group>)...]"
+msgstr ""
+
+#: builtin/fetch.c:23
+msgid "git fetch --all [<options>]"
+msgstr ""
+
+#: builtin/fetch.c:60
+msgid "fetch from all remotes"
+msgstr ""
+
+#: builtin/fetch.c:62
+msgid "append to .git/FETCH_HEAD instead of overwriting"
+msgstr ""
+
+#: builtin/fetch.c:64
+msgid "path to upload pack on remote end"
+msgstr ""
+
+#: builtin/fetch.c:65
+msgid "force overwrite of local branch"
+msgstr ""
+
+#: builtin/fetch.c:67
+msgid "fetch from multiple remotes"
+msgstr ""
+
+#: builtin/fetch.c:69
+msgid "fetch all tags and associated objects"
+msgstr ""
+
+#: builtin/fetch.c:71
+msgid "do not fetch all tags (--no-tags)"
+msgstr ""
+
+#: builtin/fetch.c:73
+msgid "prune remote-tracking branches no longer on remote"
+msgstr ""
+
+#: builtin/fetch.c:74
+msgid "on-demand"
+msgstr ""
+
+#: builtin/fetch.c:75
+msgid "control recursive fetching of submodules"
+msgstr ""
+
+#: builtin/fetch.c:79
+msgid "keep downloaded pack"
+msgstr ""
+
+#: builtin/fetch.c:81
+msgid "allow updating of HEAD ref"
+msgstr ""
+
+#: builtin/fetch.c:84
+msgid "deepen history of shallow clone"
+msgstr ""
+
+#: builtin/fetch.c:86
+msgid "convert to a complete repository"
+msgstr ""
+
+#: builtin/fetch.c:88 builtin/log.c:1130
+msgid "dir"
+msgstr ""
+
+#: builtin/fetch.c:89
+msgid "prepend this to submodule path output"
+msgstr ""
+
+#: builtin/fetch.c:92
+msgid "default mode for recursion"
+msgstr ""
+
+#: builtin/fetch.c:204
+msgid "Couldn't find remote ref HEAD"
+msgstr ""
+
+#: builtin/fetch.c:257
+#, c-format
+msgid "object %s not found"
+msgstr ""
+
+#: builtin/fetch.c:262
+msgid "[up to date]"
+msgstr ""
+
+#: builtin/fetch.c:276
+#, c-format
+msgid "! %-*s %-*s -> %s  (can't fetch in current branch)"
+msgstr ""
+
+#: builtin/fetch.c:277 builtin/fetch.c:363
+msgid "[rejected]"
+msgstr ""
+
+#: builtin/fetch.c:288
+msgid "[tag update]"
+msgstr ""
+
+#: builtin/fetch.c:290 builtin/fetch.c:325 builtin/fetch.c:343
+msgid "  (unable to update local ref)"
+msgstr ""
+
+#: builtin/fetch.c:308
+msgid "[new tag]"
+msgstr ""
+
+#: builtin/fetch.c:311
+msgid "[new branch]"
+msgstr ""
+
+#: builtin/fetch.c:314
+msgid "[new ref]"
+msgstr ""
+
+#: builtin/fetch.c:359
+msgid "unable to update local ref"
+msgstr ""
+
+#: builtin/fetch.c:359
+msgid "forced update"
+msgstr ""
+
+#: builtin/fetch.c:365
+msgid "(non-fast-forward)"
+msgstr ""
+
+#: builtin/fetch.c:396 builtin/fetch.c:688
+#, c-format
+msgid "cannot open %s: %s\n"
+msgstr "impossible d'ouvrir %s : %s\n"
+
+#: builtin/fetch.c:405
+#, c-format
+msgid "%s did not send all necessary objects\n"
+msgstr "%s n'a pas envoyé tous les objets nécessaires\n"
+
+#: builtin/fetch.c:491
+#, c-format
+msgid "From %.*s\n"
+msgstr ""
+
+#: builtin/fetch.c:502
+#, c-format
+msgid ""
+"some local refs could not be updated; try running\n"
+" 'git remote prune %s' to remove any old, conflicting branches"
+msgstr ""
+
+#: builtin/fetch.c:552
+#, c-format
+msgid "   (%s will become dangling)"
+msgstr ""
+
+#: builtin/fetch.c:553
+#, c-format
+msgid "   (%s has become dangling)"
+msgstr ""
+
+#: builtin/fetch.c:560
+msgid "[deleted]"
+msgstr ""
+
+#: builtin/fetch.c:561 builtin/remote.c:1055
+msgid "(none)"
+msgstr ""
+
+#: builtin/fetch.c:678
+#, c-format
+msgid "Refusing to fetch into current branch %s of non-bare repository"
+msgstr ""
+
+#: builtin/fetch.c:712
+#, c-format
+msgid "Don't know how to fetch from %s"
+msgstr ""
+
+#: builtin/fetch.c:789
+#, c-format
+msgid "Option \"%s\" value \"%s\" is not valid for %s"
+msgstr ""
+
+#: builtin/fetch.c:792
+#, c-format
+msgid "Option \"%s\" is ignored for %s\n"
+msgstr ""
+
+#: builtin/fetch.c:894
+#, c-format
+msgid "Fetching %s\n"
+msgstr ""
+
+#: builtin/fetch.c:896 builtin/remote.c:100
+#, c-format
+msgid "Could not fetch %s"
+msgstr ""
+
+#: builtin/fetch.c:915
+msgid ""
+"No remote repository specified.  Please, specify either a URL or a\n"
+"remote name from which new revisions should be fetched."
+msgstr ""
+
+#: builtin/fetch.c:935
+msgid "You need to specify a tag name."
+msgstr ""
+
+#: builtin/fetch.c:981
+msgid "--depth and --unshallow cannot be used together"
+msgstr ""
+
+#: builtin/fetch.c:983
+msgid "--unshallow on a complete repository does not make sense"
+msgstr ""
+
+#: builtin/fetch.c:1002
+msgid "fetch --all does not take a repository argument"
+msgstr ""
+
+#: builtin/fetch.c:1004
+msgid "fetch --all does not make sense with refspecs"
+msgstr ""
+
+#: builtin/fetch.c:1015
+#, c-format
+msgid "No such remote or remote group: %s"
+msgstr ""
+
+#: builtin/fetch.c:1023
+msgid "Fetching a group and specifying refspecs does not make sense"
+msgstr ""
+
+#: builtin/fmt-merge-msg.c:13
+msgid "git fmt-merge-msg [-m <message>] [--log[=<n>]|--no-log] [--file <file>]"
+msgstr ""
+
+#: builtin/fmt-merge-msg.c:663 builtin/fmt-merge-msg.c:666 builtin/grep.c:701
+#: builtin/merge.c:188 builtin/show-branch.c:655 builtin/show-ref.c:175
+#: builtin/tag.c:446 parse-options.h:133 parse-options.h:239
+msgid "n"
+msgstr ""
+
+#: builtin/fmt-merge-msg.c:664
+msgid "populate log with at most <n> entries from shortlog"
+msgstr ""
+
+#: builtin/fmt-merge-msg.c:667
+msgid "alias for --log (deprecated)"
+msgstr ""
+
+#: builtin/fmt-merge-msg.c:670
+msgid "text"
+msgstr ""
+
+#: builtin/fmt-merge-msg.c:671
+msgid "use <text> as start of message"
+msgstr ""
+
+#: builtin/fmt-merge-msg.c:672
+msgid "file to read from"
+msgstr ""
+
+#: builtin/for-each-ref.c:979
+msgid "git for-each-ref [options] [<pattern>]"
+msgstr ""
+
+#: builtin/for-each-ref.c:994
+msgid "quote placeholders suitably for shells"
+msgstr ""
+
+#: builtin/for-each-ref.c:996
+msgid "quote placeholders suitably for perl"
+msgstr ""
+
+#: builtin/for-each-ref.c:998
+msgid "quote placeholders suitably for python"
+msgstr ""
+
+#: builtin/for-each-ref.c:1000
+msgid "quote placeholders suitably for tcl"
+msgstr ""
+
+#: builtin/for-each-ref.c:1003
+msgid "show only <n> matched refs"
+msgstr ""
+
+#: builtin/for-each-ref.c:1004
+msgid "format"
+msgstr ""
+
+#: builtin/for-each-ref.c:1004
+msgid "format to use for the output"
+msgstr ""
+
+#: builtin/for-each-ref.c:1005
+msgid "key"
+msgstr ""
+
+#: builtin/for-each-ref.c:1006
+msgid "field name to sort on"
+msgstr ""
+
+#: builtin/fsck.c:608
+msgid "git fsck [options] [<object>...]"
+msgstr ""
+
+#: builtin/fsck.c:614
+msgid "show unreachable objects"
+msgstr ""
+
+#: builtin/fsck.c:615
+msgid "show dangling objects"
+msgstr ""
+
+#: builtin/fsck.c:616
+msgid "report tags"
+msgstr ""
+
+#: builtin/fsck.c:617
+msgid "report root nodes"
+msgstr ""
+
+#: builtin/fsck.c:618
+msgid "make index objects head nodes"
+msgstr ""
+
+#: builtin/fsck.c:619
+msgid "make reflogs head nodes (default)"
+msgstr ""
+
+#: builtin/fsck.c:620
+msgid "also consider packs and alternate objects"
+msgstr ""
+
+#: builtin/fsck.c:621
+msgid "enable more strict checking"
+msgstr ""
+
+#: builtin/fsck.c:623
+msgid "write dangling objects in .git/lost-found"
+msgstr ""
+
+#: builtin/fsck.c:624 builtin/prune.c:134
+msgid "show progress"
+msgstr ""
+
+#: builtin/gc.c:22
+msgid "git gc [options]"
+msgstr ""
+
+#: builtin/gc.c:63
+#, c-format
+msgid "Invalid %s: '%s'"
+msgstr ""
+
+#: builtin/gc.c:90
+#, c-format
+msgid "insanely long object directory %.*s"
+msgstr ""
+
+#: builtin/gc.c:179
+msgid "prune unreferenced objects"
+msgstr ""
+
+#: builtin/gc.c:181
+msgid "be more thorough (increased runtime)"
+msgstr ""
+
+#: builtin/gc.c:182
+msgid "enable auto-gc mode"
+msgstr ""
+
+#: builtin/gc.c:222
+#, c-format
+msgid ""
+"Auto packing the repository for optimum performance. You may also\n"
+"run \"git gc\" manually. See \"git help gc\" for more information.\n"
+msgstr ""
+
+#: builtin/gc.c:249
+msgid ""
+"There are too many unreachable loose objects; run 'git prune' to remove them."
+msgstr ""
+
+#: builtin/grep.c:22
+msgid "git grep [options] [-e] <pattern> [<rev>...] [[--] <path>...]"
+msgstr ""
+
+#: builtin/grep.c:217
+#, c-format
+msgid "grep: failed to create thread: %s"
+msgstr ""
+
+#: builtin/grep.c:365
+#, c-format
+msgid "Failed to chdir: %s"
+msgstr ""
+
+#: builtin/grep.c:443 builtin/grep.c:478
+#, c-format
+msgid "unable to read tree (%s)"
+msgstr ""
+
+#: builtin/grep.c:493
+#, c-format
+msgid "unable to grep from object of type %s"
+msgstr ""
+
+#: builtin/grep.c:551
+#, c-format
+msgid "switch `%c' expects a numerical value"
+msgstr ""
+
+#: builtin/grep.c:568
+#, c-format
+msgid "cannot open '%s'"
+msgstr ""
+
+#: builtin/grep.c:643
+msgid "search in index instead of in the work tree"
+msgstr ""
+
+#: builtin/grep.c:645
+msgid "find in contents not managed by git"
+msgstr ""
+
+#: builtin/grep.c:647
+msgid "search in both tracked and untracked files"
+msgstr ""
+
+#: builtin/grep.c:649
+msgid "search also in ignored files"
+msgstr ""
+
+#: builtin/grep.c:652
+msgid "show non-matching lines"
+msgstr ""
+
+#: builtin/grep.c:654
+msgid "case insensitive matching"
+msgstr ""
+
+#: builtin/grep.c:656
+msgid "match patterns only at word boundaries"
+msgstr ""
+
+#: builtin/grep.c:658
+msgid "process binary files as text"
+msgstr ""
+
+#: builtin/grep.c:660
+msgid "don't match patterns in binary files"
+msgstr ""
+
+#: builtin/grep.c:663
+msgid "descend at most <depth> levels"
+msgstr ""
+
+#: builtin/grep.c:667
+msgid "use extended POSIX regular expressions"
+msgstr ""
+
+#: builtin/grep.c:670
+msgid "use basic POSIX regular expressions (default)"
+msgstr ""
+
+#: builtin/grep.c:673
+msgid "interpret patterns as fixed strings"
+msgstr ""
+
+#: builtin/grep.c:676
+msgid "use Perl-compatible regular expressions"
+msgstr ""
+
+#: builtin/grep.c:679
+msgid "show line numbers"
+msgstr ""
+
+#: builtin/grep.c:680
+msgid "don't show filenames"
+msgstr ""
+
+#: builtin/grep.c:681
+msgid "show filenames"
+msgstr ""
+
+#: builtin/grep.c:683
+msgid "show filenames relative to top directory"
+msgstr ""
+
+#: builtin/grep.c:685
+msgid "show only filenames instead of matching lines"
+msgstr ""
+
+#: builtin/grep.c:687
+msgid "synonym for --files-with-matches"
+msgstr ""
+
+#: builtin/grep.c:690
+msgid "show only the names of files without match"
+msgstr ""
+
+#: builtin/grep.c:692
+msgid "print NUL after filenames"
+msgstr ""
+
+#: builtin/grep.c:694
+msgid "show the number of matches instead of matching lines"
+msgstr ""
+
+#: builtin/grep.c:695
+msgid "highlight matches"
+msgstr ""
+
+#: builtin/grep.c:697
+msgid "print empty line between matches from different files"
+msgstr ""
+
+#: builtin/grep.c:699
+msgid "show filename only once above matches from same file"
+msgstr ""
+
+#: builtin/grep.c:702
+msgid "show <n> context lines before and after matches"
+msgstr ""
+
+#: builtin/grep.c:705
+msgid "show <n> context lines before matches"
+msgstr ""
+
+#: builtin/grep.c:707
+msgid "show <n> context lines after matches"
+msgstr ""
+
+#: builtin/grep.c:708
+msgid "shortcut for -C NUM"
+msgstr ""
+
+#: builtin/grep.c:711
+msgid "show a line with the function name before matches"
+msgstr ""
+
+#: builtin/grep.c:713
+msgid "show the surrounding function"
+msgstr ""
+
+#: builtin/grep.c:716
+msgid "read patterns from file"
+msgstr ""
+
+#: builtin/grep.c:718
+msgid "match <pattern>"
+msgstr ""
+
+#: builtin/grep.c:720
+msgid "combine patterns specified with -e"
+msgstr ""
+
+#: builtin/grep.c:732
+msgid "indicate hit with exit status without output"
+msgstr ""
+
+#: builtin/grep.c:734
+msgid "show only matches from files that match all patterns"
+msgstr ""
+
+#: builtin/grep.c:736
+msgid "show parse tree for grep expression"
+msgstr ""
+
+#: builtin/grep.c:740
+msgid "pager"
+msgstr ""
+
+#: builtin/grep.c:740
+msgid "show matching files in the pager"
+msgstr ""
+
+#: builtin/grep.c:743
+msgid "allow calling of grep(1) (ignored by this build)"
+msgstr ""
+
+#: builtin/grep.c:744 builtin/show-ref.c:184
+msgid "show usage"
+msgstr ""
+
+#: builtin/grep.c:811
+msgid "no pattern given."
+msgstr ""
+
+#: builtin/grep.c:866
+msgid "--open-files-in-pager only works on the worktree"
+msgstr ""
+
+#: builtin/grep.c:889
+msgid "--cached or --untracked cannot be used with --no-index."
+msgstr ""
+
+#: builtin/grep.c:894
+msgid "--no-index or --untracked cannot be used with revs."
+msgstr ""
+
+#: builtin/grep.c:897
+msgid "--[no-]exclude-standard cannot be used for tracked contents."
+msgstr ""
+
+#: builtin/grep.c:905
+msgid "both --cached and trees are given."
+msgstr ""
+
+#: builtin/hash-object.c:60
+msgid ""
+"git hash-object [-t <type>] [-w] [--path=<file>|--no-filters] [--stdin] [--] "
+"<file>..."
+msgstr ""
+
+#: builtin/hash-object.c:61
+msgid "git hash-object  --stdin-paths < <list-of-paths>"
+msgstr ""
+
+#: builtin/hash-object.c:72
+msgid "type"
+msgstr ""
+
+#: builtin/hash-object.c:72
+msgid "object type"
+msgstr ""
+
+#: builtin/hash-object.c:73
+msgid "write the object into the object database"
+msgstr ""
+
+#: builtin/hash-object.c:74
+msgid "read the object from stdin"
+msgstr ""
+
+#: builtin/hash-object.c:76
+msgid "store file as is without filters"
+msgstr ""
+
+#: builtin/hash-object.c:77
+msgid "process file as it were from this path"
+msgstr ""
+
+#: builtin/help.c:43
+msgid "print all available commands"
+msgstr ""
+
+#: builtin/help.c:44
+msgid "print list of useful guides"
+msgstr ""
+
+#: builtin/help.c:45
+msgid "show man page"
+msgstr ""
+
+#: builtin/help.c:46
+msgid "show manual in web browser"
+msgstr ""
+
+#: builtin/help.c:48
+msgid "show info page"
+msgstr ""
+
+#: builtin/help.c:54
+msgid "git help [--all] [--guides] [--man|--web|--info] [command]"
+msgstr ""
+
+#: builtin/help.c:66
+#, c-format
+msgid "unrecognized help format '%s'"
+msgstr ""
+
+#: builtin/help.c:94
+msgid "Failed to start emacsclient."
+msgstr ""
+
+#: builtin/help.c:107
+msgid "Failed to parse emacsclient version."
+msgstr ""
+
+#: builtin/help.c:115
+#, c-format
+msgid "emacsclient version '%d' too old (< 22)."
+msgstr ""
+
+#: builtin/help.c:133 builtin/help.c:161 builtin/help.c:170 builtin/help.c:178
+#, c-format
+msgid "failed to exec '%s': %s"
+msgstr ""
+
+#: builtin/help.c:218
+#, c-format
+msgid ""
+"'%s': path for unsupported man viewer.\n"
+"Please consider using 'man.<tool>.cmd' instead."
+msgstr ""
+
+#: builtin/help.c:230
+#, c-format
+msgid ""
+"'%s': cmd for supported man viewer.\n"
+"Please consider using 'man.<tool>.path' instead."
+msgstr ""
+
+#: builtin/help.c:351
+#, c-format
+msgid "'%s': unknown man viewer."
+msgstr ""
+
+#: builtin/help.c:368
+msgid "no man viewer handled the request"
+msgstr ""
+
+#: builtin/help.c:376
+msgid "no info viewer handled the request"
+msgstr ""
+
+#: builtin/help.c:422
+msgid "Defining attributes per path"
+msgstr ""
+
+#: builtin/help.c:423
+msgid "A Git glossary"
+msgstr ""
+
+#: builtin/help.c:424
+msgid "Specifies intentionally untracked files to ignore"
+msgstr ""
+
+#: builtin/help.c:425
+msgid "Defining submodule properties"
+msgstr ""
+
+#: builtin/help.c:426
+msgid "Specifying revisions and ranges for Git"
+msgstr ""
+
+#: builtin/help.c:427
+msgid "A tutorial introduction to Git (for version 1.5.1 or newer)"
+msgstr ""
+
+#: builtin/help.c:428
+msgid "An overview of recommended workflows with Git"
+msgstr ""
+
+#: builtin/help.c:440
+msgid "The common Git guides are:\n"
+msgstr ""
+
+#: builtin/help.c:462 builtin/help.c:478
+#, c-format
+msgid "usage: %s%s"
+msgstr ""
+
+#: builtin/help.c:494
+#, c-format
+msgid "`git %s' is aliased to `%s'"
+msgstr ""
+
+#: builtin/index-pack.c:182
+#, c-format
+msgid "object type mismatch at %s"
+msgstr ""
+
+#: builtin/index-pack.c:202
+msgid "object of unexpected type"
+msgstr ""
+
+#: builtin/index-pack.c:239
+#, c-format
+msgid "cannot fill %d byte"
+msgid_plural "cannot fill %d bytes"
+msgstr[0] ""
+msgstr[1] ""
+
+#: builtin/index-pack.c:249
+msgid "early EOF"
+msgstr ""
+
+#: builtin/index-pack.c:250
+msgid "read error on input"
+msgstr ""
+
+#: builtin/index-pack.c:262
+msgid "used more bytes than were available"
+msgstr ""
+
+#: builtin/index-pack.c:269
+msgid "pack too large for current definition of off_t"
+msgstr ""
+
+#: builtin/index-pack.c:285
+#, c-format
+msgid "unable to create '%s'"
+msgstr ""
+
+#: builtin/index-pack.c:290
+#, c-format
+msgid "cannot open packfile '%s'"
+msgstr ""
+
+#: builtin/index-pack.c:304
+msgid "pack signature mismatch"
+msgstr ""
+
+#: builtin/index-pack.c:306
+#, c-format
+msgid "pack version %<PRIu32> unsupported"
+msgstr ""
+
+#: builtin/index-pack.c:324
+#, c-format
+msgid "pack has bad object at offset %lu: %s"
+msgstr ""
+
+#: builtin/index-pack.c:446
+#, c-format
+msgid "inflate returned %d"
+msgstr ""
+
+#: builtin/index-pack.c:495
+msgid "offset value overflow for delta base object"
+msgstr ""
+
+#: builtin/index-pack.c:503
+msgid "delta base offset is out of bound"
+msgstr ""
+
+#: builtin/index-pack.c:511
+#, c-format
+msgid "unknown object type %d"
+msgstr ""
+
+#: builtin/index-pack.c:542
+msgid "cannot pread pack file"
+msgstr ""
+
+#: builtin/index-pack.c:544
+#, c-format
+msgid "premature end of pack file, %lu byte missing"
+msgid_plural "premature end of pack file, %lu bytes missing"
+msgstr[0] ""
+msgstr[1] ""
+
+#: builtin/index-pack.c:570
+msgid "serious inflate inconsistency"
+msgstr ""
+
+#: builtin/index-pack.c:661 builtin/index-pack.c:667 builtin/index-pack.c:690
+#: builtin/index-pack.c:724 builtin/index-pack.c:733
+#, c-format
+msgid "SHA1 COLLISION FOUND WITH %s !"
+msgstr ""
+
+#: builtin/index-pack.c:664 builtin/pack-objects.c:170
+#: builtin/pack-objects.c:262
+#, c-format
+msgid "unable to read %s"
+msgstr ""
+
+#: builtin/index-pack.c:730
+#, c-format
+msgid "cannot read existing object %s"
+msgstr ""
+
+#: builtin/index-pack.c:744
+#, c-format
+msgid "invalid blob object %s"
+msgstr ""
+
+#: builtin/index-pack.c:759
+#, c-format
+msgid "invalid %s"
+msgstr ""
+
+#: builtin/index-pack.c:761
+msgid "Error in object"
+msgstr ""
+
+#: builtin/index-pack.c:763
+#, c-format
+msgid "Not all child objects of %s are reachable"
+msgstr ""
+
+#: builtin/index-pack.c:833 builtin/index-pack.c:863
+msgid "failed to apply delta"
+msgstr ""
+
+#: builtin/index-pack.c:1004
+msgid "Receiving objects"
+msgstr ""
+
+#: builtin/index-pack.c:1004
+msgid "Indexing objects"
+msgstr ""
+
+#: builtin/index-pack.c:1030
+msgid "pack is corrupted (SHA1 mismatch)"
+msgstr ""
+
+#: builtin/index-pack.c:1035
+msgid "cannot fstat packfile"
+msgstr ""
+
+#: builtin/index-pack.c:1038
+msgid "pack has junk at the end"
+msgstr ""
+
+#: builtin/index-pack.c:1049
+msgid "confusion beyond insanity in parse_pack_objects()"
+msgstr ""
+
+#: builtin/index-pack.c:1072
+msgid "Resolving deltas"
+msgstr ""
+
+#: builtin/index-pack.c:1082
+#, c-format
+msgid "unable to create thread: %s"
+msgstr ""
+
+#: builtin/index-pack.c:1124
+msgid "confusion beyond insanity"
+msgstr ""
+
+#: builtin/index-pack.c:1132
+#, c-format
+msgid "completed with %d local objects"
+msgstr ""
+
+#: builtin/index-pack.c:1142
+#, c-format
+msgid "Unexpected tail checksum for %s (disk corruption?)"
+msgstr ""
+
+#: builtin/index-pack.c:1146
+#, c-format
+msgid "pack has %d unresolved delta"
+msgid_plural "pack has %d unresolved deltas"
+msgstr[0] ""
+msgstr[1] ""
+
+#: builtin/index-pack.c:1171
+#, c-format
+msgid "unable to deflate appended object (%d)"
+msgstr ""
+
+#: builtin/index-pack.c:1250
+#, c-format
+msgid "local object %s is corrupt"
+msgstr ""
+
+#: builtin/index-pack.c:1274
+msgid "error while closing pack file"
+msgstr ""
+
+#: builtin/index-pack.c:1287
+#, c-format
+msgid "cannot write keep file '%s'"
+msgstr ""
+
+#: builtin/index-pack.c:1295
+#, c-format
+msgid "cannot close written keep file '%s'"
+msgstr ""
+
+#: builtin/index-pack.c:1308
+msgid "cannot store pack file"
+msgstr ""
+
+#: builtin/index-pack.c:1319
+msgid "cannot store index file"
+msgstr ""
+
+#: builtin/index-pack.c:1352
+#, c-format
+msgid "bad pack.indexversion=%<PRIu32>"
+msgstr ""
+
+#: builtin/index-pack.c:1358
+#, c-format
+msgid "invalid number of threads specified (%d)"
+msgstr ""
+
+#: builtin/index-pack.c:1362 builtin/index-pack.c:1535
+#, c-format
+msgid "no threads support, ignoring %s"
+msgstr ""
+
+#: builtin/index-pack.c:1420
+#, c-format
+msgid "Cannot open existing pack file '%s'"
+msgstr ""
+
+#: builtin/index-pack.c:1422
+#, c-format
+msgid "Cannot open existing pack idx file for '%s'"
+msgstr ""
+
+#: builtin/index-pack.c:1469
+#, c-format
+msgid "non delta: %d object"
+msgid_plural "non delta: %d objects"
+msgstr[0] ""
+msgstr[1] ""
+
+#: builtin/index-pack.c:1476
+#, c-format
+msgid "chain length = %d: %lu object"
+msgid_plural "chain length = %d: %lu objects"
+msgstr[0] ""
+msgstr[1] ""
+
+#: builtin/index-pack.c:1503
+msgid "Cannot come back to cwd"
+msgstr ""
+
+#: builtin/index-pack.c:1547 builtin/index-pack.c:1550
+#: builtin/index-pack.c:1562 builtin/index-pack.c:1566
+#, c-format
+msgid "bad %s"
+msgstr ""
+
+#: builtin/index-pack.c:1580
+msgid "--fix-thin cannot be used without --stdin"
+msgstr ""
+
+#: builtin/index-pack.c:1584 builtin/index-pack.c:1594
+#, c-format
+msgid "packfile name '%s' does not end with '.pack'"
+msgstr ""
+
+#: builtin/index-pack.c:1603
+msgid "--verify with no packfile name given"
+msgstr ""
+
+#: builtin/init-db.c:35
+#, c-format
+msgid "Could not make %s writable by group"
+msgstr ""
+
+#: builtin/init-db.c:62
+#, c-format
+msgid "insanely long template name %s"
+msgstr ""
+
+#: builtin/init-db.c:67
+#, c-format
+msgid "cannot stat '%s'"
+msgstr ""
+
+#: builtin/init-db.c:73
+#, c-format
+msgid "cannot stat template '%s'"
+msgstr ""
+
+#: builtin/init-db.c:80
+#, c-format
+msgid "cannot opendir '%s'"
+msgstr ""
+
+#: builtin/init-db.c:97
+#, c-format
+msgid "cannot readlink '%s'"
+msgstr ""
+
+#: builtin/init-db.c:99
+#, c-format
+msgid "insanely long symlink %s"
+msgstr ""
+
+#: builtin/init-db.c:102
+#, c-format
+msgid "cannot symlink '%s' '%s'"
+msgstr ""
+
+#: builtin/init-db.c:106
+#, c-format
+msgid "cannot copy '%s' to '%s'"
+msgstr ""
+
+#: builtin/init-db.c:110
+#, c-format
+msgid "ignoring template %s"
+msgstr ""
+
+#: builtin/init-db.c:133
+#, c-format
+msgid "insanely long template path %s"
+msgstr ""
+
+#: builtin/init-db.c:141
+#, c-format
+msgid "templates not found %s"
+msgstr ""
+
+#: builtin/init-db.c:154
+#, c-format
+msgid "not copying templates of a wrong format version %d from '%s'"
+msgstr ""
+
+#: builtin/init-db.c:192
+#, c-format
+msgid "insane git directory %s"
+msgstr ""
+
+#: builtin/init-db.c:323 builtin/init-db.c:326
+#, c-format
+msgid "%s already exists"
+msgstr "%s existe déjà"
+
+#: builtin/init-db.c:355
+#, c-format
+msgid "unable to handle file type %d"
+msgstr ""
+
+#: builtin/init-db.c:358
+#, c-format
+msgid "unable to move %s to %s"
+msgstr ""
+
+#: builtin/init-db.c:363
+#, c-format
+msgid "Could not create git link %s"
+msgstr ""
+
+#.
+#. * TRANSLATORS: The first '%s' is either "Reinitialized
+#. * existing" or "Initialized empty", the second " shared" or
+#. * "", and the last '%s%s' is the verbatim directory name.
+#.
+#: builtin/init-db.c:420
+#, c-format
+msgid "%s%s Git repository in %s%s\n"
+msgstr "%s%s Dépôt git dans %s%s\n"
+
+#: builtin/init-db.c:421
+msgid "Reinitialized existing"
+msgstr ""
+
+#: builtin/init-db.c:421
+msgid "Initialized empty"
+msgstr ""
+
+#: builtin/init-db.c:422
+msgid " shared"
+msgstr ""
+
+#: builtin/init-db.c:441
+msgid "cannot tell cwd"
+msgstr ""
+
+#: builtin/init-db.c:467
+msgid ""
+"git init [-q | --quiet] [--bare] [--template=<template-directory>] [--"
+"shared[=<permissions>]] [directory]"
+msgstr ""
+
+#: builtin/init-db.c:490
+msgid "permissions"
+msgstr ""
+
+#: builtin/init-db.c:491
+msgid "specify that the git repository is to be shared amongst several users"
+msgstr ""
+
+#: builtin/init-db.c:493 builtin/prune-packed.c:77
+msgid "be quiet"
+msgstr ""
+
+#: builtin/init-db.c:522 builtin/init-db.c:529
+#, c-format
+msgid "cannot mkdir %s"
+msgstr ""
+
+#: builtin/init-db.c:533
+#, c-format
+msgid "cannot chdir to %s"
+msgstr ""
+
+#: builtin/init-db.c:555
+#, c-format
+msgid ""
+"%s (or --work-tree=<directory>) not allowed without specifying %s (or --git-"
+"dir=<directory>)"
+msgstr ""
+
+#: builtin/init-db.c:579
+msgid "Cannot access current working directory"
+msgstr ""
+
+#: builtin/init-db.c:586
+#, c-format
+msgid "Cannot access work tree '%s'"
+msgstr ""
+
+#: builtin/log.c:40
+msgid "git log [<options>] [<revision range>] [[--] <path>...]\n"
+msgstr ""
+
+#: builtin/log.c:41
+msgid "   or: git show [options] <object>..."
+msgstr ""
+
+#: builtin/log.c:103
+msgid "suppress diff output"
+msgstr ""
+
+#: builtin/log.c:104
+msgid "show source"
+msgstr ""
+
+#: builtin/log.c:105
+msgid "Use mail map file"
+msgstr ""
+
+#: builtin/log.c:106
+msgid "decorate options"
+msgstr ""
+
+#: builtin/log.c:199
+#, c-format
+msgid "Final output: %d %s\n"
+msgstr ""
+
+#: builtin/log.c:422 builtin/log.c:514
+#, c-format
+msgid "Could not read object %s"
+msgstr ""
+
+#: builtin/log.c:538
+#, c-format
+msgid "Unknown type: %d"
+msgstr ""
+
+#: builtin/log.c:638
+msgid "format.headers without value"
+msgstr ""
+
+#: builtin/log.c:720
+msgid "name of output directory is too long"
+msgstr ""
+
+#: builtin/log.c:736
+#, c-format
+msgid "Cannot open patch file %s"
+msgstr ""
+
+#: builtin/log.c:750
+msgid "Need exactly one range."
+msgstr ""
+
+#: builtin/log.c:758
+msgid "Not a range."
+msgstr ""
+
+#: builtin/log.c:860
+msgid "Cover letter needs email format"
+msgstr ""
+
+#: builtin/log.c:936
+#, c-format
+msgid "insane in-reply-to: %s"
+msgstr ""
+
+#: builtin/log.c:964
+msgid "git format-patch [options] [<since> | <revision range>]"
+msgstr ""
+
+#: builtin/log.c:1009
+msgid "Two output directories?"
+msgstr ""
+
+#: builtin/log.c:1108
+msgid "use [PATCH n/m] even with a single patch"
+msgstr ""
+
+#: builtin/log.c:1111
+msgid "use [PATCH] even with multiple patches"
+msgstr ""
+
+#: builtin/log.c:1115
+msgid "print patches to standard out"
+msgstr ""
+
+#: builtin/log.c:1117
+msgid "generate a cover letter"
+msgstr ""
+
+#: builtin/log.c:1119
+msgid "use simple number sequence for output file names"
+msgstr ""
+
+#: builtin/log.c:1120
+msgid "sfx"
+msgstr ""
+
+#: builtin/log.c:1121
+msgid "use <sfx> instead of '.patch'"
+msgstr ""
+
+#: builtin/log.c:1123
+msgid "start numbering patches at <n> instead of 1"
+msgstr ""
+
+#: builtin/log.c:1125
+msgid "mark the series as Nth re-roll"
+msgstr ""
+
+#: builtin/log.c:1127
+msgid "Use [<prefix>] instead of [PATCH]"
+msgstr ""
+
+#: builtin/log.c:1130
+msgid "store resulting files in <dir>"
+msgstr ""
+
+#: builtin/log.c:1133
+msgid "don't strip/add [PATCH]"
+msgstr ""
+
+#: builtin/log.c:1136
+msgid "don't output binary diffs"
+msgstr ""
+
+#: builtin/log.c:1138
+msgid "don't include a patch matching a commit upstream"
+msgstr ""
+
+#: builtin/log.c:1140
+msgid "show patch format instead of default (patch + stat)"
+msgstr ""
+
+#: builtin/log.c:1142
+msgid "Messaging"
+msgstr ""
+
+#: builtin/log.c:1143
+msgid "header"
+msgstr ""
+
+#: builtin/log.c:1144
+msgid "add email header"
+msgstr ""
+
+#: builtin/log.c:1145 builtin/log.c:1147
+msgid "email"
+msgstr ""
+
+#: builtin/log.c:1145
+msgid "add To: header"
+msgstr ""
+
+#: builtin/log.c:1147
+msgid "add Cc: header"
+msgstr ""
+
+#: builtin/log.c:1149
+msgid "message-id"
+msgstr ""
+
+#: builtin/log.c:1150
+msgid "make first mail a reply to <message-id>"
+msgstr ""
+
+#: builtin/log.c:1151 builtin/log.c:1154
+msgid "boundary"
+msgstr ""
+
+#: builtin/log.c:1152
+msgid "attach the patch"
+msgstr ""
+
+#: builtin/log.c:1155
+msgid "inline the patch"
+msgstr ""
+
+#: builtin/log.c:1159
+msgid "enable message threading, styles: shallow, deep"
+msgstr ""
+
+#: builtin/log.c:1161
+msgid "signature"
+msgstr ""
+
+#: builtin/log.c:1162
+msgid "add a signature"
+msgstr ""
+
+#: builtin/log.c:1164
+msgid "don't print the patch filenames"
+msgstr ""
+
+#: builtin/log.c:1248
+msgid "-n and -k are mutually exclusive."
+msgstr ""
+
+#: builtin/log.c:1250
+msgid "--subject-prefix and -k are mutually exclusive."
+msgstr ""
+
+#: builtin/log.c:1258
+msgid "--name-only does not make sense"
+msgstr ""
+
+#: builtin/log.c:1260
+msgid "--name-status does not make sense"
+msgstr ""
+
+#: builtin/log.c:1262
+msgid "--check does not make sense"
+msgstr ""
+
+#: builtin/log.c:1285
+msgid "standard output, or directory, which one?"
+msgstr ""
+
+#: builtin/log.c:1287
+#, c-format
+msgid "Could not create directory '%s'"
+msgstr ""
+
+#: builtin/log.c:1435
+msgid "Failed to create output files"
+msgstr ""
+
+#: builtin/log.c:1484
+msgid "git cherry [-v] [<upstream> [<head> [<limit>]]]"
+msgstr ""
+
+#: builtin/log.c:1539
+#, c-format
+msgid ""
+"Could not find a tracked remote branch, please specify <upstream> manually.\n"
+msgstr ""
+
+#: builtin/log.c:1552 builtin/log.c:1554 builtin/log.c:1566
+#, c-format
+msgid "Unknown commit %s"
+msgstr ""
+
+#: builtin/ls-files.c:402
+msgid "git ls-files [options] [<file>...]"
+msgstr ""
+
+#: builtin/ls-files.c:459
+msgid "identify the file status with tags"
+msgstr ""
+
+#: builtin/ls-files.c:461
+msgid "use lowercase letters for 'assume unchanged' files"
+msgstr ""
+
+#: builtin/ls-files.c:463
+msgid "show cached files in the output (default)"
+msgstr ""
+
+#: builtin/ls-files.c:465
+msgid "show deleted files in the output"
+msgstr ""
+
+#: builtin/ls-files.c:467
+msgid "show modified files in the output"
+msgstr ""
+
+#: builtin/ls-files.c:469
+msgid "show other files in the output"
+msgstr ""
+
+#: builtin/ls-files.c:471
+msgid "show ignored files in the output"
+msgstr ""
+
+#: builtin/ls-files.c:474
+msgid "show staged contents' object name in the output"
+msgstr ""
+
+#: builtin/ls-files.c:476
+msgid "show files on the filesystem that need to be removed"
+msgstr ""
+
+#: builtin/ls-files.c:478
+msgid "show 'other' directories' name only"
+msgstr ""
+
+#: builtin/ls-files.c:481
+msgid "don't show empty directories"
+msgstr ""
+
+#: builtin/ls-files.c:484
+msgid "show unmerged files in the output"
+msgstr ""
+
+#: builtin/ls-files.c:486
+msgid "show resolve-undo information"
+msgstr ""
+
+#: builtin/ls-files.c:488
+msgid "skip files matching pattern"
+msgstr ""
+
+#: builtin/ls-files.c:491
+msgid "exclude patterns are read from <file>"
+msgstr ""
+
+#: builtin/ls-files.c:494
+msgid "read additional per-directory exclude patterns in <file>"
+msgstr ""
+
+#: builtin/ls-files.c:496
+msgid "add the standard git exclusions"
+msgstr ""
+
+#: builtin/ls-files.c:499
+msgid "make the output relative to the project top directory"
+msgstr ""
+
+#: builtin/ls-files.c:502
+msgid "if any <file> is not in the index, treat this as an error"
+msgstr ""
+
+#: builtin/ls-files.c:503
+msgid "tree-ish"
+msgstr ""
+
+#: builtin/ls-files.c:504
+msgid "pretend that paths removed since <tree-ish> are still present"
+msgstr ""
+
+#: builtin/ls-files.c:506
+msgid "show debugging data"
+msgstr ""
+
+#: builtin/ls-tree.c:27
+msgid "git ls-tree [<options>] <tree-ish> [<path>...]"
+msgstr ""
+
+#: builtin/ls-tree.c:125
+msgid "only show trees"
+msgstr ""
+
+#: builtin/ls-tree.c:127
+msgid "recurse into subtrees"
+msgstr ""
+
+#: builtin/ls-tree.c:129
+msgid "show trees when recursing"
+msgstr ""
+
+#: builtin/ls-tree.c:132
+msgid "terminate entries with NUL byte"
+msgstr ""
+
+#: builtin/ls-tree.c:133
+msgid "include object size"
+msgstr ""
+
+#: builtin/ls-tree.c:135 builtin/ls-tree.c:137
+msgid "list only filenames"
+msgstr ""
+
+#: builtin/ls-tree.c:140
+msgid "use full path names"
+msgstr ""
+
+#: builtin/ls-tree.c:142
+msgid "list entire tree; not just current directory (implies --full-name)"
+msgstr ""
+
+#: builtin/merge.c:43
+msgid "git merge [options] [<commit>...]"
+msgstr ""
+
+#: builtin/merge.c:44
+msgid "git merge [options] <msg> HEAD <commit>"
+msgstr ""
+
+#: builtin/merge.c:45
+msgid "git merge --abort"
+msgstr ""
+
+#: builtin/merge.c:90
+msgid "switch `m' requires a value"
+msgstr ""
+
+#: builtin/merge.c:127
+#, c-format
+msgid "Could not find merge strategy '%s'.\n"
+msgstr ""
+
+#: builtin/merge.c:128
+#, c-format
+msgid "Available strategies are:"
+msgstr ""
+
+#: builtin/merge.c:133
+#, c-format
+msgid "Available custom strategies are:"
+msgstr ""
+
+#: builtin/merge.c:183
+msgid "do not show a diffstat at the end of the merge"
+msgstr ""
+
+#: builtin/merge.c:186
+msgid "show a diffstat at the end of the merge"
+msgstr ""
+
+#: builtin/merge.c:187
+msgid "(synonym to --stat)"
+msgstr ""
+
+#: builtin/merge.c:189
+msgid "add (at most <n>) entries from shortlog to merge commit message"
+msgstr ""
+
+#: builtin/merge.c:192
+msgid "create a single commit instead of doing a merge"
+msgstr ""
+
+#: builtin/merge.c:194
+msgid "perform a commit if the merge succeeds (default)"
+msgstr ""
+
+#: builtin/merge.c:196
+msgid "edit message before committing"
+msgstr ""
+
+#: builtin/merge.c:198
+msgid "allow fast-forward (default)"
+msgstr ""
+
+#: builtin/merge.c:200
+msgid "abort if fast-forward is not possible"
+msgstr ""
+
+#: builtin/merge.c:203
+msgid "Verify that the named commit has a valid GPG signature"
+msgstr ""
+
+#: builtin/merge.c:204 builtin/notes.c:866 builtin/revert.c:112
+msgid "strategy"
+msgstr ""
+
+#: builtin/merge.c:205
+msgid "merge strategy to use"
+msgstr ""
+
+#: builtin/merge.c:206
+msgid "option=value"
+msgstr ""
+
+#: builtin/merge.c:207
+msgid "option for selected merge strategy"
+msgstr ""
+
+#: builtin/merge.c:209
+msgid "merge commit message (for a non-fast-forward merge)"
+msgstr ""
+
+#: builtin/merge.c:213
+msgid "abort the current in-progress merge"
+msgstr ""
+
+#: builtin/merge.c:242
+msgid "could not run stash."
+msgstr ""
+
+#: builtin/merge.c:247
+msgid "stash failed"
+msgstr ""
+
+#: builtin/merge.c:252
+#, c-format
+msgid "not a valid object: %s"
+msgstr ""
+
+#: builtin/merge.c:271 builtin/merge.c:288
+msgid "read-tree failed"
+msgstr ""
+
+#: builtin/merge.c:318
+msgid " (nothing to squash)"
+msgstr " (rien à compresser)"
+
+#: builtin/merge.c:331
+#, c-format
+msgid "Squash commit -- not updating HEAD\n"
+msgstr ""
+
+#: builtin/merge.c:363
+msgid "Writing SQUASH_MSG"
+msgstr ""
+
+#: builtin/merge.c:365
+msgid "Finishing SQUASH_MSG"
+msgstr ""
+
+#: builtin/merge.c:388
+#, c-format
+msgid "No merge message -- not updating HEAD\n"
+msgstr ""
+
+#: builtin/merge.c:438
+#, c-format
+msgid "'%s' does not point to a commit"
+msgstr ""
+
+#: builtin/merge.c:550
+#, c-format
+msgid "Bad branch.%s.mergeoptions string: %s"
+msgstr ""
+
+#: builtin/merge.c:643
+msgid "git write-tree failed to write a tree"
+msgstr ""
+
+#: builtin/merge.c:671
+msgid "Not handling anything other than two heads merge."
+msgstr ""
+
+#: builtin/merge.c:685
+#, c-format
+msgid "Unknown option for merge-recursive: -X%s"
+msgstr ""
+
+#: builtin/merge.c:699
+#, c-format
+msgid "unable to write %s"
+msgstr ""
+
+#: builtin/merge.c:788
+#, c-format
+msgid "Could not read from '%s'"
+msgstr ""
+
+#: builtin/merge.c:797
+#, c-format
+msgid "Not committing merge; use 'git commit' to complete the merge.\n"
+msgstr ""
+
+#: builtin/merge.c:803
+#, c-format
+msgid ""
+"Please enter a commit message to explain why this merge is necessary,\n"
+"especially if it merges an updated upstream into a topic branch.\n"
+"\n"
+"Lines starting with '%c' will be ignored, and an empty message aborts\n"
+"the commit.\n"
+msgstr ""
+
+#: builtin/merge.c:827
+msgid "Empty commit message."
+msgstr ""
+
+#: builtin/merge.c:839
+#, c-format
+msgid "Wonderful.\n"
+msgstr ""
+
+#: builtin/merge.c:904
+#, c-format
+msgid "Automatic merge failed; fix conflicts and then commit the result.\n"
+msgstr ""
+
+#: builtin/merge.c:920
+#, c-format
+msgid "'%s' is not a commit"
+msgstr ""
+
+#: builtin/merge.c:961
+msgid "No current branch."
+msgstr ""
+
+#: builtin/merge.c:963
+msgid "No remote for the current branch."
+msgstr ""
+
+#: builtin/merge.c:965
+msgid "No default upstream defined for the current branch."
+msgstr ""
+
+#: builtin/merge.c:970
+#, c-format
+msgid "No remote tracking branch for %s from %s"
+msgstr ""
+
+#: builtin/merge.c:1057 builtin/merge.c:1214
+#, c-format
+msgid "%s - not something we can merge"
+msgstr ""
+
+#: builtin/merge.c:1125
+msgid "There is no merge to abort (MERGE_HEAD missing)."
+msgstr ""
+
+#: builtin/merge.c:1141 git-pull.sh:31
+msgid ""
+"You have not concluded your merge (MERGE_HEAD exists).\n"
+"Please, commit your changes before you can merge."
+msgstr ""
+
+#: builtin/merge.c:1144 git-pull.sh:34
+msgid "You have not concluded your merge (MERGE_HEAD exists)."
+msgstr ""
+
+#: builtin/merge.c:1148
+msgid ""
+"You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists).\n"
+"Please, commit your changes before you can merge."
+msgstr ""
+
+#: builtin/merge.c:1151
+msgid "You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists)."
+msgstr ""
+
+#: builtin/merge.c:1160
+msgid "You cannot combine --squash with --no-ff."
+msgstr ""
+
+#: builtin/merge.c:1165
+msgid "You cannot combine --no-ff with --ff-only."
+msgstr ""
+
+#: builtin/merge.c:1172
+msgid "No commit specified and merge.defaultToUpstream not set."
+msgstr ""
+
+#: builtin/merge.c:1204
+msgid "Can merge only exactly one commit into empty head"
+msgstr ""
+
+#: builtin/merge.c:1207
+msgid "Squash commit into empty head not supported yet"
+msgstr ""
+
+#: builtin/merge.c:1209
+msgid "Non-fast-forward commit does not make sense into an empty head"
+msgstr ""
+
+#: builtin/merge.c:1265
+#, c-format
+msgid "Commit %s has an untrusted GPG signature, allegedly by %s."
+msgstr ""
+
+#: builtin/merge.c:1268
+#, c-format
+msgid "Commit %s has a bad GPG signature allegedly by %s."
+msgstr ""
+
+#. 'N'
+#: builtin/merge.c:1271
+#, c-format
+msgid "Commit %s does not have a GPG signature."
+msgstr ""
+
+#: builtin/merge.c:1274
+#, c-format
+msgid "Commit %s has a good GPG signature by %s\n"
+msgstr ""
+
+#: builtin/merge.c:1358
+#, c-format
+msgid "Updating %s..%s\n"
+msgstr ""
+
+#: builtin/merge.c:1397
+#, c-format
+msgid "Trying really trivial in-index merge...\n"
+msgstr ""
+
+#: builtin/merge.c:1404
+#, c-format
+msgid "Nope.\n"
+msgstr ""
+
+#: builtin/merge.c:1436
+msgid "Not possible to fast-forward, aborting."
+msgstr ""
+
+#: builtin/merge.c:1459 builtin/merge.c:1538
+#, c-format
+msgid "Rewinding the tree to pristine...\n"
+msgstr ""
+
+#: builtin/merge.c:1463
+#, c-format
+msgid "Trying merge strategy %s...\n"
+msgstr ""
+
+#: builtin/merge.c:1529
+#, c-format
+msgid "No merge strategy handled the merge.\n"
+msgstr ""
+
+#: builtin/merge.c:1531
+#, c-format
+msgid "Merge with strategy %s failed.\n"
+msgstr ""
+
+#: builtin/merge.c:1540
+#, c-format
+msgid "Using the %s to prepare resolving by hand.\n"
+msgstr ""
+
+#: builtin/merge.c:1552
+#, c-format
+msgid "Automatic merge went well; stopped before committing as requested\n"
+msgstr ""
+
+#: builtin/merge-base.c:26
+msgid "git merge-base [-a|--all] <commit> <commit>..."
+msgstr ""
+
+#: builtin/merge-base.c:27
+msgid "git merge-base [-a|--all] --octopus <commit>..."
+msgstr ""
+
+#: builtin/merge-base.c:28
+msgid "git merge-base --independent <commit>..."
+msgstr ""
+
+#: builtin/merge-base.c:29
+msgid "git merge-base --is-ancestor <commit> <commit>"
+msgstr ""
+
+#: builtin/merge-base.c:98
+msgid "output all common ancestors"
+msgstr ""
+
+#: builtin/merge-base.c:99
+msgid "find ancestors for a single n-way merge"
+msgstr ""
+
+#: builtin/merge-base.c:100
+msgid "list revs not reachable from others"
+msgstr ""
+
+#: builtin/merge-base.c:102
+msgid "is the first one ancestor of the other?"
+msgstr ""
+
+#: builtin/merge-file.c:8
+msgid ""
+"git merge-file [options] [-L name1 [-L orig [-L name2]]] file1 orig_file "
+"file2"
+msgstr ""
+
+#: builtin/merge-file.c:33
+msgid "send results to standard output"
+msgstr ""
+
+#: builtin/merge-file.c:34
+msgid "use a diff3 based merge"
+msgstr ""
+
+#: builtin/merge-file.c:35
+msgid "for conflicts, use our version"
+msgstr ""
+
+#: builtin/merge-file.c:37
+msgid "for conflicts, use their version"
+msgstr ""
+
+#: builtin/merge-file.c:39
+msgid "for conflicts, use a union version"
+msgstr ""
+
+#: builtin/merge-file.c:42
+msgid "for conflicts, use this marker size"
+msgstr ""
+
+#: builtin/merge-file.c:43
+msgid "do not warn about conflicts"
+msgstr ""
+
+#: builtin/merge-file.c:45
+msgid "set labels for file1/orig_file/file2"
+msgstr ""
+
+#: builtin/mktree.c:67
+msgid "git mktree [-z] [--missing] [--batch]"
+msgstr ""
+
+#: builtin/mktree.c:153
+msgid "input is NUL terminated"
+msgstr ""
+
+#: builtin/mktree.c:154 builtin/write-tree.c:24
+msgid "allow missing objects"
+msgstr ""
+
+#: builtin/mktree.c:155
+msgid "allow creation of more than one tree"
+msgstr ""
+
+#: builtin/mv.c:14
+msgid "git mv [options] <source>... <destination>"
+msgstr ""
+
+#: builtin/mv.c:64
+msgid "force move/rename even if target exists"
+msgstr ""
+
+#: builtin/mv.c:65
+msgid "skip move/rename errors"
+msgstr ""
+
+#: builtin/mv.c:108
+#, c-format
+msgid "Checking rename of '%s' to '%s'\n"
+msgstr ""
+
+#: builtin/mv.c:112
+msgid "bad source"
+msgstr ""
+
+#: builtin/mv.c:115
+msgid "can not move directory into itself"
+msgstr ""
+
+#: builtin/mv.c:118
+msgid "cannot move directory over file"
+msgstr ""
+
+#: builtin/mv.c:128
+#, c-format
+msgid "Huh? %.*s is in index?"
+msgstr ""
+
+#: builtin/mv.c:140
+msgid "source directory is empty"
+msgstr ""
+
+#: builtin/mv.c:171
+msgid "not under version control"
+msgstr ""
+
+#: builtin/mv.c:173
+msgid "destination exists"
+msgstr ""
+
+#: builtin/mv.c:181
+#, c-format
+msgid "overwriting '%s'"
+msgstr ""
+
+#: builtin/mv.c:184
+msgid "Cannot overwrite"
+msgstr ""
+
+#: builtin/mv.c:187
+msgid "multiple sources for the same target"
+msgstr ""
+
+#: builtin/mv.c:202
+#, c-format
+msgid "%s, source=%s, destination=%s"
+msgstr "%s, source=%s, destination=%s"
+
+#: builtin/mv.c:212
+#, c-format
+msgid "Renaming %s to %s\n"
+msgstr ""
+
+#: builtin/mv.c:215 builtin/remote.c:731
+#, c-format
+msgid "renaming '%s' failed"
+msgstr ""
+
+#: builtin/name-rev.c:175
+msgid "git name-rev [options] <commit>..."
+msgstr ""
+
+#: builtin/name-rev.c:176
+msgid "git name-rev [options] --all"
+msgstr ""
+
+#: builtin/name-rev.c:177
+msgid "git name-rev [options] --stdin"
+msgstr ""
+
+#: builtin/name-rev.c:229
+msgid "print only names (no SHA-1)"
+msgstr ""
+
+#: builtin/name-rev.c:230
+msgid "only use tags to name the commits"
+msgstr ""
+
+#: builtin/name-rev.c:232
+msgid "only use refs matching <pattern>"
+msgstr ""
+
+#: builtin/name-rev.c:234
+msgid "list all commits reachable from all refs"
+msgstr ""
+
+#: builtin/name-rev.c:235
+msgid "read from stdin"
+msgstr ""
+
+#: builtin/name-rev.c:236
+msgid "allow to print `undefined` names"
+msgstr ""
+
+#: builtin/notes.c:26
+msgid "git notes [--ref <notes_ref>] [list [<object>]]"
+msgstr ""
+
+#: builtin/notes.c:27
+msgid ""
+"git notes [--ref <notes_ref>] add [-f] [-m <msg> | -F <file> | (-c | -C) "
+"<object>] [<object>]"
+msgstr ""
+
+#: builtin/notes.c:28
+msgid "git notes [--ref <notes_ref>] copy [-f] <from-object> <to-object>"
+msgstr ""
+
+#: builtin/notes.c:29
+msgid ""
+"git notes [--ref <notes_ref>] append [-m <msg> | -F <file> | (-c | -C) "
+"<object>] [<object>]"
+msgstr ""
+
+#: builtin/notes.c:30
+msgid "git notes [--ref <notes_ref>] edit [<object>]"
+msgstr ""
+
+#: builtin/notes.c:31
+msgid "git notes [--ref <notes_ref>] show [<object>]"
+msgstr ""
+
+#: builtin/notes.c:32
+msgid ""
+"git notes [--ref <notes_ref>] merge [-v | -q] [-s <strategy> ] <notes_ref>"
+msgstr ""
+
+#: builtin/notes.c:33
+msgid "git notes merge --commit [-v | -q]"
+msgstr ""
+
+#: builtin/notes.c:34
+msgid "git notes merge --abort [-v | -q]"
+msgstr ""
+
+#: builtin/notes.c:35
+msgid "git notes [--ref <notes_ref>] remove [<object>...]"
+msgstr ""
+
+#: builtin/notes.c:36
+msgid "git notes [--ref <notes_ref>] prune [-n | -v]"
+msgstr ""
+
+#: builtin/notes.c:37
+msgid "git notes [--ref <notes_ref>] get-ref"
+msgstr ""
+
+#: builtin/notes.c:42
+msgid "git notes [list [<object>]]"
+msgstr ""
+
+#: builtin/notes.c:47
+msgid "git notes add [<options>] [<object>]"
+msgstr ""
+
+#: builtin/notes.c:52
+msgid "git notes copy [<options>] <from-object> <to-object>"
+msgstr ""
+
+#: builtin/notes.c:53
+msgid "git notes copy --stdin [<from-object> <to-object>]..."
+msgstr ""
+
+#: builtin/notes.c:58
+msgid "git notes append [<options>] [<object>]"
+msgstr ""
+
+#: builtin/notes.c:63
+msgid "git notes edit [<object>]"
+msgstr ""
+
+#: builtin/notes.c:68
+msgid "git notes show [<object>]"
+msgstr ""
+
+#: builtin/notes.c:73
+msgid "git notes merge [<options>] <notes_ref>"
+msgstr ""
+
+#: builtin/notes.c:74
+msgid "git notes merge --commit [<options>]"
+msgstr ""
+
+#: builtin/notes.c:75
+msgid "git notes merge --abort [<options>]"
+msgstr ""
+
+#: builtin/notes.c:80
+msgid "git notes remove [<object>]"
+msgstr ""
+
+#: builtin/notes.c:85
+msgid "git notes prune [<options>]"
+msgstr ""
+
+#: builtin/notes.c:90
+msgid "git notes get-ref"
+msgstr ""
+
+#: builtin/notes.c:139
+#, c-format
+msgid "unable to start 'show' for object '%s'"
+msgstr ""
+
+#: builtin/notes.c:143
+msgid "could not read 'show' output"
+msgstr ""
+
+#: builtin/notes.c:151
+#, c-format
+msgid "failed to finish 'show' for object '%s'"
+msgstr ""
+
+#: builtin/notes.c:169 builtin/tag.c:341
+#, c-format
+msgid "could not create file '%s'"
+msgstr ""
+
+#: builtin/notes.c:188
+msgid "Please supply the note contents using either -m or -F option"
+msgstr ""
+
+#: builtin/notes.c:209 builtin/notes.c:972
+#, c-format
+msgid "Removing note for object %s\n"
+msgstr ""
+
+#: builtin/notes.c:214
+msgid "unable to write note object"
+msgstr ""
+
+#: builtin/notes.c:216
+#, c-format
+msgid "The note contents has been left in %s"
+msgstr ""
+
+#: builtin/notes.c:250 builtin/tag.c:540
+#, c-format
+msgid "cannot read '%s'"
+msgstr ""
+
+#: builtin/notes.c:252 builtin/tag.c:543
+#, c-format
+msgid "could not open or read '%s'"
+msgstr ""
+
+#: builtin/notes.c:271 builtin/notes.c:444 builtin/notes.c:446
+#: builtin/notes.c:506 builtin/notes.c:560 builtin/notes.c:643
+#: builtin/notes.c:648 builtin/notes.c:723 builtin/notes.c:765
+#: builtin/notes.c:967 builtin/tag.c:556
+#, c-format
+msgid "Failed to resolve '%s' as a valid ref."
+msgstr ""
+
+#: builtin/notes.c:274
+#, c-format
+msgid "Failed to read object '%s'."
+msgstr ""
+
+#: builtin/notes.c:298
+msgid "Cannot commit uninitialized/unreferenced notes tree"
+msgstr ""
+
+#: builtin/notes.c:339
+#, c-format
+msgid "Bad notes.rewriteMode value: '%s'"
+msgstr ""
+
+#: builtin/notes.c:349
+#, c-format
+msgid "Refusing to rewrite notes in %s (outside of refs/notes/)"
+msgstr ""
+
+#. TRANSLATORS: The first %s is the name of the
+#. environment variable, the second %s is its value
+#: builtin/notes.c:376
+#, c-format
+msgid "Bad %s value: '%s'"
+msgstr ""
+
+#: builtin/notes.c:440
+#, c-format
+msgid "Malformed input line: '%s'."
+msgstr ""
+
+#: builtin/notes.c:455
+#, c-format
+msgid "Failed to copy notes from '%s' to '%s'"
+msgstr ""
+
+#: builtin/notes.c:499 builtin/notes.c:553 builtin/notes.c:626
+#: builtin/notes.c:638 builtin/notes.c:711 builtin/notes.c:758
+#: builtin/notes.c:1032
+msgid "too many parameters"
+msgstr ""
+
+#: builtin/notes.c:512 builtin/notes.c:771
+#, c-format
+msgid "No note found for object %s."
+msgstr ""
+
+#: builtin/notes.c:534 builtin/notes.c:691
+msgid "note contents as a string"
+msgstr ""
+
+#: builtin/notes.c:537 builtin/notes.c:694
+msgid "note contents in a file"
+msgstr ""
+
+#: builtin/notes.c:539 builtin/notes.c:542 builtin/notes.c:696
+#: builtin/notes.c:699 builtin/tag.c:474
+msgid "object"
+msgstr ""
+
+#: builtin/notes.c:540 builtin/notes.c:697
+msgid "reuse and edit specified note object"
+msgstr ""
+
+#: builtin/notes.c:543 builtin/notes.c:700
+msgid "reuse specified note object"
+msgstr ""
+
+#: builtin/notes.c:545 builtin/notes.c:613
+msgid "replace existing notes"
+msgstr ""
+
+#: builtin/notes.c:579
+#, c-format
+msgid ""
+"Cannot add notes. Found existing notes for object %s. Use '-f' to overwrite "
+"existing notes"
+msgstr ""
+
+#: builtin/notes.c:584 builtin/notes.c:661
+#, c-format
+msgid "Overwriting existing notes for object %s\n"
+msgstr ""
+
+#: builtin/notes.c:614
+msgid "read objects from stdin"
+msgstr ""
+
+#: builtin/notes.c:616
+msgid "load rewriting config for <command> (implies --stdin)"
+msgstr ""
+
+#: builtin/notes.c:634
+msgid "too few parameters"
+msgstr ""
+
+#: builtin/notes.c:655
+#, c-format
+msgid ""
+"Cannot copy notes. Found existing notes for object %s. Use '-f' to overwrite "
+"existing notes"
+msgstr ""
+
+#: builtin/notes.c:667
+#, c-format
+msgid "Missing notes on source object %s. Cannot copy."
+msgstr ""
+
+#: builtin/notes.c:716
+#, c-format
+msgid ""
+"The -m/-F/-c/-C options have been deprecated for the 'edit' subcommand.\n"
+"Please use 'git notes add -f -m/-F/-c/-C' instead.\n"
+msgstr ""
+
+#: builtin/notes.c:863
+msgid "General options"
+msgstr ""
+
+#: builtin/notes.c:865
+msgid "Merge options"
+msgstr ""
+
+#: builtin/notes.c:867
+msgid ""
+"resolve notes conflicts using the given strategy (manual/ours/theirs/union/"
+"cat_sort_uniq)"
+msgstr ""
+
+#: builtin/notes.c:869
+msgid "Committing unmerged notes"
+msgstr ""
+
+#: builtin/notes.c:871
+msgid "finalize notes merge by committing unmerged notes"
+msgstr ""
+
+#: builtin/notes.c:873
+msgid "Aborting notes merge resolution"
+msgstr ""
+
+#: builtin/notes.c:875
+msgid "abort notes merge"
+msgstr ""
+
+#: builtin/notes.c:970
+#, c-format
+msgid "Object %s has no note\n"
+msgstr ""
+
+#: builtin/notes.c:982
+msgid "attempt to remove non-existent note is not an error"
+msgstr ""
+
+#: builtin/notes.c:985
+msgid "read object names from the standard input"
+msgstr ""
+
+#: builtin/notes.c:1066
+msgid "notes_ref"
+msgstr ""
+
+#: builtin/notes.c:1067
+msgid "use notes from <notes_ref>"
+msgstr ""
+
+#: builtin/notes.c:1102 builtin/remote.c:1598
+#, c-format
+msgid "Unknown subcommand: %s"
+msgstr ""
+
+#: builtin/pack-objects.c:23
+msgid "git pack-objects --stdout [options...] [< ref-list | < object-list]"
+msgstr ""
+
+#: builtin/pack-objects.c:24
+msgid "git pack-objects [options...] base-name [< ref-list | < object-list]"
+msgstr ""
+
+#: builtin/pack-objects.c:183 builtin/pack-objects.c:186
+#, c-format
+msgid "deflate error (%d)"
+msgstr ""
+
+#: builtin/pack-objects.c:2397
+#, c-format
+msgid "unsupported index version %s"
+msgstr ""
+
+#: builtin/pack-objects.c:2401
+#, c-format
+msgid "bad index version '%s'"
+msgstr ""
+
+#: builtin/pack-objects.c:2424
+#, c-format
+msgid "option %s does not accept negative form"
+msgstr ""
+
+#: builtin/pack-objects.c:2428
+#, c-format
+msgid "unable to parse value '%s' for option %s"
+msgstr ""
+
+#: builtin/pack-objects.c:2447
+msgid "do not show progress meter"
+msgstr ""
+
+#: builtin/pack-objects.c:2449
+msgid "show progress meter"
+msgstr ""
+
+#: builtin/pack-objects.c:2451
+msgid "show progress meter during object writing phase"
+msgstr ""
+
+#: builtin/pack-objects.c:2454
+msgid "similar to --all-progress when progress meter is shown"
+msgstr ""
+
+#: builtin/pack-objects.c:2455
+msgid "version[,offset]"
+msgstr ""
+
+#: builtin/pack-objects.c:2456
+msgid "write the pack index file in the specified idx format version"
+msgstr ""
+
+#: builtin/pack-objects.c:2459
+msgid "maximum size of each output pack file"
+msgstr ""
+
+#: builtin/pack-objects.c:2461
+msgid "ignore borrowed objects from alternate object store"
+msgstr ""
+
+#: builtin/pack-objects.c:2463
+msgid "ignore packed objects"
+msgstr ""
+
+#: builtin/pack-objects.c:2465
+msgid "limit pack window by objects"
+msgstr ""
+
+#: builtin/pack-objects.c:2467
+msgid "limit pack window by memory in addition to object limit"
+msgstr ""
+
+#: builtin/pack-objects.c:2469
+msgid "maximum length of delta chain allowed in the resulting pack"
+msgstr ""
+
+#: builtin/pack-objects.c:2471
+msgid "reuse existing deltas"
+msgstr ""
+
+#: builtin/pack-objects.c:2473
+msgid "reuse existing objects"
+msgstr ""
+
+#: builtin/pack-objects.c:2475
+msgid "use OFS_DELTA objects"
+msgstr ""
+
+#: builtin/pack-objects.c:2477
+msgid "use threads when searching for best delta matches"
+msgstr ""
+
+#: builtin/pack-objects.c:2479
+msgid "do not create an empty pack output"
+msgstr ""
+
+#: builtin/pack-objects.c:2481
+msgid "read revision arguments from standard input"
+msgstr ""
+
+#: builtin/pack-objects.c:2483
+msgid "limit the objects to those that are not yet packed"
+msgstr ""
+
+#: builtin/pack-objects.c:2486
+msgid "include objects reachable from any reference"
+msgstr ""
+
+#: builtin/pack-objects.c:2489
+msgid "include objects referred by reflog entries"
+msgstr ""
+
+#: builtin/pack-objects.c:2492
+msgid "output pack to stdout"
+msgstr ""
+
+#: builtin/pack-objects.c:2494
+msgid "include tag objects that refer to objects to be packed"
+msgstr ""
+
+#: builtin/pack-objects.c:2496
+msgid "keep unreachable objects"
+msgstr ""
+
+#: builtin/pack-objects.c:2497 parse-options.h:141
+msgid "time"
+msgstr ""
+
+#: builtin/pack-objects.c:2498
+msgid "unpack unreachable objects newer than <time>"
+msgstr ""
+
+#: builtin/pack-objects.c:2501
+msgid "create thin packs"
+msgstr ""
+
+#: builtin/pack-objects.c:2503
+msgid "ignore packs that have companion .keep file"
+msgstr ""
+
+#: builtin/pack-objects.c:2505
+msgid "pack compression level"
+msgstr ""
+
+#: builtin/pack-objects.c:2507
+msgid "do not hide commits by grafts"
+msgstr ""
+
+#: builtin/pack-refs.c:6
+msgid "git pack-refs [options]"
+msgstr ""
+
+#: builtin/pack-refs.c:14
+msgid "pack everything"
+msgstr ""
+
+#: builtin/pack-refs.c:15
+msgid "prune loose refs (default)"
+msgstr ""
+
+#: builtin/prune-packed.c:7
+msgid "git prune-packed [-n|--dry-run] [-q|--quiet]"
+msgstr ""
+
+#: builtin/prune.c:12
+msgid "git prune [-n] [-v] [--expire <time>] [--] [<head>...]"
+msgstr ""
+
+#: builtin/prune.c:132
+msgid "do not remove, show only"
+msgstr ""
+
+#: builtin/prune.c:133
+msgid "report pruned objects"
+msgstr ""
+
+#: builtin/prune.c:136
+msgid "expire objects older than <time>"
+msgstr ""
+
+#: builtin/push.c:14
+msgid "git push [<options>] [<repository> [<refspec>...]]"
+msgstr ""
+
+#: builtin/push.c:45
+msgid "tag shorthand without <tag>"
+msgstr ""
+
+#: builtin/push.c:64
+msgid "--delete only accepts plain target ref names"
+msgstr ""
+
+#: builtin/push.c:99
+msgid ""
+"\n"
+"To choose either option permanently, see push.default in 'git help config'."
+msgstr ""
+
+#: builtin/push.c:102
+#, c-format
+msgid ""
+"The upstream branch of your current branch does not match\n"
+"the name of your current branch.  To push to the upstream branch\n"
+"on the remote, use\n"
+"\n"
+"    git push %s HEAD:%s\n"
+"\n"
+"To push to the branch of the same name on the remote, use\n"
+"\n"
+"    git push %s %s\n"
+"%s"
+msgstr ""
+
+#: builtin/push.c:121
+#, c-format
+msgid ""
+"You are not currently on a branch.\n"
+"To push the history leading to the current (detached HEAD)\n"
+"state now, use\n"
+"\n"
+"    git push %s HEAD:<name-of-remote-branch>\n"
+msgstr ""
+
+#: builtin/push.c:128
+#, c-format
+msgid ""
+"The current branch %s has no upstream branch.\n"
+"To push the current branch and set the remote as upstream, use\n"
+"\n"
+"    git push --set-upstream %s %s\n"
+msgstr ""
+
+#: builtin/push.c:136
+#, c-format
+msgid "The current branch %s has multiple upstream branches, refusing to push."
+msgstr ""
+
+#: builtin/push.c:139
+#, c-format
+msgid ""
+"You are pushing to remote '%s', which is not the upstream of\n"
+"your current branch '%s', without telling me what to push\n"
+"to update which remote branch."
+msgstr ""
+
+#: builtin/push.c:151
+msgid ""
+"push.default is unset; its implicit value is changing in\n"
+"Git 2.0 from 'matching' to 'simple'. To squelch this message\n"
+"and maintain the current behavior after the default changes, use:\n"
+"\n"
+"  git config --global push.default matching\n"
+"\n"
+"To squelch this message and adopt the new behavior now, use:\n"
+"\n"
+"  git config --global push.default simple\n"
+"\n"
+"See 'git help config' and search for 'push.default' for further "
+"information.\n"
+"(the 'simple' mode was introduced in Git 1.7.11. Use the similar mode\n"
+"'current' instead of 'simple' if you sometimes use older versions of Git)"
+msgstr ""
+
+#: builtin/push.c:199
+msgid ""
+"You didn't specify any refspecs to push, and push.default is \"nothing\"."
+msgstr ""
+
+#: builtin/push.c:206
+msgid ""
+"Updates were rejected because the tip of your current branch is behind\n"
+"its remote counterpart. Merge the remote changes (e.g. 'git pull')\n"
+"before pushing again.\n"
+"See the 'Note about fast-forwards' in 'git push --help' for details."
+msgstr ""
+
+#: builtin/push.c:212
+msgid ""
+"Updates were rejected because a pushed branch tip is behind its remote\n"
+"counterpart. If you did not intend to push that branch, you may want to\n"
+"specify branches to push or set the 'push.default' configuration variable\n"
+"to 'simple', 'current' or 'upstream' to push only the current branch."
+msgstr ""
+
+#: builtin/push.c:218
+msgid ""
+"Updates were rejected because a pushed branch tip is behind its remote\n"
+"counterpart. Check out this branch and merge the remote changes\n"
+"(e.g. 'git pull') before pushing again.\n"
+"See the 'Note about fast-forwards' in 'git push --help' for details."
+msgstr ""
+
+#: builtin/push.c:224
+msgid ""
+"Updates were rejected because the remote contains work that you do\n"
+"not have locally. This is usually caused by another repository pushing\n"
+"to the same ref. You may want to first merge the remote changes (e.g.,\n"
+"'git pull') before pushing again.\n"
+"See the 'Note about fast-forwards' in 'git push --help' for details."
+msgstr ""
+
+#: builtin/push.c:231
+msgid "Updates were rejected because the tag already exists in the remote."
+msgstr ""
+
+#: builtin/push.c:234
+msgid ""
+"You cannot update a remote ref that points at a non-commit object,\n"
+"or update a remote ref to make it point at a non-commit object,\n"
+"without using the '--force' option.\n"
+msgstr ""
+
+#: builtin/push.c:294
+#, c-format
+msgid "Pushing to %s\n"
+msgstr ""
+
+#: builtin/push.c:298
+#, c-format
+msgid "failed to push some refs to '%s'"
+msgstr ""
+
+#: builtin/push.c:331
+#, c-format
+msgid "bad repository '%s'"
+msgstr ""
+
+#: builtin/push.c:332
+msgid ""
+"No configured push destination.\n"
+"Either specify the URL from the command-line or configure a remote "
+"repository using\n"
+"\n"
+"    git remote add <name> <url>\n"
+"\n"
+"and then push using the remote name\n"
+"\n"
+"    git push <name>\n"
+msgstr ""
+
+#: builtin/push.c:347
+msgid "--all and --tags are incompatible"
+msgstr ""
+
+#: builtin/push.c:348
+msgid "--all can't be combined with refspecs"
+msgstr ""
+
+#: builtin/push.c:353
+msgid "--mirror and --tags are incompatible"
+msgstr ""
+
+#: builtin/push.c:354
+msgid "--mirror can't be combined with refspecs"
+msgstr ""
+
+#: builtin/push.c:359
+msgid "--all and --mirror are incompatible"
+msgstr ""
+
+#: builtin/push.c:419
+msgid "repository"
+msgstr ""
+
+#: builtin/push.c:420
+msgid "push all refs"
+msgstr ""
+
+#: builtin/push.c:421
+msgid "mirror all refs"
+msgstr ""
+
+#: builtin/push.c:423
+msgid "delete refs"
+msgstr ""
+
+#: builtin/push.c:424
+msgid "push tags (can't be used with --all or --mirror)"
+msgstr ""
+
+#: builtin/push.c:427
+msgid "force updates"
+msgstr ""
+
+#: builtin/push.c:428
+msgid "check"
+msgstr ""
+
+#: builtin/push.c:429
+msgid "control recursive pushing of submodules"
+msgstr ""
+
+#: builtin/push.c:431
+msgid "use thin pack"
+msgstr ""
+
+#: builtin/push.c:432 builtin/push.c:433
+msgid "receive pack program"
+msgstr ""
+
+#: builtin/push.c:434
+msgid "set upstream for git pull/status"
+msgstr ""
+
+#: builtin/push.c:437
+msgid "prune locally removed refs"
+msgstr ""
+
+#: builtin/push.c:439
+msgid "bypass pre-push hook"
+msgstr ""
+
+#: builtin/push.c:440
+msgid "push missing but relevant tags"
+msgstr ""
+
+#: builtin/push.c:450
+msgid "--delete is incompatible with --all, --mirror and --tags"
+msgstr ""
+
+#: builtin/push.c:452
+msgid "--delete doesn't make sense without any refs"
+msgstr ""
+
+#: builtin/read-tree.c:36
+msgid ""
+"git read-tree [[-m [--trivial] [--aggressive] | --reset | --prefix=<prefix>] "
+"[-u [--exclude-per-directory=<gitignore>] | -i]] [--no-sparse-checkout] [--"
+"index-output=<file>] (--empty | <tree-ish1> [<tree-ish2> [<tree-ish3>]])"
+msgstr ""
+
+#: builtin/read-tree.c:108
+msgid "write resulting index to <file>"
+msgstr ""
+
+#: builtin/read-tree.c:111
+msgid "only empty the index"
+msgstr ""
+
+#: builtin/read-tree.c:113
+msgid "Merging"
+msgstr ""
+
+#: builtin/read-tree.c:115
+msgid "perform a merge in addition to a read"
+msgstr ""
+
+#: builtin/read-tree.c:117
+msgid "3-way merge if no file level merging required"
+msgstr ""
+
+#: builtin/read-tree.c:119
+msgid "3-way merge in presence of adds and removes"
+msgstr ""
+
+#: builtin/read-tree.c:121
+msgid "same as -m, but discard unmerged entries"
+msgstr ""
+
+#: builtin/read-tree.c:122
+msgid "<subdirectory>/"
+msgstr ""
+
+#: builtin/read-tree.c:123
+msgid "read the tree into the index under <subdirectory>/"
+msgstr ""
+
+#: builtin/read-tree.c:126
+msgid "update working tree with merge result"
+msgstr ""
+
+#: builtin/read-tree.c:128
+msgid "gitignore"
+msgstr ""
+
+#: builtin/read-tree.c:129
+msgid "allow explicitly ignored files to be overwritten"
+msgstr ""
+
+#: builtin/read-tree.c:132
+msgid "don't check the working tree after merging"
+msgstr ""
+
+#: builtin/read-tree.c:133
+msgid "don't update the index or the work tree"
+msgstr ""
+
+#: builtin/read-tree.c:135
+msgid "skip applying sparse checkout filter"
+msgstr ""
+
+#: builtin/read-tree.c:137
+msgid "debug unpack-trees"
+msgstr ""
+
+#: builtin/remote.c:11
+msgid "git remote [-v | --verbose]"
+msgstr "git remote [-v | --verbose]"
+
+#: builtin/remote.c:12
+msgid ""
+"git remote add [-t <branch>] [-m <master>] [-f] [--tags|--no-tags] [--"
+"mirror=<fetch|push>] <name> <url>"
+msgstr "git remote add [-t <branche>] [-m <maîtresse>] [-f] [--tags|--no-tags] [--mirror=<fetch|push>] <nom> <URL>"
+
+#: builtin/remote.c:13 builtin/remote.c:32
+msgid "git remote rename <old> <new>"
+msgstr "git remote rename <ancienne> <nouvelle>"
+
+#: builtin/remote.c:14 builtin/remote.c:37
+msgid "git remote remove <name>"
+msgstr "git remote remove <nom>"
+
+#: builtin/remote.c:15 builtin/remote.c:42
+msgid "git remote set-head <name> (-a | -d | <branch>)"
+msgstr "git remote set-head <nom> (-a | -d | <branche>)"
+
+#: builtin/remote.c:16
+msgid "git remote [-v | --verbose] show [-n] <name>"
+msgstr "git remote [-v | --verbose] show [-n] <nom>"
+
+#: builtin/remote.c:17
+msgid "git remote prune [-n | --dry-run] <name>"
+msgstr "git remote prune [-n | --dry-run] <nom>"
+
+#: builtin/remote.c:18
+msgid ""
+"git remote [-v | --verbose] update [-p | --prune] [(<group> | <remote>)...]"
+msgstr "git remote [-v | --verbose] update [-p | --prune] [(<groupe> | <distante>)...]"
+
+#: builtin/remote.c:19
+msgid "git remote set-branches [--add] <name> <branch>..."
+msgstr "git remote set-branches [--add] <nom> <branche>..."
+
+#: builtin/remote.c:20 builtin/remote.c:68
+msgid "git remote set-url [--push] <name> <newurl> [<oldurl>]"
+msgstr "git remote set-url [--push] <nom> <nouvelle-URL> [<ancienne-URL>]"
+
+#: builtin/remote.c:21 builtin/remote.c:69
+msgid "git remote set-url --add <name> <newurl>"
+msgstr "git remote set-url --add <nom> <nouvelle-URL>"
+
+#: builtin/remote.c:22 builtin/remote.c:70
+msgid "git remote set-url --delete <name> <url>"
+msgstr "git remote set-url --delete <nom> <URL>"
+
+#: builtin/remote.c:27
+msgid "git remote add [<options>] <name> <url>"
+msgstr "git remote add [<options>] <nom> <URL>"
+
+#: builtin/remote.c:47
+msgid "git remote set-branches <name> <branch>..."
+msgstr "git remote set-branches <nom> <branche>..."
+
+#: builtin/remote.c:48
+msgid "git remote set-branches --add <name> <branch>..."
+msgstr "git remote set-branches --add <nom> <branche>..."
+
+#: builtin/remote.c:53
+msgid "git remote show [<options>] <name>"
+msgstr "git remote show [<options>] <nom>"
+
+#: builtin/remote.c:58
+msgid "git remote prune [<options>] <name>"
+msgstr "git remote prune [<options>] <nom>"
+
+#: builtin/remote.c:63
+msgid "git remote update [<options>] [<group> | <remote>]..."
+msgstr "git remote update [<options>] [<groupe> | <distante>]..."
+
+#: builtin/remote.c:98
+#, c-format
+msgid "Updating %s"
+msgstr "Mise à jour de %s"
+
+#: builtin/remote.c:130
+msgid ""
+"--mirror is dangerous and deprecated; please\n"
+"\t use --mirror=fetch or --mirror=push instead"
+msgstr ""
+"--mirror est dangereux et obsolète ; merci\n"
+"\t d'utiliser --mirror=fetch ou --mirror=push à la place"
+
+#: builtin/remote.c:147
+#, c-format
+msgid "unknown mirror argument: %s"
+msgstr "argument miroir inconnu : %s"
+
+#: builtin/remote.c:163
+msgid "fetch the remote branches"
+msgstr "rapatrier les branches distantes"
+
+#: builtin/remote.c:165
+msgid "import all tags and associated objects when fetching"
+msgstr "importer toutes les étiquettes et les objets associés lors du rapatriement"
+
+#: builtin/remote.c:168
+msgid "or do not fetch any tag at all (--no-tags)"
+msgstr "ou ne rapatrier aucune étiquette (--no-tags)"
+
+#: builtin/remote.c:170
+msgid "branch(es) to track"
+msgstr "branche(s) à suivre"
+
+#: builtin/remote.c:171
+msgid "master branch"
+msgstr "branche maîtresse"
+
+#: builtin/remote.c:172
+msgid "push|fetch"
+msgstr "push|fetch"
+
+#: builtin/remote.c:173
+msgid "set up remote as a mirror to push to or fetch from"
+msgstr "paramétrer la distante comme miroir pour pousser ou pour rapatrier depuis"
+
+#: builtin/remote.c:185
+msgid "specifying a master branch makes no sense with --mirror"
+msgstr "spécifier une branche maîtresse n'a pas de sens avec --mirror"
+
+#: builtin/remote.c:187
+msgid "specifying branches to track makes sense only with fetch mirrors"
+msgstr "spécifier les branches à suivre n'a de sens qu'avec des miroirs de rapatriement"
+
+#: builtin/remote.c:195 builtin/remote.c:646
+#, c-format
+msgid "remote %s already exists."
+msgstr "la distante %s existe déjà."
+
+#: builtin/remote.c:199 builtin/remote.c:650
+#, c-format
+msgid "'%s' is not a valid remote name"
+msgstr "'%s' n'est pas un nom valide de distante"
+
+#: builtin/remote.c:243
+#, c-format
+msgid "Could not setup master '%s'"
+msgstr "Impossible de paramétrer la maîtresse '%s'"
+
+#: builtin/remote.c:299
+#, c-format
+msgid "more than one %s"
+msgstr "plus d'un %s"
+
+#: builtin/remote.c:339
+#, c-format
+msgid "Could not get fetch map for refspec %s"
+msgstr ""
+
+#: builtin/remote.c:440 builtin/remote.c:448
+msgid "(matching)"
+msgstr "(correspond)"
+
+#: builtin/remote.c:452
+msgid "(delete)"
+msgstr "(supprimer)"
+
+#: builtin/remote.c:595 builtin/remote.c:601 builtin/remote.c:607
+#, c-format
+msgid "Could not append '%s' to '%s'"
+msgstr "Impossible d'ajouter '%s' à '%s'"
+
+#: builtin/remote.c:639 builtin/remote.c:792 builtin/remote.c:890
+#, c-format
+msgid "No such remote: %s"
+msgstr "Distante inconnue : %s"
+
+#: builtin/remote.c:656
+#, c-format
+msgid "Could not rename config section '%s' to '%s'"
+msgstr "Impossible de renommer la section de configuration '%s' en '%s'"
+
+#: builtin/remote.c:662 builtin/remote.c:799
+#, c-format
+msgid "Could not remove config section '%s'"
+msgstr "Impossible de supprimer la section de configuration '%s'"
+
+#: builtin/remote.c:677
+#, c-format
+msgid ""
+"Not updating non-default fetch refspec\n"
+"\t%s\n"
+"\tPlease update the configuration manually if necessary."
+msgstr ""
+"Pas de mise à jour du refspec de rapatriement qui n'est pas par défaut\n"
+"\t%s\n"
+"\tMerci de mettre à jour la configuration si nécessaire."
+
+#: builtin/remote.c:683
+#, c-format
+msgid "Could not append '%s'"
+msgstr "Impossible d'ajouter '%s'"
+
+#: builtin/remote.c:694
+#, c-format
+msgid "Could not set '%s'"
+msgstr "Impossible de définir '%s'"
+
+#: builtin/remote.c:716
+#, c-format
+msgid "deleting '%s' failed"
+msgstr "échec de suppression de '%s'"
+
+#: builtin/remote.c:750
+#, c-format
+msgid "creating '%s' failed"
+msgstr "échec de création de '%s'"
+
+#: builtin/remote.c:764
+#, c-format
+msgid "Could not remove branch %s"
+msgstr "Impossible de supprimer la branche %s"
+
+#: builtin/remote.c:834
+msgid ""
+"Note: A branch outside the refs/remotes/ hierarchy was not removed;\n"
+"to delete it, use:"
+msgid_plural ""
+"Note: Some branches outside the refs/remotes/ hierarchy were not removed;\n"
+"to delete them, use:"
+msgstr[0] ""
+"Note : Une branche en dehors de refs/remotes/ n'a pas été supprimée ;\n"
+"pour la supprimer, utilisez :"
+msgstr[1] ""
+"Note : Plusieurs branches en dehors de refs/remotes/ n'ont pas été supprimées ;\n"
+"pour les supprimer, utilisez :"
+
+#: builtin/remote.c:943
+#, c-format
+msgid " new (next fetch will store in remotes/%s)"
+msgstr " nouveau (le prochain rapatriement (fetch) stockera dans remotes/%s)"
+
+#: builtin/remote.c:946
+msgid " tracked"
+msgstr " suivi"
+
+#: builtin/remote.c:948
+msgid " stale (use 'git remote prune' to remove)"
+msgstr " dépassé (utilisez 'git remote prune' pour supprimer)"
+
+#: builtin/remote.c:950
+msgid " ???"
+msgstr " ???"
+
+#: builtin/remote.c:991
+#, c-format
+msgid "invalid branch.%s.merge; cannot rebase onto > 1 branch"
+msgstr "branch.%s.merge invalide ; ne peut pas rebaser sur plus d'une branche"
+
+#: builtin/remote.c:998
+#, c-format
+msgid "rebases onto remote %s"
+msgstr "rebase sur la distante %s"
+
+#: builtin/remote.c:1001
+#, c-format
+msgid " merges with remote %s"
+msgstr " fusionne avec la distante %s"
+
+#: builtin/remote.c:1002
+msgid "    and with remote"
+msgstr "    et avec la distante"
+
+#: builtin/remote.c:1004
+#, c-format
+msgid "merges with remote %s"
+msgstr "fusionne avec la distante %s"
+
+#: builtin/remote.c:1005
+msgid "   and with remote"
+msgstr "   et avec la distante"
+
+#: builtin/remote.c:1051
+msgid "create"
+msgstr "créer"
+
+#: builtin/remote.c:1054
+msgid "delete"
+msgstr "supprimer"
+
+#: builtin/remote.c:1058
+msgid "up to date"
+msgstr "à jour"
+
+#: builtin/remote.c:1061
+msgid "fast-forwardable"
+msgstr "peut être mis à jour en avance rapide"
+
+#: builtin/remote.c:1064
+msgid "local out of date"
+msgstr "le local n'est pas à jour"
+
+#: builtin/remote.c:1071
+#, c-format
+msgid "    %-*s forces to %-*s (%s)"
+msgstr "    %-*s force vers %-*s (%s)"
+
+#: builtin/remote.c:1074
+#, c-format
+msgid "    %-*s pushes to %-*s (%s)"
+msgstr "    %-*s pousse vers %-*s (%s)"
+
+#: builtin/remote.c:1078
+#, c-format
+msgid "    %-*s forces to %s"
+msgstr "    %-*s force vers %s"
+
+#: builtin/remote.c:1081
+#, c-format
+msgid "    %-*s pushes to %s"
+msgstr "    %-*s pousse vers %s"
+
+#: builtin/remote.c:1091
+msgid "do not query remotes"
+msgstr "ne pas interroger les distantes"
+
+#: builtin/remote.c:1118
+#, c-format
+msgid "* remote %s"
+msgstr "* distante %s"
+
+#: builtin/remote.c:1119
+#, c-format
+msgid "  Fetch URL: %s"
+msgstr "  URL de rapatriement : %s"
+
+#: builtin/remote.c:1120 builtin/remote.c:1285
+msgid "(no URL)"
+msgstr "(pas d'URL)"
+
+#: builtin/remote.c:1129 builtin/remote.c:1131
+#, c-format
+msgid "  Push  URL: %s"
+msgstr "  URL push : %s"
+
+#: builtin/remote.c:1133 builtin/remote.c:1135 builtin/remote.c:1137
+#, c-format
+msgid "  HEAD branch: %s"
+msgstr "  Branche HEAD : %s"
+
+#: builtin/remote.c:1139
+#, c-format
+msgid ""
+"  HEAD branch (remote HEAD is ambiguous, may be one of the following):\n"
+msgstr "  Branche HEAD (la HEAD distante est ambiguë, peut être l'une des suivantes) :\n"
+
+#: builtin/remote.c:1151
+#, c-format
+msgid "  Remote branch:%s"
+msgid_plural "  Remote branches:%s"
+msgstr[0] "  Branche distante :%s"
+msgstr[1] "  Branches distantes :%s"
+
+#: builtin/remote.c:1154 builtin/remote.c:1181
+msgid " (status not queried)"
+msgstr " (statut non demandé)"
+
+#: builtin/remote.c:1163
+msgid "  Local branch configured for 'git pull':"
+msgid_plural "  Local branches configured for 'git pull':"
+msgstr[0] "  Branche locale configurée pour 'git pull' :"
+msgstr[1] "  Branches locales configurées pour 'git pull' :"
+
+#: builtin/remote.c:1171
+msgid "  Local refs will be mirrored by 'git push'"
+msgstr "  Les références locales seront reflétées par 'git push'"
+
+#: builtin/remote.c:1178
+#, c-format
+msgid "  Local ref configured for 'git push'%s:"
+msgid_plural "  Local refs configured for 'git push'%s:"
+msgstr[0] "  Référence locale configurée pour 'git push'%s :"
+msgstr[1] "  Références locales configurées pour 'git push'%s :"
+
+#: builtin/remote.c:1199
+msgid "set refs/remotes/<name>/HEAD according to remote"
+msgstr "définir refs/remotes/<nom>/HEAD selon la distante"
+
+#: builtin/remote.c:1201
+msgid "delete refs/remotes/<name>/HEAD"
+msgstr "supprimer refs/remotes/<nom>/HEAD"
+
+#: builtin/remote.c:1216
+msgid "Cannot determine remote HEAD"
+msgstr "Impossible de déterminer la HEAD distante"
+
+#: builtin/remote.c:1218
+msgid "Multiple remote HEAD branches. Please choose one explicitly with:"
+msgstr "Il y a de multiples branches HEAD distantes. Merci d'en choisir une explicitement avec :"
+
+#: builtin/remote.c:1228
+#, c-format
+msgid "Could not delete %s"
+msgstr "Impossible de supprimer %s"
+
+#: builtin/remote.c:1236
+#, c-format
+msgid "Not a valid ref: %s"
+msgstr "Référence non valide : %s"
+
+#: builtin/remote.c:1238
+#, c-format
+msgid "Could not setup %s"
+msgstr "Impossible de paramétrer %s"
+
+#: builtin/remote.c:1274
+#, c-format
+msgid " %s will become dangling!"
+msgstr " %s deviendra en suspens !"
+
+#: builtin/remote.c:1275
+#, c-format
+msgid " %s has become dangling!"
+msgstr " %s est devenu en suspens !"
+
+#: builtin/remote.c:1281
+#, c-format
+msgid "Pruning %s"
+msgstr "Élagage de %s"
+
+#: builtin/remote.c:1282
+#, c-format
+msgid "URL: %s"
+msgstr "URL : %s"
+
+#: builtin/remote.c:1295
+#, c-format
+msgid " * [would prune] %s"
+msgstr " * [serait élagué] %s"
+
+#: builtin/remote.c:1298
+#, c-format
+msgid " * [pruned] %s"
+msgstr " * [élagué] %s"
+
+#: builtin/remote.c:1321
+msgid "prune remotes after fetching"
+msgstr "élaguer les distants après le rapatriement"
+
+#: builtin/remote.c:1387 builtin/remote.c:1461
+#, c-format
+msgid "No such remote '%s'"
+msgstr "Pas de serveur remote '%s'"
+
+#: builtin/remote.c:1407
+msgid "add branch"
+msgstr "ajouter une branche"
+
+#: builtin/remote.c:1414
+msgid "no remote specified"
+msgstr "pas de serveur distant spécifié"
+
+#: builtin/remote.c:1436
+msgid "manipulate push URLs"
+msgstr "manipuler les URLs push"
+
+#: builtin/remote.c:1438
+msgid "add URL"
+msgstr "ajouter une URL"
+
+#: builtin/remote.c:1440
+msgid "delete URLs"
+msgstr "supprimer des URLs"
+
+#: builtin/remote.c:1447
+msgid "--add --delete doesn't make sense"
+msgstr "--add --delete n'a aucun sens"
+
+#: builtin/remote.c:1487
+#, c-format
+msgid "Invalid old URL pattern: %s"
+msgstr "Motif d'URL ancien invalide : %s"
+
+#: builtin/remote.c:1495
+#, c-format
+msgid "No such URL found: %s"
+msgstr "Pas d'URL trouvée : %s"
+
+#: builtin/remote.c:1497
+msgid "Will not delete all non-push URLs"
+msgstr ""
+
+#: builtin/remote.c:1569
+msgid "be verbose; must be placed before a subcommand"
+msgstr "être verbeux : doit être placé avant une sous-commande"
+
+#: builtin/replace.c:17
+msgid "git replace [-f] <object> <replacement>"
+msgstr "git replace [-f] <objet> <remplacement>"
+
+#: builtin/replace.c:18
+msgid "git replace -d <object>..."
+msgstr "git replace -d <objet>..."
+
+#: builtin/replace.c:19
+msgid "git replace -l [<pattern>]"
+msgstr "git replace -l [<motif>]"
+
+#: builtin/replace.c:121
+msgid "list replace refs"
+msgstr "afficher les références de remplacement"
+
+#: builtin/replace.c:122
+msgid "delete replace refs"
+msgstr "supprimer les références de remplacement"
+
+#: builtin/replace.c:123
+msgid "replace the ref if it exists"
+msgstr "remplacer la référence si elle existe"
+
+#: builtin/rerere.c:11
+msgid "git rerere [clear | forget path... | status | remaining | diff | gc]"
+msgstr "git rerere [clear | forget chemin... | status | remaining | diff | gc]"
+
+#: builtin/rerere.c:56
+msgid "register clean resolutions in index"
+msgstr "enregistrer des résolutions propres dans l'index"
+
+#: builtin/reset.c:25
+msgid ""
+"git reset [--mixed | --soft | --hard | --merge | --keep] [-q] [<commit>]"
+msgstr "git reset [--mixed | --soft | --hard | --merge | --keep] [-q] [<commit>]"
+
+#: builtin/reset.c:26
+msgid "git reset [-q] <tree-ish> [--] <paths>..."
+msgstr "git reset [-q] <arbre> [--] <chemins>..."
+
+#: builtin/reset.c:27
+msgid "git reset --patch [<tree-ish>] [--] [<paths>...]"
+msgstr "git reset --patch [<arbre>] [--] [<chemins>...]"
+
+#: builtin/reset.c:33
+msgid "mixed"
+msgstr "mixed"
+
+#: builtin/reset.c:33
+msgid "soft"
+msgstr "soft"
+
+#: builtin/reset.c:33
+msgid "hard"
+msgstr "hard"
+
+#: builtin/reset.c:33
+msgid "merge"
+msgstr "merge"
+
+#: builtin/reset.c:33
+msgid "keep"
+msgstr "keep"
+
+#: builtin/reset.c:73
+msgid "You do not have a valid HEAD."
+msgstr "Vous n'avez pas une HEAD valide."
+
+#: builtin/reset.c:75
+msgid "Failed to find tree of HEAD."
+msgstr "Impossible de trouver l'arbre pour HEAD."
+
+#: builtin/reset.c:81
+#, c-format
+msgid "Failed to find tree of %s."
+msgstr "Impossible de trouver l'arbre pour %s."
+
+#: builtin/reset.c:98
+#, c-format
+msgid "HEAD is now at %s"
+msgstr "HEAD est maintenant à %s"
+
+#: builtin/reset.c:169
+#, c-format
+msgid "Cannot do a %s reset in the middle of a merge."
+msgstr "Impossible de faire un \"reset %s\" au milieu d'une fusion."
+
+#: builtin/reset.c:248
+msgid "be quiet, only report errors"
+msgstr "être silencieux, afficher seulement les erreurs"
+
+#: builtin/reset.c:250
+msgid "reset HEAD and index"
+msgstr "réinitialiser HEAD et l'index"
+
+#: builtin/reset.c:251
+msgid "reset only HEAD"
+msgstr "réinitialiser seulement HEAD"
+
+#: builtin/reset.c:253 builtin/reset.c:255
+msgid "reset HEAD, index and working tree"
+msgstr "réinitialiser HEAD, l'index et la copie de travail"
+
+#: builtin/reset.c:257
+msgid "reset HEAD but keep local changes"
+msgstr "réinitialiser HEAD mais garder les changements locaux"
+
+#: builtin/reset.c:275
+#, c-format
+msgid "Failed to resolve '%s' as a valid revision."
+msgstr "Échec de résolution de '%s' comme une révision valide."
+
+#: builtin/reset.c:278 builtin/reset.c:286
+#, c-format
+msgid "Could not parse object '%s'."
+msgstr "Impossible d'analyser l'objet '%s'."
+
+#: builtin/reset.c:283
+#, c-format
+msgid "Failed to resolve '%s' as a valid tree."
+msgstr "Échec de résolution de '%s' comme un arbre valide."
+
+#: builtin/reset.c:292
+msgid "--patch is incompatible with --{hard,mixed,soft}"
+msgstr "--patch est incompatible avec --{hard,mixed,soft}"
+
+#: builtin/reset.c:301
+msgid "--mixed with paths is deprecated; use 'git reset -- <paths>' instead."
+msgstr "--mixed avec des chemins est obsolète ; utilisez 'git reset -- <paths>' à la place."
+
+#: builtin/reset.c:303
+#, c-format
+msgid "Cannot do %s reset with paths."
+msgstr "Impossible de faire un \"%s reset\" avec des chemins."
+
+#: builtin/reset.c:313
+#, c-format
+msgid "%s reset is not allowed in a bare repository"
+msgstr "Le \"%s reset\" n'est pas permis dans un dépôt nu"
+
+#: builtin/reset.c:333
+#, c-format
+msgid "Could not reset index file to revision '%s'."
+msgstr "Impossible de réinitialiser le fichier d'index à la révision '%s'."
+
+#: builtin/reset.c:339
+msgid "Unstaged changes after reset:"
+msgstr "Modifications non indexées après reset :"
+
+#: builtin/reset.c:344
+msgid "Could not write new index file."
+msgstr "Impossible d'écrire le nouveau fichier d'index."
+
+#: builtin/rev-parse.c:339
+msgid "git rev-parse --parseopt [options] -- [<args>...]"
+msgstr "git rev-parse --parseopt [options] -- [<arguments>...]"
+
+#: builtin/rev-parse.c:344
+msgid "keep the `--` passed as an arg"
+msgstr "garder le `--` passé en argument"
+
+#: builtin/rev-parse.c:346
+msgid "stop parsing after the first non-option argument"
+msgstr "arrêt de l'analyse après le premier argument qui n'est pas une option"
+
+#: builtin/rev-parse.c:464
+msgid ""
+"git rev-parse --parseopt [options] -- [<args>...]\n"
+"   or: git rev-parse --sq-quote [<arg>...]\n"
+"   or: git rev-parse [options] [<arg>...]\n"
+"\n"
+"Run \"git rev-parse --parseopt -h\" for more information on the first usage."
+msgstr ""
+"git rev-parse --parseopt [options] -- [<arguments>...]\n"
+"   ou : git rev-parse --sq-quote [<argument>...]\n"
+"   ou : git rev-parse [options] [<argument>...]\n"
+"\n"
+"Lancez \"git rev-parse --parseopt -h\" pour plus d'information sur l'utilisation principale."
+
+#: builtin/revert.c:22
+msgid "git revert [options] <commit-ish>..."
+msgstr "git revert [options] <commit>..."
+
+#: builtin/revert.c:23
+msgid "git revert <subcommand>"
+msgstr "git revert <sous-commande>"
+
+#: builtin/revert.c:28
+msgid "git cherry-pick [options] <commit-ish>..."
+msgstr "git cherry-pick [options] <commit>..."
+
+#: builtin/revert.c:29
+msgid "git cherry-pick <subcommand>"
+msgstr "git cherry-pick <sous-commande>"
+
+#: builtin/revert.c:70 builtin/revert.c:92
+#, c-format
+msgid "%s: %s cannot be used with %s"
+msgstr "%s : %s ne peut pas être utilisé avec %s"
+
+#: builtin/revert.c:103
+msgid "end revert or cherry-pick sequence"
+msgstr "mettre fin au retour ou picorage"
+
+#: builtin/revert.c:104
+msgid "resume revert or cherry-pick sequence"
+msgstr "reprendre le retour ou picorage"
+
+#: builtin/revert.c:105
+msgid "cancel revert or cherry-pick sequence"
+msgstr "annuler le retour ou picorage"
+
+#: builtin/revert.c:106
+msgid "don't automatically commit"
+msgstr "ne pas valider automatiquement"
+
+#: builtin/revert.c:107
+msgid "edit the commit message"
+msgstr "éditer le message de validation"
+
+#: builtin/revert.c:110
+msgid "parent number"
+msgstr "numéro de parent"
+
+#: builtin/revert.c:112
+msgid "merge strategy"
+msgstr "stratégie de fusion"
+
+#: builtin/revert.c:113
+msgid "option"
+msgstr "option"
+
+#: builtin/revert.c:114
+msgid "option for merge strategy"
+msgstr "option pour la stratégie de fusion"
+
+#: builtin/revert.c:125
+msgid "append commit name"
+msgstr "ajouter le nom de validation"
+
+#: builtin/revert.c:126
+msgid "allow fast-forward"
+msgstr "autoriser l'avance rapide"
+
+#: builtin/revert.c:127
+msgid "preserve initially empty commits"
+msgstr "préserver les validations vides initialement"
+
+#: builtin/revert.c:128
+msgid "allow commits with empty messages"
+msgstr "autoriser les validations avec des messages vides"
+
+#: builtin/revert.c:129
+msgid "keep redundant, empty commits"
+msgstr "garder les validations redondantes, vides"
+
+#: builtin/revert.c:133
+msgid "program error"
+msgstr "erreur du programme"
+
+#: builtin/revert.c:223
+msgid "revert failed"
+msgstr "revert a échoué"
+
+#: builtin/revert.c:238
+msgid "cherry-pick failed"
+msgstr "le picorage a échoué"
+
+#: builtin/rm.c:15
+msgid "git rm [options] [--] <file>..."
+msgstr "git rm [options] [--] <fichier>..."
+
+#: builtin/rm.c:64 builtin/rm.c:186
+#, c-format
+msgid ""
+"submodule '%s' (or one of its nested submodules) uses a .git directory\n"
+"(use 'rm -rf' if you really want to remove it including all of its history)"
+msgstr ""
+"le sous-module '%s' (ou un des sous-modules imbriqués) utilise un répertoire .git\n"
+"(utilisez 'rm -rf' si vous souhaitez vraiment le supprimer avec tout son historique)"
+
+#: builtin/rm.c:174
+#, c-format
+msgid ""
+"'%s' has staged content different from both the file and the HEAD\n"
+"(use -f to force removal)"
+msgstr ""
+"'%s' a du contenu indexé différent du fichier et de HEAD\n"
+"(utilisez -f pour forcer la suppression)"
+
+#: builtin/rm.c:180
+#, c-format
+msgid ""
+"'%s' has changes staged in the index\n"
+"(use --cached to keep the file, or -f to force removal)"
+msgstr ""
+"'%s' a des changements dans l'index\n"
+"(utilisez --cached pour garder le fichier, ou -f pour forcer la suppression)"
+
+#: builtin/rm.c:191
+#, c-format
+msgid ""
+"'%s' has local modifications\n"
+"(use --cached to keep the file, or -f to force removal)"
+msgstr ""
+"'%s' a des modifications locales\n"
+"(utilisez --cached pour garder le fichier, ou -f pour forcer la suppression)"
+
+#: builtin/rm.c:207
+msgid "do not list removed files"
+msgstr "ne pas afficher les fichiers supprimés"
+
+#: builtin/rm.c:208
+msgid "only remove from the index"
+msgstr "supprimer seulement de l'index"
+
+#: builtin/rm.c:209
+msgid "override the up-to-date check"
+msgstr "outrepasser la vérification des fichiers à jour"
+
+#: builtin/rm.c:210
+msgid "allow recursive removal"
+msgstr "autoriser la suppression récursive"
+
+#: builtin/rm.c:212
+msgid "exit with a zero status even if nothing matched"
+msgstr "sortir avec un statut zéro même si rien ne correspondait"
+
+#: builtin/rm.c:283
+#, c-format
+msgid "not removing '%s' recursively without -r"
+msgstr "pas de suppression récursive de '%s' sans -r"
+
+#: builtin/rm.c:322
+#, c-format
+msgid "git rm: unable to remove %s"
+msgstr "git rm : impossible de supprimer %s"
+
+#: builtin/shortlog.c:13
+msgid "git shortlog [<options>] [<revision range>] [[--] [<path>...]]"
+msgstr "git shortlog [<options>] [<intervalle révisions>] [[--] [<chemin>...]]"
+
+#: builtin/shortlog.c:131
+#, c-format
+msgid "Missing author: %s"
+msgstr "Auteur manquant : %s"
+
+#: builtin/shortlog.c:227
+msgid "sort output according to the number of commits per author"
+msgstr "trier la sortie sur le nombre de validations par auteur"
+
+#: builtin/shortlog.c:229
+msgid "Suppress commit descriptions, only provides commit count"
+msgstr "Supprimer les descriptions de validation, fournit seulement le nombre de validations"
+
+#: builtin/shortlog.c:231
+msgid "Show the email address of each author"
+msgstr "Afficher l'adresse e-mail de chaque auteur"
+
+#: builtin/shortlog.c:232
+msgid "w[,i1[,i2]]"
+msgstr "w[,i1[,i2]]"
+
+#: builtin/shortlog.c:233
+msgid "Linewrap output"
+msgstr "Couper les lignes"
+
+#: builtin/show-branch.c:9
+msgid ""
+"git show-branch [-a|--all] [-r|--remotes] [--topo-order | --date-order] [--"
+"current] [--color[=<when>] | --no-color] [--sparse] [--more=<n> | --list | --"
+"independent | --merge-base] [--no-name | --sha1-name] [--topics] [(<rev> | "
+"<glob>)...]"
+msgstr "git show-branch [-a|--all] [-r|--remotes] [--topo-order | --date-order] [--current] [--color[=<quand>] | --no-color] [--sparse] [--more=<n> | --list | --independent | --merge-base] [--no-name | --sha1-name] [--topics] [(<révision> | <glob>)...]"
+
+#: builtin/show-branch.c:10
+msgid "git show-branch (-g|--reflog)[=<n>[,<base>]] [--list] [<ref>]"
+msgstr "git show-branch (-g|--reflog)[=<n>[,<base>]] [--list] [<référence>]"
+
+#: builtin/show-branch.c:650
+msgid "show remote-tracking and local branches"
+msgstr "afficher les branches de suivi distantes et les branches locales"
+
+#: builtin/show-branch.c:652
+msgid "show remote-tracking branches"
+msgstr "afficher les branches de suivi distantes"
+
+#: builtin/show-branch.c:654
+msgid "color '*!+-' corresponding to the branch"
+msgstr "couleur '*!+-' correspondant à la branche"
+
+#: builtin/show-branch.c:656
+msgid "show <n> more commits after the common ancestor"
+msgstr "afficher <n> validations de plus après l'ancêtre commun"
+
+#: builtin/show-branch.c:658
+msgid "synonym to more=-1"
+msgstr "synonyme de more=-1"
+
+#: builtin/show-branch.c:659
+msgid "suppress naming strings"
+msgstr ""
+
+#: builtin/show-branch.c:661
+msgid "include the current branch"
+msgstr "inclure la branche courante"
+
+#: builtin/show-branch.c:663
+msgid "name commits with their object names"
+msgstr "nommer les validations avec leurs noms d'objet"
+
+#: builtin/show-branch.c:665
+msgid "show possible merge bases"
+msgstr "afficher les bases possibles de fusion"
+
+#: builtin/show-branch.c:667
+msgid "show refs unreachable from any other ref"
+msgstr "afficher les références non accessibles depuis toute autre référence"
+
+#: builtin/show-branch.c:669
+msgid "show commits in topological order"
+msgstr "afficher les validations dans l'ordre topologique"
+
+#: builtin/show-branch.c:671
+msgid "show only commits not on the first branch"
+msgstr "afficher seulement les validations qui ne sont pas sur la première branche"
+
+#: builtin/show-branch.c:673
+msgid "show merges reachable from only one tip"
+msgstr "afficher les fusions accessibles depuis une seule pointe"
+
+#: builtin/show-branch.c:675
+msgid "show commits where no parent comes before its children"
+msgstr "afficher les validations où aucun parent ne vient avant ses enfants"
+
+#: builtin/show-branch.c:677
+msgid "<n>[,<base>]"
+msgstr "<n>[,<base>]"
+
+#: builtin/show-branch.c:678
+msgid "show <n> most recent ref-log entries starting at base"
+msgstr "afficher les <n> plus récentes entrées de ref-log en commençant à la base"
+
+#: builtin/show-ref.c:10
+msgid ""
+"git show-ref [-q|--quiet] [--verify] [--head] [-d|--dereference] [-s|--"
+"hash[=<n>]] [--abbrev[=<n>]] [--tags] [--heads] [--] [pattern*] "
+msgstr "git show-ref [-q|--quiet] [--verify] [--head] [-d|--dereference] [-s|--hash[=<n>]] [--abbrev[=<n>]] [--tags] [--heads] [--] [motif*] "
+
+#: builtin/show-ref.c:11
+msgid "git show-ref --exclude-existing[=pattern] < ref-list"
+msgstr "git show-ref --exclude-existing[=motif] < liste-références"
+
+#: builtin/show-ref.c:165
+msgid "only show tags (can be combined with heads)"
+msgstr "afficher seulement les étiquettes (peut être combiné avec des têtes)"
+
+#: builtin/show-ref.c:166
+msgid "only show heads (can be combined with tags)"
+msgstr "afficher seulement les têtes (peut être combiné avec des étiquettes)"
+
+#: builtin/show-ref.c:167
+msgid "stricter reference checking, requires exact ref path"
+msgstr "vérification de référence plus stricte, requiert un chemin de référence exact"
+
+#: builtin/show-ref.c:170 builtin/show-ref.c:172
+msgid "show the HEAD reference"
+msgstr "afficher la référence HEAD"
+
+#: builtin/show-ref.c:174
+msgid "dereference tags into object IDs"
+msgstr "déréférencer les étiquettes en IDs d'objet"
+
+#: builtin/show-ref.c:176
+msgid "only show SHA1 hash using <n> digits"
+msgstr "afficher seulement le hachage SHA1 en utilisant <n> chiffres"
+
+#: builtin/show-ref.c:180
+msgid "do not print results to stdout (useful with --verify)"
+msgstr "ne pas afficher les résultats sur la sortie standard (pratique avec --verify)"
+
+#: builtin/show-ref.c:182
+msgid "show refs from stdin that aren't in local repository"
+msgstr "afficher les références de l'entrée standard qui ne sont pas dans le dépôt local"
+
+#: builtin/symbolic-ref.c:7
+msgid "git symbolic-ref [options] name [ref]"
+msgstr "git symbolic-ref [options] nom [référence]"
+
+#: builtin/symbolic-ref.c:8
+msgid "git symbolic-ref -d [-q] name"
+msgstr "git symbolic-ref -d [-q] nom"
+
+#: builtin/symbolic-ref.c:40
+msgid "suppress error message for non-symbolic (detached) refs"
+msgstr "supprimer le message d'erreur pour une référence non symbolique (détachée)"
+
+#: builtin/symbolic-ref.c:41
+msgid "delete symbolic ref"
+msgstr "supprimer la référence symbolique"
+
+#: builtin/symbolic-ref.c:42
+msgid "shorten ref output"
+msgstr "raccourcir l'affichage de la référence"
+
+#: builtin/symbolic-ref.c:43 builtin/update-ref.c:18
+msgid "reason"
+msgstr "raison"
+
+#: builtin/symbolic-ref.c:43 builtin/update-ref.c:18
+msgid "reason of the update"
+msgstr "raison de la mise à jour"
+
+#: builtin/tag.c:22
+msgid ""
+"git tag [-a|-s|-u <key-id>] [-f] [-m <msg>|-F <file>] <tagname> [<head>]"
+msgstr "git tag [-a|-s|-u <id-clé>] [-f] [-m <msg>|-F <file>] <nométiquette> [<head>]"
+
+#: builtin/tag.c:23
+msgid "git tag -d <tagname>..."
+msgstr "git tag -d <nométiquette>..."
+
+#: builtin/tag.c:24
+msgid ""
+"git tag -l [-n[<num>]] [--contains <commit>] [--points-at <object>] \n"
+"\t\t[<pattern>...]"
+msgstr ""
+"git tag -l [-n[<num>]] [--contains <commit>] [--points-at <objet>] \n"
+"\t\t[<motif>...]"
+
+#: builtin/tag.c:26
+msgid "git tag -v <tagname>..."
+msgstr "git tag -v <nométiquette>..."
+
+#: builtin/tag.c:60
+#, c-format
+msgid "malformed object at '%s'"
+msgstr "objet malformé à '%s'"
+
+#: builtin/tag.c:207
+#, c-format
+msgid "tag name too long: %.*s..."
+msgstr "nom d'étiquette trop long : %.*s..."
+
+#: builtin/tag.c:212
+#, c-format
+msgid "tag '%s' not found."
+msgstr "étiquette '%s' non trouvée."
+
+#: builtin/tag.c:227
+#, c-format
+msgid "Deleted tag '%s' (was %s)\n"
+msgstr "Étiquette '%s' supprimée (elle était %s)\n"
+
+#: builtin/tag.c:239
+#, c-format
+msgid "could not verify the tag '%s'"
+msgstr "impossible de vérifier l'étiquette '%s'"
+
+#: builtin/tag.c:249
+#, c-format
+msgid ""
+"\n"
+"Write a tag message\n"
+"Lines starting with '%c' will be ignored.\n"
+msgstr ""
+"\n"
+"Écrire un message pour l'étiquette\n"
+"Les lignes commençant par '%c' seront ignorées.\n"
+
+#: builtin/tag.c:253
+#, c-format
+msgid ""
+"\n"
+"Write a tag message\n"
+"Lines starting with '%c' will be kept; you may remove them yourself if you "
+"want to.\n"
+msgstr ""
+"\n"
+"Écrire un message pour l'étiquette\n"
+"Les lignes commençant par '%c' seront gardées ; vous pouvez les retirer vous-même si vous le souhaitez.\n"
+
+#: builtin/tag.c:292
+msgid "unable to sign the tag"
+msgstr "impossible de signer l'étiquette"
+
+#: builtin/tag.c:294
+msgid "unable to write tag file"
+msgstr "impossible d'écrire le fichier d'étiquettes"
+
+#: builtin/tag.c:319
+msgid "bad object type."
+msgstr "mauvais type d'objet."
+
+#: builtin/tag.c:332
+msgid "tag header too big."
+msgstr "en-tête d'étiquette trop gros."
+
+#: builtin/tag.c:368
+msgid "no tag message?"
+msgstr "pas de message pour l'étiquette ?"
+
+#: builtin/tag.c:374
+#, c-format
+msgid "The tag message has been left in %s\n"
+msgstr "Le message pour l'étiquette a été laissé dans %s\n"
+
+#: builtin/tag.c:423
+msgid "switch 'points-at' requires an object"
+msgstr "le commutateur 'points-at' requiert un objet"
+
+#: builtin/tag.c:425
+#, c-format
+msgid "malformed object name '%s'"
+msgstr "nom d'objet malformé '%s'"
+
+#: builtin/tag.c:445
+msgid "list tag names"
+msgstr "afficher les noms des étiquettes"
+
+#: builtin/tag.c:447
+msgid "print <n> lines of each tag message"
+msgstr "affiche <n> lignes de chaque message d'étiquette"
+
+#: builtin/tag.c:449
+msgid "delete tags"
+msgstr "supprimer des étiquettes"
+
+#: builtin/tag.c:450
+msgid "verify tags"
+msgstr "vérifier des étiquettes"
+
+#: builtin/tag.c:452
+msgid "Tag creation options"
+msgstr "Options de création de l'étiquette"
+
+#: builtin/tag.c:454
+msgid "annotated tag, needs a message"
+msgstr "étiquette annotée, nécessite un message"
+
+#: builtin/tag.c:456
+msgid "tag message"
+msgstr "message pour l'étiquette"
+
+#: builtin/tag.c:458
+msgid "annotated and GPG-signed tag"
+msgstr "étiquette annotée et signée avec GPG"
+
+#: builtin/tag.c:462
+msgid "use another key to sign the tag"
+msgstr "utiliser une autre clé pour signer l'étiquette"
+
+#: builtin/tag.c:463
+msgid "replace the tag if exists"
+msgstr "remplacer l'étiquette si elle existe"
+
+#: builtin/tag.c:464
+msgid "show tag list in columns"
+msgstr "afficher la liste des étiquettes sous forme de colonnes"
+
+#: builtin/tag.c:466
+msgid "Tag listing options"
+msgstr "Options d'affichage des étiquettes"
+
+#: builtin/tag.c:469
+msgid "print only tags that contain the commit"
+msgstr "afficher seulement les étiquettes qui contiennent la validation"
+
+#: builtin/tag.c:475
+msgid "print only tags of the object"
+msgstr "afficher seulement les étiquettes de l'objet"
+
+#: builtin/tag.c:504
+msgid "--column and -n are incompatible"
+msgstr "--column et -n sont incompatibles"
+
+#: builtin/tag.c:521
+msgid "-n option is only allowed with -l."
+msgstr "l'option -n est autorisée seulement avec -l."
+
+#: builtin/tag.c:523
+msgid "--contains option is only allowed with -l."
+msgstr "l'option --contains est autorisée seulement avec -l."
+
+#: builtin/tag.c:525
+msgid "--points-at option is only allowed with -l."
+msgstr "l'option --points-at est autorisée seulement avec -l."
+
+#: builtin/tag.c:533
+msgid "only one -F or -m option is allowed."
+msgstr "une seule option -F ou -m est autorisée."
+
+#: builtin/tag.c:553
+msgid "too many params"
+msgstr "trop de paramètres"
+
+#: builtin/tag.c:559
+#, c-format
+msgid "'%s' is not a valid tag name."
+msgstr "'%s' n'est pas un nom d'étiquette valide."
+
+#: builtin/tag.c:564
+#, c-format
+msgid "tag '%s' already exists"
+msgstr "l'étiquette '%s' existe déjà"
+
+#: builtin/tag.c:582
+#, c-format
+msgid "%s: cannot lock the ref"
+msgstr "%s : impossible de verrouiller la référence"
+
+#: builtin/tag.c:584
+#, c-format
+msgid "%s: cannot update the ref"
+msgstr "%s : impossible de mettre à jour la référence"
+
+#: builtin/tag.c:586
+#, c-format
+msgid "Updated tag '%s' (was %s)\n"
+msgstr "Étiquette '%s' mise à jour (elle était %s)\n"
+
+#: builtin/update-index.c:401
+msgid "git update-index [options] [--] [<file>...]"
+msgstr "git update-index [options] [--] [<fichier>...]"
+
+#: builtin/update-index.c:718
+msgid "continue refresh even when index needs update"
+msgstr "continuer de rafraîchir même si l'index a besoin d'une mise à jour"
+
+#: builtin/update-index.c:721
+msgid "refresh: ignore submodules"
+msgstr "rafraîchir : ignorer les sous-modules"
+
+#: builtin/update-index.c:724
+msgid "do not ignore new files"
+msgstr "ne pas ignorer les nouveaux fichiers"
+
+#: builtin/update-index.c:726
+msgid "let files replace directories and vice-versa"
+msgstr "laisser les fichiers remplacer des répertoires et vice-versa"
+
+#: builtin/update-index.c:728
+msgid "notice files missing from worktree"
+msgstr "aviser des fichiers manquants dans la copie de travail"
+
+#: builtin/update-index.c:730
+msgid "refresh even if index contains unmerged entries"
+msgstr "rafraîchir même si l'index contient des entrées non fusionnées"
+
+#: builtin/update-index.c:733
+msgid "refresh stat information"
+msgstr "rafraîchir l'information de stat"
+
+#: builtin/update-index.c:737
+msgid "like --refresh, but ignore assume-unchanged setting"
+msgstr "comme --refresh, mais en ignorant l'option assume-unchanged"
+
+#: builtin/update-index.c:741
+msgid "<mode> <object> <path>"
+msgstr "<mode> <objet> <chemin>"
+
+#: builtin/update-index.c:742
+msgid "add the specified entry to the index"
+msgstr "ajouter l'entrée spécifiée dans l'index"
+
+#: builtin/update-index.c:746
+msgid "(+/-)x"
+msgstr "(+/-)x"
+
+#: builtin/update-index.c:747
+msgid "override the executable bit of the listed files"
+msgstr "outrepasser le bit exécutable pour les fichiers listés"
+
+#: builtin/update-index.c:751
+msgid "mark files as \"not changing\""
+msgstr "marquer les fichiers comme \"non changeants\""
+
+#: builtin/update-index.c:754
+msgid "clear assumed-unchanged bit"
+msgstr ""
+
+#: builtin/update-index.c:757
+msgid "mark files as \"index-only\""
+msgstr "marquer les fichiers comme \"index seulement\""
+
+#: builtin/update-index.c:760
+msgid "clear skip-worktree bit"
+msgstr ""
+
+#: builtin/update-index.c:763
+msgid "add to index only; do not add content to object database"
+msgstr "ajouter seulement à l'index ; ne pas ajouter le contenu dans la base de données des objets"
+
+#: builtin/update-index.c:765
+msgid "remove named paths even if present in worktree"
+msgstr "supprimer les chemins nommés même s'ils sont présents dans la copie de travail"
+
+#: builtin/update-index.c:767
+msgid "with --stdin: input lines are terminated by null bytes"
+msgstr "avec --stdin : les lignes en entrée sont terminées par des octets nuls"
+
+#: builtin/update-index.c:769
+msgid "read list of paths to be updated from standard input"
+msgstr "lire la liste des chemins à mettre à jour depuis l'entrée standard"
+
+#: builtin/update-index.c:773
+msgid "add entries from standard input to the index"
+msgstr "ajouter les entrées depuis l'entrée standard à l'index"
+
+#: builtin/update-index.c:777
+msgid "repopulate stages #2 and #3 for the listed paths"
+msgstr "repeupler les étapes n°2 et n°3 pour les chemins listés"
+
+#: builtin/update-index.c:781
+msgid "only update entries that differ from HEAD"
+msgstr "mettre à jour seulement les entrées qui diffèrent de HEAD"
+
+#: builtin/update-index.c:785
+msgid "ignore files missing from worktree"
+msgstr "ignorer les fichiers manquants dans la copie de travail"
+
+#: builtin/update-index.c:788
+msgid "report actions to standard output"
+msgstr "afficher les actions sur la sortie standard"
+
+#: builtin/update-index.c:790
+msgid "(for porcelains) forget saved unresolved conflicts"
+msgstr "(pour porcelaines) oublier les conflits sauvés et non résolus"
+
+#: builtin/update-index.c:794
+msgid "write index in this format"
+msgstr "écrire l'index dans ce format"
+
+#: builtin/update-ref.c:7
+msgid "git update-ref [options] -d <refname> [<oldval>]"
+msgstr "git update-ref [options] -d <nomréférence> [<anciennevaleur>]"
+
+#: builtin/update-ref.c:8
+msgid "git update-ref [options]    <refname> <newval> [<oldval>]"
+msgstr "git update-ref [options]    <nomréférence> <nouvellevaleur> [<anciennevaleur>]"
+
+#: builtin/update-ref.c:19
+msgid "delete the reference"
+msgstr "supprimer la référence"
+
+#: builtin/update-ref.c:21
+msgid "update <refname> not the one it points to"
+msgstr ""
+
+#: builtin/update-server-info.c:6
+msgid "git update-server-info [--force]"
+msgstr "git update-server-info [--force]"
+
+#: builtin/update-server-info.c:14
+msgid "update the info files from scratch"
+msgstr "mettre à jour les fichiers d'information à partir de zéro"
+
+#: builtin/verify-pack.c:56
+msgid "git verify-pack [-v|--verbose] [-s|--stat-only] <pack>..."
+msgstr "git verify-pack [-v|--verbose] [-s|--stat-only] <pack>..."
+
+#: builtin/verify-pack.c:66
+msgid "verbose"
+msgstr "verbeux"
+
+#: builtin/verify-pack.c:68
+msgid "show statistics only"
+msgstr "afficher seulement les statistiques"
+
+#: builtin/verify-tag.c:17
+msgid "git verify-tag [-v|--verbose] <tag>..."
+msgstr "git verify-tag [-v|--verbose] <étiquette>..."
+
+#: builtin/verify-tag.c:73
+msgid "print tag contents"
+msgstr "afficher le contenu de l'étiquette"
+
+#: builtin/write-tree.c:13
+msgid "git write-tree [--missing-ok] [--prefix=<prefix>/]"
+msgstr "git write-tree [--missing-ok] [--prefix=<préfixe>/]"
+
+#: builtin/write-tree.c:26
+msgid "<prefix>/"
+msgstr "<préfixe>/"
+
+#: builtin/write-tree.c:27
+msgid "write tree object for a subdirectory <prefix>"
+msgstr "écrire l'objet arbre pour un sous-répertoire <préfixe>"
+
+#: builtin/write-tree.c:30
+msgid "only useful for debugging"
+msgstr "seulement utile pour le débogage"
+
+#: git.c:16
+msgid ""
+"'git help -a' and 'git help -g' lists available subcommands and some\n"
+"concept guides. See 'git help <command>' or 'git help <concept>'\n"
+"to read about a specific subcommand or concept."
+msgstr ""
+"'git help -a' et 'git help -g' listent les sous-commandes disponibles et\n"
+"quelques concepts. Voir 'git help <command>' ou 'git help <concept>'\n"
+"pour en lire plus à propos d'une commande spécifique ou d'un concept."
+
+#: parse-options.h:156
+msgid "no-op (backward compatibility)"
+msgstr "sans action (rétrocompatibilité)"
+
+#: parse-options.h:232
+msgid "be more verbose"
+msgstr "être plus verbeux"
+
+#: parse-options.h:234
+msgid "be more quiet"
+msgstr "être plus silencieux"
+
+#: parse-options.h:240
+msgid "use <n> digits to display SHA-1s"
+msgstr "utiliser <n> chiffres pour afficher les SHA-1s"
+
+#: common-cmds.h:8
+msgid "Add file contents to the index"
+msgstr "Ajouter le contenu du fichier dans l'index"
+
+#: common-cmds.h:9
+msgid "Find by binary search the change that introduced a bug"
+msgstr "Rechercher de manière binaire le changement qui a introduit un bogue"
+
+#: common-cmds.h:10
+msgid "List, create, or delete branches"
+msgstr "Lister, créer ou supprimer des branches"
+
+#: common-cmds.h:11
+msgid "Checkout a branch or paths to the working tree"
+msgstr "Extraire une branche ou des chemins dans la copie de travail"
+
+#: common-cmds.h:12
+msgid "Clone a repository into a new directory"
+msgstr "Cloner un dépôt dans un nouveau répertoire"
+
+#: common-cmds.h:13
+msgid "Record changes to the repository"
+msgstr "Enregistrer les changements dans le dépôt"
+
+#: common-cmds.h:14
+msgid "Show changes between commits, commit and working tree, etc"
+msgstr "Afficher les changements entre les validations, entre validation et copie de travail, etc"
+
+#: common-cmds.h:15
+msgid "Download objects and refs from another repository"
+msgstr "Télécharger les objets et références depuis un autre dépôt"
+
+#: common-cmds.h:16
+msgid "Print lines matching a pattern"
+msgstr "Afficher les lignes correspondant à un motif"
+
+#: common-cmds.h:17
+msgid "Create an empty Git repository or reinitialize an existing one"
+msgstr "Créer un dépôt Git vide ou réinitialiser un existant"
+
+#: common-cmds.h:18
+msgid "Show commit logs"
+msgstr "Afficher l'historique des validations"
+
+#: common-cmds.h:19
+msgid "Join two or more development histories together"
+msgstr "Joindre deux ou plusieurs historiques de développement ensemble"
+
+#: common-cmds.h:20
+msgid "Move or rename a file, a directory, or a symlink"
+msgstr "Déplacer ou renommer un fichier, un répertoire, ou un lien symbolique"
+
+#: common-cmds.h:21
+msgid "Fetch from and merge with another repository or a local branch"
+msgstr "Rapatrier et fusionner avec un autre dépôt ou une branche locale"
+
+#: common-cmds.h:22
+msgid "Update remote refs along with associated objects"
+msgstr "Mettre à jour les références distantes ainsi que les objets associés"
+
+#: common-cmds.h:23
+msgid "Forward-port local commits to the updated upstream head"
+msgstr "Reporter en avant les validations locales dans la tête en amont mise à jour"
+
+#: common-cmds.h:24
+msgid "Reset current HEAD to the specified state"
+msgstr "Réinitialiser la HEAD courante à l'état spécifié"
+
+#: common-cmds.h:25
+msgid "Remove files from the working tree and from the index"
+msgstr "Supprimer les fichiers de la copie de travail et de l'index"
+
+#: common-cmds.h:26
+msgid "Show various types of objects"
+msgstr "Afficher différents types d'objects"
+
+#: common-cmds.h:27
+msgid "Show the working tree status"
+msgstr "Afficher le statut de la copie de travail"
+
+#: common-cmds.h:28
+msgid "Create, list, delete or verify a tag object signed with GPG"
+msgstr "Créer, lister, supprimer ou vérifier un objet d'étiquette signé avec GPG"
+
+#: git-am.sh:50
+msgid "You need to set your committer info first"
+msgstr "Vous devez d'abord définir vos informations de validateur"
+
+#: git-am.sh:95
+msgid ""
+"You seem to have moved HEAD since the last 'am' failure.\n"
+"Not rewinding to ORIG_HEAD"
+msgstr ""
+"Vous semblez avoir déplacé la HEAD depuis le dernier échec de 'am'.\n"
+"Pas de retour à ORIG_HEAD"
+
+#: git-am.sh:105
+#, sh-format
+msgid ""
+"When you have resolved this problem, run \"$cmdline --resolved\".\n"
+"If you prefer to skip this patch, run \"$cmdline --skip\" instead.\n"
+"To restore the original branch and stop patching, run \"$cmdline --abort\"."
+msgstr ""
+"Lorsque vous aurez résolu ce problème, lancez \"$cmdline --resolved\".\n"
+"Si vous préférez sauter ce patch, lancez \"$cmdline --skip\" à la place.\n"
+"Pour restaurer la branche d'origine et stopper le patchage, lancez \"$cmdline --abort\"."
+
+#: git-am.sh:121
+msgid "Cannot fall back to three-way merge."
+msgstr "Impossible de retourner à une fusion 3-way."
+
+#: git-am.sh:137
+msgid "Repository lacks necessary blobs to fall back on 3-way merge."
+msgstr "Le dépôt n'a pas les blobs nécessaires pour un retour à une fusion 3-way."
+
+#: git-am.sh:139
+msgid "Using index info to reconstruct a base tree..."
+msgstr "Utilisation de l'information de l'index pour reconstruire un arbre de base..."
+
+#: git-am.sh:154
+msgid ""
+"Did you hand edit your patch?\n"
+"It does not apply to blobs recorded in its index."
+msgstr ""
+"Avez-vous édité le patch à la main ?\n"
+"Il ne s'applique pas aux blobs enregistrés dans son index."
+
+#: git-am.sh:163
+msgid "Falling back to patching base and 3-way merge..."
+msgstr "Retour à un patch de la base et fusion 3-way..."
+
+#: git-am.sh:179
+msgid "Failed to merge in the changes."
+msgstr "Échec de fusion dans les changements."
+
+#: git-am.sh:274
+msgid "Only one StGIT patch series can be applied at once"
+msgstr "Seulement une série de patches StGIT peut être appliquée à la fois"
+
+#: git-am.sh:361
+#, sh-format
+msgid "Patch format $patch_format is not supported."
+msgstr "Le format de patch $patch_format n'est pas supporté."
+
+#: git-am.sh:363
+msgid "Patch format detection failed."
+msgstr "Échec de détection du format du patch."
+
+#: git-am.sh:389
+msgid ""
+"The -b/--binary option has been a no-op for long time, and\n"
+"it will be removed. Please do not use it anymore."
+msgstr ""
+"L'option -b/--binary ne fait plus rien depuis longtemps,\n"
+"et elle sera supprimée. Merci de ne plus l'utiliser."
+
+#: git-am.sh:477
+#, sh-format
+msgid "previous rebase directory $dotest still exists but mbox given."
+msgstr "le répertoire précédent de rebasage $dotest existe toujours mais mbox donnée."
+
+#: git-am.sh:482
+msgid "Please make up your mind. --skip or --abort?"
+msgstr "Décidez-vous. --skip ou --abort ?"
+
+#: git-am.sh:509
+msgid "Resolve operation not in progress, we are not resuming."
+msgstr "Pas de résolution de l'opération en cours, nous ne sommes pas dans une reprise."
+
+#: git-am.sh:575
+#, sh-format
+msgid "Dirty index: cannot apply patches (dirty: $files)"
+msgstr "Index sale : impossible d'appliquer des patches (sales : $files)"
+
+#: git-am.sh:679
+#, sh-format
+msgid ""
+"Patch is empty.  Was it split wrong?\n"
+"If you would prefer to skip this patch, instead run \"$cmdline --skip\".\n"
+"To restore the original branch and stop patching run \"$cmdline --abort\"."
+msgstr ""
+"Le patch est vide.  Était-il mal découpé ?\n"
+"Si vous préférez sauter ce patch, lancez plutôt \"$cmdline --skip\".\n"
+"Pour restaurer la branche d'origine et stopper le patchage, lancez \"$cmdline --abort\"."
+
+#: git-am.sh:706
+msgid "Patch does not have a valid e-mail address."
+msgstr "Le patch n'a pas d'adresse e-mail valide."
+
+#: git-am.sh:753
+msgid "cannot be interactive without stdin connected to a terminal."
+msgstr "impossible d'être interactif sans entrée standard connectée à un terminal."
+
+#: git-am.sh:757
+msgid "Commit Body is:"
+msgstr "Le corps de la validation est :"
+
+#. TRANSLATORS: Make sure to include [y], [n], [e], [v] and [a]
+#. in your translation. The program will only accept English
+#. input at this point.
+#: git-am.sh:764
+msgid "Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all "
+msgstr "Appliquer ? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all "
+
+#: git-am.sh:800
+#, sh-format
+msgid "Applying: $FIRSTLINE"
+msgstr "Application : $FIRSTLINE"
+
+#: git-am.sh:821
+msgid ""
+"No changes - did you forget to use 'git add'?\n"
+"If there is nothing left to stage, chances are that something else\n"
+"already introduced the same changes; you might want to skip this patch."
+msgstr ""
+
+#: git-am.sh:829
+msgid ""
+"You still have unmerged paths in your index\n"
+"did you forget to use 'git add'?"
+msgstr ""
+"Vous avez toujours des chemins non fusionnés dans votre index\n"
+"auriez-vous oublié de faire 'git add' ?"
+
+#: git-am.sh:845
+msgid "No changes -- Patch already applied."
+msgstr "Pas de changement -- Patch déjà appliqué."
+
+#: git-am.sh:855
+#, sh-format
+msgid "Patch failed at $msgnum $FIRSTLINE"
+msgstr "Le patch a échoué à $msgnum $FIRSTLINE"
+
+#: git-am.sh:858
+#, sh-format
+msgid ""
+"The copy of the patch that failed is found in:\n"
+"   $dotest/patch"
+msgstr ""
+"La copie du patch qui a échoué se trouve dans :\n"
+"   $dotest/patch"
+
+#: git-am.sh:876
+msgid "applying to an empty history"
+msgstr "application à un historique vide"
+
+#: git-bisect.sh:48
+msgid "You need to start by \"git bisect start\""
+msgstr "Vous devez démarrer avec \"git bisect start\""
+
+#. TRANSLATORS: Make sure to include [Y] and [n] in your
+#. translation. The program will only accept English input
+#. at this point.
+#: git-bisect.sh:54
+msgid "Do you want me to do it for you [Y/n]? "
+msgstr "Souhaitez-vous que je le fasse pour vous [Y/n] ? "
+
+#: git-bisect.sh:95
+#, sh-format
+msgid "unrecognised option: '$arg'"
+msgstr "option inconnue : '$arg'"
+
+#: git-bisect.sh:99
+#, sh-format
+msgid "'$arg' does not appear to be a valid revision"
+msgstr "'$arg' ne semble être une révision valide"
+
+#: git-bisect.sh:117
+msgid "Bad HEAD - I need a HEAD"
+msgstr "Mauvaise HEAD - j'ai besoin d'une HEAD"
+
+#: git-bisect.sh:130
+#, sh-format
+msgid ""
+"Checking out '$start_head' failed. Try 'git bisect reset <validbranch>'."
+msgstr "L'extraction de '$start_head' a échoué. Essayez 'git bisect reset <branchevalide>'."
+
+#: git-bisect.sh:140
+msgid "won't bisect on seeked tree"
+msgstr ""
+
+#: git-bisect.sh:144
+msgid "Bad HEAD - strange symbolic ref"
+msgstr "Mauvaise HEAD - référence symbolique douteuse"
+
+#: git-bisect.sh:189
+#, sh-format
+msgid "Bad bisect_write argument: $state"
+msgstr "Mauvais argument pour bisect_write : $state"
+
+#: git-bisect.sh:218
+#, sh-format
+msgid "Bad rev input: $arg"
+msgstr "Mauvaise révision en entrée : $arg"
+
+#: git-bisect.sh:232
+msgid "Please call 'bisect_state' with at least one argument."
+msgstr "Merci d'appeler 'bisect_state' avec au moins un argument."
+
+#: git-bisect.sh:244
+#, sh-format
+msgid "Bad rev input: $rev"
+msgstr "Mauvaise révision en entrée : $rev"
+
+#: git-bisect.sh:250
+msgid "'git bisect bad' can take only one argument."
+msgstr "'git bisect bad' n'accepte qu'un seul argument."
+
+#. have bad but not good.  we could bisect although
+#. this is less optimum.
+#: git-bisect.sh:273
+msgid "Warning: bisecting only with a bad commit."
+msgstr "Attention : bissection avec seulement une mauvaise validation."
+
+#. TRANSLATORS: Make sure to include [Y] and [n] in your
+#. translation. The program will only accept English input
+#. at this point.
+#: git-bisect.sh:279
+msgid "Are you sure [Y/n]? "
+msgstr "Êtes-vous sûr [Y/n] ? "
+
+#: git-bisect.sh:289
+msgid ""
+"You need to give me at least one good and one bad revisions.\n"
+"(You can use \"git bisect bad\" and \"git bisect good\" for that.)"
+msgstr ""
+"Vous devez me donner au moins une bonne et une mauvaise révision.\n"
+"(Vous pouvez utiliser \"git bisect bad\" et \"git bisect good\" pour cela.)"
+
+#: git-bisect.sh:292
+msgid ""
+"You need to start by \"git bisect start\".\n"
+"You then need to give me at least one good and one bad revisions.\n"
+"(You can use \"git bisect bad\" and \"git bisect good\" for that.)"
+msgstr ""
+"Vous devez démarrer avec \"git bisect start\".\n"
+"Puis vous devez me donner au moins une bonne et une mauvaise révision.\n"
+"(Vous pouvez utiliser \"git bisect bad\" et \"git bisect good\" pour cela.)"
+
+#: git-bisect.sh:363 git-bisect.sh:490
+msgid "We are not bisecting."
+msgstr "Pas de bissection en cours."
+
+#: git-bisect.sh:370
+#, sh-format
+msgid "'$invalid' is not a valid commit"
+msgstr "'$invalid' n'est pas une validation valide"
+
+#: git-bisect.sh:379
+#, sh-format
+msgid ""
+"Could not check out original HEAD '$branch'.\n"
+"Try 'git bisect reset <commit>'."
+msgstr ""
+"Échec d'extraction de la HEAD d'origine '$branch'.\n"
+"Essayez 'git bisect reset <commit>'."
+
+#: git-bisect.sh:406
+msgid "No logfile given"
+msgstr "Pas de fichier de log donné"
+
+#: git-bisect.sh:407
+#, sh-format
+msgid "cannot read $file for replaying"
+msgstr "impossible de lire $file pour rejouer"
+
+#: git-bisect.sh:424
+msgid "?? what are you talking about?"
+msgstr "?? de quoi parlez-vous ?"
+
+#: git-bisect.sh:436
+#, sh-format
+msgid "running $command"
+msgstr "lancement de $command"
+
+#: git-bisect.sh:443
+#, sh-format
+msgid ""
+"bisect run failed:\n"
+"exit code $res from '$command' is < 0 or >= 128"
+msgstr ""
+"la bissection a échoué :\n"
+"le code retour $res de '$command' est < 0 ou >= 128"
+
+#: git-bisect.sh:469
+msgid "bisect run cannot continue any more"
+msgstr "la bissection ne peut plus continuer"
+
+#: git-bisect.sh:475
+#, sh-format
+msgid ""
+"bisect run failed:\n"
+"'bisect_state $state' exited with error code $res"
+msgstr ""
+"la bissection a échoué :\n"
+"'bisect_state $state' a retourné le code erreur $res"
+
+#: git-bisect.sh:482
+msgid "bisect run success"
+msgstr "succès de la bissection"
+
+#: git-pull.sh:21
+msgid ""
+"Pull is not possible because you have unmerged files.\n"
+"Please, fix them up in the work tree, and then use 'git add/rm <file>'\n"
+"as appropriate to mark resolution, or use 'git commit -a'."
+msgstr ""
+"Le pull n'est pas possible car vous avez des fichiers non fusionnés.\n"
+"Merci de corriger dans votre copie de travail, et utilisez alors 'git add/rm <file>'\n"
+"si nécessaire pour marquer comme résolu, ou utilisez 'git commit -a'."
+
+#: git-pull.sh:25
+msgid "Pull is not possible because you have unmerged files."
+msgstr "Le pull n'est pas possible car vous avez des fichiers non fusionnés."
+
+#: git-pull.sh:203
+msgid "updating an unborn branch with changes added to the index"
+msgstr "mise à jour d'une branche non encore créée avec les changements ajoutés dans l'index"
+
+#. The fetch involved updating the current branch.
+#. The working tree and the index file is still based on the
+#. $orig_head commit, but we are merging into $curr_head.
+#. First update the working tree to match $curr_head.
+#: git-pull.sh:235
+#, sh-format
+msgid ""
+"Warning: fetch updated the current branch head.\n"
+"Warning: fast-forwarding your working tree from\n"
+"Warning: commit $orig_head."
+msgstr ""
+"Attention : fetch a mis à jour la tête de la branche courante.\n"
+"Attention : mise à jour en avance rapide de votre copie de travail\n"
+"Attention : depuis la validation $orig_head."
+
+#: git-pull.sh:260
+msgid "Cannot merge multiple branches into empty head"
+msgstr "Impossible de fusionner de multiples branches sur une tête vide"
+
+#: git-pull.sh:264
+msgid "Cannot rebase onto multiple branches"
+msgstr "Impossible de rebaser sur de multiples branches"
+
+#: git-rebase.sh:53
+msgid ""
+"When you have resolved this problem, run \"git rebase --continue\".\n"
+"If you prefer to skip this patch, run \"git rebase --skip\" instead.\n"
+"To check out the original branch and stop rebasing, run \"git rebase --abort"
+"\"."
+msgstr ""
+"Lorsque vous aurez résolu ce problème, lancez \"git rebase --continue\".\n"
+"Si vous préférez sauter ce patch, lancez \"git rebase --skip\" à la place.\n"
+"Pour extraire la branche d'origine et stopper le rebasage, lancez \"git rebase --abort\"."
+
+#: git-rebase.sh:160
+msgid "The pre-rebase hook refused to rebase."
+msgstr "Le hook pre-rebase a refusé de rebaser."
+
+#: git-rebase.sh:165
+msgid "It looks like git-am is in progress. Cannot rebase."
+msgstr "Il semble que git-am soit en cours. Impossible de rebaser."
+
+#: git-rebase.sh:296
+msgid "The --exec option must be used with the --interactive option"
+msgstr "L'option --exec doit être utilisée avec l'option --interactive"
+
+#: git-rebase.sh:301
+msgid "No rebase in progress?"
+msgstr "Pas de rebasage en cours ?"
+
+#: git-rebase.sh:312
+msgid "The --edit-todo action can only be used during interactive rebase."
+msgstr "L'action --edit-todo peut seulement être utilisée lors d'un rebasage interactif."
+
+#: git-rebase.sh:319
+msgid "Cannot read HEAD"
+msgstr "Impossible de lire HEAD"
+
+#: git-rebase.sh:322
+msgid ""
+"You must edit all merge conflicts and then\n"
+"mark them as resolved using git add"
+msgstr ""
+"Vous devez éditer tous les conflits de fusion et\n"
+"les marquer comme résolus avec git add"
+
+#: git-rebase.sh:340
+#, sh-format
+msgid "Could not move back to $head_name"
+msgstr "Impossible de revenir à $head_name"
+
+#: git-rebase.sh:359
+#, sh-format
+msgid ""
+"It seems that there is already a $state_dir_base directory, and\n"
+"I wonder if you are in the middle of another rebase.  If that is the\n"
+"case, please try\n"
+"\t$cmd_live_rebase\n"
+"If that is not the case, please\n"
+"\t$cmd_clear_stale_rebase\n"
+"and run me again.  I am stopping in case you still have something\n"
+"valuable there."
+msgstr ""
+"Il semble qu'il y ait déjà un répertoire $state_dir_base, et je me demande\n"
+"si vous n'êtes pas au milieu d'un autre rebasage.  Si c'est le cas,\n"
+"merci d'essayer\n"
+"\t$cmd_live_rebase\n"
+"Si ça n'est pas le cas, merci de\n"
+"\t$cmd_clear_stale_rebase\n"
+"et relancer à nouveau.  Je m'arrête au cas où vous auriez quelque chose\n"
+"d'important ici."
+
+#: git-rebase.sh:404
+#, sh-format
+msgid "invalid upstream $upstream_name"
+msgstr "invalide $upstream_name en amont"
+
+#: git-rebase.sh:428
+#, sh-format
+msgid "$onto_name: there are more than one merge bases"
+msgstr "$onto_name : il y a plus d'une base de fusion"
+
+#: git-rebase.sh:431 git-rebase.sh:435
+#, sh-format
+msgid "$onto_name: there is no merge base"
+msgstr "$onto_name : il n'y a pas de base de fusion"
+
+#: git-rebase.sh:440
+#, sh-format
+msgid "Does not point to a valid commit: $onto_name"
+msgstr "Ne pointe pas sur une validation valide : $onto_name"
+
+#: git-rebase.sh:463
+#, sh-format
+msgid "fatal: no such branch: $branch_name"
+msgstr "fatal : pas de branche : $branch_name"
+
+#: git-rebase.sh:483
+msgid "Please commit or stash them."
+msgstr "Merci de les valider ou de les remiser."
+
+#: git-rebase.sh:501
+#, sh-format
+msgid "Current branch $branch_name is up to date."
+msgstr "La branche courante $branch_name est à jour."
+
+#: git-rebase.sh:504
+#, sh-format
+msgid "Current branch $branch_name is up to date, rebase forced."
+msgstr "La branche courante $branch_name est à jour, rebasage forcé."
+
+#: git-rebase.sh:515
+#, sh-format
+msgid "Changes from $mb to $onto:"
+msgstr "Changements de $mb sur $onto :"
+
+#. Detach HEAD and reset the tree
+#: git-rebase.sh:524
+msgid "First, rewinding head to replay your work on top of it..."
+msgstr "Premièrement, retour de head pour rejouer votre travail par-dessus..."
+
+#: git-rebase.sh:532
+#, sh-format
+msgid "Fast-forwarded $branch_name to $onto_name."
+msgstr "$branch_name mise à jour en avance rapide sur $onto_name."
+
+#: git-stash.sh:51
+msgid "git stash clear with parameters is unimplemented"
+msgstr "git stash clear avec des paramètres n'est pas implémenté"
+
+#: git-stash.sh:74
+msgid "You do not have the initial commit yet"
+msgstr "Vous n'avez pas encore la validation initiale"
+
+#: git-stash.sh:89
+msgid "Cannot save the current index state"
+msgstr "Impossible de sauver l'état courant de l'index"
+
+#: git-stash.sh:123 git-stash.sh:136
+msgid "Cannot save the current worktree state"
+msgstr "Impossible de sauver l'état courant de la copie de travail"
+
+#: git-stash.sh:140
+msgid "No changes selected"
+msgstr "Aucun changement sélectionné"
+
+#: git-stash.sh:143
+msgid "Cannot remove temporary index (can't happen)"
+msgstr "Impossible de supprimer l'index temporaire (ne peut pas se produire)"
+
+#: git-stash.sh:156
+msgid "Cannot record working tree state"
+msgstr "Impossible d'enregistrer l'état de la copie de travail"
+
+#. TRANSLATORS: $option is an invalid option, like
+#. `--blah-blah'. The 7 spaces at the beginning of the
+#. second line correspond to "error: ". So you should line
+#. up the second line with however many characters the
+#. translation of "error: " takes in your language. E.g. in
+#. English this is:
+#.
+#. $ git stash save --blah-blah 2>&1 | head -n 2
+#. error: unknown option for 'stash save': --blah-blah
+#. To provide a message, use git stash save -- '--blah-blah'
+#: git-stash.sh:202
+#, sh-format
+msgid ""
+"error: unknown option for 'stash save': $option\n"
+"       To provide a message, use git stash save -- '$option'"
+msgstr ""
+"erreur: option inconnue pour 'stash save': $option\n"
+"        Pour fournir un message, utilisez git stash save -- '$option'"
+
+#: git-stash.sh:223
+msgid "No local changes to save"
+msgstr "Pas de changements en local à sauver"
+
+#: git-stash.sh:227
+msgid "Cannot initialize stash"
+msgstr "Impossible d'initialiser le remisage"
+
+#: git-stash.sh:235
+msgid "Cannot save the current status"
+msgstr "Impossible de sauver le statut courant"
+
+#: git-stash.sh:253
+msgid "Cannot remove worktree changes"
+msgstr "Impossible de supprimer les changements de la copie de travail"
+
+#: git-stash.sh:352
+msgid "No stash found."
+msgstr "Pas de remisage trouvé."
+
+#: git-stash.sh:359
+#, sh-format
+msgid "Too many revisions specified: $REV"
+msgstr "Trop de révisions spécifiées : $REV"
+
+#: git-stash.sh:365
+#, sh-format
+msgid "$reference is not valid reference"
+msgstr "$reference n'est pas une référence valide"
+
+#: git-stash.sh:393
+#, sh-format
+msgid "'$args' is not a stash-like commit"
+msgstr "'$args' n'est pas une validation de type remisage"
+
+#: git-stash.sh:404
+#, sh-format
+msgid "'$args' is not a stash reference"
+msgstr "'$args' n'est pas une référence de remisage"
+
+#: git-stash.sh:412
+msgid "unable to refresh index"
+msgstr "impossible de rafraîchir l'index"
+
+#: git-stash.sh:416
+msgid "Cannot apply a stash in the middle of a merge"
+msgstr "Impossible d'appliquer un remisage au milieu d'une fusion"
+
+#: git-stash.sh:424
+msgid "Conflicts in index. Try without --index."
+msgstr "Conflits dans l'index. Essayez sans --index."
+
+#: git-stash.sh:426
+msgid "Could not save index tree"
+msgstr "Impossible de sauver l'arbre d'index"
+
+#: git-stash.sh:460
+msgid "Cannot unstage modified files"
+msgstr "Impossible de désindexer les fichiers modifiés"
+
+#: git-stash.sh:475
+msgid "Index was not unstashed."
+msgstr ""
+
+#: git-stash.sh:492
+#, sh-format
+msgid "Dropped ${REV} ($s)"
+msgstr "${REV} supprimé ($s)"
+
+#: git-stash.sh:493
+#, sh-format
+msgid "${REV}: Could not drop stash entry"
+msgstr "${REV}: Impossible de supprimer l'entrée de stash"
+
+#: git-stash.sh:500
+msgid "No branch name specified"
+msgstr "Aucune branche spécifiée"
+
+#: git-stash.sh:571
+msgid "(To restore them type \"git stash apply\")"
+msgstr "(Pour les restaurer tapez \"git stash apply\")"
+
+#: git-submodule.sh:91
+#, sh-format
+msgid "cannot strip one component off url '$remoteurl'"
+msgstr "impossible de supprimer un composant de l'URL '$remoteurl'"
+
+#: git-submodule.sh:196
+#, sh-format
+msgid "No submodule mapping found in .gitmodules for path '$sm_path'"
+msgstr "Pas de mappage du sous-module trouvé dans .gitmodules pour le chemin '$sm_path'"
+
+#: git-submodule.sh:239
+#, sh-format
+msgid "Clone of '$url' into submodule path '$sm_path' failed"
+msgstr "Le clonage de '$url' dans le chemin de sous-module '$sm_path' a échoué"
+
+#: git-submodule.sh:251
+#, sh-format
+msgid "Gitdir '$a' is part of the submodule path '$b' or vice versa"
+msgstr "Le répertoire Git '$a' fait partie du chemin de sous-module '$b' ou vice-versa"
+
+#: git-submodule.sh:349
+#, sh-format
+msgid "repo URL: '$repo' must be absolute or begin with ./|../"
+msgstr "L'URL de dépôt '$repo' doit être absolu ou commencer par ./|../"
+
+#: git-submodule.sh:366
+#, sh-format
+msgid "'$sm_path' already exists in the index"
+msgstr "'$sm_path' existe déjà dans l'index"
+
+#: git-submodule.sh:370
+#, sh-format
+msgid ""
+"The following path is ignored by one of your .gitignore files:\n"
+"$sm_path\n"
+"Use -f if you really want to add it."
+msgstr ""
+"Le chemin suivant est ignoré par un de vos fichiers .gitignore :\n"
+"$sm_path\n"
+"Utilisez -f si vous voulez vraiment l'ajouter."
+
+#: git-submodule.sh:388
+#, sh-format
+msgid "Adding existing repo at '$sm_path' to the index"
+msgstr "Ajout du dépôt existant à '$sm_path' dans l'index"
+
+#: git-submodule.sh:390
+#, sh-format
+msgid "'$sm_path' already exists and is not a valid git repo"
+msgstr "'$sm_path' existe déjà et n'est pas un dépôt git valide"
+
+#: git-submodule.sh:398
+#, sh-format
+msgid "A git directory for '$sm_name' is found locally with remote(s):"
+msgstr "Un répertoire git pour '$sm_name' est trouvé en local avec le(s) serveur(s) distant(s) :"
+
+#: git-submodule.sh:400
+#, sh-format
+msgid ""
+"If you want to reuse this local git directory instead of cloning again from"
+msgstr "Si vous voulez réutiliser ce répertoire git local au lieu de cloner à nouveau depuis"
+
+#: git-submodule.sh:402
+#, sh-format
+msgid ""
+"use the '--force' option. If the local git directory is not the correct repo"
+msgstr "utilisez l'option '--force'. Si le répertoire local git n'est pas le dépôt correct"
+
+#: git-submodule.sh:403
+#, sh-format
+msgid ""
+"or you are unsure what this means choose another name with the '--name' "
+"option."
+msgstr "ou vous ne savez pas ce que cela signifie de choisir un autre nom avec l'option '--name'."
+
+#: git-submodule.sh:405
+#, sh-format
+msgid "Reactivating local git directory for submodule '$sm_name'."
+msgstr "Réactivation du répertoire git local pour le sous-module '$sm_name'."
+
+#: git-submodule.sh:417
+#, sh-format
+msgid "Unable to checkout submodule '$sm_path'"
+msgstr "Impossible d'extraire le sous-module '$sm_path'"
+
+#: git-submodule.sh:422
+#, sh-format
+msgid "Failed to add submodule '$sm_path'"
+msgstr "Échec d'ajout du sous-module '$sm_path'"
+
+#: git-submodule.sh:431
+#, sh-format
+msgid "Failed to register submodule '$sm_path'"
+msgstr "Échec d'enregistrement du sous-module '$sm_path'"
+
+#: git-submodule.sh:474
+#, sh-format
+msgid "Entering '$prefix$sm_path'"
+msgstr "Entrée dans '$prefix$sm_path'"
+
+#: git-submodule.sh:488
+#, sh-format
+msgid "Stopping at '$sm_path'; script returned non-zero status."
+msgstr "Arrêt sur '$sm_path' ; le script a retourné un statut non nul."
+
+#: git-submodule.sh:532
+#, sh-format
+msgid "No url found for submodule path '$sm_path' in .gitmodules"
+msgstr "URL non trouvé pour le chemin de sous-module '$sm_path' dans .gitmodules"
+
+#: git-submodule.sh:541
+#, sh-format
+msgid "Failed to register url for submodule path '$sm_path'"
+msgstr "Échec d'enregistrement de l'URL pour le chemin de sous-module '$sm_path'"
+
+#: git-submodule.sh:543
+#, sh-format
+msgid "Submodule '$name' ($url) registered for path '$sm_path'"
+msgstr "Sous-module '$name' ($url) enregistré pour le chemin '$sm_path'"
+
+#: git-submodule.sh:551
+#, sh-format
+msgid "Failed to register update mode for submodule path '$sm_path'"
+msgstr "Échec d'enregistrement du mode de mise à jour pour le chemin de sous-module '$sm_path'"
+
+#: git-submodule.sh:588
+#, sh-format
+msgid "Use '.' if you really want to deinitialize all submodules"
+msgstr "Utilisez '.' si vous voulez vraiment réinitialiser tous les sous-modules"
+
+#: git-submodule.sh:603
+#, sh-format
+msgid "Submodule work tree '$sm_path' contains a .git directory"
+msgstr "La copie de travail du sous-module '$sm_path' contient un répertoire .git"
+
+#: git-submodule.sh:604
+#, sh-format
+msgid ""
+"(use 'rm -rf' if you really want to remove it including all of its history)"
+msgstr "(utilisez 'rm -rf' si vous voulez vraiment le supprimer en incluant tout son historique)"
+
+#: git-submodule.sh:610
+#, sh-format
+msgid ""
+"Submodule work tree '$sm_path' contains local modifications; use '-f' to "
+"discard them"
+msgstr "La copie de travail du sous-module '$sm_path' contient des modifications locales; utilisez '-f' pour les annuler"
+
+#: git-submodule.sh:613
+#, sh-format
+msgid "Cleared directory '$sm_path'"
+msgstr "Répertoire '$sm_path' nettoyé"
+
+#: git-submodule.sh:614
+#, sh-format
+msgid "Could not remove submodule work tree '$sm_path'"
+msgstr "Impossible de supprimer la copie de travail du sous-module '$sm_path'"
+
+#: git-submodule.sh:617
+#, sh-format
+msgid "Could not create empty submodule directory '$sm_path'"
+msgstr "Impossible de créer le répertoire vide du sous-module '$sm_path'"
+
+#: git-submodule.sh:626
+#, sh-format
+msgid "Submodule '$name' ($url) unregistered for path '$sm_path'"
+msgstr "Le sous-module '$name' ($url) n'est pas enregistré pour le chemin '$sm_path'"
+
+#: git-submodule.sh:731
+#, sh-format
+msgid ""
+"Submodule path '$prefix$sm_path' not initialized\n"
+"Maybe you want to use 'update --init'?"
+msgstr ""
+"Chemin de sous-module '$prefix$sm_path' non initialisé\n"
+"Peut-être souhaitez-vous utiliser 'update --init' ?"
+
+#: git-submodule.sh:744
+#, sh-format
+msgid "Unable to find current revision in submodule path '$prefix$sm_path'"
+msgstr "Impossible de trouver la révision courante dans le chemin de sous-module '$prefix$sm_path'"
+
+#: git-submodule.sh:753
+#, sh-format
+msgid "Unable to fetch in submodule path '$sm_path'"
+msgstr "Impossible de rapatrier dans le chemin de sous-module '$sm_path'"
+
+#: git-submodule.sh:777
+#, sh-format
+msgid "Unable to fetch in submodule path '$prefix$sm_path'"
+msgstr "Impossible de rapatrier dans le chemin de sous-module '$prefix$sm_path'"
+
+#: git-submodule.sh:791
+#, sh-format
+msgid "Unable to rebase '$sha1' in submodule path '$prefix$sm_path'"
+msgstr "Impossible de rebaser '$sha1' dans le chemin de sous-module '$prefix$sm_path'"
+
+#: git-submodule.sh:792
+#, sh-format
+msgid "Submodule path '$prefix$sm_path': rebased into '$sha1'"
+msgstr "Chemin de sous-module '$prefix$sm_path' : rebasé dans '$sha1'"
+
+#: git-submodule.sh:797
+#, sh-format
+msgid "Unable to merge '$sha1' in submodule path '$prefix$sm_path'"
+msgstr "Impossible de fusionner '$sha1' dans le chemin de sous-module '$prefix$sm_path'"
+
+#: git-submodule.sh:798
+#, sh-format
+msgid "Submodule path '$prefix$sm_path': merged in '$sha1'"
+msgstr "Chemin de sous-module '$prefix$sm_path' : fusionné dans '$sha1'"
+
+#: git-submodule.sh:803
+#, sh-format
+msgid "Unable to checkout '$sha1' in submodule path '$prefix$sm_path'"
+msgstr "Impossible d'extraire '$sha1' dans le chemin de sous-module '$prefix$sm_path'"
+
+#: git-submodule.sh:804
+#, sh-format
+msgid "Submodule path '$prefix$sm_path': checked out '$sha1'"
+msgstr "Chemin de sous-module '$prefix$sm_path' : '$sha1' extrait"
+
+#: git-submodule.sh:831
+#, sh-format
+msgid "Failed to recurse into submodule path '$prefix$sm_path'"
+msgstr "Échec de parcours dans le chemin du sous-module '$prefix$sm_path'"
+
+#: git-submodule.sh:939
+msgid "The --cached option cannot be used with the --files option"
+msgstr "L'option --cached ne peut pas être utilisée avec l'option --files"
+
+#. unexpected type
+#: git-submodule.sh:979
+#, sh-format
+msgid "unexpected mode $mod_dst"
+msgstr "mode $mod_dst inattendu"
+
+#: git-submodule.sh:997
+#, sh-format
+msgid "  Warn: $name doesn't contain commit $sha1_src"
+msgstr "  Attention : $name ne contient pas la validation $sha1_src"
+
+#: git-submodule.sh:1000
+#, sh-format
+msgid "  Warn: $name doesn't contain commit $sha1_dst"
+msgstr "  Attention : $name ne contient pas la validation $sha1_dst"
+
+#: git-submodule.sh:1003
+#, sh-format
+msgid "  Warn: $name doesn't contain commits $sha1_src and $sha1_dst"
+msgstr "  Attention : $name ne contient pas les validations $sha1_src et $sha1_dst"
+
+#: git-submodule.sh:1028
+msgid "blob"
+msgstr "blob"
+
+#: git-submodule.sh:1066
+msgid "Submodules changed but not updated:"
+msgstr "Sous-modules modifiés mais non mis à jour :"
+
+#: git-submodule.sh:1068
+msgid "Submodule changes to be committed:"
+msgstr "Changements du sous-module à valider :"
+
+#: git-submodule.sh:1153
+#, sh-format
+msgid "Failed to recurse into submodule path '$sm_path'"
+msgstr "Échec de parcours dans le chemin du sous-module '$sm_path'"
+
+#: git-submodule.sh:1216
+#, sh-format
+msgid "Synchronizing submodule url for '$prefix$sm_path'"
+msgstr "Synchronisation de l'URL sous-module pour '$prefix$sm_path'"
diff --git a/po/git.pot b/po/git.pot
index 9a3e0a8..cf1e446 100644
--- a/po/git.pot
+++ b/po/git.pot
@@ -8,7 +8,7 @@
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
-"POT-Creation-Date: 2013-04-10 15:16+0800\n"
+"POT-Creation-Date: 2013-08-06 14:10+0800\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -18,7 +18,7 @@
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
 
-#: advice.c:53
+#: advice.c:57
 #, c-format
 msgid "hint: %.*s\n"
 msgstr ""
@@ -27,7 +27,7 @@
 #. * Message used both when 'git commit' fails and when
 #. * other commands doing a merge do.
 #.
-#: advice.c:83
+#: advice.c:87
 msgid ""
 "Fix them up in the work tree,\n"
 "and then use 'git add/rm <file>' as\n"
@@ -60,7 +60,7 @@
 msgid "archive format"
 msgstr ""
 
-#: archive.c:324 builtin/log.c:1117
+#: archive.c:324 builtin/log.c:1173
 msgid "prefix"
 msgstr ""
 
@@ -68,11 +68,11 @@
 msgid "prepend prefix to each pathname in the archive"
 msgstr ""
 
-#: archive.c:326 builtin/archive.c:88 builtin/blame.c:2366
-#: builtin/blame.c:2367 builtin/config.c:55 builtin/fast-export.c:659
-#: builtin/fast-export.c:661 builtin/grep.c:715 builtin/hash-object.c:77
-#: builtin/ls-files.c:497 builtin/ls-files.c:500 builtin/notes.c:536
-#: builtin/notes.c:693 builtin/read-tree.c:107 parse-options.h:149
+#: archive.c:326 builtin/archive.c:88 builtin/blame.c:2292
+#: builtin/blame.c:2293 builtin/config.c:56 builtin/fast-export.c:673
+#: builtin/fast-export.c:675 builtin/grep.c:714 builtin/hash-object.c:77
+#: builtin/ls-files.c:496 builtin/ls-files.c:499 builtin/notes.c:408
+#: builtin/notes.c:565 builtin/read-tree.c:108 parse-options.h:152
 msgid "file"
 msgstr ""
 
@@ -104,7 +104,7 @@
 msgid "list supported archive formats"
 msgstr ""
 
-#: archive.c:345 builtin/archive.c:90 builtin/clone.c:86
+#: archive.c:345 builtin/archive.c:90 builtin/clone.c:85
 msgid "repo"
 msgstr ""
 
@@ -112,7 +112,7 @@
 msgid "retrieve the archive from remote repository <repo>"
 msgstr ""
 
-#: archive.c:347 builtin/archive.c:92 builtin/notes.c:615
+#: archive.c:347 builtin/archive.c:92 builtin/notes.c:487
 msgid "command"
 msgstr ""
 
@@ -126,17 +126,86 @@
 "Use '\\!' for literal leading exclamation."
 msgstr ""
 
-#: branch.c:201
+#: branch.c:60
+#, c-format
+msgid "Not setting branch %s as its own upstream."
+msgstr ""
+
+#: branch.c:82
+#, c-format
+msgid "Branch %s set up to track remote branch %s from %s by rebasing."
+msgstr ""
+
+#: branch.c:83
+#, c-format
+msgid "Branch %s set up to track remote branch %s from %s."
+msgstr ""
+
+#: branch.c:87
+#, c-format
+msgid "Branch %s set up to track local branch %s by rebasing."
+msgstr ""
+
+#: branch.c:88
+#, c-format
+msgid "Branch %s set up to track local branch %s."
+msgstr ""
+
+#: branch.c:92
+#, c-format
+msgid "Branch %s set up to track remote ref %s by rebasing."
+msgstr ""
+
+#: branch.c:93
+#, c-format
+msgid "Branch %s set up to track remote ref %s."
+msgstr ""
+
+#: branch.c:97
+#, c-format
+msgid "Branch %s set up to track local ref %s by rebasing."
+msgstr ""
+
+#: branch.c:98
+#, c-format
+msgid "Branch %s set up to track local ref %s."
+msgstr ""
+
+#: branch.c:118
+#, c-format
+msgid "Tracking not set up: name too long: %s"
+msgstr ""
+
+#: branch.c:137
+#, c-format
+msgid "Not tracking: ambiguous information for ref %s"
+msgstr ""
+
+#: branch.c:182
+#, c-format
+msgid "'%s' is not a valid branch name."
+msgstr ""
+
+#: branch.c:187
+#, c-format
+msgid "A branch named '%s' already exists."
+msgstr ""
+
+#: branch.c:195
+msgid "Cannot force update the current branch."
+msgstr ""
+
+#: branch.c:216
 #, c-format
 msgid "Cannot setup tracking information; starting point '%s' is not a branch."
 msgstr ""
 
-#: branch.c:203
+#: branch.c:218
 #, c-format
 msgid "the requested upstream branch '%s' does not exist"
 msgstr ""
 
-#: branch.c:205
+#: branch.c:220
 msgid ""
 "\n"
 "If you are planning on basing your work on an upstream\n"
@@ -148,6 +217,29 @@
 "\"git push -u\" to set the upstream config as you push."
 msgstr ""
 
+#: branch.c:265
+#, c-format
+msgid "Not a valid object name: '%s'."
+msgstr ""
+
+#: branch.c:285
+#, c-format
+msgid "Ambiguous object name: '%s'."
+msgstr ""
+
+#: branch.c:290
+#, c-format
+msgid "Not a valid branch point: '%s'."
+msgstr ""
+
+#: branch.c:296
+msgid "Failed to lock ref for update"
+msgstr ""
+
+#: branch.c:314
+msgid "Failed to write ref"
+msgstr ""
+
 #: bundle.c:36
 #, c-format
 msgid "'%s' does not look like a v2 bundle file"
@@ -158,7 +250,7 @@
 msgid "unrecognized header: %s%s (%d)"
 msgstr ""
 
-#: bundle.c:89 builtin/commit.c:676
+#: bundle.c:89 builtin/commit.c:697
 #, c-format
 msgid "could not open '%s'"
 msgstr ""
@@ -167,9 +259,9 @@
 msgid "Repository lacks these prerequisite commits:"
 msgstr ""
 
-#: bundle.c:164 sequencer.c:651 sequencer.c:1083 builtin/log.c:300
-#: builtin/log.c:754 builtin/log.c:1350 builtin/log.c:1566 builtin/merge.c:349
-#: builtin/shortlog.c:157
+#: bundle.c:164 sequencer.c:661 sequencer.c:1111 builtin/log.c:331
+#: builtin/log.c:801 builtin/log.c:1399 builtin/log.c:1625 builtin/merge.c:364
+#: builtin/shortlog.c:156
 msgid "revision walk setup failed"
 msgstr ""
 
@@ -195,7 +287,7 @@
 msgid "rev-list died"
 msgstr ""
 
-#: bundle.c:300 builtin/log.c:1246 builtin/shortlog.c:260
+#: bundle.c:300 builtin/log.c:1310 builtin/shortlog.c:259
 #, c-format
 msgid "unrecognized argument: %s"
 msgstr ""
@@ -226,12 +318,12 @@
 msgid "index-pack died"
 msgstr ""
 
-#: commit.c:50
+#: commit.c:53
 #, c-format
 msgid "could not parse %s"
 msgstr ""
 
-#: commit.c:52
+#: commit.c:55
 #, c-format
 msgid "%s %s is not a commit!"
 msgstr ""
@@ -240,16 +332,16 @@
 msgid "memory exhausted"
 msgstr ""
 
-#: connected.c:39
+#: connected.c:60
 msgid "Could not run 'git rev-list'"
 msgstr ""
 
-#: connected.c:48
+#: connected.c:80
 #, c-format
 msgid "failed write to rev-list: %s"
 msgstr ""
 
-#: connected.c:56
+#: connected.c:88
 #, c-format
 msgid "failed to close rev-list's stdin: %s"
 msgstr ""
@@ -343,14 +435,14 @@
 "%s"
 msgstr ""
 
-#: diff.c:3480
+#: diff.c:3487
 #, c-format
 msgid ""
 "Failed to parse --dirstat/-X option parameter:\n"
 "%s"
 msgstr ""
 
-#: diff.c:3494
+#: diff.c:3501
 #, c-format
 msgid "Failed to parse --submodule option parameter: '%s'"
 msgstr ""
@@ -392,48 +484,48 @@
 msgid "'%s': short read %s"
 msgstr ""
 
-#: help.c:212
+#: help.c:210
 #, c-format
 msgid "available git commands in '%s'"
 msgstr ""
 
-#: help.c:219
+#: help.c:217
 msgid "git commands available from elsewhere on your $PATH"
 msgstr ""
 
-#: help.c:235
+#: help.c:233
 msgid "The most commonly used git commands are:"
 msgstr ""
 
-#: help.c:292
+#: help.c:290
 #, c-format
 msgid ""
 "'%s' appears to be a git command, but we were not\n"
 "able to execute it. Maybe git-%s is broken?"
 msgstr ""
 
-#: help.c:349
+#: help.c:347
 msgid "Uh oh. Your system reports no Git commands at all."
 msgstr ""
 
-#: help.c:371
+#: help.c:369
 #, c-format
 msgid ""
 "WARNING: You called a Git command named '%s', which does not exist.\n"
 "Continuing under the assumption that you meant '%s'"
 msgstr ""
 
-#: help.c:376
+#: help.c:374
 #, c-format
 msgid "in %0.1f seconds automatically..."
 msgstr ""
 
-#: help.c:383
+#: help.c:381
 #, c-format
 msgid "git: '%s' is not a git command. See 'git --help'."
 msgstr ""
 
-#: help.c:387
+#: help.c:385 help.c:444
 msgid ""
 "\n"
 "Did you mean this?"
@@ -443,12 +535,17 @@
 msgstr[0] ""
 msgstr[1] ""
 
+#: help.c:440
+#, c-format
+msgid "%s: %s - %s"
+msgstr ""
+
 #: merge.c:56
 msgid "failed to read the cache"
 msgstr ""
 
-#: merge.c:110 builtin/checkout.c:362 builtin/checkout.c:563
-#: builtin/clone.c:635
+#: merge.c:110 builtin/checkout.c:365 builtin/checkout.c:566
+#: builtin/clone.c:656
 msgid "unable to write new index file"
 msgstr ""
 
@@ -462,243 +559,264 @@
 msgid "addinfo_cache failed for path '%s'"
 msgstr ""
 
-#: merge-recursive.c:268
+#: merge-recursive.c:269
 msgid "error building trees"
 msgstr ""
 
-#: merge-recursive.c:672
+#: merge-recursive.c:673
 #, c-format
 msgid "failed to create path '%s'%s"
 msgstr ""
 
-#: merge-recursive.c:683
+#: merge-recursive.c:684
 #, c-format
 msgid "Removing %s to make room for subdirectory\n"
 msgstr ""
 
 #. something else exists
 #. .. but not some other error (who really cares what?)
-#: merge-recursive.c:697 merge-recursive.c:718
+#: merge-recursive.c:698 merge-recursive.c:719
 msgid ": perhaps a D/F conflict?"
 msgstr ""
 
-#: merge-recursive.c:708
+#: merge-recursive.c:709
 #, c-format
 msgid "refusing to lose untracked file at '%s'"
 msgstr ""
 
-#: merge-recursive.c:748
+#: merge-recursive.c:749
 #, c-format
 msgid "cannot read object %s '%s'"
 msgstr ""
 
-#: merge-recursive.c:750
+#: merge-recursive.c:751
 #, c-format
 msgid "blob expected for %s '%s'"
 msgstr ""
 
-#: merge-recursive.c:773 builtin/clone.c:303
+#: merge-recursive.c:774 builtin/clone.c:312
 #, c-format
 msgid "failed to open '%s'"
 msgstr ""
 
-#: merge-recursive.c:781
+#: merge-recursive.c:782
 #, c-format
 msgid "failed to symlink '%s'"
 msgstr ""
 
-#: merge-recursive.c:784
+#: merge-recursive.c:785
 #, c-format
 msgid "do not know what to do with %06o %s '%s'"
 msgstr ""
 
-#: merge-recursive.c:922
+#: merge-recursive.c:923
 msgid "Failed to execute internal merge"
 msgstr ""
 
-#: merge-recursive.c:926
+#: merge-recursive.c:927
 #, c-format
 msgid "Unable to add %s to database"
 msgstr ""
 
-#: merge-recursive.c:942
+#: merge-recursive.c:943
 msgid "unsupported object type in the tree"
 msgstr ""
 
-#: merge-recursive.c:1021 merge-recursive.c:1035
+#: merge-recursive.c:1022 merge-recursive.c:1036
 #, c-format
 msgid ""
 "CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s left "
 "in tree."
 msgstr ""
 
-#: merge-recursive.c:1027 merge-recursive.c:1040
+#: merge-recursive.c:1028 merge-recursive.c:1041
 #, c-format
 msgid ""
 "CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s left "
 "in tree at %s."
 msgstr ""
 
-#: merge-recursive.c:1081
+#: merge-recursive.c:1082
 msgid "rename"
 msgstr ""
 
-#: merge-recursive.c:1081
+#: merge-recursive.c:1082
 msgid "renamed"
 msgstr ""
 
-#: merge-recursive.c:1137
+#: merge-recursive.c:1138
 #, c-format
 msgid "%s is a directory in %s adding as %s instead"
 msgstr ""
 
-#: merge-recursive.c:1159
+#: merge-recursive.c:1160
 #, c-format
 msgid ""
 "CONFLICT (rename/rename): Rename \"%s\"->\"%s\" in branch \"%s\" rename \"%s"
 "\"->\"%s\" in \"%s\"%s"
 msgstr ""
 
-#: merge-recursive.c:1164
+#: merge-recursive.c:1165
 msgid " (left unresolved)"
 msgstr ""
 
-#: merge-recursive.c:1218
+#: merge-recursive.c:1219
 #, c-format
 msgid "CONFLICT (rename/rename): Rename %s->%s in %s. Rename %s->%s in %s"
 msgstr ""
 
-#: merge-recursive.c:1248
+#: merge-recursive.c:1249
 #, c-format
 msgid "Renaming %s to %s and %s to %s instead"
 msgstr ""
 
-#: merge-recursive.c:1447
+#: merge-recursive.c:1448
 #, c-format
 msgid "CONFLICT (rename/add): Rename %s->%s in %s. %s added in %s"
 msgstr ""
 
-#: merge-recursive.c:1457
+#: merge-recursive.c:1458
 #, c-format
 msgid "Adding merged %s"
 msgstr ""
 
-#: merge-recursive.c:1462 merge-recursive.c:1660
+#: merge-recursive.c:1463 merge-recursive.c:1661
 #, c-format
 msgid "Adding as %s instead"
 msgstr ""
 
-#: merge-recursive.c:1513
+#: merge-recursive.c:1514
 #, c-format
 msgid "cannot read object %s"
 msgstr ""
 
-#: merge-recursive.c:1516
+#: merge-recursive.c:1517
 #, c-format
 msgid "object %s is not a blob"
 msgstr ""
 
-#: merge-recursive.c:1564
+#: merge-recursive.c:1565
 msgid "modify"
 msgstr ""
 
-#: merge-recursive.c:1564
+#: merge-recursive.c:1565
 msgid "modified"
 msgstr ""
 
-#: merge-recursive.c:1574
+#: merge-recursive.c:1575
 msgid "content"
 msgstr ""
 
-#: merge-recursive.c:1581
+#: merge-recursive.c:1582
 msgid "add/add"
 msgstr ""
 
-#: merge-recursive.c:1615
+#: merge-recursive.c:1616
 #, c-format
 msgid "Skipped %s (merged same as existing)"
 msgstr ""
 
-#: merge-recursive.c:1629
+#: merge-recursive.c:1630
 #, c-format
 msgid "Auto-merging %s"
 msgstr ""
 
-#: merge-recursive.c:1633 git-submodule.sh:1029
+#: merge-recursive.c:1634 git-submodule.sh:1118
 msgid "submodule"
 msgstr ""
 
-#: merge-recursive.c:1634
+#: merge-recursive.c:1635
 #, c-format
 msgid "CONFLICT (%s): Merge conflict in %s"
 msgstr ""
 
-#: merge-recursive.c:1724
+#: merge-recursive.c:1725
 #, c-format
 msgid "Removing %s"
 msgstr ""
 
-#: merge-recursive.c:1749
+#: merge-recursive.c:1750
 msgid "file/directory"
 msgstr ""
 
-#: merge-recursive.c:1755
+#: merge-recursive.c:1756
 msgid "directory/file"
 msgstr ""
 
-#: merge-recursive.c:1760
+#: merge-recursive.c:1761
 #, c-format
 msgid "CONFLICT (%s): There is a directory with name %s in %s. Adding %s as %s"
 msgstr ""
 
-#: merge-recursive.c:1770
+#: merge-recursive.c:1771
 #, c-format
 msgid "Adding %s"
 msgstr ""
 
-#: merge-recursive.c:1787
+#: merge-recursive.c:1788
 msgid "Fatal merge failure, shouldn't happen."
 msgstr ""
 
-#: merge-recursive.c:1806
+#: merge-recursive.c:1807
 msgid "Already up-to-date!"
 msgstr ""
 
-#: merge-recursive.c:1815
+#: merge-recursive.c:1816
 #, c-format
 msgid "merging of trees %s and %s failed"
 msgstr ""
 
-#: merge-recursive.c:1845
+#: merge-recursive.c:1846
 #, c-format
 msgid "Unprocessed path??? %s"
 msgstr ""
 
-#: merge-recursive.c:1890
+#: merge-recursive.c:1891
 msgid "Merging:"
 msgstr ""
 
-#: merge-recursive.c:1903
+#: merge-recursive.c:1904
 #, c-format
 msgid "found %u common ancestor:"
 msgid_plural "found %u common ancestors:"
 msgstr[0] ""
 msgstr[1] ""
 
-#: merge-recursive.c:1940
+#: merge-recursive.c:1941
 msgid "merge returned no commit"
 msgstr ""
 
-#: merge-recursive.c:1997
+#: merge-recursive.c:1998
 #, c-format
 msgid "Could not parse object '%s'"
 msgstr ""
 
-#: merge-recursive.c:2009 builtin/merge.c:658
+#: merge-recursive.c:2010 builtin/merge.c:672
 msgid "Unable to write index."
 msgstr ""
 
-#: object.c:195
+#: notes-utils.c:40
+msgid "Cannot commit uninitialized/unreferenced notes tree"
+msgstr ""
+
+#: notes-utils.c:81
+#, c-format
+msgid "Bad notes.rewriteMode value: '%s'"
+msgstr ""
+
+#: notes-utils.c:91
+#, c-format
+msgid "Refusing to rewrite notes in %s (outside of refs/notes/)"
+msgstr ""
+
+#. TRANSLATORS: The first %s is the name of the
+#. environment variable, the second %s is its value
+#: notes-utils.c:118
+#, c-format
+msgid "Bad %s value: '%s'"
+msgstr ""
+
+#: object.c:204
 #, c-format
 msgid "unable to parse object: %s"
 msgstr ""
@@ -738,18 +856,18 @@
 msgid "'%s' is beyond a symbolic link"
 msgstr ""
 
-#: remote.c:1781
+#: remote.c:1788
 #, c-format
 msgid "Your branch is ahead of '%s' by %d commit.\n"
 msgid_plural "Your branch is ahead of '%s' by %d commits.\n"
 msgstr[0] ""
 msgstr[1] ""
 
-#: remote.c:1787
+#: remote.c:1794
 msgid "  (use \"git push\" to publish your local commits)\n"
 msgstr ""
 
-#: remote.c:1790
+#: remote.c:1797
 #, c-format
 msgid "Your branch is behind '%s' by %d commit, and can be fast-forwarded.\n"
 msgid_plural ""
@@ -757,11 +875,11 @@
 msgstr[0] ""
 msgstr[1] ""
 
-#: remote.c:1798
+#: remote.c:1805
 msgid "  (use \"git pull\" to update your local branch)\n"
 msgstr ""
 
-#: remote.c:1801
+#: remote.c:1808
 #, c-format
 msgid ""
 "Your branch and '%s' have diverged,\n"
@@ -772,18 +890,27 @@
 msgstr[0] ""
 msgstr[1] ""
 
-#: remote.c:1811
+#: remote.c:1818
 msgid "  (use \"git pull\" to merge the remote branch into yours)\n"
 msgstr ""
 
-#: sequencer.c:206 builtin/merge.c:776 builtin/merge.c:889 builtin/merge.c:999
-#: builtin/merge.c:1009
+#: run-command.c:80
+msgid "open /dev/null failed"
+msgstr ""
+
+#: run-command.c:82
+#, c-format
+msgid "dup2(%d,%d) failed"
+msgstr ""
+
+#: sequencer.c:206 builtin/merge.c:790 builtin/merge.c:903
+#: builtin/merge.c:1013 builtin/merge.c:1023
 #, c-format
 msgid "Could not open '%s' for writing"
 msgstr ""
 
-#: sequencer.c:208 builtin/merge.c:335 builtin/merge.c:779
-#: builtin/merge.c:1001 builtin/merge.c:1014
+#: sequencer.c:208 builtin/merge.c:350 builtin/merge.c:793
+#: builtin/merge.c:1015 builtin/merge.c:1028
 #, c-format
 msgid "Could not write to '%s'"
 msgstr ""
@@ -801,7 +928,7 @@
 "and commit the result with 'git commit'"
 msgstr ""
 
-#: sequencer.c:245 sequencer.c:859 sequencer.c:942
+#: sequencer.c:245 sequencer.c:869 sequencer.c:952
 #, c-format
 msgid "Could not write to %s"
 msgstr ""
@@ -824,205 +951,228 @@
 msgstr ""
 
 #. TRANSLATORS: %s will be "revert" or "cherry-pick"
-#: sequencer.c:319
+#: sequencer.c:324
 #, c-format
 msgid "%s: Unable to write new index file"
 msgstr ""
 
-#: sequencer.c:350
+#: sequencer.c:355
 msgid "Could not resolve HEAD commit\n"
 msgstr ""
 
-#: sequencer.c:371
+#: sequencer.c:377
 msgid "Unable to update cache tree\n"
 msgstr ""
 
-#: sequencer.c:416
+#: sequencer.c:422
 #, c-format
 msgid "Could not parse commit %s\n"
 msgstr ""
 
-#: sequencer.c:421
+#: sequencer.c:427
 #, c-format
 msgid "Could not parse parent commit %s\n"
 msgstr ""
 
-#: sequencer.c:487
+#: sequencer.c:493
 msgid "Your index file is unmerged."
 msgstr ""
 
-#: sequencer.c:506
+#: sequencer.c:512
 #, c-format
 msgid "Commit %s is a merge but no -m option was given."
 msgstr ""
 
-#: sequencer.c:514
+#: sequencer.c:520
 #, c-format
 msgid "Commit %s does not have parent %d"
 msgstr ""
 
-#: sequencer.c:518
+#: sequencer.c:524
 #, c-format
 msgid "Mainline was specified but commit %s is not a merge."
 msgstr ""
 
 #. TRANSLATORS: The first %s will be "revert" or
 #. "cherry-pick", the second %s a SHA1
-#: sequencer.c:531
+#: sequencer.c:537
 #, c-format
 msgid "%s: cannot parse parent commit %s"
 msgstr ""
 
-#: sequencer.c:535
+#: sequencer.c:541
 #, c-format
 msgid "Cannot get commit message for %s"
 msgstr ""
 
-#: sequencer.c:621
+#: sequencer.c:627
 #, c-format
 msgid "could not revert %s... %s"
 msgstr ""
 
-#: sequencer.c:622
+#: sequencer.c:628
 #, c-format
 msgid "could not apply %s... %s"
 msgstr ""
 
-#: sequencer.c:654
+#: sequencer.c:664
 msgid "empty commit set passed"
 msgstr ""
 
-#: sequencer.c:662
+#: sequencer.c:672
 #, c-format
 msgid "git %s: failed to read the index"
 msgstr ""
 
-#: sequencer.c:667
+#: sequencer.c:677
 #, c-format
 msgid "git %s: failed to refresh the index"
 msgstr ""
 
-#: sequencer.c:725
+#: sequencer.c:735
 #, c-format
 msgid "Cannot %s during a %s"
 msgstr ""
 
-#: sequencer.c:747
+#: sequencer.c:757
 #, c-format
 msgid "Could not parse line %d."
 msgstr ""
 
-#: sequencer.c:752
+#: sequencer.c:762
 msgid "No commits parsed."
 msgstr ""
 
-#: sequencer.c:765
+#: sequencer.c:775
 #, c-format
 msgid "Could not open %s"
 msgstr ""
 
-#: sequencer.c:769
+#: sequencer.c:779
 #, c-format
 msgid "Could not read %s."
 msgstr ""
 
-#: sequencer.c:776
+#: sequencer.c:786
 #, c-format
 msgid "Unusable instruction sheet: %s"
 msgstr ""
 
-#: sequencer.c:804
+#: sequencer.c:814
 #, c-format
 msgid "Invalid key: %s"
 msgstr ""
 
-#: sequencer.c:807
+#: sequencer.c:817
 #, c-format
 msgid "Invalid value for %s: %s"
 msgstr ""
 
-#: sequencer.c:819
+#: sequencer.c:829
 #, c-format
 msgid "Malformed options sheet: %s"
 msgstr ""
 
-#: sequencer.c:840
+#: sequencer.c:850
 msgid "a cherry-pick or revert is already in progress"
 msgstr ""
 
-#: sequencer.c:841
+#: sequencer.c:851
 msgid "try \"git cherry-pick (--continue | --quit | --abort)\""
 msgstr ""
 
-#: sequencer.c:845
+#: sequencer.c:855
 #, c-format
 msgid "Could not create sequencer directory %s"
 msgstr ""
 
-#: sequencer.c:861 sequencer.c:946
+#: sequencer.c:871 sequencer.c:956
 #, c-format
 msgid "Error wrapping up %s."
 msgstr ""
 
-#: sequencer.c:880 sequencer.c:1014
+#: sequencer.c:890 sequencer.c:1024
 msgid "no cherry-pick or revert in progress"
 msgstr ""
 
-#: sequencer.c:882
+#: sequencer.c:892
 msgid "cannot resolve HEAD"
 msgstr ""
 
-#: sequencer.c:884
+#: sequencer.c:894
 msgid "cannot abort from a branch yet to be born"
 msgstr ""
 
-#: sequencer.c:906 builtin/apply.c:4060
+#: sequencer.c:916 builtin/apply.c:4061
 #, c-format
 msgid "cannot open %s: %s"
 msgstr ""
 
-#: sequencer.c:909
+#: sequencer.c:919
 #, c-format
 msgid "cannot read %s: %s"
 msgstr ""
 
-#: sequencer.c:910
+#: sequencer.c:920
 msgid "unexpected end of file"
 msgstr ""
 
-#: sequencer.c:916
+#: sequencer.c:926
 #, c-format
 msgid "stored pre-cherry-pick HEAD file '%s' is corrupt"
 msgstr ""
 
-#: sequencer.c:939
+#: sequencer.c:949
 #, c-format
 msgid "Could not format %s."
 msgstr ""
 
-#: sequencer.c:1101
+#: sequencer.c:1092
+#, c-format
+msgid "%s: can't cherry-pick a %s"
+msgstr ""
+
+#: sequencer.c:1095
+#, c-format
+msgid "%s: bad revision"
+msgstr ""
+
+#: sequencer.c:1129
 msgid "Can't revert as initial commit"
 msgstr ""
 
-#: sequencer.c:1102
+#: sequencer.c:1130
 msgid "Can't cherry-pick into empty head"
 msgstr ""
 
-#: sha1_name.c:1036
+#: sha1_name.c:440
+msgid ""
+"Git normally never creates a ref that ends with 40 hex characters\n"
+"because it will be ignored when you just specify 40-hex. These refs\n"
+"may be created by mistake. For example,\n"
+"\n"
+"  git checkout -b $br $(git rev-parse ...)\n"
+"\n"
+"where \"$br\" is somehow empty and a 40-hex ref is created. Please\n"
+"examine these refs and maybe delete them. Turn this message off by\n"
+"running \"git config advice.objectNameWarning false\""
+msgstr ""
+
+#: sha1_name.c:1097
 msgid "HEAD does not point to a branch"
 msgstr ""
 
-#: sha1_name.c:1039
+#: sha1_name.c:1100
 #, c-format
 msgid "No such branch: '%s'"
 msgstr ""
 
-#: sha1_name.c:1041
+#: sha1_name.c:1102
 #, c-format
 msgid "No upstream configured for branch '%s'"
 msgstr ""
 
-#: sha1_name.c:1044
+#: sha1_name.c:1106
 #, c-format
 msgid "Upstream branch '%s' not stored as a remote-tracking branch"
 msgstr ""
@@ -1032,263 +1182,271 @@
 msgid "unable to access '%s': %s"
 msgstr ""
 
-#: wrapper.c:423
+#: wrapper.c:429
 #, c-format
 msgid "unable to access '%s'"
 msgstr ""
 
-#: wrapper.c:434
+#: wrapper.c:440
 #, c-format
 msgid "unable to look up current user in the passwd file: %s"
 msgstr ""
 
-#: wrapper.c:435
+#: wrapper.c:441
 msgid "no such user"
 msgstr ""
 
-#: wt-status.c:140
+#: wt-status.c:141
 msgid "Unmerged paths:"
 msgstr ""
 
-#: wt-status.c:167 wt-status.c:194
+#: wt-status.c:168 wt-status.c:195
 #, c-format
 msgid "  (use \"git reset %s <file>...\" to unstage)"
 msgstr ""
 
-#: wt-status.c:169 wt-status.c:196
+#: wt-status.c:170 wt-status.c:197
 msgid "  (use \"git rm --cached <file>...\" to unstage)"
 msgstr ""
 
-#: wt-status.c:173
+#: wt-status.c:174
 msgid "  (use \"git add <file>...\" to mark resolution)"
 msgstr ""
 
-#: wt-status.c:175 wt-status.c:179
+#: wt-status.c:176 wt-status.c:180
 msgid "  (use \"git add/rm <file>...\" as appropriate to mark resolution)"
 msgstr ""
 
-#: wt-status.c:177
+#: wt-status.c:178
 msgid "  (use \"git rm <file>...\" to mark resolution)"
 msgstr ""
 
-#: wt-status.c:188
+#: wt-status.c:189
 msgid "Changes to be committed:"
 msgstr ""
 
-#: wt-status.c:206
+#: wt-status.c:207
 msgid "Changes not staged for commit:"
 msgstr ""
 
-#: wt-status.c:210
+#: wt-status.c:211
 msgid "  (use \"git add <file>...\" to update what will be committed)"
 msgstr ""
 
-#: wt-status.c:212
+#: wt-status.c:213
 msgid "  (use \"git add/rm <file>...\" to update what will be committed)"
 msgstr ""
 
-#: wt-status.c:213
+#: wt-status.c:214
 msgid ""
 "  (use \"git checkout -- <file>...\" to discard changes in working directory)"
 msgstr ""
 
-#: wt-status.c:215
+#: wt-status.c:216
 msgid "  (commit or discard the untracked or modified content in submodules)"
 msgstr ""
 
-#: wt-status.c:227
+#: wt-status.c:228
 #, c-format
 msgid "  (use \"git %s <file>...\" to include in what will be committed)"
 msgstr ""
 
-#: wt-status.c:244
+#: wt-status.c:245
 msgid "bug"
 msgstr ""
 
-#: wt-status.c:249
+#: wt-status.c:250
 msgid "both deleted:"
 msgstr ""
 
-#: wt-status.c:250
+#: wt-status.c:251
 msgid "added by us:"
 msgstr ""
 
-#: wt-status.c:251
+#: wt-status.c:252
 msgid "deleted by them:"
 msgstr ""
 
-#: wt-status.c:252
+#: wt-status.c:253
 msgid "added by them:"
 msgstr ""
 
-#: wt-status.c:253
+#: wt-status.c:254
 msgid "deleted by us:"
 msgstr ""
 
-#: wt-status.c:254
+#: wt-status.c:255
 msgid "both added:"
 msgstr ""
 
-#: wt-status.c:255
+#: wt-status.c:256
 msgid "both modified:"
 msgstr ""
 
-#: wt-status.c:285
+#: wt-status.c:286
 msgid "new commits, "
 msgstr ""
 
-#: wt-status.c:287
+#: wt-status.c:288
 msgid "modified content, "
 msgstr ""
 
-#: wt-status.c:289
+#: wt-status.c:290
 msgid "untracked content, "
 msgstr ""
 
-#: wt-status.c:306
+#: wt-status.c:307
 #, c-format
 msgid "new file:   %s"
 msgstr ""
 
-#: wt-status.c:309
+#: wt-status.c:310
 #, c-format
 msgid "copied:     %s -> %s"
 msgstr ""
 
-#: wt-status.c:312
+#: wt-status.c:313
 #, c-format
 msgid "deleted:    %s"
 msgstr ""
 
-#: wt-status.c:315
+#: wt-status.c:316
 #, c-format
 msgid "modified:   %s"
 msgstr ""
 
-#: wt-status.c:318
+#: wt-status.c:319
 #, c-format
 msgid "renamed:    %s -> %s"
 msgstr ""
 
-#: wt-status.c:321
+#: wt-status.c:322
 #, c-format
 msgid "typechange: %s"
 msgstr ""
 
-#: wt-status.c:324
+#: wt-status.c:325
 #, c-format
 msgid "unknown:    %s"
 msgstr ""
 
-#: wt-status.c:327
+#: wt-status.c:328
 #, c-format
 msgid "unmerged:   %s"
 msgstr ""
 
-#: wt-status.c:330
+#: wt-status.c:331
 #, c-format
 msgid "bug: unhandled diff status %c"
 msgstr ""
 
-#: wt-status.c:805
+#: wt-status.c:803
 msgid "You have unmerged paths."
 msgstr ""
 
-#: wt-status.c:808 wt-status.c:960
+#: wt-status.c:806
 msgid "  (fix conflicts and run \"git commit\")"
 msgstr ""
 
-#: wt-status.c:811
+#: wt-status.c:809
 msgid "All conflicts fixed but you are still merging."
 msgstr ""
 
-#: wt-status.c:814
+#: wt-status.c:812
 msgid "  (use \"git commit\" to conclude merge)"
 msgstr ""
 
-#: wt-status.c:824
+#: wt-status.c:822
 msgid "You are in the middle of an am session."
 msgstr ""
 
-#: wt-status.c:827
+#: wt-status.c:825
 msgid "The current patch is empty."
 msgstr ""
 
-#: wt-status.c:831
-msgid "  (fix conflicts and then run \"git am --resolved\")"
+#: wt-status.c:829
+msgid "  (fix conflicts and then run \"git am --continue\")"
 msgstr ""
 
-#: wt-status.c:833
+#: wt-status.c:831
 msgid "  (use \"git am --skip\" to skip this patch)"
 msgstr ""
 
-#: wt-status.c:835
+#: wt-status.c:833
 msgid "  (use \"git am --abort\" to restore the original branch)"
 msgstr ""
 
-#: wt-status.c:895 wt-status.c:912
+#: wt-status.c:893 wt-status.c:910
 #, c-format
 msgid "You are currently rebasing branch '%s' on '%s'."
 msgstr ""
 
-#: wt-status.c:900 wt-status.c:917
+#: wt-status.c:898 wt-status.c:915
 msgid "You are currently rebasing."
 msgstr ""
 
-#: wt-status.c:903
+#: wt-status.c:901
 msgid "  (fix conflicts and then run \"git rebase --continue\")"
 msgstr ""
 
-#: wt-status.c:905
+#: wt-status.c:903
 msgid "  (use \"git rebase --skip\" to skip this patch)"
 msgstr ""
 
-#: wt-status.c:907
+#: wt-status.c:905
 msgid "  (use \"git rebase --abort\" to check out the original branch)"
 msgstr ""
 
-#: wt-status.c:920
+#: wt-status.c:918
 msgid "  (all conflicts fixed: run \"git rebase --continue\")"
 msgstr ""
 
-#: wt-status.c:924
+#: wt-status.c:922
 #, c-format
 msgid ""
 "You are currently splitting a commit while rebasing branch '%s' on '%s'."
 msgstr ""
 
-#: wt-status.c:929
+#: wt-status.c:927
 msgid "You are currently splitting a commit during a rebase."
 msgstr ""
 
-#: wt-status.c:932
+#: wt-status.c:930
 msgid "  (Once your working directory is clean, run \"git rebase --continue\")"
 msgstr ""
 
-#: wt-status.c:936
+#: wt-status.c:934
 #, c-format
 msgid "You are currently editing a commit while rebasing branch '%s' on '%s'."
 msgstr ""
 
-#: wt-status.c:941
+#: wt-status.c:939
 msgid "You are currently editing a commit during a rebase."
 msgstr ""
 
-#: wt-status.c:944
+#: wt-status.c:942
 msgid "  (use \"git commit --amend\" to amend the current commit)"
 msgstr ""
 
-#: wt-status.c:946
+#: wt-status.c:944
 msgid ""
 "  (use \"git rebase --continue\" once you are satisfied with your changes)"
 msgstr ""
 
-#: wt-status.c:956
+#: wt-status.c:954
 msgid "You are currently cherry-picking."
 msgstr ""
 
+#: wt-status.c:958
+msgid "  (fix conflicts and run \"git cherry-pick --continue\")"
+msgstr ""
+
+#: wt-status.c:961
+msgid "  (all conflicts fixed: run \"git cherry-pick --continue\")"
+msgstr ""
+
 #: wt-status.c:963
-msgid "  (all conflicts fixed: run \"git commit\")"
+msgid "  (use \"git cherry-pick --abort\" to cancel the cherry-pick operation)"
 msgstr ""
 
 #: wt-status.c:972
@@ -1321,123 +1479,122 @@
 msgid "  (use \"git bisect reset\" to get back to the original branch)"
 msgstr ""
 
-#: wt-status.c:1175
+#: wt-status.c:1173
 msgid "On branch "
 msgstr ""
 
-#: wt-status.c:1186
+#: wt-status.c:1180
+msgid "rebase in progress; onto "
+msgstr ""
+
+#: wt-status.c:1187
 msgid "HEAD detached at "
 msgstr ""
 
-#: wt-status.c:1188
+#: wt-status.c:1189
 msgid "HEAD detached from "
 msgstr ""
 
-#: wt-status.c:1191
+#: wt-status.c:1192
 msgid "Not currently on any branch."
 msgstr ""
 
-#: wt-status.c:1208
+#: wt-status.c:1209
 msgid "Initial commit"
 msgstr ""
 
-#: wt-status.c:1222
+#: wt-status.c:1223
 msgid "Untracked files"
 msgstr ""
 
-#: wt-status.c:1224
+#: wt-status.c:1225
 msgid "Ignored files"
 msgstr ""
 
-#: wt-status.c:1228
+#: wt-status.c:1229
 #, c-format
-msgid "It took %.2f seconds to enumerate untracked files.  'status -uno'"
-msgstr ""
-
-#: wt-status.c:1232
-msgid "may speed it up, but you have to be careful not to forget to add"
+msgid ""
+"It took %.2f seconds to enumerate untracked files. 'status -uno'\n"
+"may speed it up, but you have to be careful not to forget to add\n"
+"new files yourself (see 'git help status')."
 msgstr ""
 
 #: wt-status.c:1235
-msgid "new files yourself (see 'git help status')."
-msgstr ""
-
-#: wt-status.c:1238
 #, c-format
 msgid "Untracked files not listed%s"
 msgstr ""
 
-#: wt-status.c:1240
+#: wt-status.c:1237
 msgid " (use -u option to show untracked files)"
 msgstr ""
 
-#: wt-status.c:1246
+#: wt-status.c:1243
 msgid "No changes"
 msgstr ""
 
-#: wt-status.c:1251
+#: wt-status.c:1248
 #, c-format
 msgid "no changes added to commit (use \"git add\" and/or \"git commit -a\")\n"
 msgstr ""
 
-#: wt-status.c:1254
+#: wt-status.c:1251
 #, c-format
 msgid "no changes added to commit\n"
 msgstr ""
 
-#: wt-status.c:1257
+#: wt-status.c:1254
 #, c-format
 msgid ""
 "nothing added to commit but untracked files present (use \"git add\" to "
 "track)\n"
 msgstr ""
 
-#: wt-status.c:1260
+#: wt-status.c:1257
 #, c-format
 msgid "nothing added to commit but untracked files present\n"
 msgstr ""
 
-#: wt-status.c:1263
+#: wt-status.c:1260
 #, c-format
 msgid "nothing to commit (create/copy files and use \"git add\" to track)\n"
 msgstr ""
 
-#: wt-status.c:1266 wt-status.c:1271
+#: wt-status.c:1263 wt-status.c:1268
 #, c-format
 msgid "nothing to commit\n"
 msgstr ""
 
-#: wt-status.c:1269
+#: wt-status.c:1266
 #, c-format
 msgid "nothing to commit (use -u to show untracked files)\n"
 msgstr ""
 
-#: wt-status.c:1273
+#: wt-status.c:1270
 #, c-format
 msgid "nothing to commit, working directory clean\n"
 msgstr ""
 
-#: wt-status.c:1381
+#: wt-status.c:1378
 msgid "HEAD (no branch)"
 msgstr ""
 
-#: wt-status.c:1387
+#: wt-status.c:1384
 msgid "Initial commit on "
 msgstr ""
 
-#: wt-status.c:1402
+#: wt-status.c:1399
 msgid "behind "
 msgstr ""
 
-#: wt-status.c:1405 wt-status.c:1408
+#: wt-status.c:1402 wt-status.c:1405
 msgid "ahead "
 msgstr ""
 
-#: wt-status.c:1410
+#: wt-status.c:1407
 msgid ", behind "
 msgstr ""
 
-#: compat/precompose_utf8.c:58 builtin/clone.c:342
+#: compat/precompose_utf8.c:58 builtin/clone.c:351
 #, c-format
 msgid "failed to unlink '%s'"
 msgstr ""
@@ -1446,125 +1603,6 @@
 msgid "git add [options] [--] <pathspec>..."
 msgstr ""
 
-#: builtin/add.c:63
-#, c-format
-msgid "unexpected diff status %c"
-msgstr ""
-
-#: builtin/add.c:68 builtin/commit.c:233
-msgid "updating files failed"
-msgstr ""
-
-#: builtin/add.c:78
-#, c-format
-msgid "remove '%s'\n"
-msgstr ""
-
-#: builtin/add.c:148
-msgid "Unstaged changes after refreshing the index:"
-msgstr ""
-
-#: builtin/add.c:151 builtin/add.c:460 builtin/rm.c:275
-#, c-format
-msgid "pathspec '%s' did not match any files"
-msgstr ""
-
-#: builtin/add.c:234
-msgid "Could not read the index"
-msgstr ""
-
-#: builtin/add.c:244
-#, c-format
-msgid "Could not open '%s' for writing."
-msgstr ""
-
-#: builtin/add.c:248
-msgid "Could not write patch"
-msgstr ""
-
-#: builtin/add.c:253
-#, c-format
-msgid "Could not stat '%s'"
-msgstr ""
-
-#: builtin/add.c:255
-msgid "Empty patch. Aborted."
-msgstr ""
-
-#: builtin/add.c:261
-#, c-format
-msgid "Could not apply '%s'"
-msgstr ""
-
-#: builtin/add.c:271
-msgid "The following paths are ignored by one of your .gitignore files:\n"
-msgstr ""
-
-#: builtin/add.c:277 builtin/clean.c:161 builtin/fetch.c:78 builtin/mv.c:63
-#: builtin/prune-packed.c:76 builtin/push.c:425 builtin/remote.c:1253
-#: builtin/rm.c:206
-msgid "dry run"
-msgstr ""
-
-#: builtin/add.c:278 builtin/apply.c:4409 builtin/check-ignore.c:19
-#: builtin/commit.c:1152 builtin/count-objects.c:95 builtin/fsck.c:613
-#: builtin/log.c:1514 builtin/mv.c:62 builtin/read-tree.c:112
-msgid "be verbose"
-msgstr ""
-
-#: builtin/add.c:280
-msgid "interactive picking"
-msgstr ""
-
-#: builtin/add.c:281 builtin/checkout.c:1060 builtin/reset.c:258
-msgid "select hunks interactively"
-msgstr ""
-
-#: builtin/add.c:282
-msgid "edit current diff and apply"
-msgstr ""
-
-#: builtin/add.c:283
-msgid "allow adding otherwise ignored files"
-msgstr ""
-
-#: builtin/add.c:284
-msgid "update tracked files"
-msgstr ""
-
-#: builtin/add.c:285
-msgid "record only the fact that the path will be added later"
-msgstr ""
-
-#: builtin/add.c:286
-msgid "add changes from all tracked and untracked files"
-msgstr ""
-
-#: builtin/add.c:287
-msgid "don't add, only refresh the index"
-msgstr ""
-
-#: builtin/add.c:288
-msgid "just skip files which cannot be added because of errors"
-msgstr ""
-
-#: builtin/add.c:289
-msgid "check if - even missing - files are ignored in dry run"
-msgstr ""
-
-#: builtin/add.c:311
-#, c-format
-msgid "Use -f if you really want to add them.\n"
-msgstr ""
-
-#: builtin/add.c:312
-msgid "no files added"
-msgstr ""
-
-#: builtin/add.c:318
-msgid "adding files failed"
-msgstr ""
-
 #.
 #. * To be consistent with "git add -p" and most Git
 #. * commands, we should default to being tree-wide, but
@@ -1575,7 +1613,7 @@
 #. * to tree-wide, keeping the warning for a while, and
 #. * eventually we can drop the warning.
 #.
-#: builtin/add.c:335
+#: builtin/add.c:58
 #, c-format
 msgid ""
 "The behavior of 'git add %s (or %s)' with no path argument from a\n"
@@ -1592,33 +1630,173 @@
 "  (or git add %s .)\n"
 "\n"
 "With the current Git version, the command is restricted to the current "
-"directory."
+"directory.\n"
 msgstr ""
 
-#: builtin/add.c:381
+#: builtin/add.c:100
+#, c-format
+msgid ""
+"You ran 'git add' with neither '-A (--all)' or '--ignore-removal',\n"
+"whose behaviour will change in Git 2.0 with respect to paths you removed.\n"
+"Paths like '%s' that are\n"
+"removed from your working tree are ignored with this version of Git.\n"
+"\n"
+"* 'git add --ignore-removal <pathspec>', which is the current default,\n"
+"  ignores paths you removed from your working tree.\n"
+"\n"
+"* 'git add --all <pathspec>' will let you also record the removals.\n"
+"\n"
+"Run 'git status' to check the paths you removed from your working tree.\n"
+msgstr ""
+
+#: builtin/add.c:144
+#, c-format
+msgid "unexpected diff status %c"
+msgstr ""
+
+#: builtin/add.c:149 builtin/commit.c:252
+msgid "updating files failed"
+msgstr ""
+
+#: builtin/add.c:163
+#, c-format
+msgid "remove '%s'\n"
+msgstr ""
+
+#: builtin/add.c:253
+msgid "Unstaged changes after refreshing the index:"
+msgstr ""
+
+#: builtin/add.c:256 builtin/add.c:573 builtin/rm.c:337
+#, c-format
+msgid "pathspec '%s' did not match any files"
+msgstr ""
+
+#: builtin/add.c:339
+msgid "Could not read the index"
+msgstr ""
+
+#: builtin/add.c:350
+#, c-format
+msgid "Could not open '%s' for writing."
+msgstr ""
+
+#: builtin/add.c:354
+msgid "Could not write patch"
+msgstr ""
+
+#: builtin/add.c:359
+#, c-format
+msgid "Could not stat '%s'"
+msgstr ""
+
+#: builtin/add.c:361
+msgid "Empty patch. Aborted."
+msgstr ""
+
+#: builtin/add.c:367
+#, c-format
+msgid "Could not apply '%s'"
+msgstr ""
+
+#: builtin/add.c:377
+msgid "The following paths are ignored by one of your .gitignore files:\n"
+msgstr ""
+
+#: builtin/add.c:394 builtin/clean.c:875 builtin/fetch.c:78 builtin/mv.c:63
+#: builtin/prune-packed.c:73 builtin/push.c:451 builtin/remote.c:1253
+#: builtin/rm.c:268
+msgid "dry run"
+msgstr ""
+
+#: builtin/add.c:395 builtin/apply.c:4410 builtin/check-ignore.c:19
+#: builtin/commit.c:1220 builtin/count-objects.c:95 builtin/fsck.c:613
+#: builtin/log.c:1573 builtin/mv.c:62 builtin/read-tree.c:113
+msgid "be verbose"
+msgstr ""
+
+#: builtin/add.c:397
+msgid "interactive picking"
+msgstr ""
+
+#: builtin/add.c:398 builtin/checkout.c:1073 builtin/reset.c:261
+msgid "select hunks interactively"
+msgstr ""
+
+#: builtin/add.c:399
+msgid "edit current diff and apply"
+msgstr ""
+
+#: builtin/add.c:400
+msgid "allow adding otherwise ignored files"
+msgstr ""
+
+#: builtin/add.c:401
+msgid "update tracked files"
+msgstr ""
+
+#: builtin/add.c:402
+msgid "record only the fact that the path will be added later"
+msgstr ""
+
+#: builtin/add.c:403
+msgid "add changes from all tracked and untracked files"
+msgstr ""
+
+#. takes no arguments
+#: builtin/add.c:406
+msgid "ignore paths removed in the working tree (same as --no-all)"
+msgstr ""
+
+#: builtin/add.c:408
+msgid "don't add, only refresh the index"
+msgstr ""
+
+#: builtin/add.c:409
+msgid "just skip files which cannot be added because of errors"
+msgstr ""
+
+#: builtin/add.c:410
+msgid "check if - even missing - files are ignored in dry run"
+msgstr ""
+
+#: builtin/add.c:432
+#, c-format
+msgid "Use -f if you really want to add them.\n"
+msgstr ""
+
+#: builtin/add.c:433
+msgid "no files added"
+msgstr ""
+
+#: builtin/add.c:439
+msgid "adding files failed"
+msgstr ""
+
+#: builtin/add.c:478
 msgid "-A and -u are mutually incompatible"
 msgstr ""
 
-#: builtin/add.c:383
+#: builtin/add.c:496
 msgid "Option --ignore-missing can only be used together with --dry-run"
 msgstr ""
 
-#: builtin/add.c:414
+#: builtin/add.c:526
 #, c-format
 msgid "Nothing specified, nothing added.\n"
 msgstr ""
 
-#: builtin/add.c:415
+#: builtin/add.c:527
 #, c-format
 msgid "Maybe you wanted to say 'git add .'?\n"
 msgstr ""
 
-#: builtin/add.c:421 builtin/check-ignore.c:67 builtin/clean.c:204
-#: builtin/commit.c:293 builtin/mv.c:82 builtin/rm.c:235
+#: builtin/add.c:533 builtin/check-ignore.c:161 builtin/clean.c:919
+#: builtin/commit.c:312 builtin/mv.c:82 builtin/rm.c:297
 msgid "index file corrupt"
 msgstr ""
 
-#: builtin/add.c:481 builtin/apply.c:4505 builtin/mv.c:229 builtin/rm.c:370
+#: builtin/add.c:605 builtin/apply.c:4506 builtin/mv.c:229 builtin/rm.c:432
 msgid "Unable to write new index file"
 msgstr ""
 
@@ -1795,293 +1973,293 @@
 msgid "cannot checkout %s"
 msgstr ""
 
-#: builtin/apply.c:3140 builtin/apply.c:3149 builtin/apply.c:3193
+#: builtin/apply.c:3140 builtin/apply.c:3149 builtin/apply.c:3194
 #, c-format
 msgid "read of %s failed"
 msgstr ""
 
-#: builtin/apply.c:3173 builtin/apply.c:3395
+#: builtin/apply.c:3174 builtin/apply.c:3396
 #, c-format
 msgid "path %s has been renamed/deleted"
 msgstr ""
 
-#: builtin/apply.c:3254 builtin/apply.c:3409
+#: builtin/apply.c:3255 builtin/apply.c:3410
 #, c-format
 msgid "%s: does not exist in index"
 msgstr ""
 
-#: builtin/apply.c:3258 builtin/apply.c:3401 builtin/apply.c:3423
+#: builtin/apply.c:3259 builtin/apply.c:3402 builtin/apply.c:3424
 #, c-format
 msgid "%s: %s"
 msgstr ""
 
-#: builtin/apply.c:3263 builtin/apply.c:3417
+#: builtin/apply.c:3264 builtin/apply.c:3418
 #, c-format
 msgid "%s: does not match index"
 msgstr ""
 
-#: builtin/apply.c:3365
+#: builtin/apply.c:3366
 msgid "removal patch leaves file contents"
 msgstr ""
 
-#: builtin/apply.c:3434
+#: builtin/apply.c:3435
 #, c-format
 msgid "%s: wrong type"
 msgstr ""
 
-#: builtin/apply.c:3436
+#: builtin/apply.c:3437
 #, c-format
 msgid "%s has type %o, expected %o"
 msgstr ""
 
-#: builtin/apply.c:3537
+#: builtin/apply.c:3538
 #, c-format
 msgid "%s: already exists in index"
 msgstr ""
 
-#: builtin/apply.c:3540
+#: builtin/apply.c:3541
 #, c-format
 msgid "%s: already exists in working directory"
 msgstr ""
 
-#: builtin/apply.c:3560
+#: builtin/apply.c:3561
 #, c-format
 msgid "new mode (%o) of %s does not match old mode (%o)"
 msgstr ""
 
-#: builtin/apply.c:3565
+#: builtin/apply.c:3566
 #, c-format
 msgid "new mode (%o) of %s does not match old mode (%o) of %s"
 msgstr ""
 
-#: builtin/apply.c:3573
+#: builtin/apply.c:3574
 #, c-format
 msgid "%s: patch does not apply"
 msgstr ""
 
-#: builtin/apply.c:3586
+#: builtin/apply.c:3587
 #, c-format
 msgid "Checking patch %s..."
 msgstr ""
 
-#: builtin/apply.c:3679 builtin/checkout.c:215 builtin/reset.c:124
+#: builtin/apply.c:3680 builtin/checkout.c:216 builtin/reset.c:127
 #, c-format
 msgid "make_cache_entry failed for path '%s'"
 msgstr ""
 
-#: builtin/apply.c:3822
+#: builtin/apply.c:3823
 #, c-format
 msgid "unable to remove %s from index"
 msgstr ""
 
-#: builtin/apply.c:3850
+#: builtin/apply.c:3851
 #, c-format
-msgid "corrupt patch for subproject %s"
+msgid "corrupt patch for submodule %s"
 msgstr ""
 
-#: builtin/apply.c:3854
+#: builtin/apply.c:3855
 #, c-format
 msgid "unable to stat newly created file '%s'"
 msgstr ""
 
-#: builtin/apply.c:3859
+#: builtin/apply.c:3860
 #, c-format
 msgid "unable to create backing store for newly created file %s"
 msgstr ""
 
-#: builtin/apply.c:3862 builtin/apply.c:3970
+#: builtin/apply.c:3863 builtin/apply.c:3971
 #, c-format
 msgid "unable to add cache entry for %s"
 msgstr ""
 
-#: builtin/apply.c:3895
+#: builtin/apply.c:3896
 #, c-format
 msgid "closing file '%s'"
 msgstr ""
 
-#: builtin/apply.c:3944
+#: builtin/apply.c:3945
 #, c-format
 msgid "unable to write file '%s' mode %o"
 msgstr ""
 
-#: builtin/apply.c:4031
+#: builtin/apply.c:4032
 #, c-format
 msgid "Applied patch %s cleanly."
 msgstr ""
 
-#: builtin/apply.c:4039
+#: builtin/apply.c:4040
 msgid "internal error"
 msgstr ""
 
 #. Say this even without --verbose
-#: builtin/apply.c:4042
+#: builtin/apply.c:4043
 #, c-format
 msgid "Applying patch %%s with %d reject..."
 msgid_plural "Applying patch %%s with %d rejects..."
 msgstr[0] ""
 msgstr[1] ""
 
-#: builtin/apply.c:4052
+#: builtin/apply.c:4053
 #, c-format
 msgid "truncating .rej filename to %.*s.rej"
 msgstr ""
 
-#: builtin/apply.c:4073
+#: builtin/apply.c:4074
 #, c-format
 msgid "Hunk #%d applied cleanly."
 msgstr ""
 
-#: builtin/apply.c:4076
+#: builtin/apply.c:4077
 #, c-format
 msgid "Rejected hunk #%d."
 msgstr ""
 
-#: builtin/apply.c:4226
+#: builtin/apply.c:4227
 msgid "unrecognized input"
 msgstr ""
 
-#: builtin/apply.c:4237
+#: builtin/apply.c:4238
 msgid "unable to read index file"
 msgstr ""
 
-#: builtin/apply.c:4356 builtin/apply.c:4359 builtin/clone.c:92
+#: builtin/apply.c:4357 builtin/apply.c:4360 builtin/clone.c:91
 #: builtin/fetch.c:63
 msgid "path"
 msgstr ""
 
-#: builtin/apply.c:4357
+#: builtin/apply.c:4358
 msgid "don't apply changes matching the given path"
 msgstr ""
 
-#: builtin/apply.c:4360
+#: builtin/apply.c:4361
 msgid "apply changes matching the given path"
 msgstr ""
 
-#: builtin/apply.c:4362
+#: builtin/apply.c:4363
 msgid "num"
 msgstr ""
 
-#: builtin/apply.c:4363
+#: builtin/apply.c:4364
 msgid "remove <num> leading slashes from traditional diff paths"
 msgstr ""
 
-#: builtin/apply.c:4366
+#: builtin/apply.c:4367
 msgid "ignore additions made by the patch"
 msgstr ""
 
-#: builtin/apply.c:4368
+#: builtin/apply.c:4369
 msgid "instead of applying the patch, output diffstat for the input"
 msgstr ""
 
-#: builtin/apply.c:4372
+#: builtin/apply.c:4373
 msgid "show number of added and deleted lines in decimal notation"
 msgstr ""
 
-#: builtin/apply.c:4374
+#: builtin/apply.c:4375
 msgid "instead of applying the patch, output a summary for the input"
 msgstr ""
 
-#: builtin/apply.c:4376
+#: builtin/apply.c:4377
 msgid "instead of applying the patch, see if the patch is applicable"
 msgstr ""
 
-#: builtin/apply.c:4378
+#: builtin/apply.c:4379
 msgid "make sure the patch is applicable to the current index"
 msgstr ""
 
-#: builtin/apply.c:4380
+#: builtin/apply.c:4381
 msgid "apply a patch without touching the working tree"
 msgstr ""
 
-#: builtin/apply.c:4382
+#: builtin/apply.c:4383
 msgid "also apply the patch (use with --stat/--summary/--check)"
 msgstr ""
 
-#: builtin/apply.c:4384
+#: builtin/apply.c:4385
 msgid "attempt three-way merge if a patch does not apply"
 msgstr ""
 
-#: builtin/apply.c:4386
+#: builtin/apply.c:4387
 msgid "build a temporary index based on embedded index information"
 msgstr ""
 
-#: builtin/apply.c:4388 builtin/checkout-index.c:197 builtin/ls-files.c:463
+#: builtin/apply.c:4389 builtin/checkout-index.c:197 builtin/ls-files.c:462
 msgid "paths are separated with NUL character"
 msgstr ""
 
-#: builtin/apply.c:4391
+#: builtin/apply.c:4392
 msgid "ensure at least <n> lines of context match"
 msgstr ""
 
-#: builtin/apply.c:4392
+#: builtin/apply.c:4393
 msgid "action"
 msgstr ""
 
-#: builtin/apply.c:4393
+#: builtin/apply.c:4394
 msgid "detect new or modified lines that have whitespace errors"
 msgstr ""
 
-#: builtin/apply.c:4396 builtin/apply.c:4399
+#: builtin/apply.c:4397 builtin/apply.c:4400
 msgid "ignore changes in whitespace when finding context"
 msgstr ""
 
-#: builtin/apply.c:4402
+#: builtin/apply.c:4403
 msgid "apply the patch in reverse"
 msgstr ""
 
-#: builtin/apply.c:4404
+#: builtin/apply.c:4405
 msgid "don't expect at least one line of context"
 msgstr ""
 
-#: builtin/apply.c:4406
+#: builtin/apply.c:4407
 msgid "leave the rejected hunks in corresponding *.rej files"
 msgstr ""
 
-#: builtin/apply.c:4408
+#: builtin/apply.c:4409
 msgid "allow overlapping hunks"
 msgstr ""
 
-#: builtin/apply.c:4411
+#: builtin/apply.c:4412
 msgid "tolerate incorrectly detected missing new-line at the end of file"
 msgstr ""
 
-#: builtin/apply.c:4414
+#: builtin/apply.c:4415
 msgid "do not trust the line counts in the hunk headers"
 msgstr ""
 
-#: builtin/apply.c:4416
+#: builtin/apply.c:4417
 msgid "root"
 msgstr ""
 
-#: builtin/apply.c:4417
+#: builtin/apply.c:4418
 msgid "prepend <root> to all filenames"
 msgstr ""
 
-#: builtin/apply.c:4439
+#: builtin/apply.c:4440
 msgid "--3way outside a repository"
 msgstr ""
 
-#: builtin/apply.c:4447
+#: builtin/apply.c:4448
 msgid "--index outside a repository"
 msgstr ""
 
-#: builtin/apply.c:4450
+#: builtin/apply.c:4451
 msgid "--cached outside a repository"
 msgstr ""
 
-#: builtin/apply.c:4466
+#: builtin/apply.c:4467
 #, c-format
 msgid "can't open patch '%s'"
 msgstr ""
 
-#: builtin/apply.c:4480
+#: builtin/apply.c:4481
 #, c-format
 msgid "squelched %d whitespace error"
 msgid_plural "squelched %d whitespace errors"
 msgstr[0] ""
 msgstr[1] ""
 
-#: builtin/apply.c:4486 builtin/apply.c:4496
+#: builtin/apply.c:4487 builtin/apply.c:4497
 #, c-format
 msgid "%d line adds whitespace errors."
 msgid_plural "%d lines add whitespace errors."
@@ -2135,103 +2313,103 @@
 msgid "update BISECT_HEAD instead of checking out the current commit"
 msgstr ""
 
-#: builtin/blame.c:25
+#: builtin/blame.c:26
 msgid "git blame [options] [rev-opts] [rev] [--] file"
 msgstr ""
 
-#: builtin/blame.c:30 builtin/shortlog.c:15
+#: builtin/blame.c:31
 msgid "[rev-opts] are documented in git-rev-list(1)"
 msgstr ""
 
-#: builtin/blame.c:2350
+#: builtin/blame.c:2276
 msgid "Show blame entries as we find them, incrementally"
 msgstr ""
 
-#: builtin/blame.c:2351
+#: builtin/blame.c:2277
 msgid "Show blank SHA-1 for boundary commits (Default: off)"
 msgstr ""
 
-#: builtin/blame.c:2352
+#: builtin/blame.c:2278
 msgid "Do not treat root commits as boundaries (Default: off)"
 msgstr ""
 
-#: builtin/blame.c:2353
+#: builtin/blame.c:2279
 msgid "Show work cost statistics"
 msgstr ""
 
-#: builtin/blame.c:2354
+#: builtin/blame.c:2280
 msgid "Show output score for blame entries"
 msgstr ""
 
-#: builtin/blame.c:2355
+#: builtin/blame.c:2281
 msgid "Show original filename (Default: auto)"
 msgstr ""
 
-#: builtin/blame.c:2356
+#: builtin/blame.c:2282
 msgid "Show original linenumber (Default: off)"
 msgstr ""
 
-#: builtin/blame.c:2357
+#: builtin/blame.c:2283
 msgid "Show in a format designed for machine consumption"
 msgstr ""
 
-#: builtin/blame.c:2358
+#: builtin/blame.c:2284
 msgid "Show porcelain format with per-line commit information"
 msgstr ""
 
-#: builtin/blame.c:2359
+#: builtin/blame.c:2285
 msgid "Use the same output mode as git-annotate (Default: off)"
 msgstr ""
 
-#: builtin/blame.c:2360
+#: builtin/blame.c:2286
 msgid "Show raw timestamp (Default: off)"
 msgstr ""
 
-#: builtin/blame.c:2361
+#: builtin/blame.c:2287
 msgid "Show long commit SHA1 (Default: off)"
 msgstr ""
 
-#: builtin/blame.c:2362
+#: builtin/blame.c:2288
 msgid "Suppress author name and timestamp (Default: off)"
 msgstr ""
 
-#: builtin/blame.c:2363
+#: builtin/blame.c:2289
 msgid "Show author email instead of name (Default: off)"
 msgstr ""
 
-#: builtin/blame.c:2364
+#: builtin/blame.c:2290
 msgid "Ignore whitespace differences"
 msgstr ""
 
-#: builtin/blame.c:2365
+#: builtin/blame.c:2291
 msgid "Spend extra cycles to find better match"
 msgstr ""
 
-#: builtin/blame.c:2366
+#: builtin/blame.c:2292
 msgid "Use revisions from <file> instead of calling git-rev-list"
 msgstr ""
 
-#: builtin/blame.c:2367
+#: builtin/blame.c:2293
 msgid "Use <file>'s contents as the final image"
 msgstr ""
 
-#: builtin/blame.c:2368 builtin/blame.c:2369
+#: builtin/blame.c:2294 builtin/blame.c:2295
 msgid "score"
 msgstr ""
 
-#: builtin/blame.c:2368
+#: builtin/blame.c:2294
 msgid "Find line copies within and across files"
 msgstr ""
 
-#: builtin/blame.c:2369
+#: builtin/blame.c:2295
 msgid "Find line movements within and across files"
 msgstr ""
 
-#: builtin/blame.c:2370
+#: builtin/blame.c:2296
 msgid "n,m"
 msgstr ""
 
-#: builtin/blame.c:2370
+#: builtin/blame.c:2296
 msgid "Process only line range n,m, counting from 1"
 msgstr ""
 
@@ -2251,360 +2429,360 @@
 msgid "git branch [options] (-m | -M) [<oldbranch>] <newbranch>"
 msgstr ""
 
-#: builtin/branch.c:146
+#: builtin/branch.c:150
 #, c-format
 msgid ""
 "deleting branch '%s' that has been merged to\n"
 "         '%s', but not yet merged to HEAD."
 msgstr ""
 
-#: builtin/branch.c:150
+#: builtin/branch.c:154
 #, c-format
 msgid ""
 "not deleting branch '%s' that is not yet merged to\n"
 "         '%s', even though it is merged to HEAD."
 msgstr ""
 
-#: builtin/branch.c:164
+#: builtin/branch.c:168
 #, c-format
 msgid "Couldn't look up commit object for '%s'"
 msgstr ""
 
-#: builtin/branch.c:168
+#: builtin/branch.c:172
 #, c-format
 msgid ""
 "The branch '%s' is not fully merged.\n"
 "If you are sure you want to delete it, run 'git branch -D %s'."
 msgstr ""
 
-#: builtin/branch.c:181
+#: builtin/branch.c:185
 msgid "Update of config-file failed"
 msgstr ""
 
-#: builtin/branch.c:209
+#: builtin/branch.c:213
 msgid "cannot use -a with -d"
 msgstr ""
 
-#: builtin/branch.c:215
+#: builtin/branch.c:219
 msgid "Couldn't look up commit object for HEAD"
 msgstr ""
 
-#: builtin/branch.c:223
+#: builtin/branch.c:227
 #, c-format
 msgid "Cannot delete the branch '%s' which you are currently on."
 msgstr ""
 
-#: builtin/branch.c:236
+#: builtin/branch.c:240
 #, c-format
 msgid "remote branch '%s' not found."
 msgstr ""
 
-#: builtin/branch.c:237
+#: builtin/branch.c:241
 #, c-format
 msgid "branch '%s' not found."
 msgstr ""
 
-#: builtin/branch.c:251
+#: builtin/branch.c:255
 #, c-format
 msgid "Error deleting remote branch '%s'"
 msgstr ""
 
-#: builtin/branch.c:252
+#: builtin/branch.c:256
 #, c-format
 msgid "Error deleting branch '%s'"
 msgstr ""
 
-#: builtin/branch.c:259
+#: builtin/branch.c:263
 #, c-format
 msgid "Deleted remote branch %s (was %s).\n"
 msgstr ""
 
-#: builtin/branch.c:260
+#: builtin/branch.c:264
 #, c-format
 msgid "Deleted branch %s (was %s).\n"
 msgstr ""
 
-#: builtin/branch.c:362
+#: builtin/branch.c:366
 #, c-format
 msgid "branch '%s' does not point at a commit"
 msgstr ""
 
-#: builtin/branch.c:434
+#: builtin/branch.c:453
 #, c-format
 msgid "[%s: behind %d]"
 msgstr ""
 
-#: builtin/branch.c:436
+#: builtin/branch.c:455
 #, c-format
 msgid "[behind %d]"
 msgstr ""
 
-#: builtin/branch.c:440
+#: builtin/branch.c:459
 #, c-format
 msgid "[%s: ahead %d]"
 msgstr ""
 
-#: builtin/branch.c:442
+#: builtin/branch.c:461
 #, c-format
 msgid "[ahead %d]"
 msgstr ""
 
-#: builtin/branch.c:445
+#: builtin/branch.c:464
 #, c-format
 msgid "[%s: ahead %d, behind %d]"
 msgstr ""
 
-#: builtin/branch.c:448
+#: builtin/branch.c:467
 #, c-format
 msgid "[ahead %d, behind %d]"
 msgstr ""
 
-#: builtin/branch.c:470
+#: builtin/branch.c:490
 msgid " **** invalid ref ****"
 msgstr ""
 
-#: builtin/branch.c:562
+#: builtin/branch.c:582
 #, c-format
 msgid "(no branch, rebasing %s)"
 msgstr ""
 
-#: builtin/branch.c:565
+#: builtin/branch.c:585
 #, c-format
 msgid "(no branch, bisect started on %s)"
 msgstr ""
 
-#: builtin/branch.c:568
+#: builtin/branch.c:588
 #, c-format
 msgid "(detached from %s)"
 msgstr ""
 
-#: builtin/branch.c:571
+#: builtin/branch.c:591
 msgid "(no branch)"
 msgstr ""
 
-#: builtin/branch.c:617
+#: builtin/branch.c:637
 #, c-format
 msgid "object '%s' does not point to a commit"
 msgstr ""
 
-#: builtin/branch.c:649
+#: builtin/branch.c:669
 msgid "some refs could not be read"
 msgstr ""
 
-#: builtin/branch.c:662
+#: builtin/branch.c:682
 msgid "cannot rename the current branch while not on any."
 msgstr ""
 
-#: builtin/branch.c:672
+#: builtin/branch.c:692
 #, c-format
 msgid "Invalid branch name: '%s'"
 msgstr ""
 
-#: builtin/branch.c:687
+#: builtin/branch.c:707
 msgid "Branch rename failed"
 msgstr ""
 
-#: builtin/branch.c:691
+#: builtin/branch.c:711
 #, c-format
 msgid "Renamed a misnamed branch '%s' away"
 msgstr ""
 
-#: builtin/branch.c:695
+#: builtin/branch.c:715
 #, c-format
 msgid "Branch renamed to %s, but HEAD is not updated!"
 msgstr ""
 
-#: builtin/branch.c:702
+#: builtin/branch.c:722
 msgid "Branch is renamed, but update of config-file failed"
 msgstr ""
 
-#: builtin/branch.c:717
+#: builtin/branch.c:737
 #, c-format
 msgid "malformed object name %s"
 msgstr ""
 
-#: builtin/branch.c:741
+#: builtin/branch.c:761
 #, c-format
 msgid "could not write branch description template: %s"
 msgstr ""
 
-#: builtin/branch.c:771
+#: builtin/branch.c:791
 msgid "Generic options"
 msgstr ""
 
-#: builtin/branch.c:773
+#: builtin/branch.c:793
 msgid "show hash and subject, give twice for upstream branch"
 msgstr ""
 
-#: builtin/branch.c:774
+#: builtin/branch.c:794
 msgid "suppress informational messages"
 msgstr ""
 
-#: builtin/branch.c:775
+#: builtin/branch.c:795
 msgid "set up tracking mode (see git-pull(1))"
 msgstr ""
 
-#: builtin/branch.c:777
+#: builtin/branch.c:797
 msgid "change upstream info"
 msgstr ""
 
-#: builtin/branch.c:781
+#: builtin/branch.c:801
 msgid "use colored output"
 msgstr ""
 
-#: builtin/branch.c:782
+#: builtin/branch.c:802
 msgid "act on remote-tracking branches"
 msgstr ""
 
-#: builtin/branch.c:785 builtin/branch.c:791 builtin/branch.c:812
-#: builtin/branch.c:818 builtin/commit.c:1368 builtin/commit.c:1369
-#: builtin/commit.c:1370 builtin/commit.c:1371 builtin/tag.c:468
+#: builtin/branch.c:805 builtin/branch.c:811 builtin/branch.c:832
+#: builtin/branch.c:838 builtin/commit.c:1433 builtin/commit.c:1434
+#: builtin/commit.c:1435 builtin/commit.c:1436 builtin/tag.c:468
 msgid "commit"
 msgstr ""
 
-#: builtin/branch.c:786 builtin/branch.c:792
+#: builtin/branch.c:806 builtin/branch.c:812
 msgid "print only branches that contain the commit"
 msgstr ""
 
-#: builtin/branch.c:798
+#: builtin/branch.c:818
 msgid "Specific git-branch actions:"
 msgstr ""
 
-#: builtin/branch.c:799
+#: builtin/branch.c:819
 msgid "list both remote-tracking and local branches"
 msgstr ""
 
-#: builtin/branch.c:801
+#: builtin/branch.c:821
 msgid "delete fully merged branch"
 msgstr ""
 
-#: builtin/branch.c:802
+#: builtin/branch.c:822
 msgid "delete branch (even if not merged)"
 msgstr ""
 
-#: builtin/branch.c:803
+#: builtin/branch.c:823
 msgid "move/rename a branch and its reflog"
 msgstr ""
 
-#: builtin/branch.c:804
+#: builtin/branch.c:824
 msgid "move/rename a branch, even if target exists"
 msgstr ""
 
-#: builtin/branch.c:805
+#: builtin/branch.c:825
 msgid "list branch names"
 msgstr ""
 
-#: builtin/branch.c:806
+#: builtin/branch.c:826
 msgid "create the branch's reflog"
 msgstr ""
 
-#: builtin/branch.c:808
+#: builtin/branch.c:828
 msgid "edit the description for the branch"
 msgstr ""
 
-#: builtin/branch.c:809
+#: builtin/branch.c:829
 msgid "force creation (when already exists)"
 msgstr ""
 
-#: builtin/branch.c:812
+#: builtin/branch.c:832
 msgid "print only not merged branches"
 msgstr ""
 
-#: builtin/branch.c:818
+#: builtin/branch.c:838
 msgid "print only merged branches"
 msgstr ""
 
-#: builtin/branch.c:822
+#: builtin/branch.c:842
 msgid "list branches in columns"
 msgstr ""
 
-#: builtin/branch.c:835
+#: builtin/branch.c:855
 msgid "Failed to resolve HEAD as a valid ref."
 msgstr ""
 
-#: builtin/branch.c:840 builtin/clone.c:609
+#: builtin/branch.c:860 builtin/clone.c:630
 msgid "HEAD not found below refs/heads!"
 msgstr ""
 
-#: builtin/branch.c:863
+#: builtin/branch.c:883
 msgid "--column and --verbose are incompatible"
 msgstr ""
 
-#: builtin/branch.c:869 builtin/branch.c:908
+#: builtin/branch.c:889 builtin/branch.c:928
 msgid "branch name required"
 msgstr ""
 
-#: builtin/branch.c:884
+#: builtin/branch.c:904
 msgid "Cannot give description to detached HEAD"
 msgstr ""
 
-#: builtin/branch.c:889
+#: builtin/branch.c:909
 msgid "cannot edit description of more than one branch"
 msgstr ""
 
-#: builtin/branch.c:896
+#: builtin/branch.c:916
 #, c-format
 msgid "No commit on branch '%s' yet."
 msgstr ""
 
-#: builtin/branch.c:899
+#: builtin/branch.c:919
 #, c-format
 msgid "No branch named '%s'."
 msgstr ""
 
-#: builtin/branch.c:914
+#: builtin/branch.c:934
 msgid "too many branches for a rename operation"
 msgstr ""
 
-#: builtin/branch.c:919
+#: builtin/branch.c:939
 msgid "too many branches to set new upstream"
 msgstr ""
 
-#: builtin/branch.c:923
+#: builtin/branch.c:943
 #, c-format
 msgid ""
 "could not set upstream of HEAD to %s when it does not point to any branch."
 msgstr ""
 
-#: builtin/branch.c:926 builtin/branch.c:948 builtin/branch.c:970
+#: builtin/branch.c:946 builtin/branch.c:968 builtin/branch.c:990
 #, c-format
 msgid "no such branch '%s'"
 msgstr ""
 
-#: builtin/branch.c:930
+#: builtin/branch.c:950
 #, c-format
 msgid "branch '%s' does not exist"
 msgstr ""
 
-#: builtin/branch.c:942
+#: builtin/branch.c:962
 msgid "too many branches to unset upstream"
 msgstr ""
 
-#: builtin/branch.c:946
+#: builtin/branch.c:966
 msgid "could not unset upstream of HEAD when it does not point to any branch."
 msgstr ""
 
-#: builtin/branch.c:952
+#: builtin/branch.c:972
 #, c-format
 msgid "Branch '%s' has no upstream information"
 msgstr ""
 
-#: builtin/branch.c:967
+#: builtin/branch.c:987
 msgid "it does not make sense to create 'HEAD' manually"
 msgstr ""
 
-#: builtin/branch.c:973
+#: builtin/branch.c:993
 msgid "-a and -r options to 'git branch' do not make sense with a branch name"
 msgstr ""
 
-#: builtin/branch.c:976
+#: builtin/branch.c:996
 #, c-format
 msgid ""
 "The --set-upstream flag is deprecated and will be removed. Consider using --"
 "track or --set-upstream-to\n"
 msgstr ""
 
-#: builtin/branch.c:993
+#: builtin/branch.c:1013
 #, c-format
 msgid ""
 "\n"
@@ -2612,12 +2790,12 @@
 "\n"
 msgstr ""
 
-#: builtin/branch.c:994
+#: builtin/branch.c:1014
 #, c-format
 msgid "    git branch -d %s\n"
 msgstr ""
 
-#: builtin/branch.c:995
+#: builtin/branch.c:1015
 #, c-format
 msgid "    git branch --set-upstream-to %s\n"
 msgstr ""
@@ -2635,43 +2813,43 @@
 msgid "Need a repository to unbundle."
 msgstr ""
 
-#: builtin/cat-file.c:247
+#: builtin/cat-file.c:285
 msgid "git cat-file (-t|-s|-e|-p|<type>|--textconv) <object>"
 msgstr ""
 
-#: builtin/cat-file.c:248
+#: builtin/cat-file.c:286
 msgid "git cat-file (--batch|--batch-check) < <list_of_objects>"
 msgstr ""
 
-#: builtin/cat-file.c:266
+#: builtin/cat-file.c:323
 msgid "<type> can be one of: blob, tree, commit, tag"
 msgstr ""
 
-#: builtin/cat-file.c:267
+#: builtin/cat-file.c:324
 msgid "show object type"
 msgstr ""
 
-#: builtin/cat-file.c:268
+#: builtin/cat-file.c:325
 msgid "show object size"
 msgstr ""
 
-#: builtin/cat-file.c:270
+#: builtin/cat-file.c:327
 msgid "exit with zero when there's no error"
 msgstr ""
 
-#: builtin/cat-file.c:271
+#: builtin/cat-file.c:328
 msgid "pretty-print object's content"
 msgstr ""
 
-#: builtin/cat-file.c:273
+#: builtin/cat-file.c:330
 msgid "for blob objects, run textconv on object's content"
 msgstr ""
 
-#: builtin/cat-file.c:275
+#: builtin/cat-file.c:332
 msgid "show info and content of objects fed from the standard input"
 msgstr ""
 
-#: builtin/cat-file.c:278
+#: builtin/cat-file.c:335
 msgid "show info about objects fed from the standard input"
 msgstr ""
 
@@ -2699,30 +2877,55 @@
 msgid "input paths are terminated by a null character"
 msgstr ""
 
-#: builtin/check-ignore.c:18 builtin/checkout.c:1041 builtin/gc.c:177
+#: builtin/check-ignore.c:18 builtin/checkout.c:1054 builtin/gc.c:177
 msgid "suppress progress reporting"
 msgstr ""
 
-#: builtin/check-ignore.c:151
+#: builtin/check-ignore.c:26
+msgid "show non-matching input paths"
+msgstr ""
+
+#: builtin/check-ignore.c:143
 msgid "cannot specify pathnames with --stdin"
 msgstr ""
 
-#: builtin/check-ignore.c:154
+#: builtin/check-ignore.c:146
 msgid "-z only makes sense with --stdin"
 msgstr ""
 
-#: builtin/check-ignore.c:156
+#: builtin/check-ignore.c:148
 msgid "no path specified"
 msgstr ""
 
-#: builtin/check-ignore.c:160
+#: builtin/check-ignore.c:152
 msgid "--quiet is only valid with a single pathname"
 msgstr ""
 
-#: builtin/check-ignore.c:162
+#: builtin/check-ignore.c:154
 msgid "cannot have both --quiet and --verbose"
 msgstr ""
 
+#: builtin/check-ignore.c:157
+msgid "--non-matching is only valid with --verbose"
+msgstr ""
+
+#: builtin/check-mailmap.c:8
+msgid "git check-mailmap [options] <contact>..."
+msgstr ""
+
+#: builtin/check-mailmap.c:13
+msgid "also read contacts from stdin"
+msgstr ""
+
+#: builtin/check-mailmap.c:24
+#, c-format
+msgid "unable to parse contact: %s"
+msgstr ""
+
+#: builtin/check-mailmap.c:47
+msgid "no contacts specified"
+msgstr ""
+
 #: builtin/checkout-index.c:126
 msgid "git checkout-index [options] [--] [<file>...]"
 msgstr ""
@@ -2775,106 +2978,106 @@
 msgid "git checkout [options] [<branch>] -- <file>..."
 msgstr ""
 
-#: builtin/checkout.c:116 builtin/checkout.c:149
+#: builtin/checkout.c:117 builtin/checkout.c:150
 #, c-format
 msgid "path '%s' does not have our version"
 msgstr ""
 
-#: builtin/checkout.c:118 builtin/checkout.c:151
+#: builtin/checkout.c:119 builtin/checkout.c:152
 #, c-format
 msgid "path '%s' does not have their version"
 msgstr ""
 
-#: builtin/checkout.c:134
+#: builtin/checkout.c:135
 #, c-format
 msgid "path '%s' does not have all necessary versions"
 msgstr ""
 
-#: builtin/checkout.c:178
+#: builtin/checkout.c:179
 #, c-format
 msgid "path '%s' does not have necessary versions"
 msgstr ""
 
-#: builtin/checkout.c:195
+#: builtin/checkout.c:196
 #, c-format
 msgid "path '%s': cannot merge"
 msgstr ""
 
-#: builtin/checkout.c:212
+#: builtin/checkout.c:213
 #, c-format
 msgid "Unable to add merge result for '%s'"
 msgstr ""
 
-#: builtin/checkout.c:236 builtin/checkout.c:239 builtin/checkout.c:242
-#: builtin/checkout.c:245
+#: builtin/checkout.c:237 builtin/checkout.c:240 builtin/checkout.c:243
+#: builtin/checkout.c:246
 #, c-format
 msgid "'%s' cannot be used with updating paths"
 msgstr ""
 
-#: builtin/checkout.c:248 builtin/checkout.c:251
+#: builtin/checkout.c:249 builtin/checkout.c:252
 #, c-format
 msgid "'%s' cannot be used with %s"
 msgstr ""
 
-#: builtin/checkout.c:254
+#: builtin/checkout.c:255
 #, c-format
 msgid "Cannot update paths and switch to branch '%s' at the same time."
 msgstr ""
 
-#: builtin/checkout.c:265 builtin/checkout.c:455
+#: builtin/checkout.c:266 builtin/checkout.c:458
 msgid "corrupt index file"
 msgstr ""
 
-#: builtin/checkout.c:326 builtin/checkout.c:333
+#: builtin/checkout.c:329 builtin/checkout.c:336
 #, c-format
 msgid "path '%s' is unmerged"
 msgstr ""
 
-#: builtin/checkout.c:477
+#: builtin/checkout.c:480
 msgid "you need to resolve your current index first"
 msgstr ""
 
-#: builtin/checkout.c:598
+#: builtin/checkout.c:601
 #, c-format
 msgid "Can not do reflog for '%s'\n"
 msgstr ""
 
-#: builtin/checkout.c:631
+#: builtin/checkout.c:639
 msgid "HEAD is now at"
 msgstr ""
 
-#: builtin/checkout.c:638
+#: builtin/checkout.c:646
 #, c-format
 msgid "Reset branch '%s'\n"
 msgstr ""
 
-#: builtin/checkout.c:641
+#: builtin/checkout.c:649
 #, c-format
 msgid "Already on '%s'\n"
 msgstr ""
 
-#: builtin/checkout.c:645
+#: builtin/checkout.c:653
 #, c-format
 msgid "Switched to and reset branch '%s'\n"
 msgstr ""
 
-#: builtin/checkout.c:647 builtin/checkout.c:984
+#: builtin/checkout.c:655 builtin/checkout.c:997
 #, c-format
 msgid "Switched to a new branch '%s'\n"
 msgstr ""
 
-#: builtin/checkout.c:649
+#: builtin/checkout.c:657
 #, c-format
 msgid "Switched to branch '%s'\n"
 msgstr ""
 
-#: builtin/checkout.c:705
+#: builtin/checkout.c:713
 #, c-format
 msgid " ... and %d more.\n"
 msgstr ""
 
 #. The singular version
-#: builtin/checkout.c:711
+#: builtin/checkout.c:719
 #, c-format
 msgid ""
 "Warning: you are leaving %d commit behind, not connected to\n"
@@ -2889,7 +3092,7 @@
 msgstr[0] ""
 msgstr[1] ""
 
-#: builtin/checkout.c:729
+#: builtin/checkout.c:737
 #, c-format
 msgid ""
 "If you want to keep them by creating a new branch, this may be a good time\n"
@@ -2899,446 +3102,547 @@
 "\n"
 msgstr ""
 
-#: builtin/checkout.c:759
+#: builtin/checkout.c:767
 msgid "internal error in revision walk"
 msgstr ""
 
-#: builtin/checkout.c:763
+#: builtin/checkout.c:771
 msgid "Previous HEAD position was"
 msgstr ""
 
-#: builtin/checkout.c:790 builtin/checkout.c:979
+#: builtin/checkout.c:798 builtin/checkout.c:992
 msgid "You are on a branch yet to be born"
 msgstr ""
 
 #. case (1)
-#: builtin/checkout.c:915
+#: builtin/checkout.c:928
 #, c-format
 msgid "invalid reference: %s"
 msgstr ""
 
 #. case (1): want a tree
-#: builtin/checkout.c:954
+#: builtin/checkout.c:967
 #, c-format
 msgid "reference is not a tree: %s"
 msgstr ""
 
-#: builtin/checkout.c:993
+#: builtin/checkout.c:1006
 msgid "paths cannot be used with switching branches"
 msgstr ""
 
-#: builtin/checkout.c:996 builtin/checkout.c:1000
+#: builtin/checkout.c:1009 builtin/checkout.c:1013
 #, c-format
 msgid "'%s' cannot be used with switching branches"
 msgstr ""
 
-#: builtin/checkout.c:1004 builtin/checkout.c:1007 builtin/checkout.c:1012
-#: builtin/checkout.c:1015
+#: builtin/checkout.c:1017 builtin/checkout.c:1020 builtin/checkout.c:1025
+#: builtin/checkout.c:1028
 #, c-format
 msgid "'%s' cannot be used with '%s'"
 msgstr ""
 
-#: builtin/checkout.c:1020
+#: builtin/checkout.c:1033
 #, c-format
 msgid "Cannot switch branch to a non-commit '%s'"
 msgstr ""
 
-#: builtin/checkout.c:1042 builtin/checkout.c:1044 builtin/clone.c:90
+#: builtin/checkout.c:1055 builtin/checkout.c:1057 builtin/clone.c:89
 #: builtin/remote.c:169 builtin/remote.c:171
 msgid "branch"
 msgstr ""
 
-#: builtin/checkout.c:1043
+#: builtin/checkout.c:1056
 msgid "create and checkout a new branch"
 msgstr ""
 
-#: builtin/checkout.c:1045
+#: builtin/checkout.c:1058
 msgid "create/reset and checkout a branch"
 msgstr ""
 
-#: builtin/checkout.c:1046
+#: builtin/checkout.c:1059
 msgid "create reflog for new branch"
 msgstr ""
 
-#: builtin/checkout.c:1047
+#: builtin/checkout.c:1060
 msgid "detach the HEAD at named commit"
 msgstr ""
 
-#: builtin/checkout.c:1048
+#: builtin/checkout.c:1061
 msgid "set upstream info for new branch"
 msgstr ""
 
-#: builtin/checkout.c:1050
+#: builtin/checkout.c:1063
 msgid "new branch"
 msgstr ""
 
-#: builtin/checkout.c:1050
+#: builtin/checkout.c:1063
 msgid "new unparented branch"
 msgstr ""
 
-#: builtin/checkout.c:1051
+#: builtin/checkout.c:1064
 msgid "checkout our version for unmerged files"
 msgstr ""
 
-#: builtin/checkout.c:1053
+#: builtin/checkout.c:1066
 msgid "checkout their version for unmerged files"
 msgstr ""
 
-#: builtin/checkout.c:1055
+#: builtin/checkout.c:1068
 msgid "force checkout (throw away local modifications)"
 msgstr ""
 
-#: builtin/checkout.c:1056
+#: builtin/checkout.c:1069
 msgid "perform a 3-way merge with the new branch"
 msgstr ""
 
-#: builtin/checkout.c:1057 builtin/merge.c:217
+#: builtin/checkout.c:1070 builtin/merge.c:232
 msgid "update ignored files (default)"
 msgstr ""
 
-#: builtin/checkout.c:1058 builtin/log.c:1149 parse-options.h:245
+#: builtin/checkout.c:1071 builtin/log.c:1208 parse-options.h:249
 msgid "style"
 msgstr ""
 
-#: builtin/checkout.c:1059
+#: builtin/checkout.c:1072
 msgid "conflict style (merge or diff3)"
 msgstr ""
 
-#: builtin/checkout.c:1062
+#: builtin/checkout.c:1075
+msgid "do not limit pathspecs to sparse entries only"
+msgstr ""
+
+#: builtin/checkout.c:1077
 msgid "second guess 'git checkout no-such-branch'"
 msgstr ""
 
-#: builtin/checkout.c:1086
+#: builtin/checkout.c:1101
 msgid "-b, -B and --orphan are mutually exclusive"
 msgstr ""
 
-#: builtin/checkout.c:1103
+#: builtin/checkout.c:1118
 msgid "--track needs a branch name"
 msgstr ""
 
-#: builtin/checkout.c:1110
+#: builtin/checkout.c:1125
 msgid "Missing branch name; try -b"
 msgstr ""
 
-#: builtin/checkout.c:1145
+#: builtin/checkout.c:1160
 msgid "invalid path specification"
 msgstr ""
 
-#: builtin/checkout.c:1152
+#: builtin/checkout.c:1167
 #, c-format
 msgid ""
 "Cannot update paths and switch to branch '%s' at the same time.\n"
 "Did you intend to checkout '%s' which can not be resolved as commit?"
 msgstr ""
 
-#: builtin/checkout.c:1157
+#: builtin/checkout.c:1172
 #, c-format
 msgid "git checkout: --detach does not take a path argument '%s'"
 msgstr ""
 
-#: builtin/checkout.c:1161
+#: builtin/checkout.c:1176
 msgid ""
 "git checkout: --ours/--theirs, --force and --merge are incompatible when\n"
 "checking out of the index."
 msgstr ""
 
-#: builtin/clean.c:20
-msgid "git clean [-d] [-f] [-n] [-q] [-e <pattern>] [-x | -X] [--] <paths>..."
+#: builtin/clean.c:25
+msgid ""
+"git clean [-d] [-f] [-i] [-n] [-q] [-e <pattern>] [-x | -X] [--] <paths>..."
 msgstr ""
 
-#: builtin/clean.c:24
+#: builtin/clean.c:29
 #, c-format
 msgid "Removing %s\n"
 msgstr ""
 
-#: builtin/clean.c:25
+#: builtin/clean.c:30
 #, c-format
 msgid "Would remove %s\n"
 msgstr ""
 
-#: builtin/clean.c:26
+#: builtin/clean.c:31
 #, c-format
 msgid "Skipping repository %s\n"
 msgstr ""
 
-#: builtin/clean.c:27
+#: builtin/clean.c:32
 #, c-format
 msgid "Would skip repository %s\n"
 msgstr ""
 
-#: builtin/clean.c:28
+#: builtin/clean.c:33
 #, c-format
 msgid "failed to remove %s"
 msgstr ""
 
-#: builtin/clean.c:160
+#: builtin/clean.c:293
+msgid ""
+"Prompt help:\n"
+"1          - select a numbered item\n"
+"foo        - select item based on unique prefix\n"
+"           - (empty) select nothing"
+msgstr ""
+
+#: builtin/clean.c:297
+msgid ""
+"Prompt help:\n"
+"1          - select a single item\n"
+"3-5        - select a range of items\n"
+"2-3,6-9    - select multiple ranges\n"
+"foo        - select item based on unique prefix\n"
+"-...       - unselect specified items\n"
+"*          - choose all items\n"
+"           - (empty) finish selecting"
+msgstr ""
+
+#: builtin/clean.c:515
+#, c-format
+msgid "Huh (%s)?"
+msgstr ""
+
+#: builtin/clean.c:658
+#, c-format
+msgid "Input ignore patterns>> "
+msgstr ""
+
+#: builtin/clean.c:695
+#, c-format
+msgid "WARNING: Cannot find items matched by: %s"
+msgstr ""
+
+#: builtin/clean.c:716
+msgid "Select items to delete"
+msgstr ""
+
+#: builtin/clean.c:756
+#, c-format
+msgid "remove %s? "
+msgstr ""
+
+#: builtin/clean.c:781
+msgid "Bye."
+msgstr ""
+
+#: builtin/clean.c:789
+msgid ""
+"clean               - start cleaning\n"
+"filter by pattern   - exclude items from deletion\n"
+"select by numbers   - select items to be deleted by numbers\n"
+"ask each            - confirm each deletion (like \"rm -i\")\n"
+"quit                - stop cleaning\n"
+"help                - this screen\n"
+"?                   - help for prompt selection"
+msgstr ""
+
+#: builtin/clean.c:816
+msgid "*** Commands ***"
+msgstr ""
+
+#: builtin/clean.c:817
+msgid "What now"
+msgstr ""
+
+#: builtin/clean.c:825
+msgid "Would remove the following item:"
+msgid_plural "Would remove the following items:"
+msgstr[0] ""
+msgstr[1] ""
+
+#: builtin/clean.c:842
+msgid "No more files to clean, exiting."
+msgstr ""
+
+#: builtin/clean.c:874
 msgid "do not print names of files removed"
 msgstr ""
 
-#: builtin/clean.c:162
+#: builtin/clean.c:876
 msgid "force"
 msgstr ""
 
-#: builtin/clean.c:164
+#: builtin/clean.c:877
+msgid "interactive cleaning"
+msgstr ""
+
+#: builtin/clean.c:879
 msgid "remove whole directories"
 msgstr ""
 
-#: builtin/clean.c:165 builtin/describe.c:412 builtin/grep.c:717
-#: builtin/ls-files.c:494 builtin/name-rev.c:231 builtin/show-ref.c:182
+#: builtin/clean.c:880 builtin/describe.c:420 builtin/grep.c:716
+#: builtin/ls-files.c:493 builtin/name-rev.c:315 builtin/show-ref.c:186
 msgid "pattern"
 msgstr ""
 
-#: builtin/clean.c:166
+#: builtin/clean.c:881
 msgid "add <pattern> to ignore rules"
 msgstr ""
 
-#: builtin/clean.c:167
+#: builtin/clean.c:882
 msgid "remove ignored files, too"
 msgstr ""
 
-#: builtin/clean.c:169
+#: builtin/clean.c:884
 msgid "remove only ignored files"
 msgstr ""
 
-#: builtin/clean.c:187
+#: builtin/clean.c:902
 msgid "-x and -X cannot be used together"
 msgstr ""
 
-#: builtin/clean.c:191
+#: builtin/clean.c:906
 msgid ""
-"clean.requireForce set to true and neither -n nor -f given; refusing to clean"
-msgstr ""
-
-#: builtin/clean.c:194
-msgid ""
-"clean.requireForce defaults to true and neither -n nor -f given; refusing to "
+"clean.requireForce set to true and neither -i, -n nor -f given; refusing to "
 "clean"
 msgstr ""
 
-#: builtin/clone.c:37
+#: builtin/clean.c:909
+msgid ""
+"clean.requireForce defaults to true and neither -i, -n nor -f given; "
+"refusing to clean"
+msgstr ""
+
+#: builtin/clone.c:36
 msgid "git clone [options] [--] <repo> [<dir>]"
 msgstr ""
 
-#: builtin/clone.c:65 builtin/fetch.c:82 builtin/merge.c:214
-#: builtin/push.c:436
+#: builtin/clone.c:64 builtin/fetch.c:82 builtin/merge.c:229
+#: builtin/push.c:462
 msgid "force progress reporting"
 msgstr ""
 
-#: builtin/clone.c:67
+#: builtin/clone.c:66
 msgid "don't create a checkout"
 msgstr ""
 
-#: builtin/clone.c:68 builtin/clone.c:70 builtin/init-db.c:488
+#: builtin/clone.c:67 builtin/clone.c:69 builtin/init-db.c:488
 msgid "create a bare repository"
 msgstr ""
 
-#: builtin/clone.c:73
+#: builtin/clone.c:72
 msgid "create a mirror repository (implies bare)"
 msgstr ""
 
-#: builtin/clone.c:75
+#: builtin/clone.c:74
 msgid "to clone from a local repository"
 msgstr ""
 
-#: builtin/clone.c:77
+#: builtin/clone.c:76
 msgid "don't use local hardlinks, always copy"
 msgstr ""
 
-#: builtin/clone.c:79
+#: builtin/clone.c:78
 msgid "setup as shared repository"
 msgstr ""
 
-#: builtin/clone.c:81 builtin/clone.c:83
+#: builtin/clone.c:80 builtin/clone.c:82
 msgid "initialize submodules in the clone"
 msgstr ""
 
-#: builtin/clone.c:84 builtin/init-db.c:485
+#: builtin/clone.c:83 builtin/init-db.c:485
 msgid "template-directory"
 msgstr ""
 
-#: builtin/clone.c:85 builtin/init-db.c:486
+#: builtin/clone.c:84 builtin/init-db.c:486
 msgid "directory from which templates will be used"
 msgstr ""
 
-#: builtin/clone.c:87
+#: builtin/clone.c:86
 msgid "reference repository"
 msgstr ""
 
-#: builtin/clone.c:88 builtin/column.c:26 builtin/merge-file.c:44
+#: builtin/clone.c:87 builtin/column.c:26 builtin/merge-file.c:44
 msgid "name"
 msgstr ""
 
-#: builtin/clone.c:89
+#: builtin/clone.c:88
 msgid "use <name> instead of 'origin' to track upstream"
 msgstr ""
 
-#: builtin/clone.c:91
+#: builtin/clone.c:90
 msgid "checkout <branch> instead of the remote's HEAD"
 msgstr ""
 
-#: builtin/clone.c:93
+#: builtin/clone.c:92
 msgid "path to git-upload-pack on the remote"
 msgstr ""
 
-#: builtin/clone.c:94 builtin/fetch.c:83 builtin/grep.c:662
+#: builtin/clone.c:93 builtin/fetch.c:83 builtin/grep.c:661
 msgid "depth"
 msgstr ""
 
-#: builtin/clone.c:95
+#: builtin/clone.c:94
 msgid "create a shallow clone of that depth"
 msgstr ""
 
-#: builtin/clone.c:97
+#: builtin/clone.c:96
 msgid "clone only one branch, HEAD or --branch"
 msgstr ""
 
-#: builtin/clone.c:98 builtin/init-db.c:494
+#: builtin/clone.c:97 builtin/init-db.c:494
 msgid "gitdir"
 msgstr ""
 
-#: builtin/clone.c:99 builtin/init-db.c:495
+#: builtin/clone.c:98 builtin/init-db.c:495
 msgid "separate git dir from working tree"
 msgstr ""
 
-#: builtin/clone.c:100
+#: builtin/clone.c:99
 msgid "key=value"
 msgstr ""
 
-#: builtin/clone.c:101
+#: builtin/clone.c:100
 msgid "set config inside the new repository"
 msgstr ""
 
-#: builtin/clone.c:244
+#: builtin/clone.c:253
 #, c-format
-msgid "reference repository '%s' is not a local directory."
+msgid "reference repository '%s' is not a local repository."
 msgstr ""
 
-#: builtin/clone.c:307
+#: builtin/clone.c:316
 #, c-format
 msgid "failed to create directory '%s'"
 msgstr ""
 
-#: builtin/clone.c:309 builtin/diff.c:77
+#: builtin/clone.c:318 builtin/diff.c:77
 #, c-format
 msgid "failed to stat '%s'"
 msgstr ""
 
-#: builtin/clone.c:311
+#: builtin/clone.c:320
 #, c-format
 msgid "%s exists and is not a directory"
 msgstr ""
 
-#: builtin/clone.c:325
+#: builtin/clone.c:334
 #, c-format
 msgid "failed to stat %s\n"
 msgstr ""
 
-#: builtin/clone.c:347
+#: builtin/clone.c:356
 #, c-format
 msgid "failed to create link '%s'"
 msgstr ""
 
-#: builtin/clone.c:351
+#: builtin/clone.c:360
 #, c-format
 msgid "failed to copy file to '%s'"
 msgstr ""
 
-#: builtin/clone.c:374
+#: builtin/clone.c:383
 #, c-format
 msgid "done.\n"
 msgstr ""
 
-#: builtin/clone.c:387
+#: builtin/clone.c:396
 msgid ""
 "Clone succeeded, but checkout failed.\n"
 "You can inspect what was checked out with 'git status'\n"
 "and retry the checkout with 'git checkout -f HEAD'\n"
 msgstr ""
 
-#: builtin/clone.c:466
+#: builtin/clone.c:475
 #, c-format
 msgid "Could not find remote branch %s to clone."
 msgstr ""
 
-#: builtin/clone.c:540
+#: builtin/clone.c:555
+#, c-format
+msgid "Checking connectivity... "
+msgstr ""
+
+#: builtin/clone.c:558
 msgid "remote did not send all necessary objects"
 msgstr ""
 
-#: builtin/clone.c:600
+#: builtin/clone.c:560
+#, c-format
+msgid "done\n"
+msgstr ""
+
+#: builtin/clone.c:621
 msgid "remote HEAD refers to nonexistent ref, unable to checkout.\n"
 msgstr ""
 
-#: builtin/clone.c:631
+#: builtin/clone.c:652
 msgid "unable to checkout working tree"
 msgstr ""
 
-#: builtin/clone.c:739
+#: builtin/clone.c:760
 msgid "Too many arguments."
 msgstr ""
 
-#: builtin/clone.c:743
+#: builtin/clone.c:764
 msgid "You must specify a repository to clone."
 msgstr ""
 
-#: builtin/clone.c:754
+#: builtin/clone.c:775
 #, c-format
 msgid "--bare and --origin %s options are incompatible."
 msgstr ""
 
-#: builtin/clone.c:757
+#: builtin/clone.c:778
 msgid "--bare and --separate-git-dir are incompatible."
 msgstr ""
 
-#: builtin/clone.c:770
+#: builtin/clone.c:791
 #, c-format
 msgid "repository '%s' does not exist"
 msgstr ""
 
-#: builtin/clone.c:775
+#: builtin/clone.c:796
 msgid "--depth is ignored in local clones; use file:// instead."
 msgstr ""
 
-#: builtin/clone.c:785
+#: builtin/clone.c:798
+msgid "--local is ignored"
+msgstr ""
+
+#: builtin/clone.c:808
 #, c-format
 msgid "destination path '%s' already exists and is not an empty directory."
 msgstr ""
 
-#: builtin/clone.c:795
+#: builtin/clone.c:818
 #, c-format
 msgid "working tree '%s' already exists."
 msgstr ""
 
-#: builtin/clone.c:808 builtin/clone.c:820
+#: builtin/clone.c:831 builtin/clone.c:843
 #, c-format
 msgid "could not create leading directories of '%s'"
 msgstr ""
 
-#: builtin/clone.c:811
+#: builtin/clone.c:834
 #, c-format
 msgid "could not create work tree dir '%s'."
 msgstr ""
 
-#: builtin/clone.c:830
+#: builtin/clone.c:853
 #, c-format
 msgid "Cloning into bare repository '%s'...\n"
 msgstr ""
 
-#: builtin/clone.c:832
+#: builtin/clone.c:855
 #, c-format
 msgid "Cloning into '%s'...\n"
 msgstr ""
 
-#: builtin/clone.c:867
+#: builtin/clone.c:890
 #, c-format
 msgid "Don't know how to clone %s"
 msgstr ""
 
-#: builtin/clone.c:916
+#: builtin/clone.c:942
 #, c-format
 msgid "Remote branch %s not found in upstream %s"
 msgstr ""
 
-#: builtin/clone.c:923
+#: builtin/clone.c:949
 msgid "You appear to have cloned an empty repository."
 msgstr ""
 
@@ -3374,15 +3678,15 @@
 msgid "--command must be the first argument"
 msgstr ""
 
-#: builtin/commit.c:34
+#: builtin/commit.c:35
 msgid "git commit [options] [--] <pathspec>..."
 msgstr ""
 
-#: builtin/commit.c:39
+#: builtin/commit.c:40
 msgid "git status [options] [--] <pathspec>..."
 msgstr ""
 
-#: builtin/commit.c:44
+#: builtin/commit.c:45
 msgid ""
 "Your name and email address were configured automatically based\n"
 "on your username and hostname. Please check that they are accurate.\n"
@@ -3396,110 +3700,123 @@
 "    git commit --amend --reset-author\n"
 msgstr ""
 
-#: builtin/commit.c:56
+#: builtin/commit.c:57
 msgid ""
 "You asked to amend the most recent commit, but doing so would make\n"
 "it empty. You can repeat your command with --allow-empty, or you can\n"
 "remove the commit entirely with \"git reset HEAD^\".\n"
 msgstr ""
 
-#: builtin/commit.c:61
+#: builtin/commit.c:62
 msgid ""
 "The previous cherry-pick is now empty, possibly due to conflict resolution.\n"
 "If you wish to commit it anyway, use:\n"
 "\n"
 "    git commit --allow-empty\n"
 "\n"
-"Otherwise, please use 'git reset'\n"
 msgstr ""
 
-#: builtin/commit.c:260
+#: builtin/commit.c:69
+msgid "Otherwise, please use 'git reset'\n"
+msgstr ""
+
+#: builtin/commit.c:72
+msgid ""
+"If you wish to skip this commit, use:\n"
+"\n"
+"    git reset\n"
+"\n"
+"Then \"git cherry-pick --continue\" will resume cherry-picking\n"
+"the remaining commits.\n"
+msgstr ""
+
+#: builtin/commit.c:279
 msgid "failed to unpack HEAD tree object"
 msgstr ""
 
-#: builtin/commit.c:302
+#: builtin/commit.c:321
 msgid "unable to create temporary index"
 msgstr ""
 
-#: builtin/commit.c:308
+#: builtin/commit.c:327
 msgid "interactive add failed"
 msgstr ""
 
-#: builtin/commit.c:341 builtin/commit.c:362 builtin/commit.c:412
+#: builtin/commit.c:360 builtin/commit.c:381 builtin/commit.c:431
 msgid "unable to write new_index file"
 msgstr ""
 
-#: builtin/commit.c:393
+#: builtin/commit.c:412
 msgid "cannot do a partial commit during a merge."
 msgstr ""
 
-#: builtin/commit.c:395
+#: builtin/commit.c:414
 msgid "cannot do a partial commit during a cherry-pick."
 msgstr ""
 
-#: builtin/commit.c:405
+#: builtin/commit.c:424
 msgid "cannot read the index"
 msgstr ""
 
-#: builtin/commit.c:425
+#: builtin/commit.c:444
 msgid "unable to write temporary index file"
 msgstr ""
 
-#: builtin/commit.c:513 builtin/commit.c:519
+#: builtin/commit.c:535 builtin/commit.c:541
 #, c-format
 msgid "invalid commit: %s"
 msgstr ""
 
-#: builtin/commit.c:542
+#: builtin/commit.c:563
 msgid "malformed --author parameter"
 msgstr ""
 
-#: builtin/commit.c:562
+#: builtin/commit.c:583
 #, c-format
 msgid "Malformed ident string: '%s'"
 msgstr ""
 
-#: builtin/commit.c:600 builtin/commit.c:633 builtin/commit.c:956
+#: builtin/commit.c:621 builtin/commit.c:654 builtin/commit.c:982
 #, c-format
 msgid "could not lookup commit %s"
 msgstr ""
 
-#: builtin/commit.c:612 builtin/shortlog.c:272
+#: builtin/commit.c:633 builtin/shortlog.c:271
 #, c-format
 msgid "(reading log message from standard input)\n"
 msgstr ""
 
-#: builtin/commit.c:614
+#: builtin/commit.c:635
 msgid "could not read log from standard input"
 msgstr ""
 
-#: builtin/commit.c:618
+#: builtin/commit.c:639
 #, c-format
 msgid "could not read log file '%s'"
 msgstr ""
 
-#: builtin/commit.c:624
+#: builtin/commit.c:645
 msgid "commit has empty message"
 msgstr ""
 
-#: builtin/commit.c:640
+#: builtin/commit.c:661
 msgid "could not read MERGE_MSG"
 msgstr ""
 
-#: builtin/commit.c:644
+#: builtin/commit.c:665
 msgid "could not read SQUASH_MSG"
 msgstr ""
 
-#: builtin/commit.c:648
+#: builtin/commit.c:669
 #, c-format
 msgid "could not read '%s'"
 msgstr ""
 
-#: builtin/commit.c:709
+#: builtin/commit.c:730
 msgid "could not write commit template"
 msgstr ""
 
-#: builtin/commit.c:720
+#: builtin/commit.c:741
 #, c-format
 msgid ""
 "\n"
@@ -3509,7 +3826,7 @@
 "and try again.\n"
 msgstr ""
 
-#: builtin/commit.c:725
+#: builtin/commit.c:746
 #, c-format
 msgid ""
 "\n"
@@ -3519,14 +3836,14 @@
 "and try again.\n"
 msgstr ""
 
-#: builtin/commit.c:737
+#: builtin/commit.c:758
 #, c-format
 msgid ""
 "Please enter the commit message for your changes. Lines starting\n"
 "with '%c' will be ignored, and an empty message aborts the commit.\n"
 msgstr ""
 
-#: builtin/commit.c:742
+#: builtin/commit.c:763
 #, c-format
 msgid ""
 "Please enter the commit message for your changes. Lines starting\n"
@@ -3534,351 +3851,351 @@
 "An empty message aborts the commit.\n"
 msgstr ""
 
-#: builtin/commit.c:755
+#: builtin/commit.c:776
 #, c-format
 msgid "%sAuthor:    %s"
 msgstr ""
 
-#: builtin/commit.c:762
+#: builtin/commit.c:783
 #, c-format
 msgid "%sCommitter: %s"
 msgstr ""
 
-#: builtin/commit.c:782
+#: builtin/commit.c:803
 msgid "Cannot read index"
 msgstr ""
 
-#: builtin/commit.c:819
+#: builtin/commit.c:845
 msgid "Error building trees"
 msgstr ""
 
-#: builtin/commit.c:834 builtin/tag.c:359
+#: builtin/commit.c:860 builtin/tag.c:359
 #, c-format
 msgid "Please supply the message using either -m or -F option.\n"
 msgstr ""
 
-#: builtin/commit.c:931
+#: builtin/commit.c:957
 #, c-format
 msgid "No existing author found with '%s'"
 msgstr ""
 
-#: builtin/commit.c:946 builtin/commit.c:1140
+#: builtin/commit.c:972 builtin/commit.c:1208
 #, c-format
 msgid "Invalid untracked files mode '%s'"
 msgstr ""
 
-#: builtin/commit.c:976
+#: builtin/commit.c:1009
+msgid "--long and -z are incompatible"
+msgstr ""
+
+#: builtin/commit.c:1039
 msgid "Using both --reset-author and --author does not make sense"
 msgstr ""
 
-#: builtin/commit.c:987
+#: builtin/commit.c:1050
 msgid "You have nothing to amend."
 msgstr ""
 
-#: builtin/commit.c:990
+#: builtin/commit.c:1053
 msgid "You are in the middle of a merge -- cannot amend."
 msgstr ""
 
-#: builtin/commit.c:992
+#: builtin/commit.c:1055
 msgid "You are in the middle of a cherry-pick -- cannot amend."
 msgstr ""
 
-#: builtin/commit.c:995
+#: builtin/commit.c:1058
 msgid "Options --squash and --fixup cannot be used together"
 msgstr ""
 
-#: builtin/commit.c:1005
+#: builtin/commit.c:1068
 msgid "Only one of -c/-C/-F/--fixup can be used."
 msgstr ""
 
-#: builtin/commit.c:1007
+#: builtin/commit.c:1070
 msgid "Option -m cannot be combined with -c/-C/-F/--fixup."
 msgstr ""
 
-#: builtin/commit.c:1015
+#: builtin/commit.c:1078
 msgid "--reset-author can be used only with -C, -c or --amend."
 msgstr ""
 
-#: builtin/commit.c:1032
+#: builtin/commit.c:1095
 msgid "Only one of --include/--only/--all/--interactive/--patch can be used."
 msgstr ""
 
-#: builtin/commit.c:1034
+#: builtin/commit.c:1097
 msgid "No paths with --include/--only does not make sense."
 msgstr ""
 
-#: builtin/commit.c:1036
+#: builtin/commit.c:1099
 msgid "Clever... amending the last one with dirty index."
 msgstr ""
 
-#: builtin/commit.c:1038
+#: builtin/commit.c:1101
 msgid "Explicit paths specified without -i nor -o; assuming --only paths..."
 msgstr ""
 
-#: builtin/commit.c:1048 builtin/tag.c:575
+#: builtin/commit.c:1111 builtin/tag.c:575
 #, c-format
 msgid "Invalid cleanup mode %s"
 msgstr ""
 
-#: builtin/commit.c:1053
+#: builtin/commit.c:1116
 msgid "Paths with -a does not make sense."
 msgstr ""
 
-#: builtin/commit.c:1059 builtin/commit.c:1194
-msgid "--long and -z are incompatible"
-msgstr ""
-
-#: builtin/commit.c:1154 builtin/commit.c:1390
+#: builtin/commit.c:1222 builtin/commit.c:1455
 msgid "show status concisely"
 msgstr ""
 
-#: builtin/commit.c:1156 builtin/commit.c:1392
+#: builtin/commit.c:1224 builtin/commit.c:1457
 msgid "show branch information"
 msgstr ""
 
-#: builtin/commit.c:1158 builtin/commit.c:1394 builtin/push.c:426
+#: builtin/commit.c:1226 builtin/commit.c:1459 builtin/push.c:452
 msgid "machine-readable output"
 msgstr ""
 
-#: builtin/commit.c:1161 builtin/commit.c:1396
+#: builtin/commit.c:1229 builtin/commit.c:1461
 msgid "show status in long format (default)"
 msgstr ""
 
-#: builtin/commit.c:1164 builtin/commit.c:1399
+#: builtin/commit.c:1232 builtin/commit.c:1464
 msgid "terminate entries with NUL"
 msgstr ""
 
-#: builtin/commit.c:1166 builtin/commit.c:1402 builtin/fast-export.c:653
-#: builtin/fast-export.c:656 builtin/tag.c:459
+#: builtin/commit.c:1234 builtin/commit.c:1467 builtin/fast-export.c:667
+#: builtin/fast-export.c:670 builtin/tag.c:459
 msgid "mode"
 msgstr ""
 
-#: builtin/commit.c:1167 builtin/commit.c:1402
+#: builtin/commit.c:1235 builtin/commit.c:1467
 msgid "show untracked files, optional modes: all, normal, no. (Default: all)"
 msgstr ""
 
-#: builtin/commit.c:1170
+#: builtin/commit.c:1238
 msgid "show ignored files"
 msgstr ""
 
-#: builtin/commit.c:1171 parse-options.h:151
+#: builtin/commit.c:1239 parse-options.h:154
 msgid "when"
 msgstr ""
 
-#: builtin/commit.c:1172
+#: builtin/commit.c:1240
 msgid ""
 "ignore changes to submodules, optional when: all, dirty, untracked. "
 "(Default: all)"
 msgstr ""
 
-#: builtin/commit.c:1174
+#: builtin/commit.c:1242
 msgid "list untracked files in columns"
 msgstr ""
 
-#: builtin/commit.c:1248
+#: builtin/commit.c:1313
 msgid "couldn't look up newly created commit"
 msgstr ""
 
-#: builtin/commit.c:1250
+#: builtin/commit.c:1315
 msgid "could not parse newly created commit"
 msgstr ""
 
-#: builtin/commit.c:1291
+#: builtin/commit.c:1356
 msgid "detached HEAD"
 msgstr ""
 
-#: builtin/commit.c:1293
+#: builtin/commit.c:1358
 msgid " (root-commit)"
 msgstr ""
 
-#: builtin/commit.c:1360
+#: builtin/commit.c:1425
 msgid "suppress summary after successful commit"
 msgstr ""
 
-#: builtin/commit.c:1361
+#: builtin/commit.c:1426
 msgid "show diff in commit message template"
 msgstr ""
 
-#: builtin/commit.c:1363
+#: builtin/commit.c:1428
 msgid "Commit message options"
 msgstr ""
 
-#: builtin/commit.c:1364 builtin/tag.c:457
+#: builtin/commit.c:1429 builtin/tag.c:457
 msgid "read message from file"
 msgstr ""
 
-#: builtin/commit.c:1365
+#: builtin/commit.c:1430
 msgid "author"
 msgstr ""
 
-#: builtin/commit.c:1365
+#: builtin/commit.c:1430
 msgid "override author for commit"
 msgstr ""
 
-#: builtin/commit.c:1366 builtin/gc.c:178
+#: builtin/commit.c:1431 builtin/gc.c:178
 msgid "date"
 msgstr ""
 
-#: builtin/commit.c:1366
+#: builtin/commit.c:1431
 msgid "override date for commit"
 msgstr ""
 
-#: builtin/commit.c:1367 builtin/merge.c:208 builtin/notes.c:533
-#: builtin/notes.c:690 builtin/tag.c:455
+#: builtin/commit.c:1432 builtin/merge.c:223 builtin/notes.c:405
+#: builtin/notes.c:562 builtin/tag.c:455
 msgid "message"
 msgstr ""
 
-#: builtin/commit.c:1367
+#: builtin/commit.c:1432
 msgid "commit message"
 msgstr ""
 
-#: builtin/commit.c:1368
+#: builtin/commit.c:1433
 msgid "reuse and edit message from specified commit"
 msgstr ""
 
-#: builtin/commit.c:1369
+#: builtin/commit.c:1434
 msgid "reuse message from specified commit"
 msgstr ""
 
-#: builtin/commit.c:1370
+#: builtin/commit.c:1435
 msgid "use autosquash formatted message to fixup specified commit"
 msgstr ""
 
-#: builtin/commit.c:1371
+#: builtin/commit.c:1436
 msgid "use autosquash formatted message to squash specified commit"
 msgstr ""
 
-#: builtin/commit.c:1372
+#: builtin/commit.c:1437
 msgid "the commit is authored by me now (used with -C/-c/--amend)"
 msgstr ""
 
-#: builtin/commit.c:1373 builtin/log.c:1104 builtin/revert.c:109
+#: builtin/commit.c:1438 builtin/log.c:1160 builtin/revert.c:111
 msgid "add Signed-off-by:"
 msgstr ""
 
-#: builtin/commit.c:1374
+#: builtin/commit.c:1439
 msgid "use specified template file"
 msgstr ""
 
-#: builtin/commit.c:1375
+#: builtin/commit.c:1440
 msgid "force edit of commit"
 msgstr ""
 
-#: builtin/commit.c:1376
+#: builtin/commit.c:1441
 msgid "default"
 msgstr ""
 
-#: builtin/commit.c:1376 builtin/tag.c:460
+#: builtin/commit.c:1441 builtin/tag.c:460
 msgid "how to strip spaces and #comments from message"
 msgstr ""
 
-#: builtin/commit.c:1377
+#: builtin/commit.c:1442
 msgid "include status in commit message template"
 msgstr ""
 
-#: builtin/commit.c:1378 builtin/merge.c:215 builtin/tag.c:461
+#: builtin/commit.c:1443 builtin/merge.c:230 builtin/tag.c:461
 msgid "key id"
 msgstr ""
 
-#: builtin/commit.c:1379 builtin/merge.c:216
+#: builtin/commit.c:1444 builtin/merge.c:231
 msgid "GPG sign commit"
 msgstr ""
 
 #. end commit message options
-#: builtin/commit.c:1382
+#: builtin/commit.c:1447
 msgid "Commit contents options"
 msgstr ""
 
-#: builtin/commit.c:1383
+#: builtin/commit.c:1448
 msgid "commit all changed files"
 msgstr ""
 
-#: builtin/commit.c:1384
+#: builtin/commit.c:1449
 msgid "add specified files to index for commit"
 msgstr ""
 
-#: builtin/commit.c:1385
+#: builtin/commit.c:1450
 msgid "interactively add files"
 msgstr ""
 
-#: builtin/commit.c:1386
+#: builtin/commit.c:1451
 msgid "interactively add changes"
 msgstr ""
 
-#: builtin/commit.c:1387
+#: builtin/commit.c:1452
 msgid "commit only specified files"
 msgstr ""
 
-#: builtin/commit.c:1388
+#: builtin/commit.c:1453
 msgid "bypass pre-commit hook"
 msgstr ""
 
-#: builtin/commit.c:1389
+#: builtin/commit.c:1454
 msgid "show what would be committed"
 msgstr ""
 
-#: builtin/commit.c:1400
+#: builtin/commit.c:1465
 msgid "amend previous commit"
 msgstr ""
 
-#: builtin/commit.c:1401
+#: builtin/commit.c:1466
 msgid "bypass post-rewrite hook"
 msgstr ""
 
-#: builtin/commit.c:1406
+#: builtin/commit.c:1471
 msgid "ok to record an empty change"
 msgstr ""
 
-#: builtin/commit.c:1409
+#: builtin/commit.c:1474
 msgid "ok to record a change with an empty message"
 msgstr ""
 
-#: builtin/commit.c:1441
+#: builtin/commit.c:1507
 msgid "could not parse HEAD commit"
 msgstr ""
 
-#: builtin/commit.c:1479 builtin/merge.c:510
+#: builtin/commit.c:1545 builtin/merge.c:525
 #, c-format
 msgid "could not open '%s' for reading"
 msgstr ""
 
-#: builtin/commit.c:1486
+#: builtin/commit.c:1552
 #, c-format
 msgid "Corrupt MERGE_HEAD file (%s)"
 msgstr ""
 
-#: builtin/commit.c:1493
+#: builtin/commit.c:1559
 msgid "could not read MERGE_MODE"
 msgstr ""
 
-#: builtin/commit.c:1512
+#: builtin/commit.c:1578
 #, c-format
 msgid "could not read commit message: %s"
 msgstr ""
 
-#: builtin/commit.c:1526
+#: builtin/commit.c:1592
 #, c-format
 msgid "Aborting commit; you did not edit the message.\n"
 msgstr ""
 
-#: builtin/commit.c:1531
+#: builtin/commit.c:1597
 #, c-format
 msgid "Aborting commit due to empty commit message.\n"
 msgstr ""
 
-#: builtin/commit.c:1546 builtin/merge.c:847 builtin/merge.c:872
+#: builtin/commit.c:1612 builtin/merge.c:861 builtin/merge.c:886
 msgid "failed to write commit object"
 msgstr ""
 
-#: builtin/commit.c:1567
+#: builtin/commit.c:1633
 msgid "cannot lock HEAD ref"
 msgstr ""
 
-#: builtin/commit.c:1571
+#: builtin/commit.c:1637
 msgid "cannot update HEAD ref"
 msgstr ""
 
-#: builtin/commit.c:1582
+#: builtin/commit.c:1648
 msgid ""
 "Repository has been updated, but unable to write\n"
 "new_index file. Check that disk is not full or quota is\n"
@@ -3889,249 +4206,265 @@
 msgid "git config [options]"
 msgstr ""
 
-#: builtin/config.c:51
+#: builtin/config.c:52
 msgid "Config file location"
 msgstr ""
 
-#: builtin/config.c:52
+#: builtin/config.c:53
 msgid "use global config file"
 msgstr ""
 
-#: builtin/config.c:53
+#: builtin/config.c:54
 msgid "use system config file"
 msgstr ""
 
-#: builtin/config.c:54
+#: builtin/config.c:55
 msgid "use repository config file"
 msgstr ""
 
-#: builtin/config.c:55
+#: builtin/config.c:56
 msgid "use given config file"
 msgstr ""
 
-#: builtin/config.c:56
-msgid "Action"
+#: builtin/config.c:57
+msgid "blob-id"
 msgstr ""
 
 #: builtin/config.c:57
-msgid "get value: name [value-regex]"
+msgid "read config from given blob object"
 msgstr ""
 
 #: builtin/config.c:58
-msgid "get all values: key [value-regex]"
+msgid "Action"
 msgstr ""
 
 #: builtin/config.c:59
-msgid "get values for regexp: name-regex [value-regex]"
+msgid "get value: name [value-regex]"
 msgstr ""
 
 #: builtin/config.c:60
-msgid "replace all matching variables: name value [value_regex]"
+msgid "get all values: key [value-regex]"
 msgstr ""
 
 #: builtin/config.c:61
-msgid "add a new variable: name value"
+msgid "get values for regexp: name-regex [value-regex]"
 msgstr ""
 
 #: builtin/config.c:62
-msgid "remove a variable: name [value-regex]"
+msgid "replace all matching variables: name value [value_regex]"
 msgstr ""
 
 #: builtin/config.c:63
-msgid "remove all matches: name [value-regex]"
+msgid "add a new variable: name value"
 msgstr ""
 
 #: builtin/config.c:64
-msgid "rename section: old-name new-name"
+msgid "remove a variable: name [value-regex]"
 msgstr ""
 
 #: builtin/config.c:65
-msgid "remove a section: name"
+msgid "remove all matches: name [value-regex]"
 msgstr ""
 
 #: builtin/config.c:66
-msgid "list all"
+msgid "rename section: old-name new-name"
 msgstr ""
 
 #: builtin/config.c:67
-msgid "open an editor"
-msgstr ""
-
-#: builtin/config.c:68 builtin/config.c:69
-msgid "slot"
+msgid "remove a section: name"
 msgstr ""
 
 #: builtin/config.c:68
-msgid "find the color configured: [default]"
+msgid "list all"
 msgstr ""
 
 #: builtin/config.c:69
-msgid "find the color setting: [stdout-is-tty]"
+msgid "open an editor"
+msgstr ""
+
+#: builtin/config.c:70 builtin/config.c:71
+msgid "slot"
 msgstr ""
 
 #: builtin/config.c:70
-msgid "Type"
+msgid "find the color configured: [default]"
 msgstr ""
 
 #: builtin/config.c:71
-msgid "value is \"true\" or \"false\""
+msgid "find the color setting: [stdout-is-tty]"
 msgstr ""
 
 #: builtin/config.c:72
-msgid "value is decimal number"
+msgid "Type"
 msgstr ""
 
 #: builtin/config.c:73
-msgid "value is --bool or --int"
+msgid "value is \"true\" or \"false\""
 msgstr ""
 
 #: builtin/config.c:74
-msgid "value is a path (file or directory name)"
+msgid "value is decimal number"
 msgstr ""
 
 #: builtin/config.c:75
-msgid "Other"
+msgid "value is --bool or --int"
 msgstr ""
 
 #: builtin/config.c:76
-msgid "terminate values with NUL byte"
+msgid "value is a path (file or directory name)"
 msgstr ""
 
 #: builtin/config.c:77
+msgid "Other"
+msgstr ""
+
+#: builtin/config.c:78
+msgid "terminate values with NUL byte"
+msgstr ""
+
+#: builtin/config.c:79
 msgid "respect include directives on lookup"
 msgstr ""
 
 #: builtin/count-objects.c:82
-msgid "git count-objects [-v]"
+msgid "git count-objects [-v] [-H | --human-readable]"
 msgstr ""
 
-#: builtin/describe.c:15
-msgid "git describe [options] <committish>*"
+#: builtin/count-objects.c:97
+msgid "print sizes in human readable format"
 msgstr ""
 
 #: builtin/describe.c:16
-msgid "git describe [options] --dirty"
+msgid "git describe [options] <committish>*"
 msgstr ""
 
-#: builtin/describe.c:233
-#, c-format
-msgid "annotated tag %s not available"
+#: builtin/describe.c:17
+msgid "git describe [options] --dirty"
 msgstr ""
 
 #: builtin/describe.c:237
 #, c-format
+msgid "annotated tag %s not available"
+msgstr ""
+
+#: builtin/describe.c:241
+#, c-format
 msgid "annotated tag %s has no embedded name"
 msgstr ""
 
-#: builtin/describe.c:239
+#: builtin/describe.c:243
 #, c-format
 msgid "tag '%s' is really '%s' here"
 msgstr ""
 
-#: builtin/describe.c:266
+#: builtin/describe.c:270
 #, c-format
 msgid "Not a valid object name %s"
 msgstr ""
 
-#: builtin/describe.c:269
+#: builtin/describe.c:273
 #, c-format
 msgid "%s is not a valid '%s' object"
 msgstr ""
 
-#: builtin/describe.c:286
+#: builtin/describe.c:290
 #, c-format
 msgid "no tag exactly matches '%s'"
 msgstr ""
 
-#: builtin/describe.c:288
+#: builtin/describe.c:292
 #, c-format
 msgid "searching to describe %s\n"
 msgstr ""
 
-#: builtin/describe.c:328
+#: builtin/describe.c:332
 #, c-format
 msgid "finished search at %s\n"
 msgstr ""
 
-#: builtin/describe.c:352
+#: builtin/describe.c:359
 #, c-format
 msgid ""
 "No annotated tags can describe '%s'.\n"
 "However, there were unannotated tags: try --tags."
 msgstr ""
 
-#: builtin/describe.c:356
+#: builtin/describe.c:363
 #, c-format
 msgid ""
 "No tags can describe '%s'.\n"
 "Try --always, or create some tags."
 msgstr ""
 
-#: builtin/describe.c:377
+#: builtin/describe.c:384
 #, c-format
 msgid "traversed %lu commits\n"
 msgstr ""
 
-#: builtin/describe.c:380
+#: builtin/describe.c:387
 #, c-format
 msgid ""
 "more than %i tags found; listed %i most recent\n"
 "gave up search at %s\n"
 msgstr ""
 
-#: builtin/describe.c:402
+#: builtin/describe.c:409
 msgid "find the tag that comes after the commit"
 msgstr ""
 
-#: builtin/describe.c:403
+#: builtin/describe.c:410
 msgid "debug search strategy on stderr"
 msgstr ""
 
-#: builtin/describe.c:404
+#: builtin/describe.c:411
 msgid "use any ref"
 msgstr ""
 
-#: builtin/describe.c:405
+#: builtin/describe.c:412
 msgid "use any tag, even unannotated"
 msgstr ""
 
-#: builtin/describe.c:406
+#: builtin/describe.c:413
 msgid "always use long format"
 msgstr ""
 
-#: builtin/describe.c:409
-msgid "only output exact matches"
-msgstr ""
-
-#: builtin/describe.c:411
-msgid "consider <n> most recent tags (default: 10)"
-msgstr ""
-
-#: builtin/describe.c:413
-msgid "only consider tags matching <pattern>"
-msgstr ""
-
-#: builtin/describe.c:415 builtin/name-rev.c:238
-msgid "show abbreviated commit object as fallback"
-msgstr ""
-
-#: builtin/describe.c:416
-msgid "mark"
+#: builtin/describe.c:414
+msgid "only follow first parent"
 msgstr ""
 
 #: builtin/describe.c:417
+msgid "only output exact matches"
+msgstr ""
+
+#: builtin/describe.c:419
+msgid "consider <n> most recent tags (default: 10)"
+msgstr ""
+
+#: builtin/describe.c:421
+msgid "only consider tags matching <pattern>"
+msgstr ""
+
+#: builtin/describe.c:423 builtin/name-rev.c:322
+msgid "show abbreviated commit object as fallback"
+msgstr ""
+
+#: builtin/describe.c:424
+msgid "mark"
+msgstr ""
+
+#: builtin/describe.c:425
 msgid "append <mark> on dirty working tree (default: \"-dirty\")"
 msgstr ""
 
-#: builtin/describe.c:435
+#: builtin/describe.c:443
 msgid "--long is incompatible with --abbrev=0"
 msgstr ""
 
-#: builtin/describe.c:461
+#: builtin/describe.c:469
 msgid "No names found, cannot describe anything."
 msgstr ""
 
-#: builtin/describe.c:481
+#: builtin/describe.c:489
 msgid "--dirty is incompatible with committishes"
 msgstr ""
 
@@ -4140,31 +4473,26 @@
 msgid "'%s': not a regular file or symlink"
 msgstr ""
 
-#: builtin/diff.c:228
+#: builtin/diff.c:230
 #, c-format
 msgid "invalid option: %s"
 msgstr ""
 
-#: builtin/diff.c:305
+#: builtin/diff.c:307
 msgid "Not a git repository"
 msgstr ""
 
-#: builtin/diff.c:348
+#: builtin/diff.c:350
 #, c-format
 msgid "invalid object '%s' given."
 msgstr ""
 
-#: builtin/diff.c:353
-#, c-format
-msgid "more than %d trees given: '%s'"
-msgstr ""
-
-#: builtin/diff.c:363
+#: builtin/diff.c:359
 #, c-format
 msgid "more than two blobs given: '%s'"
 msgstr ""
 
-#: builtin/diff.c:371
+#: builtin/diff.c:366
 #, c-format
 msgid "unhandled object '%s' given."
 msgstr ""
@@ -4173,39 +4501,39 @@
 msgid "git fast-export [rev-list-opts]"
 msgstr ""
 
-#: builtin/fast-export.c:652
+#: builtin/fast-export.c:666
 msgid "show progress after <n> objects"
 msgstr ""
 
-#: builtin/fast-export.c:654
+#: builtin/fast-export.c:668
 msgid "select handling of signed tags"
 msgstr ""
 
-#: builtin/fast-export.c:657
+#: builtin/fast-export.c:671
 msgid "select handling of tags that tag filtered objects"
 msgstr ""
 
-#: builtin/fast-export.c:660
+#: builtin/fast-export.c:674
 msgid "Dump marks to this file"
 msgstr ""
 
-#: builtin/fast-export.c:662
+#: builtin/fast-export.c:676
 msgid "Import marks from this file"
 msgstr ""
 
-#: builtin/fast-export.c:664
+#: builtin/fast-export.c:678
 msgid "Fake a tagger when tags lack one"
 msgstr ""
 
-#: builtin/fast-export.c:666
+#: builtin/fast-export.c:680
 msgid "Output full tree for each commit"
 msgstr ""
 
-#: builtin/fast-export.c:668
+#: builtin/fast-export.c:682
 msgid "Use the done feature to terminate the stream"
 msgstr ""
 
-#: builtin/fast-export.c:669
+#: builtin/fast-export.c:683
 msgid "Skip output of blob data"
 msgstr ""
 
@@ -4281,7 +4609,7 @@
 msgid "convert to a complete repository"
 msgstr ""
 
-#: builtin/fetch.c:88 builtin/log.c:1121
+#: builtin/fetch.c:88 builtin/log.c:1177
 msgid "dir"
 msgstr ""
 
@@ -4293,162 +4621,162 @@
 msgid "default mode for recursion"
 msgstr ""
 
-#: builtin/fetch.c:204
+#: builtin/fetch.c:220
 msgid "Couldn't find remote ref HEAD"
 msgstr ""
 
-#: builtin/fetch.c:257
+#: builtin/fetch.c:273
 #, c-format
 msgid "object %s not found"
 msgstr ""
 
-#: builtin/fetch.c:262
+#: builtin/fetch.c:278
 msgid "[up to date]"
 msgstr ""
 
-#: builtin/fetch.c:276
+#: builtin/fetch.c:292
 #, c-format
 msgid "! %-*s %-*s -> %s  (can't fetch in current branch)"
 msgstr ""
 
-#: builtin/fetch.c:277 builtin/fetch.c:363
+#: builtin/fetch.c:293 builtin/fetch.c:379
 msgid "[rejected]"
 msgstr ""
 
-#: builtin/fetch.c:288
+#: builtin/fetch.c:304
 msgid "[tag update]"
 msgstr ""
 
-#: builtin/fetch.c:290 builtin/fetch.c:325 builtin/fetch.c:343
+#: builtin/fetch.c:306 builtin/fetch.c:341 builtin/fetch.c:359
 msgid "  (unable to update local ref)"
 msgstr ""
 
-#: builtin/fetch.c:308
+#: builtin/fetch.c:324
 msgid "[new tag]"
 msgstr ""
 
-#: builtin/fetch.c:311
+#: builtin/fetch.c:327
 msgid "[new branch]"
 msgstr ""
 
-#: builtin/fetch.c:314
+#: builtin/fetch.c:330
 msgid "[new ref]"
 msgstr ""
 
-#: builtin/fetch.c:359
+#: builtin/fetch.c:375
 msgid "unable to update local ref"
 msgstr ""
 
-#: builtin/fetch.c:359
+#: builtin/fetch.c:375
 msgid "forced update"
 msgstr ""
 
-#: builtin/fetch.c:365
+#: builtin/fetch.c:381
 msgid "(non-fast-forward)"
 msgstr ""
 
-#: builtin/fetch.c:396 builtin/fetch.c:688
+#: builtin/fetch.c:412 builtin/fetch.c:718
 #, c-format
 msgid "cannot open %s: %s\n"
 msgstr ""
 
-#: builtin/fetch.c:405
+#: builtin/fetch.c:421
 #, c-format
 msgid "%s did not send all necessary objects\n"
 msgstr ""
 
-#: builtin/fetch.c:491
+#: builtin/fetch.c:520
 #, c-format
 msgid "From %.*s\n"
 msgstr ""
 
-#: builtin/fetch.c:502
+#: builtin/fetch.c:531
 #, c-format
 msgid ""
 "some local refs could not be updated; try running\n"
 " 'git remote prune %s' to remove any old, conflicting branches"
 msgstr ""
 
-#: builtin/fetch.c:552
+#: builtin/fetch.c:581
 #, c-format
 msgid "   (%s will become dangling)"
 msgstr ""
 
-#: builtin/fetch.c:553
+#: builtin/fetch.c:582
 #, c-format
 msgid "   (%s has become dangling)"
 msgstr ""
 
-#: builtin/fetch.c:560
+#: builtin/fetch.c:589
 msgid "[deleted]"
 msgstr ""
 
-#: builtin/fetch.c:561 builtin/remote.c:1055
+#: builtin/fetch.c:590 builtin/remote.c:1055
 msgid "(none)"
 msgstr ""
 
-#: builtin/fetch.c:678
+#: builtin/fetch.c:708
 #, c-format
 msgid "Refusing to fetch into current branch %s of non-bare repository"
 msgstr ""
 
-#: builtin/fetch.c:712
+#: builtin/fetch.c:742
 #, c-format
 msgid "Don't know how to fetch from %s"
 msgstr ""
 
-#: builtin/fetch.c:789
+#: builtin/fetch.c:823
 #, c-format
 msgid "Option \"%s\" value \"%s\" is not valid for %s"
 msgstr ""
 
-#: builtin/fetch.c:792
+#: builtin/fetch.c:826
 #, c-format
 msgid "Option \"%s\" is ignored for %s\n"
 msgstr ""
 
-#: builtin/fetch.c:894
+#: builtin/fetch.c:928
 #, c-format
 msgid "Fetching %s\n"
 msgstr ""
 
-#: builtin/fetch.c:896 builtin/remote.c:100
+#: builtin/fetch.c:930 builtin/remote.c:100
 #, c-format
 msgid "Could not fetch %s"
 msgstr ""
 
-#: builtin/fetch.c:915
+#: builtin/fetch.c:949
 msgid ""
 "No remote repository specified.  Please, specify either a URL or a\n"
 "remote name from which new revisions should be fetched."
 msgstr ""
 
-#: builtin/fetch.c:935
+#: builtin/fetch.c:969
 msgid "You need to specify a tag name."
 msgstr ""
 
-#: builtin/fetch.c:981
+#: builtin/fetch.c:1015
 msgid "--depth and --unshallow cannot be used together"
 msgstr ""
 
-#: builtin/fetch.c:983
+#: builtin/fetch.c:1017
 msgid "--unshallow on a complete repository does not make sense"
 msgstr ""
 
-#: builtin/fetch.c:1002
+#: builtin/fetch.c:1036
 msgid "fetch --all does not take a repository argument"
 msgstr ""
 
-#: builtin/fetch.c:1004
+#: builtin/fetch.c:1038
 msgid "fetch --all does not make sense with refspecs"
 msgstr ""
 
-#: builtin/fetch.c:1015
+#: builtin/fetch.c:1049
 #, c-format
 msgid "No such remote or remote group: %s"
 msgstr ""
 
-#: builtin/fetch.c:1023
+#: builtin/fetch.c:1057
 msgid "Fetching a group and specifying refspecs does not make sense"
 msgstr ""
 
@@ -4456,29 +4784,29 @@
 msgid "git fmt-merge-msg [-m <message>] [--log[=<n>]|--no-log] [--file <file>]"
 msgstr ""
 
-#: builtin/fmt-merge-msg.c:659 builtin/fmt-merge-msg.c:662 builtin/grep.c:701
-#: builtin/merge.c:188 builtin/show-branch.c:656 builtin/show-ref.c:175
-#: builtin/tag.c:446 parse-options.h:133 parse-options.h:239
+#: builtin/fmt-merge-msg.c:663 builtin/fmt-merge-msg.c:666 builtin/grep.c:700
+#: builtin/merge.c:203 builtin/show-branch.c:655 builtin/show-ref.c:179
+#: builtin/tag.c:446 parse-options.h:133 parse-options.h:243
 msgid "n"
 msgstr ""
 
-#: builtin/fmt-merge-msg.c:660
+#: builtin/fmt-merge-msg.c:664
 msgid "populate log with at most <n> entries from shortlog"
 msgstr ""
 
-#: builtin/fmt-merge-msg.c:663
+#: builtin/fmt-merge-msg.c:667
 msgid "alias for --log (deprecated)"
 msgstr ""
 
-#: builtin/fmt-merge-msg.c:666
+#: builtin/fmt-merge-msg.c:670
 msgid "text"
 msgstr ""
 
-#: builtin/fmt-merge-msg.c:667
+#: builtin/fmt-merge-msg.c:671
 msgid "use <text> as start of message"
 msgstr ""
 
-#: builtin/fmt-merge-msg.c:668
+#: builtin/fmt-merge-msg.c:672
 msgid "file to read from"
 msgstr ""
 
@@ -4613,220 +4941,220 @@
 msgid "grep: failed to create thread: %s"
 msgstr ""
 
-#: builtin/grep.c:365
+#: builtin/grep.c:364
 #, c-format
 msgid "Failed to chdir: %s"
 msgstr ""
 
-#: builtin/grep.c:443 builtin/grep.c:478
+#: builtin/grep.c:442 builtin/grep.c:477
 #, c-format
 msgid "unable to read tree (%s)"
 msgstr ""
 
-#: builtin/grep.c:493
+#: builtin/grep.c:492
 #, c-format
 msgid "unable to grep from object of type %s"
 msgstr ""
 
-#: builtin/grep.c:551
+#: builtin/grep.c:550
 #, c-format
 msgid "switch `%c' expects a numerical value"
 msgstr ""
 
-#: builtin/grep.c:568
+#: builtin/grep.c:567
 #, c-format
 msgid "cannot open '%s'"
 msgstr ""
 
-#: builtin/grep.c:643
+#: builtin/grep.c:642
 msgid "search in index instead of in the work tree"
 msgstr ""
 
-#: builtin/grep.c:645
+#: builtin/grep.c:644
 msgid "find in contents not managed by git"
 msgstr ""
 
-#: builtin/grep.c:647
+#: builtin/grep.c:646
 msgid "search in both tracked and untracked files"
 msgstr ""
 
-#: builtin/grep.c:649
+#: builtin/grep.c:648
 msgid "search also in ignored files"
 msgstr ""
 
-#: builtin/grep.c:652
+#: builtin/grep.c:651
 msgid "show non-matching lines"
 msgstr ""
 
-#: builtin/grep.c:654
+#: builtin/grep.c:653
 msgid "case insensitive matching"
 msgstr ""
 
-#: builtin/grep.c:656
+#: builtin/grep.c:655
 msgid "match patterns only at word boundaries"
 msgstr ""
 
-#: builtin/grep.c:658
+#: builtin/grep.c:657
 msgid "process binary files as text"
 msgstr ""
 
-#: builtin/grep.c:660
+#: builtin/grep.c:659
 msgid "don't match patterns in binary files"
 msgstr ""
 
-#: builtin/grep.c:663
+#: builtin/grep.c:662
 msgid "descend at most <depth> levels"
 msgstr ""
 
-#: builtin/grep.c:667
+#: builtin/grep.c:666
 msgid "use extended POSIX regular expressions"
 msgstr ""
 
-#: builtin/grep.c:670
+#: builtin/grep.c:669
 msgid "use basic POSIX regular expressions (default)"
 msgstr ""
 
-#: builtin/grep.c:673
+#: builtin/grep.c:672
 msgid "interpret patterns as fixed strings"
 msgstr ""
 
-#: builtin/grep.c:676
+#: builtin/grep.c:675
 msgid "use Perl-compatible regular expressions"
 msgstr ""
 
-#: builtin/grep.c:679
+#: builtin/grep.c:678
 msgid "show line numbers"
 msgstr ""
 
-#: builtin/grep.c:680
+#: builtin/grep.c:679
 msgid "don't show filenames"
 msgstr ""
 
-#: builtin/grep.c:681
+#: builtin/grep.c:680
 msgid "show filenames"
 msgstr ""
 
-#: builtin/grep.c:683
+#: builtin/grep.c:682
 msgid "show filenames relative to top directory"
 msgstr ""
 
-#: builtin/grep.c:685
+#: builtin/grep.c:684
 msgid "show only filenames instead of matching lines"
 msgstr ""
 
-#: builtin/grep.c:687
+#: builtin/grep.c:686
 msgid "synonym for --files-with-matches"
 msgstr ""
 
-#: builtin/grep.c:690
+#: builtin/grep.c:689
 msgid "show only the names of files without match"
 msgstr ""
 
-#: builtin/grep.c:692
+#: builtin/grep.c:691
 msgid "print NUL after filenames"
 msgstr ""
 
-#: builtin/grep.c:694
+#: builtin/grep.c:693
 msgid "show the number of matches instead of matching lines"
 msgstr ""
 
-#: builtin/grep.c:695
+#: builtin/grep.c:694
 msgid "highlight matches"
 msgstr ""
 
-#: builtin/grep.c:697
+#: builtin/grep.c:696
 msgid "print empty line between matches from different files"
 msgstr ""
 
-#: builtin/grep.c:699
+#: builtin/grep.c:698
 msgid "show filename only once above matches from same file"
 msgstr ""
 
-#: builtin/grep.c:702
+#: builtin/grep.c:701
 msgid "show <n> context lines before and after matches"
 msgstr ""
 
-#: builtin/grep.c:705
+#: builtin/grep.c:704
 msgid "show <n> context lines before matches"
 msgstr ""
 
-#: builtin/grep.c:707
+#: builtin/grep.c:706
 msgid "show <n> context lines after matches"
 msgstr ""
 
-#: builtin/grep.c:708
+#: builtin/grep.c:707
 msgid "shortcut for -C NUM"
 msgstr ""
 
-#: builtin/grep.c:711
+#: builtin/grep.c:710
 msgid "show a line with the function name before matches"
 msgstr ""
 
-#: builtin/grep.c:713
+#: builtin/grep.c:712
 msgid "show the surrounding function"
 msgstr ""
 
-#: builtin/grep.c:716
+#: builtin/grep.c:715
 msgid "read patterns from file"
 msgstr ""
 
-#: builtin/grep.c:718
+#: builtin/grep.c:717
 msgid "match <pattern>"
 msgstr ""
 
-#: builtin/grep.c:720
+#: builtin/grep.c:719
 msgid "combine patterns specified with -e"
 msgstr ""
 
-#: builtin/grep.c:732
+#: builtin/grep.c:731
 msgid "indicate hit with exit status without output"
 msgstr ""
 
-#: builtin/grep.c:734
+#: builtin/grep.c:733
 msgid "show only matches from files that match all patterns"
 msgstr ""
 
-#: builtin/grep.c:736
+#: builtin/grep.c:735
 msgid "show parse tree for grep expression"
 msgstr ""
 
-#: builtin/grep.c:740
+#: builtin/grep.c:739
 msgid "pager"
 msgstr ""
 
-#: builtin/grep.c:740
+#: builtin/grep.c:739
 msgid "show matching files in the pager"
 msgstr ""
 
-#: builtin/grep.c:743
+#: builtin/grep.c:742
 msgid "allow calling of grep(1) (ignored by this build)"
 msgstr ""
 
-#: builtin/grep.c:744 builtin/show-ref.c:184
+#: builtin/grep.c:743 builtin/show-ref.c:188
 msgid "show usage"
 msgstr ""
 
-#: builtin/grep.c:811
+#: builtin/grep.c:810
 msgid "no pattern given."
 msgstr ""
 
-#: builtin/grep.c:866
+#: builtin/grep.c:865
 msgid "--open-files-in-pager only works on the worktree"
 msgstr ""
 
-#: builtin/grep.c:889
+#: builtin/grep.c:888
 msgid "--cached or --untracked cannot be used with --no-index."
 msgstr ""
 
-#: builtin/grep.c:894
+#: builtin/grep.c:893
 msgid "--no-index or --untracked cannot be used with revs."
 msgstr ""
 
-#: builtin/grep.c:897
+#: builtin/grep.c:896
 msgid "--[no-]exclude-standard cannot be used for tracked contents."
 msgstr ""
 
-#: builtin/grep.c:905
+#: builtin/grep.c:904
 msgid "both --cached and trees are given."
 msgstr ""
 
@@ -4864,10 +5192,14 @@
 msgid "process file as it were from this path"
 msgstr ""
 
-#: builtin/help.c:42
+#: builtin/help.c:41
 msgid "print all available commands"
 msgstr ""
 
+#: builtin/help.c:42
+msgid "print list of useful guides"
+msgstr ""
+
 #: builtin/help.c:43
 msgid "show man page"
 msgstr ""
@@ -4881,7 +5213,7 @@
 msgstr ""
 
 #: builtin/help.c:52
-msgid "git help [--all] [--man|--web|--info] [command]"
+msgid "git help [--all] [--guides] [--man|--web|--info] [command]"
 msgstr ""
 
 #: builtin/help.c:64
@@ -4934,290 +5266,322 @@
 msgid "no info viewer handled the request"
 msgstr ""
 
-#: builtin/help.c:429 builtin/help.c:436
+#: builtin/help.c:420
+msgid "Defining attributes per path"
+msgstr ""
+
+#: builtin/help.c:421
+msgid "A Git glossary"
+msgstr ""
+
+#: builtin/help.c:422
+msgid "Specifies intentionally untracked files to ignore"
+msgstr ""
+
+#: builtin/help.c:423
+msgid "Defining submodule properties"
+msgstr ""
+
+#: builtin/help.c:424
+msgid "Specifying revisions and ranges for Git"
+msgstr ""
+
+#: builtin/help.c:425
+msgid "A tutorial introduction to Git (for version 1.5.1 or newer)"
+msgstr ""
+
+#: builtin/help.c:426
+msgid "An overview of recommended workflows with Git"
+msgstr ""
+
+#: builtin/help.c:438
+msgid "The common Git guides are:\n"
+msgstr ""
+
+#: builtin/help.c:460 builtin/help.c:476
 #, c-format
 msgid "usage: %s%s"
 msgstr ""
 
-#: builtin/help.c:452
+#: builtin/help.c:492
 #, c-format
 msgid "`git %s' is aliased to `%s'"
 msgstr ""
 
-#: builtin/index-pack.c:182
+#: builtin/index-pack.c:184
 #, c-format
 msgid "object type mismatch at %s"
 msgstr ""
 
-#: builtin/index-pack.c:202
+#: builtin/index-pack.c:204
 msgid "object of unexpected type"
 msgstr ""
 
-#: builtin/index-pack.c:239
+#: builtin/index-pack.c:244
 #, c-format
 msgid "cannot fill %d byte"
 msgid_plural "cannot fill %d bytes"
 msgstr[0] ""
 msgstr[1] ""
 
-#: builtin/index-pack.c:249
+#: builtin/index-pack.c:254
 msgid "early EOF"
 msgstr ""
 
-#: builtin/index-pack.c:250
+#: builtin/index-pack.c:255
 msgid "read error on input"
 msgstr ""
 
-#: builtin/index-pack.c:262
+#: builtin/index-pack.c:267
 msgid "used more bytes than were available"
 msgstr ""
 
-#: builtin/index-pack.c:269
+#: builtin/index-pack.c:274
 msgid "pack too large for current definition of off_t"
 msgstr ""
 
-#: builtin/index-pack.c:285
-#, c-format
-msgid "unable to create '%s'"
-msgstr ""
-
 #: builtin/index-pack.c:290
 #, c-format
+msgid "unable to create '%s'"
+msgstr ""
+
+#: builtin/index-pack.c:295
+#, c-format
 msgid "cannot open packfile '%s'"
 msgstr ""
 
-#: builtin/index-pack.c:304
+#: builtin/index-pack.c:309
 msgid "pack signature mismatch"
 msgstr ""
 
-#: builtin/index-pack.c:306
+#: builtin/index-pack.c:311
 #, c-format
 msgid "pack version %<PRIu32> unsupported"
 msgstr ""
 
-#: builtin/index-pack.c:324
+#: builtin/index-pack.c:329
 #, c-format
 msgid "pack has bad object at offset %lu: %s"
 msgstr ""
 
-#: builtin/index-pack.c:446
+#: builtin/index-pack.c:451
 #, c-format
 msgid "inflate returned %d"
 msgstr ""
 
-#: builtin/index-pack.c:495
+#: builtin/index-pack.c:500
 msgid "offset value overflow for delta base object"
 msgstr ""
 
-#: builtin/index-pack.c:503
+#: builtin/index-pack.c:508
 msgid "delta base offset is out of bound"
 msgstr ""
 
-#: builtin/index-pack.c:511
+#: builtin/index-pack.c:516
 #, c-format
 msgid "unknown object type %d"
 msgstr ""
 
-#: builtin/index-pack.c:542
+#: builtin/index-pack.c:547
 msgid "cannot pread pack file"
 msgstr ""
 
-#: builtin/index-pack.c:544
+#: builtin/index-pack.c:549
 #, c-format
 msgid "premature end of pack file, %lu byte missing"
 msgid_plural "premature end of pack file, %lu bytes missing"
 msgstr[0] ""
 msgstr[1] ""
 
-#: builtin/index-pack.c:570
+#: builtin/index-pack.c:575
 msgid "serious inflate inconsistency"
 msgstr ""
 
-#: builtin/index-pack.c:661 builtin/index-pack.c:667 builtin/index-pack.c:690
-#: builtin/index-pack.c:724 builtin/index-pack.c:733
+#: builtin/index-pack.c:666 builtin/index-pack.c:672 builtin/index-pack.c:695
+#: builtin/index-pack.c:729 builtin/index-pack.c:738
 #, c-format
 msgid "SHA1 COLLISION FOUND WITH %s !"
 msgstr ""
 
-#: builtin/index-pack.c:664 builtin/pack-objects.c:170
+#: builtin/index-pack.c:669 builtin/pack-objects.c:170
 #: builtin/pack-objects.c:262
 #, c-format
 msgid "unable to read %s"
 msgstr ""
 
-#: builtin/index-pack.c:730
+#: builtin/index-pack.c:735
 #, c-format
 msgid "cannot read existing object %s"
 msgstr ""
 
-#: builtin/index-pack.c:744
+#: builtin/index-pack.c:749
 #, c-format
 msgid "invalid blob object %s"
 msgstr ""
 
-#: builtin/index-pack.c:759
+#: builtin/index-pack.c:763
 #, c-format
 msgid "invalid %s"
 msgstr ""
 
-#: builtin/index-pack.c:761
+#: builtin/index-pack.c:766
 msgid "Error in object"
 msgstr ""
 
-#: builtin/index-pack.c:763
+#: builtin/index-pack.c:768
 #, c-format
 msgid "Not all child objects of %s are reachable"
 msgstr ""
 
-#: builtin/index-pack.c:833 builtin/index-pack.c:863
+#: builtin/index-pack.c:838 builtin/index-pack.c:868
 msgid "failed to apply delta"
 msgstr ""
 
-#: builtin/index-pack.c:1004
+#: builtin/index-pack.c:1009
 msgid "Receiving objects"
 msgstr ""
 
-#: builtin/index-pack.c:1004
+#: builtin/index-pack.c:1009
 msgid "Indexing objects"
 msgstr ""
 
-#: builtin/index-pack.c:1030
+#: builtin/index-pack.c:1035
 msgid "pack is corrupted (SHA1 mismatch)"
 msgstr ""
 
-#: builtin/index-pack.c:1035
+#: builtin/index-pack.c:1040
 msgid "cannot fstat packfile"
 msgstr ""
 
-#: builtin/index-pack.c:1038
+#: builtin/index-pack.c:1043
 msgid "pack has junk at the end"
 msgstr ""
 
-#: builtin/index-pack.c:1049
+#: builtin/index-pack.c:1054
 msgid "confusion beyond insanity in parse_pack_objects()"
 msgstr ""
 
-#: builtin/index-pack.c:1072
+#: builtin/index-pack.c:1077
 msgid "Resolving deltas"
 msgstr ""
 
-#: builtin/index-pack.c:1082
+#: builtin/index-pack.c:1087
 #, c-format
 msgid "unable to create thread: %s"
 msgstr ""
 
-#: builtin/index-pack.c:1124
+#: builtin/index-pack.c:1129
 msgid "confusion beyond insanity"
 msgstr ""
 
-#: builtin/index-pack.c:1132
+#: builtin/index-pack.c:1137
 #, c-format
 msgid "completed with %d local objects"
 msgstr ""
 
-#: builtin/index-pack.c:1142
+#: builtin/index-pack.c:1147
 #, c-format
 msgid "Unexpected tail checksum for %s (disk corruption?)"
 msgstr ""
 
-#: builtin/index-pack.c:1146
+#: builtin/index-pack.c:1151
 #, c-format
 msgid "pack has %d unresolved delta"
 msgid_plural "pack has %d unresolved deltas"
 msgstr[0] ""
 msgstr[1] ""
 
-#: builtin/index-pack.c:1171
+#: builtin/index-pack.c:1176
 #, c-format
 msgid "unable to deflate appended object (%d)"
 msgstr ""
 
-#: builtin/index-pack.c:1250
+#: builtin/index-pack.c:1255
 #, c-format
 msgid "local object %s is corrupt"
 msgstr ""
 
-#: builtin/index-pack.c:1274
+#: builtin/index-pack.c:1279
 msgid "error while closing pack file"
 msgstr ""
 
-#: builtin/index-pack.c:1287
+#: builtin/index-pack.c:1292
 #, c-format
 msgid "cannot write keep file '%s'"
 msgstr ""
 
-#: builtin/index-pack.c:1295
+#: builtin/index-pack.c:1300
 #, c-format
 msgid "cannot close written keep file '%s'"
 msgstr ""
 
-#: builtin/index-pack.c:1308
+#: builtin/index-pack.c:1313
 msgid "cannot store pack file"
 msgstr ""
 
-#: builtin/index-pack.c:1319
+#: builtin/index-pack.c:1324
 msgid "cannot store index file"
 msgstr ""
 
-#: builtin/index-pack.c:1352
+#: builtin/index-pack.c:1357
 #, c-format
 msgid "bad pack.indexversion=%<PRIu32>"
 msgstr ""
 
-#: builtin/index-pack.c:1358
+#: builtin/index-pack.c:1363
 #, c-format
 msgid "invalid number of threads specified (%d)"
 msgstr ""
 
-#: builtin/index-pack.c:1362 builtin/index-pack.c:1535
+#: builtin/index-pack.c:1367 builtin/index-pack.c:1545
 #, c-format
 msgid "no threads support, ignoring %s"
 msgstr ""
 
-#: builtin/index-pack.c:1420
+#: builtin/index-pack.c:1425
 #, c-format
 msgid "Cannot open existing pack file '%s'"
 msgstr ""
 
-#: builtin/index-pack.c:1422
+#: builtin/index-pack.c:1427
 #, c-format
 msgid "Cannot open existing pack idx file for '%s'"
 msgstr ""
 
-#: builtin/index-pack.c:1469
+#: builtin/index-pack.c:1474
 #, c-format
 msgid "non delta: %d object"
 msgid_plural "non delta: %d objects"
 msgstr[0] ""
 msgstr[1] ""
 
-#: builtin/index-pack.c:1476
+#: builtin/index-pack.c:1481
 #, c-format
 msgid "chain length = %d: %lu object"
 msgid_plural "chain length = %d: %lu objects"
 msgstr[0] ""
 msgstr[1] ""
 
-#: builtin/index-pack.c:1503
+#: builtin/index-pack.c:1509
 msgid "Cannot come back to cwd"
 msgstr ""
 
-#: builtin/index-pack.c:1547 builtin/index-pack.c:1550
-#: builtin/index-pack.c:1562 builtin/index-pack.c:1566
+#: builtin/index-pack.c:1557 builtin/index-pack.c:1560
+#: builtin/index-pack.c:1572 builtin/index-pack.c:1576
 #, c-format
 msgid "bad %s"
 msgstr ""
 
-#: builtin/index-pack.c:1580
+#: builtin/index-pack.c:1590
 msgid "--fix-thin cannot be used without --stdin"
 msgstr ""
 
-#: builtin/index-pack.c:1584 builtin/index-pack.c:1594
+#: builtin/index-pack.c:1594 builtin/index-pack.c:1604
 #, c-format
 msgid "packfile name '%s' does not end with '.pack'"
 msgstr ""
 
-#: builtin/index-pack.c:1603
+#: builtin/index-pack.c:1613
 msgid "--verify with no packfile name given"
 msgstr ""
 
@@ -5351,7 +5715,7 @@
 msgid "specify that the git repository is to be shared amongst several users"
 msgstr ""
 
-#: builtin/init-db.c:493 builtin/prune-packed.c:77
+#: builtin/init-db.c:493 builtin/prune-packed.c:75
 msgid "be quiet"
 msgstr ""
 
@@ -5381,340 +5745,353 @@
 msgid "Cannot access work tree '%s'"
 msgstr ""
 
-#: builtin/log.c:40
-msgid "git log [<options>] [<since>..<until>] [[--] <path>...]\n"
+#: builtin/log.c:41
+msgid "git log [<options>] [<revision range>] [[--] <path>...]\n"
 msgstr ""
 
-#: builtin/log.c:41
+#: builtin/log.c:42
 msgid "   or: git show [options] <object>..."
 msgstr ""
 
-#: builtin/log.c:103
+#: builtin/log.c:124
 msgid "suppress diff output"
 msgstr ""
 
-#: builtin/log.c:104
+#: builtin/log.c:125
 msgid "show source"
 msgstr ""
 
-#: builtin/log.c:105
+#: builtin/log.c:126
 msgid "Use mail map file"
 msgstr ""
 
-#: builtin/log.c:106
+#: builtin/log.c:127
 msgid "decorate options"
 msgstr ""
 
-#: builtin/log.c:199
+#: builtin/log.c:230
 #, c-format
 msgid "Final output: %d %s\n"
 msgstr ""
 
-#: builtin/log.c:422 builtin/log.c:514
+#: builtin/log.c:453 builtin/log.c:545
 #, c-format
 msgid "Could not read object %s"
 msgstr ""
 
-#: builtin/log.c:538
+#: builtin/log.c:569
 #, c-format
 msgid "Unknown type: %d"
 msgstr ""
 
-#: builtin/log.c:630
+#: builtin/log.c:669
 msgid "format.headers without value"
 msgstr ""
 
-#: builtin/log.c:704
+#: builtin/log.c:751
 msgid "name of output directory is too long"
 msgstr ""
 
-#: builtin/log.c:720
+#: builtin/log.c:767
 #, c-format
 msgid "Cannot open patch file %s"
 msgstr ""
 
-#: builtin/log.c:734
+#: builtin/log.c:781
 msgid "Need exactly one range."
 msgstr ""
 
-#: builtin/log.c:742
+#: builtin/log.c:789
 msgid "Not a range."
 msgstr ""
 
-#: builtin/log.c:815
+#: builtin/log.c:891
 msgid "Cover letter needs email format"
 msgstr ""
 
-#: builtin/log.c:888
+#: builtin/log.c:967
 #, c-format
 msgid "insane in-reply-to: %s"
 msgstr ""
 
-#: builtin/log.c:916
+#: builtin/log.c:995
 msgid "git format-patch [options] [<since> | <revision range>]"
 msgstr ""
 
-#: builtin/log.c:961
+#: builtin/log.c:1040
 msgid "Two output directories?"
 msgstr ""
 
-#: builtin/log.c:1099
+#: builtin/log.c:1155
 msgid "use [PATCH n/m] even with a single patch"
 msgstr ""
 
-#: builtin/log.c:1102
+#: builtin/log.c:1158
 msgid "use [PATCH] even with multiple patches"
 msgstr ""
 
-#: builtin/log.c:1106
+#: builtin/log.c:1162
 msgid "print patches to standard out"
 msgstr ""
 
-#: builtin/log.c:1108
+#: builtin/log.c:1164
 msgid "generate a cover letter"
 msgstr ""
 
-#: builtin/log.c:1110
+#: builtin/log.c:1166
 msgid "use simple number sequence for output file names"
 msgstr ""
 
-#: builtin/log.c:1111
+#: builtin/log.c:1167
 msgid "sfx"
 msgstr ""
 
-#: builtin/log.c:1112
+#: builtin/log.c:1168
 msgid "use <sfx> instead of '.patch'"
 msgstr ""
 
-#: builtin/log.c:1114
+#: builtin/log.c:1170
 msgid "start numbering patches at <n> instead of 1"
 msgstr ""
 
-#: builtin/log.c:1116
+#: builtin/log.c:1172
 msgid "mark the series as Nth re-roll"
 msgstr ""
 
-#: builtin/log.c:1118
+#: builtin/log.c:1174
 msgid "Use [<prefix>] instead of [PATCH]"
 msgstr ""
 
-#: builtin/log.c:1121
+#: builtin/log.c:1177
 msgid "store resulting files in <dir>"
 msgstr ""
 
-#: builtin/log.c:1124
+#: builtin/log.c:1180
 msgid "don't strip/add [PATCH]"
 msgstr ""
 
-#: builtin/log.c:1127
+#: builtin/log.c:1183
 msgid "don't output binary diffs"
 msgstr ""
 
-#: builtin/log.c:1129
+#: builtin/log.c:1185
 msgid "don't include a patch matching a commit upstream"
 msgstr ""
 
-#: builtin/log.c:1131
+#: builtin/log.c:1187
 msgid "show patch format instead of default (patch + stat)"
 msgstr ""
 
-#: builtin/log.c:1133
+#: builtin/log.c:1189
 msgid "Messaging"
 msgstr ""
 
-#: builtin/log.c:1134
+#: builtin/log.c:1190
 msgid "header"
 msgstr ""
 
-#: builtin/log.c:1135
+#: builtin/log.c:1191
 msgid "add email header"
 msgstr ""
 
-#: builtin/log.c:1136 builtin/log.c:1138
+#: builtin/log.c:1192 builtin/log.c:1194
 msgid "email"
 msgstr ""
 
-#: builtin/log.c:1136
+#: builtin/log.c:1192
 msgid "add To: header"
 msgstr ""
 
-#: builtin/log.c:1138
+#: builtin/log.c:1194
 msgid "add Cc: header"
 msgstr ""
 
-#: builtin/log.c:1140
+#: builtin/log.c:1196
+msgid "ident"
+msgstr ""
+
+#: builtin/log.c:1197
+msgid "set From address to <ident> (or committer ident if absent)"
+msgstr ""
+
+#: builtin/log.c:1199
 msgid "message-id"
 msgstr ""
 
-#: builtin/log.c:1141
+#: builtin/log.c:1200
 msgid "make first mail a reply to <message-id>"
 msgstr ""
 
-#: builtin/log.c:1142 builtin/log.c:1145
+#: builtin/log.c:1201 builtin/log.c:1204
 msgid "boundary"
 msgstr ""
 
-#: builtin/log.c:1143
+#: builtin/log.c:1202
 msgid "attach the patch"
 msgstr ""
 
-#: builtin/log.c:1146
+#: builtin/log.c:1205
 msgid "inline the patch"
 msgstr ""
 
-#: builtin/log.c:1150
+#: builtin/log.c:1209
 msgid "enable message threading, styles: shallow, deep"
 msgstr ""
 
-#: builtin/log.c:1152
+#: builtin/log.c:1211
 msgid "signature"
 msgstr ""
 
-#: builtin/log.c:1153
+#: builtin/log.c:1212
 msgid "add a signature"
 msgstr ""
 
-#: builtin/log.c:1155
+#: builtin/log.c:1214
 msgid "don't print the patch filenames"
 msgstr ""
 
-#: builtin/log.c:1239
+#: builtin/log.c:1288
+#, c-format
+msgid "invalid ident line: %s"
+msgstr ""
+
+#: builtin/log.c:1303
 msgid "-n and -k are mutually exclusive."
 msgstr ""
 
-#: builtin/log.c:1241
+#: builtin/log.c:1305
 msgid "--subject-prefix and -k are mutually exclusive."
 msgstr ""
 
-#: builtin/log.c:1249
+#: builtin/log.c:1313
 msgid "--name-only does not make sense"
 msgstr ""
 
-#: builtin/log.c:1251
+#: builtin/log.c:1315
 msgid "--name-status does not make sense"
 msgstr ""
 
-#: builtin/log.c:1253
+#: builtin/log.c:1317
 msgid "--check does not make sense"
 msgstr ""
 
-#: builtin/log.c:1276
+#: builtin/log.c:1340
 msgid "standard output, or directory, which one?"
 msgstr ""
 
-#: builtin/log.c:1278
+#: builtin/log.c:1342
 #, c-format
 msgid "Could not create directory '%s'"
 msgstr ""
 
-#: builtin/log.c:1431
+#: builtin/log.c:1490
 msgid "Failed to create output files"
 msgstr ""
 
-#: builtin/log.c:1480
+#: builtin/log.c:1539
 msgid "git cherry [-v] [<upstream> [<head> [<limit>]]]"
 msgstr ""
 
-#: builtin/log.c:1535
+#: builtin/log.c:1594
 #, c-format
 msgid ""
 "Could not find a tracked remote branch, please specify <upstream> manually.\n"
 msgstr ""
 
-#: builtin/log.c:1548 builtin/log.c:1550 builtin/log.c:1562
+#: builtin/log.c:1607 builtin/log.c:1609 builtin/log.c:1621
 #, c-format
 msgid "Unknown commit %s"
 msgstr ""
 
-#: builtin/ls-files.c:409
+#: builtin/ls-files.c:408
 msgid "git ls-files [options] [<file>...]"
 msgstr ""
 
-#: builtin/ls-files.c:466
+#: builtin/ls-files.c:465
 msgid "identify the file status with tags"
 msgstr ""
 
-#: builtin/ls-files.c:468
+#: builtin/ls-files.c:467
 msgid "use lowercase letters for 'assume unchanged' files"
 msgstr ""
 
-#: builtin/ls-files.c:470
+#: builtin/ls-files.c:469
 msgid "show cached files in the output (default)"
 msgstr ""
 
-#: builtin/ls-files.c:472
+#: builtin/ls-files.c:471
 msgid "show deleted files in the output"
 msgstr ""
 
-#: builtin/ls-files.c:474
+#: builtin/ls-files.c:473
 msgid "show modified files in the output"
 msgstr ""
 
-#: builtin/ls-files.c:476
+#: builtin/ls-files.c:475
 msgid "show other files in the output"
 msgstr ""
 
-#: builtin/ls-files.c:478
+#: builtin/ls-files.c:477
 msgid "show ignored files in the output"
 msgstr ""
 
-#: builtin/ls-files.c:481
+#: builtin/ls-files.c:480
 msgid "show staged contents' object name in the output"
 msgstr ""
 
-#: builtin/ls-files.c:483
+#: builtin/ls-files.c:482
 msgid "show files on the filesystem that need to be removed"
 msgstr ""
 
-#: builtin/ls-files.c:485
+#: builtin/ls-files.c:484
 msgid "show 'other' directories' name only"
 msgstr ""
 
-#: builtin/ls-files.c:488
+#: builtin/ls-files.c:487
 msgid "don't show empty directories"
 msgstr ""
 
-#: builtin/ls-files.c:491
+#: builtin/ls-files.c:490
 msgid "show unmerged files in the output"
 msgstr ""
 
-#: builtin/ls-files.c:493
+#: builtin/ls-files.c:492
 msgid "show resolve-undo information"
 msgstr ""
 
-#: builtin/ls-files.c:495
+#: builtin/ls-files.c:494
 msgid "skip files matching pattern"
 msgstr ""
 
-#: builtin/ls-files.c:498
+#: builtin/ls-files.c:497
 msgid "exclude patterns are read from <file>"
 msgstr ""
 
-#: builtin/ls-files.c:501
+#: builtin/ls-files.c:500
 msgid "read additional per-directory exclude patterns in <file>"
 msgstr ""
 
-#: builtin/ls-files.c:503
+#: builtin/ls-files.c:502
 msgid "add the standard git exclusions"
 msgstr ""
 
-#: builtin/ls-files.c:506
+#: builtin/ls-files.c:505
 msgid "make the output relative to the project top directory"
 msgstr ""
 
-#: builtin/ls-files.c:509
+#: builtin/ls-files.c:508
 msgid "if any <file> is not in the index, treat this as an error"
 msgstr ""
 
-#: builtin/ls-files.c:510
+#: builtin/ls-files.c:509
 msgid "tree-ish"
 msgstr ""
 
-#: builtin/ls-files.c:511
+#: builtin/ls-files.c:510
 msgid "pretend that paths removed since <tree-ish> are still present"
 msgstr ""
 
-#: builtin/ls-files.c:513
+#: builtin/ls-files.c:512
 msgid "show debugging data"
 msgstr ""
 
@@ -5766,167 +6143,167 @@
 msgid "git merge --abort"
 msgstr ""
 
-#: builtin/merge.c:90
+#: builtin/merge.c:98
 msgid "switch `m' requires a value"
 msgstr ""
 
-#: builtin/merge.c:127
+#: builtin/merge.c:135
 #, c-format
 msgid "Could not find merge strategy '%s'.\n"
 msgstr ""
 
-#: builtin/merge.c:128
+#: builtin/merge.c:136
 #, c-format
 msgid "Available strategies are:"
 msgstr ""
 
-#: builtin/merge.c:133
+#: builtin/merge.c:141
 #, c-format
 msgid "Available custom strategies are:"
 msgstr ""
 
-#: builtin/merge.c:183
+#: builtin/merge.c:198
 msgid "do not show a diffstat at the end of the merge"
 msgstr ""
 
-#: builtin/merge.c:186
+#: builtin/merge.c:201
 msgid "show a diffstat at the end of the merge"
 msgstr ""
 
-#: builtin/merge.c:187
+#: builtin/merge.c:202
 msgid "(synonym to --stat)"
 msgstr ""
 
-#: builtin/merge.c:189
+#: builtin/merge.c:204
 msgid "add (at most <n>) entries from shortlog to merge commit message"
 msgstr ""
 
-#: builtin/merge.c:192
+#: builtin/merge.c:207
 msgid "create a single commit instead of doing a merge"
 msgstr ""
 
-#: builtin/merge.c:194
+#: builtin/merge.c:209
 msgid "perform a commit if the merge succeeds (default)"
 msgstr ""
 
-#: builtin/merge.c:196
+#: builtin/merge.c:211
 msgid "edit message before committing"
 msgstr ""
 
-#: builtin/merge.c:198
+#: builtin/merge.c:212
 msgid "allow fast-forward (default)"
 msgstr ""
 
-#: builtin/merge.c:200
+#: builtin/merge.c:214
 msgid "abort if fast-forward is not possible"
 msgstr ""
 
-#: builtin/merge.c:203
+#: builtin/merge.c:218
 msgid "Verify that the named commit has a valid GPG signature"
 msgstr ""
 
-#: builtin/merge.c:204 builtin/notes.c:866 builtin/revert.c:112
+#: builtin/merge.c:219 builtin/notes.c:738 builtin/revert.c:114
 msgid "strategy"
 msgstr ""
 
-#: builtin/merge.c:205
+#: builtin/merge.c:220
 msgid "merge strategy to use"
 msgstr ""
 
-#: builtin/merge.c:206
+#: builtin/merge.c:221
 msgid "option=value"
 msgstr ""
 
-#: builtin/merge.c:207
+#: builtin/merge.c:222
 msgid "option for selected merge strategy"
 msgstr ""
 
-#: builtin/merge.c:209
+#: builtin/merge.c:224
 msgid "merge commit message (for a non-fast-forward merge)"
 msgstr ""
 
-#: builtin/merge.c:213
+#: builtin/merge.c:228
 msgid "abort the current in-progress merge"
 msgstr ""
 
-#: builtin/merge.c:242
+#: builtin/merge.c:257
 msgid "could not run stash."
 msgstr ""
 
-#: builtin/merge.c:247
+#: builtin/merge.c:262
 msgid "stash failed"
 msgstr ""
 
-#: builtin/merge.c:252
+#: builtin/merge.c:267
 #, c-format
 msgid "not a valid object: %s"
 msgstr ""
 
-#: builtin/merge.c:271 builtin/merge.c:288
+#: builtin/merge.c:286 builtin/merge.c:303
 msgid "read-tree failed"
 msgstr ""
 
-#: builtin/merge.c:318
+#: builtin/merge.c:333
 msgid " (nothing to squash)"
 msgstr ""
 
-#: builtin/merge.c:331
+#: builtin/merge.c:346
 #, c-format
 msgid "Squash commit -- not updating HEAD\n"
 msgstr ""
 
-#: builtin/merge.c:363
+#: builtin/merge.c:378
 msgid "Writing SQUASH_MSG"
 msgstr ""
 
-#: builtin/merge.c:365
+#: builtin/merge.c:380
 msgid "Finishing SQUASH_MSG"
 msgstr ""
 
-#: builtin/merge.c:388
+#: builtin/merge.c:403
 #, c-format
 msgid "No merge message -- not updating HEAD\n"
 msgstr ""
 
-#: builtin/merge.c:438
+#: builtin/merge.c:453
 #, c-format
 msgid "'%s' does not point to a commit"
 msgstr ""
 
-#: builtin/merge.c:550
+#: builtin/merge.c:565
 #, c-format
 msgid "Bad branch.%s.mergeoptions string: %s"
 msgstr ""
 
-#: builtin/merge.c:643
+#: builtin/merge.c:657
 msgid "git write-tree failed to write a tree"
 msgstr ""
 
-#: builtin/merge.c:671
-msgid "Not handling anything other than two heads merge."
-msgstr ""
-
 #: builtin/merge.c:685
-#, c-format
-msgid "Unknown option for merge-recursive: -X%s"
+msgid "Not handling anything other than two heads merge."
 msgstr ""
 
 #: builtin/merge.c:699
 #, c-format
+msgid "Unknown option for merge-recursive: -X%s"
+msgstr ""
+
+#: builtin/merge.c:713
+#, c-format
 msgid "unable to write %s"
 msgstr ""
 
-#: builtin/merge.c:788
+#: builtin/merge.c:802
 #, c-format
 msgid "Could not read from '%s'"
 msgstr ""
 
-#: builtin/merge.c:797
+#: builtin/merge.c:811
 #, c-format
 msgid "Not committing merge; use 'git commit' to complete the merge.\n"
 msgstr ""
 
-#: builtin/merge.c:803
+#: builtin/merge.c:817
 #, c-format
 msgid ""
 "Please enter a commit message to explain why this merge is necessary,\n"
@@ -5936,161 +6313,157 @@
 "the commit.\n"
 msgstr ""
 
-#: builtin/merge.c:827
+#: builtin/merge.c:841
 msgid "Empty commit message."
 msgstr ""
 
-#: builtin/merge.c:839
+#: builtin/merge.c:853
 #, c-format
 msgid "Wonderful.\n"
 msgstr ""
 
-#: builtin/merge.c:904
+#: builtin/merge.c:918
 #, c-format
 msgid "Automatic merge failed; fix conflicts and then commit the result.\n"
 msgstr ""
 
-#: builtin/merge.c:920
+#: builtin/merge.c:934
 #, c-format
 msgid "'%s' is not a commit"
 msgstr ""
 
-#: builtin/merge.c:961
+#: builtin/merge.c:975
 msgid "No current branch."
 msgstr ""
 
-#: builtin/merge.c:963
+#: builtin/merge.c:977
 msgid "No remote for the current branch."
 msgstr ""
 
-#: builtin/merge.c:965
+#: builtin/merge.c:979
 msgid "No default upstream defined for the current branch."
 msgstr ""
 
-#: builtin/merge.c:970
+#: builtin/merge.c:984
 #, c-format
-msgid "No remote tracking branch for %s from %s"
+msgid "No remote-tracking branch for %s from %s"
 msgstr ""
 
-#: builtin/merge.c:1057 builtin/merge.c:1214
-#, c-format
-msgid "%s - not something we can merge"
-msgstr ""
-
-#: builtin/merge.c:1125
+#: builtin/merge.c:1140
 msgid "There is no merge to abort (MERGE_HEAD missing)."
 msgstr ""
 
-#: builtin/merge.c:1141 git-pull.sh:31
+#: builtin/merge.c:1156 git-pull.sh:31
 msgid ""
 "You have not concluded your merge (MERGE_HEAD exists).\n"
 "Please, commit your changes before you can merge."
 msgstr ""
 
-#: builtin/merge.c:1144 git-pull.sh:34
+#: builtin/merge.c:1159 git-pull.sh:34
 msgid "You have not concluded your merge (MERGE_HEAD exists)."
 msgstr ""
 
-#: builtin/merge.c:1148
+#: builtin/merge.c:1163
 msgid ""
 "You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists).\n"
 "Please, commit your changes before you can merge."
 msgstr ""
 
-#: builtin/merge.c:1151
+#: builtin/merge.c:1166
 msgid "You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists)."
 msgstr ""
 
-#: builtin/merge.c:1160
+#: builtin/merge.c:1175
 msgid "You cannot combine --squash with --no-ff."
 msgstr ""
 
-#: builtin/merge.c:1165
-msgid "You cannot combine --no-ff with --ff-only."
-msgstr ""
-
-#: builtin/merge.c:1172
+#: builtin/merge.c:1184
 msgid "No commit specified and merge.defaultToUpstream not set."
 msgstr ""
 
-#: builtin/merge.c:1204
+#: builtin/merge.c:1216
 msgid "Can merge only exactly one commit into empty head"
 msgstr ""
 
-#: builtin/merge.c:1207
+#: builtin/merge.c:1219
 msgid "Squash commit into empty head not supported yet"
 msgstr ""
 
-#: builtin/merge.c:1209
+#: builtin/merge.c:1221
 msgid "Non-fast-forward commit does not make sense into an empty head"
 msgstr ""
 
-#: builtin/merge.c:1265
+#: builtin/merge.c:1226
+#, c-format
+msgid "%s - not something we can merge"
+msgstr ""
+
+#: builtin/merge.c:1277
 #, c-format
 msgid "Commit %s has an untrusted GPG signature, allegedly by %s."
 msgstr ""
 
-#: builtin/merge.c:1268
+#: builtin/merge.c:1280
 #, c-format
 msgid "Commit %s has a bad GPG signature allegedly by %s."
 msgstr ""
 
 #. 'N'
-#: builtin/merge.c:1271
+#: builtin/merge.c:1283
 #, c-format
 msgid "Commit %s does not have a GPG signature."
 msgstr ""
 
-#: builtin/merge.c:1274
+#: builtin/merge.c:1286
 #, c-format
 msgid "Commit %s has a good GPG signature by %s\n"
 msgstr ""
 
-#: builtin/merge.c:1358
+#: builtin/merge.c:1370
 #, c-format
 msgid "Updating %s..%s\n"
 msgstr ""
 
-#: builtin/merge.c:1397
+#: builtin/merge.c:1409
 #, c-format
 msgid "Trying really trivial in-index merge...\n"
 msgstr ""
 
-#: builtin/merge.c:1404
+#: builtin/merge.c:1416
 #, c-format
 msgid "Nope.\n"
 msgstr ""
 
-#: builtin/merge.c:1436
+#: builtin/merge.c:1448
 msgid "Not possible to fast-forward, aborting."
 msgstr ""
 
-#: builtin/merge.c:1459 builtin/merge.c:1538
+#: builtin/merge.c:1471 builtin/merge.c:1550
 #, c-format
 msgid "Rewinding the tree to pristine...\n"
 msgstr ""
 
-#: builtin/merge.c:1463
+#: builtin/merge.c:1475
 #, c-format
 msgid "Trying merge strategy %s...\n"
 msgstr ""
 
-#: builtin/merge.c:1529
+#: builtin/merge.c:1541
 #, c-format
 msgid "No merge strategy handled the merge.\n"
 msgstr ""
 
-#: builtin/merge.c:1531
+#: builtin/merge.c:1543
 #, c-format
 msgid "Merge with strategy %s failed.\n"
 msgstr ""
 
-#: builtin/merge.c:1540
+#: builtin/merge.c:1552
 #, c-format
 msgid "Using the %s to prepare resolving by hand.\n"
 msgstr ""
 
-#: builtin/merge.c:1552
+#: builtin/merge.c:1564
 #, c-format
 msgid "Automatic merge went well; stopped before committing as requested\n"
 msgstr ""
@@ -6255,369 +6628,352 @@
 msgid "renaming '%s' failed"
 msgstr ""
 
-#: builtin/name-rev.c:175
+#: builtin/name-rev.c:259
 msgid "git name-rev [options] <commit>..."
 msgstr ""
 
-#: builtin/name-rev.c:176
+#: builtin/name-rev.c:260
 msgid "git name-rev [options] --all"
 msgstr ""
 
-#: builtin/name-rev.c:177
+#: builtin/name-rev.c:261
 msgid "git name-rev [options] --stdin"
 msgstr ""
 
-#: builtin/name-rev.c:229
+#: builtin/name-rev.c:313
 msgid "print only names (no SHA-1)"
 msgstr ""
 
-#: builtin/name-rev.c:230
+#: builtin/name-rev.c:314
 msgid "only use tags to name the commits"
 msgstr ""
 
-#: builtin/name-rev.c:232
+#: builtin/name-rev.c:316
 msgid "only use refs matching <pattern>"
 msgstr ""
 
-#: builtin/name-rev.c:234
+#: builtin/name-rev.c:318
 msgid "list all commits reachable from all refs"
 msgstr ""
 
-#: builtin/name-rev.c:235
+#: builtin/name-rev.c:319
 msgid "read from stdin"
 msgstr ""
 
-#: builtin/name-rev.c:236
+#: builtin/name-rev.c:320
 msgid "allow to print `undefined` names"
 msgstr ""
 
-#: builtin/notes.c:26
+#: builtin/name-rev.c:326
+msgid "dereference tags in the input (internal use)"
+msgstr ""
+
+#: builtin/notes.c:24
 msgid "git notes [--ref <notes_ref>] [list [<object>]]"
 msgstr ""
 
-#: builtin/notes.c:27
+#: builtin/notes.c:25
 msgid ""
 "git notes [--ref <notes_ref>] add [-f] [-m <msg> | -F <file> | (-c | -C) "
 "<object>] [<object>]"
 msgstr ""
 
-#: builtin/notes.c:28
+#: builtin/notes.c:26
 msgid "git notes [--ref <notes_ref>] copy [-f] <from-object> <to-object>"
 msgstr ""
 
-#: builtin/notes.c:29
+#: builtin/notes.c:27
 msgid ""
 "git notes [--ref <notes_ref>] append [-m <msg> | -F <file> | (-c | -C) "
 "<object>] [<object>]"
 msgstr ""
 
-#: builtin/notes.c:30
+#: builtin/notes.c:28
 msgid "git notes [--ref <notes_ref>] edit [<object>]"
 msgstr ""
 
-#: builtin/notes.c:31
+#: builtin/notes.c:29
 msgid "git notes [--ref <notes_ref>] show [<object>]"
 msgstr ""
 
-#: builtin/notes.c:32
+#: builtin/notes.c:30
 msgid ""
 "git notes [--ref <notes_ref>] merge [-v | -q] [-s <strategy> ] <notes_ref>"
 msgstr ""
 
-#: builtin/notes.c:33
+#: builtin/notes.c:31
 msgid "git notes merge --commit [-v | -q]"
 msgstr ""
 
-#: builtin/notes.c:34
+#: builtin/notes.c:32
 msgid "git notes merge --abort [-v | -q]"
 msgstr ""
 
-#: builtin/notes.c:35
+#: builtin/notes.c:33
 msgid "git notes [--ref <notes_ref>] remove [<object>...]"
 msgstr ""
 
-#: builtin/notes.c:36
+#: builtin/notes.c:34
 msgid "git notes [--ref <notes_ref>] prune [-n | -v]"
 msgstr ""
 
-#: builtin/notes.c:37
+#: builtin/notes.c:35
 msgid "git notes [--ref <notes_ref>] get-ref"
 msgstr ""
 
-#: builtin/notes.c:42
+#: builtin/notes.c:40
 msgid "git notes [list [<object>]]"
 msgstr ""
 
-#: builtin/notes.c:47
+#: builtin/notes.c:45
 msgid "git notes add [<options>] [<object>]"
 msgstr ""
 
-#: builtin/notes.c:52
+#: builtin/notes.c:50
 msgid "git notes copy [<options>] <from-object> <to-object>"
 msgstr ""
 
-#: builtin/notes.c:53
+#: builtin/notes.c:51
 msgid "git notes copy --stdin [<from-object> <to-object>]..."
 msgstr ""
 
-#: builtin/notes.c:58
+#: builtin/notes.c:56
 msgid "git notes append [<options>] [<object>]"
 msgstr ""
 
-#: builtin/notes.c:63
+#: builtin/notes.c:61
 msgid "git notes edit [<object>]"
 msgstr ""
 
-#: builtin/notes.c:68
+#: builtin/notes.c:66
 msgid "git notes show [<object>]"
 msgstr ""
 
-#: builtin/notes.c:73
+#: builtin/notes.c:71
 msgid "git notes merge [<options>] <notes_ref>"
 msgstr ""
 
-#: builtin/notes.c:74
+#: builtin/notes.c:72
 msgid "git notes merge --commit [<options>]"
 msgstr ""
 
-#: builtin/notes.c:75
+#: builtin/notes.c:73
 msgid "git notes merge --abort [<options>]"
 msgstr ""
 
-#: builtin/notes.c:80
+#: builtin/notes.c:78
 msgid "git notes remove [<object>]"
 msgstr ""
 
-#: builtin/notes.c:85
+#: builtin/notes.c:83
 msgid "git notes prune [<options>]"
 msgstr ""
 
-#: builtin/notes.c:90
+#: builtin/notes.c:88
 msgid "git notes get-ref"
 msgstr ""
 
-#: builtin/notes.c:139
+#: builtin/notes.c:137
 #, c-format
 msgid "unable to start 'show' for object '%s'"
 msgstr ""
 
-#: builtin/notes.c:143
+#: builtin/notes.c:141
 msgid "could not read 'show' output"
 msgstr ""
 
-#: builtin/notes.c:151
+#: builtin/notes.c:149
 #, c-format
 msgid "failed to finish 'show' for object '%s'"
 msgstr ""
 
-#: builtin/notes.c:169 builtin/tag.c:341
+#: builtin/notes.c:167 builtin/tag.c:341
 #, c-format
 msgid "could not create file '%s'"
 msgstr ""
 
-#: builtin/notes.c:188
+#: builtin/notes.c:186
 msgid "Please supply the note contents using either -m or -F option"
 msgstr ""
 
-#: builtin/notes.c:209 builtin/notes.c:972
+#: builtin/notes.c:207 builtin/notes.c:844
 #, c-format
 msgid "Removing note for object %s\n"
 msgstr ""
 
-#: builtin/notes.c:214
+#: builtin/notes.c:212
 msgid "unable to write note object"
 msgstr ""
 
-#: builtin/notes.c:216
+#: builtin/notes.c:214
 #, c-format
 msgid "The note contents has been left in %s"
 msgstr ""
 
-#: builtin/notes.c:250 builtin/tag.c:540
+#: builtin/notes.c:248 builtin/tag.c:540
 #, c-format
 msgid "cannot read '%s'"
 msgstr ""
 
-#: builtin/notes.c:252 builtin/tag.c:543
+#: builtin/notes.c:250 builtin/tag.c:543
 #, c-format
 msgid "could not open or read '%s'"
 msgstr ""
 
-#: builtin/notes.c:271 builtin/notes.c:444 builtin/notes.c:446
-#: builtin/notes.c:506 builtin/notes.c:560 builtin/notes.c:643
-#: builtin/notes.c:648 builtin/notes.c:723 builtin/notes.c:765
-#: builtin/notes.c:967 builtin/tag.c:556
+#: builtin/notes.c:269 builtin/notes.c:316 builtin/notes.c:318
+#: builtin/notes.c:378 builtin/notes.c:432 builtin/notes.c:515
+#: builtin/notes.c:520 builtin/notes.c:595 builtin/notes.c:637
+#: builtin/notes.c:839 builtin/tag.c:556
 #, c-format
 msgid "Failed to resolve '%s' as a valid ref."
 msgstr ""
 
-#: builtin/notes.c:274
+#: builtin/notes.c:272
 #, c-format
 msgid "Failed to read object '%s'."
 msgstr ""
 
-#: builtin/notes.c:298
-msgid "Cannot commit uninitialized/unreferenced notes tree"
-msgstr ""
-
-#: builtin/notes.c:339
-#, c-format
-msgid "Bad notes.rewriteMode value: '%s'"
-msgstr ""
-
-#: builtin/notes.c:349
-#, c-format
-msgid "Refusing to rewrite notes in %s (outside of refs/notes/)"
-msgstr ""
-
-#. TRANSLATORS: The first %s is the name of the
-#. environment variable, the second %s is its value
-#: builtin/notes.c:376
-#, c-format
-msgid "Bad %s value: '%s'"
-msgstr ""
-
-#: builtin/notes.c:440
+#: builtin/notes.c:312
 #, c-format
 msgid "Malformed input line: '%s'."
 msgstr ""
 
-#: builtin/notes.c:455
+#: builtin/notes.c:327
 #, c-format
 msgid "Failed to copy notes from '%s' to '%s'"
 msgstr ""
 
-#: builtin/notes.c:499 builtin/notes.c:553 builtin/notes.c:626
-#: builtin/notes.c:638 builtin/notes.c:711 builtin/notes.c:758
-#: builtin/notes.c:1032
+#: builtin/notes.c:371 builtin/notes.c:425 builtin/notes.c:498
+#: builtin/notes.c:510 builtin/notes.c:583 builtin/notes.c:630
+#: builtin/notes.c:904
 msgid "too many parameters"
 msgstr ""
 
-#: builtin/notes.c:512 builtin/notes.c:771
+#: builtin/notes.c:384 builtin/notes.c:643
 #, c-format
 msgid "No note found for object %s."
 msgstr ""
 
-#: builtin/notes.c:534 builtin/notes.c:691
+#: builtin/notes.c:406 builtin/notes.c:563
 msgid "note contents as a string"
 msgstr ""
 
-#: builtin/notes.c:537 builtin/notes.c:694
+#: builtin/notes.c:409 builtin/notes.c:566
 msgid "note contents in a file"
 msgstr ""
 
-#: builtin/notes.c:539 builtin/notes.c:542 builtin/notes.c:696
-#: builtin/notes.c:699 builtin/tag.c:474
+#: builtin/notes.c:411 builtin/notes.c:414 builtin/notes.c:568
+#: builtin/notes.c:571 builtin/tag.c:474
 msgid "object"
 msgstr ""
 
-#: builtin/notes.c:540 builtin/notes.c:697
+#: builtin/notes.c:412 builtin/notes.c:569
 msgid "reuse and edit specified note object"
 msgstr ""
 
-#: builtin/notes.c:543 builtin/notes.c:700
+#: builtin/notes.c:415 builtin/notes.c:572
 msgid "reuse specified note object"
 msgstr ""
 
-#: builtin/notes.c:545 builtin/notes.c:613
+#: builtin/notes.c:417 builtin/notes.c:485
 msgid "replace existing notes"
 msgstr ""
 
-#: builtin/notes.c:579
+#: builtin/notes.c:451
 #, c-format
 msgid ""
 "Cannot add notes. Found existing notes for object %s. Use '-f' to overwrite "
 "existing notes"
 msgstr ""
 
-#: builtin/notes.c:584 builtin/notes.c:661
+#: builtin/notes.c:456 builtin/notes.c:533
 #, c-format
 msgid "Overwriting existing notes for object %s\n"
 msgstr ""
 
-#: builtin/notes.c:614
+#: builtin/notes.c:486
 msgid "read objects from stdin"
 msgstr ""
 
-#: builtin/notes.c:616
+#: builtin/notes.c:488
 msgid "load rewriting config for <command> (implies --stdin)"
 msgstr ""
 
-#: builtin/notes.c:634
+#: builtin/notes.c:506
 msgid "too few parameters"
 msgstr ""
 
-#: builtin/notes.c:655
+#: builtin/notes.c:527
 #, c-format
 msgid ""
 "Cannot copy notes. Found existing notes for object %s. Use '-f' to overwrite "
 "existing notes"
 msgstr ""
 
-#: builtin/notes.c:667
+#: builtin/notes.c:539
 #, c-format
 msgid "Missing notes on source object %s. Cannot copy."
 msgstr ""
 
-#: builtin/notes.c:716
+#: builtin/notes.c:588
 #, c-format
 msgid ""
 "The -m/-F/-c/-C options have been deprecated for the 'edit' subcommand.\n"
 "Please use 'git notes add -f -m/-F/-c/-C' instead.\n"
 msgstr ""
 
-#: builtin/notes.c:863
+#: builtin/notes.c:735
 msgid "General options"
 msgstr ""
 
-#: builtin/notes.c:865
+#: builtin/notes.c:737
 msgid "Merge options"
 msgstr ""
 
-#: builtin/notes.c:867
+#: builtin/notes.c:739
 msgid ""
 "resolve notes conflicts using the given strategy (manual/ours/theirs/union/"
 "cat_sort_uniq)"
 msgstr ""
 
-#: builtin/notes.c:869
+#: builtin/notes.c:741
 msgid "Committing unmerged notes"
 msgstr ""
 
-#: builtin/notes.c:871
+#: builtin/notes.c:743
 msgid "finalize notes merge by committing unmerged notes"
 msgstr ""
 
-#: builtin/notes.c:873
+#: builtin/notes.c:745
 msgid "Aborting notes merge resolution"
 msgstr ""
 
-#: builtin/notes.c:875
+#: builtin/notes.c:747
 msgid "abort notes merge"
 msgstr ""
 
-#: builtin/notes.c:970
+#: builtin/notes.c:842
 #, c-format
 msgid "Object %s has no note\n"
 msgstr ""
 
-#: builtin/notes.c:982
+#: builtin/notes.c:854
 msgid "attempt to remove non-existent note is not an error"
 msgstr ""
 
-#: builtin/notes.c:985
+#: builtin/notes.c:857
 msgid "read object names from the standard input"
 msgstr ""
 
-#: builtin/notes.c:1066
+#: builtin/notes.c:938
 msgid "notes_ref"
 msgstr ""
 
-#: builtin/notes.c:1067
+#: builtin/notes.c:939
 msgid "use notes from <notes_ref>"
 msgstr ""
 
-#: builtin/notes.c:1102 builtin/remote.c:1598
+#: builtin/notes.c:974 builtin/remote.c:1598
 #, c-format
 msgid "Unknown subcommand: %s"
 msgstr ""
@@ -6840,7 +7196,7 @@
 "%s"
 msgstr ""
 
-#: builtin/push.c:121
+#: builtin/push.c:117
 #, c-format
 msgid ""
 "You are not currently on a branch.\n"
@@ -6850,7 +7206,7 @@
 "    git push %s HEAD:<name-of-remote-branch>\n"
 msgstr ""
 
-#: builtin/push.c:128
+#: builtin/push.c:131
 #, c-format
 msgid ""
 "The current branch %s has no upstream branch.\n"
@@ -6859,12 +7215,12 @@
 "    git push --set-upstream %s %s\n"
 msgstr ""
 
-#: builtin/push.c:136
+#: builtin/push.c:139
 #, c-format
 msgid "The current branch %s has multiple upstream branches, refusing to push."
 msgstr ""
 
-#: builtin/push.c:139
+#: builtin/push.c:142
 #, c-format
 msgid ""
 "You are pushing to remote '%s', which is not the upstream of\n"
@@ -6872,7 +7228,7 @@
 "to update which remote branch."
 msgstr ""
 
-#: builtin/push.c:151
+#: builtin/push.c:165
 msgid ""
 "push.default is unset; its implicit value is changing in\n"
 "Git 2.0 from 'matching' to 'simple'. To squelch this message\n"
@@ -6890,20 +7246,20 @@
 "'current' instead of 'simple' if you sometimes use older versions of Git)"
 msgstr ""
 
-#: builtin/push.c:199
+#: builtin/push.c:225
 msgid ""
 "You didn't specify any refspecs to push, and push.default is \"nothing\"."
 msgstr ""
 
-#: builtin/push.c:206
+#: builtin/push.c:232
 msgid ""
 "Updates were rejected because the tip of your current branch is behind\n"
-"its remote counterpart. Merge the remote changes (e.g. 'git pull')\n"
-"before pushing again.\n"
+"its remote counterpart. Integrate the remote changes (e.g.\n"
+"'git pull ...') before pushing again.\n"
 "See the 'Note about fast-forwards' in 'git push --help' for details."
 msgstr ""
 
-#: builtin/push.c:212
+#: builtin/push.c:238
 msgid ""
 "Updates were rejected because a pushed branch tip is behind its remote\n"
 "counterpart. If you did not intend to push that branch, you may want to\n"
@@ -6911,50 +7267,50 @@
 "to 'simple', 'current' or 'upstream' to push only the current branch."
 msgstr ""
 
-#: builtin/push.c:218
+#: builtin/push.c:244
 msgid ""
 "Updates were rejected because a pushed branch tip is behind its remote\n"
-"counterpart. Check out this branch and merge the remote changes\n"
-"(e.g. 'git pull') before pushing again.\n"
+"counterpart. Check out this branch and integrate the remote changes\n"
+"(e.g. 'git pull ...') before pushing again.\n"
 "See the 'Note about fast-forwards' in 'git push --help' for details."
 msgstr ""
 
-#: builtin/push.c:224
+#: builtin/push.c:250
 msgid ""
 "Updates were rejected because the remote contains work that you do\n"
 "not have locally. This is usually caused by another repository pushing\n"
-"to the same ref. You may want to first merge the remote changes (e.g.,\n"
-"'git pull') before pushing again.\n"
+"to the same ref. You may want to first integrate the remote changes\n"
+"(e.g., 'git pull ...') before pushing again.\n"
 "See the 'Note about fast-forwards' in 'git push --help' for details."
 msgstr ""
 
-#: builtin/push.c:231
+#: builtin/push.c:257
 msgid "Updates were rejected because the tag already exists in the remote."
 msgstr ""
 
-#: builtin/push.c:234
+#: builtin/push.c:260
 msgid ""
 "You cannot update a remote ref that points at a non-commit object,\n"
 "or update a remote ref to make it point at a non-commit object,\n"
 "without using the '--force' option.\n"
 msgstr ""
 
-#: builtin/push.c:294
+#: builtin/push.c:320
 #, c-format
 msgid "Pushing to %s\n"
 msgstr ""
 
-#: builtin/push.c:298
+#: builtin/push.c:324
 #, c-format
 msgid "failed to push some refs to '%s'"
 msgstr ""
 
-#: builtin/push.c:331
+#: builtin/push.c:357
 #, c-format
 msgid "bad repository '%s'"
 msgstr ""
 
-#: builtin/push.c:332
+#: builtin/push.c:358
 msgid ""
 "No configured push destination.\n"
 "Either specify the URL from the command-line or configure a remote "
@@ -6967,87 +7323,87 @@
 "    git push <name>\n"
 msgstr ""
 
-#: builtin/push.c:347
+#: builtin/push.c:373
 msgid "--all and --tags are incompatible"
 msgstr ""
 
-#: builtin/push.c:348
+#: builtin/push.c:374
 msgid "--all can't be combined with refspecs"
 msgstr ""
 
-#: builtin/push.c:353
+#: builtin/push.c:379
 msgid "--mirror and --tags are incompatible"
 msgstr ""
 
-#: builtin/push.c:354
+#: builtin/push.c:380
 msgid "--mirror can't be combined with refspecs"
 msgstr ""
 
-#: builtin/push.c:359
+#: builtin/push.c:385
 msgid "--all and --mirror are incompatible"
 msgstr ""
 
-#: builtin/push.c:419
+#: builtin/push.c:445
 msgid "repository"
 msgstr ""
 
-#: builtin/push.c:420
+#: builtin/push.c:446
 msgid "push all refs"
 msgstr ""
 
-#: builtin/push.c:421
+#: builtin/push.c:447
 msgid "mirror all refs"
 msgstr ""
 
-#: builtin/push.c:423
+#: builtin/push.c:449
 msgid "delete refs"
 msgstr ""
 
-#: builtin/push.c:424
+#: builtin/push.c:450
 msgid "push tags (can't be used with --all or --mirror)"
 msgstr ""
 
-#: builtin/push.c:427
+#: builtin/push.c:453
 msgid "force updates"
 msgstr ""
 
-#: builtin/push.c:428
+#: builtin/push.c:454
 msgid "check"
 msgstr ""
 
-#: builtin/push.c:429
+#: builtin/push.c:455
 msgid "control recursive pushing of submodules"
 msgstr ""
 
-#: builtin/push.c:431
+#: builtin/push.c:457
 msgid "use thin pack"
 msgstr ""
 
-#: builtin/push.c:432 builtin/push.c:433
+#: builtin/push.c:458 builtin/push.c:459
 msgid "receive pack program"
 msgstr ""
 
-#: builtin/push.c:434
+#: builtin/push.c:460
 msgid "set upstream for git pull/status"
 msgstr ""
 
-#: builtin/push.c:437
+#: builtin/push.c:463
 msgid "prune locally removed refs"
 msgstr ""
 
-#: builtin/push.c:439
+#: builtin/push.c:465
 msgid "bypass pre-push hook"
 msgstr ""
 
-#: builtin/push.c:440
+#: builtin/push.c:466
 msgid "push missing but relevant tags"
 msgstr ""
 
-#: builtin/push.c:450
+#: builtin/push.c:476
 msgid "--delete is incompatible with --all, --mirror and --tags"
 msgstr ""
 
-#: builtin/push.c:452
+#: builtin/push.c:478
 msgid "--delete doesn't make sense without any refs"
 msgstr ""
 
@@ -7058,70 +7414,80 @@
 "index-output=<file>] (--empty | <tree-ish1> [<tree-ish2> [<tree-ish3>]])"
 msgstr ""
 
-#: builtin/read-tree.c:108
+#: builtin/read-tree.c:109
 msgid "write resulting index to <file>"
 msgstr ""
 
-#: builtin/read-tree.c:111
+#: builtin/read-tree.c:112
 msgid "only empty the index"
 msgstr ""
 
-#: builtin/read-tree.c:113
+#: builtin/read-tree.c:114
 msgid "Merging"
 msgstr ""
 
-#: builtin/read-tree.c:115
+#: builtin/read-tree.c:116
 msgid "perform a merge in addition to a read"
 msgstr ""
 
-#: builtin/read-tree.c:117
+#: builtin/read-tree.c:118
 msgid "3-way merge if no file level merging required"
 msgstr ""
 
-#: builtin/read-tree.c:119
+#: builtin/read-tree.c:120
 msgid "3-way merge in presence of adds and removes"
 msgstr ""
 
-#: builtin/read-tree.c:121
+#: builtin/read-tree.c:122
 msgid "same as -m, but discard unmerged entries"
 msgstr ""
 
-#: builtin/read-tree.c:122
+#: builtin/read-tree.c:123
 msgid "<subdirectory>/"
 msgstr ""
 
-#: builtin/read-tree.c:123
+#: builtin/read-tree.c:124
 msgid "read the tree into the index under <subdirectory>/"
 msgstr ""
 
-#: builtin/read-tree.c:126
+#: builtin/read-tree.c:127
 msgid "update working tree with merge result"
 msgstr ""
 
-#: builtin/read-tree.c:128
+#: builtin/read-tree.c:129
 msgid "gitignore"
 msgstr ""
 
-#: builtin/read-tree.c:129
+#: builtin/read-tree.c:130
 msgid "allow explicitly ignored files to be overwritten"
 msgstr ""
 
-#: builtin/read-tree.c:132
+#: builtin/read-tree.c:133
 msgid "don't check the working tree after merging"
 msgstr ""
 
-#: builtin/read-tree.c:133
+#: builtin/read-tree.c:134
 msgid "don't update the index or the work tree"
 msgstr ""
 
-#: builtin/read-tree.c:135
+#: builtin/read-tree.c:136
 msgid "skip applying sparse checkout filter"
 msgstr ""
 
-#: builtin/read-tree.c:137
+#: builtin/read-tree.c:138
 msgid "debug unpack-trees"
 msgstr ""
 
+#: builtin/reflog.c:500
+#, c-format
+msgid "%s' for '%s' is not a valid timestamp"
+msgstr ""
+
+#: builtin/reflog.c:616 builtin/reflog.c:621
+#, c-format
+msgid "'%s' is not a valid timestamp"
+msgstr ""
+
 #: builtin/remote.c:11
 msgid "git remote [-v | --verbose]"
 msgstr ""
@@ -7682,95 +8048,95 @@
 msgid "Failed to find tree of %s."
 msgstr ""
 
-#: builtin/reset.c:98
+#: builtin/reset.c:99
 #, c-format
 msgid "HEAD is now at %s"
 msgstr ""
 
-#: builtin/reset.c:169
+#: builtin/reset.c:172
 #, c-format
 msgid "Cannot do a %s reset in the middle of a merge."
 msgstr ""
 
-#: builtin/reset.c:248
+#: builtin/reset.c:251
 msgid "be quiet, only report errors"
 msgstr ""
 
-#: builtin/reset.c:250
+#: builtin/reset.c:253
 msgid "reset HEAD and index"
 msgstr ""
 
-#: builtin/reset.c:251
+#: builtin/reset.c:254
 msgid "reset only HEAD"
 msgstr ""
 
-#: builtin/reset.c:253 builtin/reset.c:255
+#: builtin/reset.c:256 builtin/reset.c:258
 msgid "reset HEAD, index and working tree"
 msgstr ""
 
-#: builtin/reset.c:257
+#: builtin/reset.c:260
 msgid "reset HEAD but keep local changes"
 msgstr ""
 
-#: builtin/reset.c:275
+#: builtin/reset.c:278
 #, c-format
 msgid "Failed to resolve '%s' as a valid revision."
 msgstr ""
 
-#: builtin/reset.c:278 builtin/reset.c:286
+#: builtin/reset.c:281 builtin/reset.c:289
 #, c-format
 msgid "Could not parse object '%s'."
 msgstr ""
 
-#: builtin/reset.c:283
+#: builtin/reset.c:286
 #, c-format
 msgid "Failed to resolve '%s' as a valid tree."
 msgstr ""
 
-#: builtin/reset.c:292
+#: builtin/reset.c:295
 msgid "--patch is incompatible with --{hard,mixed,soft}"
 msgstr ""
 
-#: builtin/reset.c:301
+#: builtin/reset.c:304
 msgid "--mixed with paths is deprecated; use 'git reset -- <paths>' instead."
 msgstr ""
 
-#: builtin/reset.c:303
+#: builtin/reset.c:306
 #, c-format
 msgid "Cannot do %s reset with paths."
 msgstr ""
 
-#: builtin/reset.c:313
+#: builtin/reset.c:316
 #, c-format
 msgid "%s reset is not allowed in a bare repository"
 msgstr ""
 
-#: builtin/reset.c:333
+#: builtin/reset.c:336
 #, c-format
 msgid "Could not reset index file to revision '%s'."
 msgstr ""
 
-#: builtin/reset.c:339
+#: builtin/reset.c:342
 msgid "Unstaged changes after reset:"
 msgstr ""
 
-#: builtin/reset.c:344
+#: builtin/reset.c:347
 msgid "Could not write new index file."
 msgstr ""
 
-#: builtin/rev-parse.c:339
+#: builtin/rev-parse.c:345
 msgid "git rev-parse --parseopt [options] -- [<args>...]"
 msgstr ""
 
-#: builtin/rev-parse.c:344
+#: builtin/rev-parse.c:350
 msgid "keep the `--` passed as an arg"
 msgstr ""
 
-#: builtin/rev-parse.c:346
+#: builtin/rev-parse.c:352
 msgid "stop parsing after the first non-option argument"
 msgstr ""
 
-#: builtin/rev-parse.c:464
+#: builtin/rev-parse.c:470
 msgid ""
 "git rev-parse --parseopt [options] -- [<args>...]\n"
 "   or: git rev-parse --sq-quote [<arg>...]\n"
@@ -7780,7 +8146,7 @@
 msgstr ""
 
 #: builtin/revert.c:22
-msgid "git revert [options] <commit-ish>"
+msgid "git revert [options] <commit-ish>..."
 msgstr ""
 
 #: builtin/revert.c:23
@@ -7788,174 +8154,196 @@
 msgstr ""
 
 #: builtin/revert.c:28
-msgid "git cherry-pick [options] <commit-ish>"
+msgid "git cherry-pick [options] <commit-ish>..."
 msgstr ""
 
 #: builtin/revert.c:29
 msgid "git cherry-pick <subcommand>"
 msgstr ""
 
-#: builtin/revert.c:70 builtin/revert.c:92
+#: builtin/revert.c:71 builtin/revert.c:94
 #, c-format
 msgid "%s: %s cannot be used with %s"
 msgstr ""
 
-#: builtin/revert.c:103
+#: builtin/revert.c:105
 msgid "end revert or cherry-pick sequence"
 msgstr ""
 
-#: builtin/revert.c:104
+#: builtin/revert.c:106
 msgid "resume revert or cherry-pick sequence"
 msgstr ""
 
-#: builtin/revert.c:105
+#: builtin/revert.c:107
 msgid "cancel revert or cherry-pick sequence"
 msgstr ""
 
-#: builtin/revert.c:106
+#: builtin/revert.c:108
 msgid "don't automatically commit"
 msgstr ""
 
-#: builtin/revert.c:107
+#: builtin/revert.c:109
 msgid "edit the commit message"
 msgstr ""
 
-#: builtin/revert.c:110
+#: builtin/revert.c:112
 msgid "parent number"
 msgstr ""
 
-#: builtin/revert.c:112
+#: builtin/revert.c:114
 msgid "merge strategy"
 msgstr ""
 
-#: builtin/revert.c:113
+#: builtin/revert.c:115
 msgid "option"
 msgstr ""
 
-#: builtin/revert.c:114
+#: builtin/revert.c:116
 msgid "option for merge strategy"
 msgstr ""
 
-#: builtin/revert.c:125
+#: builtin/revert.c:127
 msgid "append commit name"
 msgstr ""
 
-#: builtin/revert.c:126
+#: builtin/revert.c:128
 msgid "allow fast-forward"
 msgstr ""
 
-#: builtin/revert.c:127
+#: builtin/revert.c:129
 msgid "preserve initially empty commits"
 msgstr ""
 
-#: builtin/revert.c:128
+#: builtin/revert.c:130
 msgid "allow commits with empty messages"
 msgstr ""
 
-#: builtin/revert.c:129
+#: builtin/revert.c:131
 msgid "keep redundant, empty commits"
 msgstr ""
 
-#: builtin/revert.c:133
+#: builtin/revert.c:135
 msgid "program error"
 msgstr ""
 
-#: builtin/revert.c:223
+#: builtin/revert.c:225
 msgid "revert failed"
 msgstr ""
 
-#: builtin/revert.c:238
+#: builtin/revert.c:240
 msgid "cherry-pick failed"
 msgstr ""
 
-#: builtin/rm.c:15
+#: builtin/rm.c:16
 msgid "git rm [options] [--] <file>..."
 msgstr ""
 
-#: builtin/rm.c:64 builtin/rm.c:186
-#, c-format
+#: builtin/rm.c:64
 msgid ""
-"submodule '%s' (or one of its nested submodules) uses a .git directory\n"
+"the following submodule (or one of its nested submodules)\n"
+"uses a .git directory:"
+msgid_plural ""
+"the following submodules (or one of its nested submodules)\n"
+"use a .git directory:"
+msgstr[0] ""
+msgstr[1] ""
+
+#: builtin/rm.c:70
+msgid ""
+"\n"
 "(use 'rm -rf' if you really want to remove it including all of its history)"
 msgstr ""
 
-#: builtin/rm.c:174
-#, c-format
+#: builtin/rm.c:230
 msgid ""
-"'%s' has staged content different from both the file and the HEAD\n"
+"the following file has staged content different from both the\n"
+"file and the HEAD:"
+msgid_plural ""
+"the following files have staged content different from both the\n"
+"file and the HEAD:"
+msgstr[0] ""
+msgstr[1] ""
+
+#: builtin/rm.c:235
+msgid ""
+"\n"
 "(use -f to force removal)"
 msgstr ""
 
-#: builtin/rm.c:180
-#, c-format
+#: builtin/rm.c:239
+msgid "the following file has changes staged in the index:"
+msgid_plural "the following files have changes staged in the index:"
+msgstr[0] ""
+msgstr[1] ""
+
+#: builtin/rm.c:243 builtin/rm.c:254
 msgid ""
-"'%s' has changes staged in the index\n"
+"\n"
 "(use --cached to keep the file, or -f to force removal)"
 msgstr ""
 
-#: builtin/rm.c:191
-#, c-format
-msgid ""
-"'%s' has local modifications\n"
-"(use --cached to keep the file, or -f to force removal)"
-msgstr ""
+#: builtin/rm.c:251
+msgid "the following file has local modifications:"
+msgid_plural "the following files have local modifications:"
+msgstr[0] ""
+msgstr[1] ""
 
-#: builtin/rm.c:207
+#: builtin/rm.c:269
 msgid "do not list removed files"
 msgstr ""
 
-#: builtin/rm.c:208
+#: builtin/rm.c:270
 msgid "only remove from the index"
 msgstr ""
 
-#: builtin/rm.c:209
+#: builtin/rm.c:271
 msgid "override the up-to-date check"
 msgstr ""
 
-#: builtin/rm.c:210
+#: builtin/rm.c:272
 msgid "allow recursive removal"
 msgstr ""
 
-#: builtin/rm.c:212
+#: builtin/rm.c:274
 msgid "exit with a zero status even if nothing matched"
 msgstr ""
 
-#: builtin/rm.c:283
+#: builtin/rm.c:345
 #, c-format
 msgid "not removing '%s' recursively without -r"
 msgstr ""
 
-#: builtin/rm.c:322
+#: builtin/rm.c:384
 #, c-format
 msgid "git rm: unable to remove %s"
 msgstr ""
 
 #: builtin/shortlog.c:13
-msgid "git shortlog [-n] [-s] [-e] [-w] [rev-opts] [--] [<commit-id>... ]"
+msgid "git shortlog [<options>] [<revision range>] [[--] [<path>...]]"
 msgstr ""
 
-#: builtin/shortlog.c:133
+#: builtin/shortlog.c:131
 #, c-format
 msgid "Missing author: %s"
 msgstr ""
 
-#: builtin/shortlog.c:229
+#: builtin/shortlog.c:228
 msgid "sort output according to the number of commits per author"
 msgstr ""
 
-#: builtin/shortlog.c:231
+#: builtin/shortlog.c:230
 msgid "Suppress commit descriptions, only provides commit count"
 msgstr ""
 
-#: builtin/shortlog.c:233
+#: builtin/shortlog.c:232
 msgid "Show the email address of each author"
 msgstr ""
 
-#: builtin/shortlog.c:234
+#: builtin/shortlog.c:233
 msgid "w[,i1[,i2]]"
 msgstr ""
 
-#: builtin/shortlog.c:235
+#: builtin/shortlog.c:234
 msgid "Linewrap output"
 msgstr ""
 
@@ -7971,47 +8359,47 @@
 msgid "git show-branch (-g|--reflog)[=<n>[,<base>]] [--list] [<ref>]"
 msgstr ""
 
-#: builtin/show-branch.c:651
+#: builtin/show-branch.c:650
 msgid "show remote-tracking and local branches"
 msgstr ""
 
-#: builtin/show-branch.c:653
+#: builtin/show-branch.c:652
 msgid "show remote-tracking branches"
 msgstr ""
 
-#: builtin/show-branch.c:655
+#: builtin/show-branch.c:654
 msgid "color '*!+-' corresponding to the branch"
 msgstr ""
 
-#: builtin/show-branch.c:657
+#: builtin/show-branch.c:656
 msgid "show <n> more commits after the common ancestor"
 msgstr ""
 
-#: builtin/show-branch.c:659
+#: builtin/show-branch.c:658
 msgid "synonym to more=-1"
 msgstr ""
 
-#: builtin/show-branch.c:660
+#: builtin/show-branch.c:659
 msgid "suppress naming strings"
 msgstr ""
 
-#: builtin/show-branch.c:662
+#: builtin/show-branch.c:661
 msgid "include the current branch"
 msgstr ""
 
-#: builtin/show-branch.c:664
+#: builtin/show-branch.c:663
 msgid "name commits with their object names"
 msgstr ""
 
-#: builtin/show-branch.c:666
+#: builtin/show-branch.c:665
 msgid "show possible merge bases"
 msgstr ""
 
-#: builtin/show-branch.c:668
+#: builtin/show-branch.c:667
 msgid "show refs unreachable from any other ref"
 msgstr ""
 
-#: builtin/show-branch.c:670
+#: builtin/show-branch.c:669
 msgid "show commits in topological order"
 msgstr ""
 
@@ -8024,14 +8412,14 @@
 msgstr ""
 
 #: builtin/show-branch.c:676
-msgid "show commits where no parent comes before its children"
-msgstr ""
-
-#: builtin/show-branch.c:678
-msgid "<n>[,<base>]"
+msgid "topologically sort, maintaining date order where possible"
 msgstr ""
 
 #: builtin/show-branch.c:679
+msgid "<n>[,<base>]"
+msgstr ""
+
+#: builtin/show-branch.c:680
 msgid "show <n> most recent ref-log entries starting at base"
 msgstr ""
 
@@ -8045,35 +8433,35 @@
 msgid "git show-ref --exclude-existing[=pattern] < ref-list"
 msgstr ""
 
-#: builtin/show-ref.c:165
+#: builtin/show-ref.c:168
 msgid "only show tags (can be combined with heads)"
 msgstr ""
 
-#: builtin/show-ref.c:166
+#: builtin/show-ref.c:169
 msgid "only show heads (can be combined with tags)"
 msgstr ""
 
-#: builtin/show-ref.c:167
+#: builtin/show-ref.c:170
 msgid "stricter reference checking, requires exact ref path"
 msgstr ""
 
-#: builtin/show-ref.c:170 builtin/show-ref.c:172
-msgid "show the HEAD reference"
+#: builtin/show-ref.c:173 builtin/show-ref.c:176
+msgid "show the HEAD reference, even if it would be filtered out"
 msgstr ""
 
-#: builtin/show-ref.c:174
+#: builtin/show-ref.c:178
 msgid "dereference tags into object IDs"
 msgstr ""
 
-#: builtin/show-ref.c:176
+#: builtin/show-ref.c:180
 msgid "only show SHA1 hash using <n> digits"
 msgstr ""
 
-#: builtin/show-ref.c:180
+#: builtin/show-ref.c:184
 msgid "do not print results to stdout (useful with --verify)"
 msgstr ""
 
-#: builtin/show-ref.c:182
+#: builtin/show-ref.c:186
 msgid "show refs from stdin that aren't in local repository"
 msgstr ""
 
@@ -8477,23 +8865,30 @@
 msgid "only useful for debugging"
 msgstr ""
 
-#: git.c:16
-msgid "See 'git help <command>' for more information on a specific command."
+#: git.c:17
+msgid ""
+"'git help -a' and 'git help -g' lists available subcommands and some\n"
+"concept guides. See 'git help <command>' or 'git help <concept>'\n"
+"to read about a specific subcommand or concept."
 msgstr ""
 
-#: parse-options.h:156
+#: parse-options.h:144
+msgid "expiry date"
+msgstr ""
+
+#: parse-options.h:159
 msgid "no-op (backward compatibility)"
 msgstr ""
 
-#: parse-options.h:232
+#: parse-options.h:236
 msgid "be more verbose"
 msgstr ""
 
-#: parse-options.h:234
+#: parse-options.h:238
 msgid "be more quiet"
 msgstr ""
 
-#: parse-options.h:240
+#: parse-options.h:244
 msgid "use <n> digits to display SHA-1s"
 msgstr ""
 
@@ -8550,7 +8945,7 @@
 msgstr ""
 
 #: common-cmds.h:21
-msgid "Fetch from and merge with another repository or a local branch"
+msgid "Fetch from and integrate with another repository or a local branch"
 msgstr ""
 
 #: common-cmds.h:22
@@ -8594,7 +8989,7 @@
 #: git-am.sh:105
 #, sh-format
 msgid ""
-"When you have resolved this problem, run \"$cmdline --resolved\".\n"
+"When you have resolved this problem, run \"$cmdline --continue\".\n"
 "If you prefer to skip this patch, run \"$cmdline --skip\" instead.\n"
 "To restore the original branch and stop patching, run \"$cmdline --abort\"."
 msgstr ""
@@ -8644,25 +9039,32 @@
 "it will be removed. Please do not use it anymore."
 msgstr ""
 
-#: git-am.sh:477
+#: git-am.sh:479
 #, sh-format
 msgid "previous rebase directory $dotest still exists but mbox given."
 msgstr ""
 
-#: git-am.sh:482
+#: git-am.sh:484
 msgid "Please make up your mind. --skip or --abort?"
 msgstr ""
 
-#: git-am.sh:509
+#: git-am.sh:520
+#, sh-format
+msgid ""
+"Stray $dotest directory found.\n"
+"Use \"git am --abort\" to remove it."
+msgstr ""
+
+#: git-am.sh:528
 msgid "Resolve operation not in progress, we are not resuming."
 msgstr ""
 
-#: git-am.sh:575
+#: git-am.sh:594
 #, sh-format
 msgid "Dirty index: cannot apply patches (dirty: $files)"
 msgstr ""
 
-#: git-am.sh:679
+#: git-am.sh:698
 #, sh-format
 msgid ""
 "Patch is empty.  Was it split wrong?\n"
@@ -8670,60 +9072,60 @@
 "To restore the original branch and stop patching run \"$cmdline --abort\"."
 msgstr ""
 
-#: git-am.sh:706
+#: git-am.sh:725
 msgid "Patch does not have a valid e-mail address."
 msgstr ""
 
-#: git-am.sh:753
+#: git-am.sh:772
 msgid "cannot be interactive without stdin connected to a terminal."
 msgstr ""
 
-#: git-am.sh:757
+#: git-am.sh:776
 msgid "Commit Body is:"
 msgstr ""
 
 #. TRANSLATORS: Make sure to include [y], [n], [e], [v] and [a]
 #. in your translation. The program will only accept English
 #. input at this point.
-#: git-am.sh:764
+#: git-am.sh:783
 msgid "Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all "
 msgstr ""
 
-#: git-am.sh:800
+#: git-am.sh:819
 #, sh-format
 msgid "Applying: $FIRSTLINE"
 msgstr ""
 
-#: git-am.sh:821
+#: git-am.sh:840
 msgid ""
 "No changes - did you forget to use 'git add'?\n"
 "If there is nothing left to stage, chances are that something else\n"
 "already introduced the same changes; you might want to skip this patch."
 msgstr ""
 
-#: git-am.sh:829
+#: git-am.sh:848
 msgid ""
 "You still have unmerged paths in your index\n"
 "did you forget to use 'git add'?"
 msgstr ""
 
-#: git-am.sh:845
+#: git-am.sh:864
 msgid "No changes -- Patch already applied."
 msgstr ""
 
-#: git-am.sh:855
+#: git-am.sh:874
 #, sh-format
 msgid "Patch failed at $msgnum $FIRSTLINE"
 msgstr ""
 
-#: git-am.sh:858
+#: git-am.sh:877
 #, sh-format
 msgid ""
 "The copy of the patch that failed is found in:\n"
 "   $dotest/patch"
 msgstr ""
 
-#: git-am.sh:876
+#: git-am.sh:895
 msgid "applying to an empty history"
 msgstr ""
 
@@ -8815,59 +9217,59 @@
 "(You can use \"git bisect bad\" and \"git bisect good\" for that.)"
 msgstr ""
 
-#: git-bisect.sh:347 git-bisect.sh:474
+#: git-bisect.sh:363 git-bisect.sh:490
 msgid "We are not bisecting."
 msgstr ""
 
-#: git-bisect.sh:354
+#: git-bisect.sh:370
 #, sh-format
 msgid "'$invalid' is not a valid commit"
 msgstr ""
 
-#: git-bisect.sh:363
+#: git-bisect.sh:379
 #, sh-format
 msgid ""
 "Could not check out original HEAD '$branch'.\n"
 "Try 'git bisect reset <commit>'."
 msgstr ""
 
-#: git-bisect.sh:390
+#: git-bisect.sh:406
 msgid "No logfile given"
 msgstr ""
 
-#: git-bisect.sh:391
+#: git-bisect.sh:407
 #, sh-format
 msgid "cannot read $file for replaying"
 msgstr ""
 
-#: git-bisect.sh:408
+#: git-bisect.sh:424
 msgid "?? what are you talking about?"
 msgstr ""
 
-#: git-bisect.sh:420
+#: git-bisect.sh:436
 #, sh-format
 msgid "running $command"
 msgstr ""
 
-#: git-bisect.sh:427
+#: git-bisect.sh:443
 #, sh-format
 msgid ""
 "bisect run failed:\n"
 "exit code $res from '$command' is < 0 or >= 128"
 msgstr ""
 
-#: git-bisect.sh:453
+#: git-bisect.sh:469
 msgid "bisect run cannot continue any more"
 msgstr ""
 
-#: git-bisect.sh:459
+#: git-bisect.sh:475
 #, sh-format
 msgid ""
 "bisect run failed:\n"
 "'bisect_state $state' exited with error code $res"
 msgstr ""
 
-#: git-bisect.sh:466
+#: git-bisect.sh:482
 msgid "bisect run success"
 msgstr ""
 
@@ -8906,7 +9308,7 @@
 msgid "Cannot rebase onto multiple branches"
 msgstr ""
 
-#: git-rebase.sh:53
+#: git-rebase.sh:54
 msgid ""
 "When you have resolved this problem, run \"git rebase --continue\".\n"
 "If you prefer to skip this patch, run \"git rebase --skip\" instead.\n"
@@ -8914,42 +9316,58 @@
 "\"."
 msgstr ""
 
+#: git-rebase.sh:156
+msgid "Applied autostash."
+msgstr ""
+
+#: git-rebase.sh:159
+#, sh-format
+msgid "Cannot store $stash_sha1"
+msgstr ""
+
 #: git-rebase.sh:160
+msgid ""
+"Applying autostash resulted in conflicts.\n"
+"Your changes are safe in the stash.\n"
+"You can run \"git stash pop\" or \"git stash drop\" at any time.\n"
+msgstr ""
+
+#: git-rebase.sh:190
 msgid "The pre-rebase hook refused to rebase."
 msgstr ""
 
-#: git-rebase.sh:165
+#: git-rebase.sh:195
 msgid "It looks like git-am is in progress. Cannot rebase."
 msgstr ""
 
-#: git-rebase.sh:296
+#: git-rebase.sh:329
 msgid "The --exec option must be used with the --interactive option"
 msgstr ""
 
-#: git-rebase.sh:301
+#: git-rebase.sh:334
 msgid "No rebase in progress?"
 msgstr ""
 
-#: git-rebase.sh:312
+#: git-rebase.sh:345
 msgid "The --edit-todo action can only be used during interactive rebase."
 msgstr ""
 
-#: git-rebase.sh:319
+#: git-rebase.sh:352
 msgid "Cannot read HEAD"
 msgstr ""
 
-#: git-rebase.sh:322
+#: git-rebase.sh:355
 msgid ""
 "You must edit all merge conflicts and then\n"
 "mark them as resolved using git add"
 msgstr ""
 
-#: git-rebase.sh:340
+#: git-rebase.sh:373
 #, sh-format
 msgid "Could not move back to $head_name"
 msgstr ""
 
-#: git-rebase.sh:359
+#: git-rebase.sh:392
 #, sh-format
 msgid ""
 "It seems that there is already a $state_dir_base directory, and\n"
@@ -8962,56 +9380,65 @@
 "valuable there."
 msgstr ""
 
-#: git-rebase.sh:404
+#: git-rebase.sh:437
 #, sh-format
 msgid "invalid upstream $upstream_name"
 msgstr ""
 
-#: git-rebase.sh:428
+#: git-rebase.sh:461
 #, sh-format
 msgid "$onto_name: there are more than one merge bases"
 msgstr ""
 
-#: git-rebase.sh:431 git-rebase.sh:435
+#: git-rebase.sh:464 git-rebase.sh:468
 #, sh-format
 msgid "$onto_name: there is no merge base"
 msgstr ""
 
-#: git-rebase.sh:440
+#: git-rebase.sh:473
 #, sh-format
 msgid "Does not point to a valid commit: $onto_name"
 msgstr ""
 
-#: git-rebase.sh:463
+#: git-rebase.sh:496
 #, sh-format
 msgid "fatal: no such branch: $branch_name"
 msgstr ""
 
-#: git-rebase.sh:483
+#: git-rebase.sh:519
+msgid "Cannot autostash"
+msgstr ""
+
+#: git-rebase.sh:524
+#, sh-format
+msgid "Created autostash: $stash_abbrev"
+msgstr ""
+
+#: git-rebase.sh:528
 msgid "Please commit or stash them."
 msgstr ""
 
-#: git-rebase.sh:501
+#: git-rebase.sh:548
 #, sh-format
 msgid "Current branch $branch_name is up to date."
 msgstr ""
 
-#: git-rebase.sh:504
+#: git-rebase.sh:552
 #, sh-format
 msgid "Current branch $branch_name is up to date, rebase forced."
 msgstr ""
 
-#: git-rebase.sh:515
+#: git-rebase.sh:563
 #, sh-format
 msgid "Changes from $mb to $onto:"
 msgstr ""
 
 #. Detach HEAD and reset the tree
-#: git-rebase.sh:524
+#: git-rebase.sh:572
 msgid "First, rewinding head to replay your work on top of it..."
 msgstr ""
 
-#: git-rebase.sh:532
+#: git-rebase.sh:582
 #, sh-format
 msgid "Fast-forwarded $branch_name to $onto_name."
 msgstr ""
@@ -9044,6 +9471,11 @@
 msgid "Cannot record working tree state"
 msgstr ""
 
+#: git-stash.sh:190
+#, sh-format
+msgid "Cannot update $ref_stash with $w_commit"
+msgstr ""
+
 #. TRANSLATORS: $option is an invalid option, like
 #. `--blah-blah'. The 7 spaces at the beginning of the
 #. second line correspond to "error: ". So you should line
@@ -9054,126 +9486,141 @@
 #. $ git stash save --blah-blah 2>&1 | head -n 2
 #. error: unknown option for 'stash save': --blah-blah
 #. To provide a message, use git stash save -- '--blah-blah'
-#: git-stash.sh:202
+#: git-stash.sh:241
 #, sh-format
 msgid ""
 "error: unknown option for 'stash save': $option\n"
 "       To provide a message, use git stash save -- '$option'"
 msgstr ""
 
-#: git-stash.sh:223
+#: git-stash.sh:262
 msgid "No local changes to save"
 msgstr ""
 
-#: git-stash.sh:227
+#: git-stash.sh:268
+msgid ""
+"The following untracked files would NOT be saved but need to be removed by "
+"stash save:"
+msgstr ""
+
+#: git-stash.sh:270
+msgid ""
+"Aborting. Consider using either the --force or --include-untracked option."
+msgstr ""
+
+#: git-stash.sh:274
 msgid "Cannot initialize stash"
 msgstr ""
 
-#: git-stash.sh:235
+#: git-stash.sh:278
 msgid "Cannot save the current status"
 msgstr ""
 
-#: git-stash.sh:253
+#: git-stash.sh:296
 msgid "Cannot remove worktree changes"
 msgstr ""
 
-#: git-stash.sh:352
+#: git-stash.sh:395
 msgid "No stash found."
 msgstr ""
 
-#: git-stash.sh:359
+#: git-stash.sh:402
 #, sh-format
 msgid "Too many revisions specified: $REV"
 msgstr ""
 
-#: git-stash.sh:365
+#: git-stash.sh:408
 #, sh-format
 msgid "$reference is not valid reference"
 msgstr ""
 
-#: git-stash.sh:393
+#: git-stash.sh:436
 #, sh-format
 msgid "'$args' is not a stash-like commit"
 msgstr ""
 
-#: git-stash.sh:404
+#: git-stash.sh:447
 #, sh-format
 msgid "'$args' is not a stash reference"
 msgstr ""
 
-#: git-stash.sh:412
+#: git-stash.sh:455
 msgid "unable to refresh index"
 msgstr ""
 
-#: git-stash.sh:416
+#: git-stash.sh:459
 msgid "Cannot apply a stash in the middle of a merge"
 msgstr ""
 
-#: git-stash.sh:424
+#: git-stash.sh:467
 msgid "Conflicts in index. Try without --index."
 msgstr ""
 
-#: git-stash.sh:426
+#: git-stash.sh:469
 msgid "Could not save index tree"
 msgstr ""
 
-#: git-stash.sh:460
+#: git-stash.sh:503
 msgid "Cannot unstage modified files"
 msgstr ""
 
-#: git-stash.sh:475
+#: git-stash.sh:518
 msgid "Index was not unstashed."
 msgstr ""
 
-#: git-stash.sh:492
+#: git-stash.sh:535
 #, sh-format
 msgid "Dropped ${REV} ($s)"
 msgstr ""
 
-#: git-stash.sh:493
+#: git-stash.sh:536
 #, sh-format
 msgid "${REV}: Could not drop stash entry"
 msgstr ""
 
-#: git-stash.sh:500
+#: git-stash.sh:543
 msgid "No branch name specified"
 msgstr ""
 
-#: git-stash.sh:571
+#: git-stash.sh:615
 msgid "(To restore them type \"git stash apply\")"
 msgstr ""
 
-#: git-submodule.sh:91
+#: git-submodule.sh:95
 #, sh-format
 msgid "cannot strip one component off url '$remoteurl'"
 msgstr ""
 
-#: git-submodule.sh:196
+#: git-submodule.sh:237
 #, sh-format
 msgid "No submodule mapping found in .gitmodules for path '$sm_path'"
 msgstr ""
 
-#: git-submodule.sh:239
+#: git-submodule.sh:281
 #, sh-format
 msgid "Clone of '$url' into submodule path '$sm_path' failed"
 msgstr ""
 
-#: git-submodule.sh:251
+#: git-submodule.sh:293
 #, sh-format
 msgid "Gitdir '$a' is part of the submodule path '$b' or vice versa"
 msgstr ""
 
-#: git-submodule.sh:349
+#: git-submodule.sh:403
+msgid "Relative path can only be used from the toplevel of the working tree"
+msgstr ""
+
+#: git-submodule.sh:413
 #, sh-format
 msgid "repo URL: '$repo' must be absolute or begin with ./|../"
 msgstr ""
 
-#: git-submodule.sh:366
+#: git-submodule.sh:430
 #, sh-format
 msgid "'$sm_path' already exists in the index"
 msgstr ""
 
-#: git-submodule.sh:370
+#: git-submodule.sh:434
 #, sh-format
 msgid ""
 "The following path is ignored by one of your .gitignore files:\n"
@@ -9181,233 +9628,244 @@
 "Use -f if you really want to add it."
 msgstr ""
 
-#: git-submodule.sh:388
+#: git-submodule.sh:452
 #, sh-format
 msgid "Adding existing repo at '$sm_path' to the index"
 msgstr ""
 
-#: git-submodule.sh:390
+#: git-submodule.sh:454
 #, sh-format
 msgid "'$sm_path' already exists and is not a valid git repo"
 msgstr ""
 
-#: git-submodule.sh:398
+#: git-submodule.sh:462
 #, sh-format
 msgid "A git directory for '$sm_name' is found locally with remote(s):"
 msgstr ""
 
-#: git-submodule.sh:400
+#: git-submodule.sh:464
 #, sh-format
 msgid ""
 "If you want to reuse this local git directory instead of cloning again from"
 msgstr ""
 
-#: git-submodule.sh:402
+#: git-submodule.sh:466
 #, sh-format
 msgid ""
 "use the '--force' option. If the local git directory is not the correct repo"
 msgstr ""
 
-#: git-submodule.sh:403
+#: git-submodule.sh:467
 #, sh-format
 msgid ""
 "or you are unsure what this means choose another name with the '--name' "
 "option."
 msgstr ""
 
-#: git-submodule.sh:405
+#: git-submodule.sh:469
 #, sh-format
 msgid "Reactivating local git directory for submodule '$sm_name'."
 msgstr ""
 
-#: git-submodule.sh:417
+#: git-submodule.sh:481
 #, sh-format
 msgid "Unable to checkout submodule '$sm_path'"
 msgstr ""
 
-#: git-submodule.sh:422
+#: git-submodule.sh:486
 #, sh-format
 msgid "Failed to add submodule '$sm_path'"
 msgstr ""
 
-#: git-submodule.sh:431
+#: git-submodule.sh:495
 #, sh-format
 msgid "Failed to register submodule '$sm_path'"
 msgstr ""
 
-#: git-submodule.sh:474
+#: git-submodule.sh:539
 #, sh-format
-msgid "Entering '$prefix$sm_path'"
+msgid "Entering '$prefix$displaypath'"
 msgstr ""
 
-#: git-submodule.sh:488
+#: git-submodule.sh:554
 #, sh-format
-msgid "Stopping at '$sm_path'; script returned non-zero status."
+msgid "Stopping at '$prefix$displaypath'; script returned non-zero status."
 msgstr ""
 
-#: git-submodule.sh:532
+#: git-submodule.sh:600
 #, sh-format
-msgid "No url found for submodule path '$sm_path' in .gitmodules"
+msgid "No url found for submodule path '$displaypath' in .gitmodules"
 msgstr ""
 
-#: git-submodule.sh:541
+#: git-submodule.sh:609
 #, sh-format
-msgid "Failed to register url for submodule path '$sm_path'"
+msgid "Failed to register url for submodule path '$displaypath'"
 msgstr ""
 
-#: git-submodule.sh:543
+#: git-submodule.sh:611
 #, sh-format
-msgid "Submodule '$name' ($url) registered for path '$sm_path'"
+msgid "Submodule '$name' ($url) registered for path '$displaypath'"
 msgstr ""
 
-#: git-submodule.sh:551
+#: git-submodule.sh:619
 #, sh-format
-msgid "Failed to register update mode for submodule path '$sm_path'"
+msgid "Failed to register update mode for submodule path '$displaypath'"
 msgstr ""
 
-#: git-submodule.sh:588
+#: git-submodule.sh:656
 #, sh-format
 msgid "Use '.' if you really want to deinitialize all submodules"
 msgstr ""
 
-#: git-submodule.sh:603
+#: git-submodule.sh:673
 #, sh-format
-msgid "Submodule work tree '$sm_path' contains a .git directory"
+msgid "Submodule work tree '$displaypath' contains a .git directory"
 msgstr ""
 
-#: git-submodule.sh:604
+#: git-submodule.sh:674
 #, sh-format
 msgid ""
 "(use 'rm -rf' if you really want to remove it including all of its history)"
 msgstr ""
 
-#: git-submodule.sh:610
+#: git-submodule.sh:680
 #, sh-format
 msgid ""
-"Submodule work tree '$sm_path' contains local modifications; use '-f' to "
+"Submodule work tree '$displaypath' contains local modifications; use '-f' to "
 "discard them"
 msgstr ""
 
-#: git-submodule.sh:613
+#: git-submodule.sh:683
 #, sh-format
-msgid "Cleared directory '$sm_path'"
+msgid "Cleared directory '$displaypath'"
 msgstr ""
 
-#: git-submodule.sh:614
+#: git-submodule.sh:684
 #, sh-format
-msgid "Could not remove submodule work tree '$sm_path'"
+msgid "Could not remove submodule work tree '$displaypath'"
 msgstr ""
 
-#: git-submodule.sh:617
+#: git-submodule.sh:687
 #, sh-format
-msgid "Could not create empty submodule directory '$sm_path'"
+msgid "Could not create empty submodule directory '$displaypath'"
 msgstr ""
 
-#: git-submodule.sh:626
+#: git-submodule.sh:696
 #, sh-format
-msgid "Submodule '$name' ($url) unregistered for path '$sm_path'"
+msgid "Submodule '$name' ($url) unregistered for path '$displaypath'"
 msgstr ""
 
-#: git-submodule.sh:731
+#: git-submodule.sh:811
 #, sh-format
 msgid ""
-"Submodule path '$prefix$sm_path' not initialized\n"
+"Submodule path '$displaypath' not initialized\n"
 "Maybe you want to use 'update --init'?"
 msgstr ""
 
-#: git-submodule.sh:744
+#: git-submodule.sh:824
 #, sh-format
-msgid "Unable to find current revision in submodule path '$prefix$sm_path'"
+msgid "Unable to find current revision in submodule path '$displaypath'"
 msgstr ""
 
-#: git-submodule.sh:753
+#: git-submodule.sh:833
 #, sh-format
 msgid "Unable to fetch in submodule path '$sm_path'"
 msgstr ""
 
-#: git-submodule.sh:777
+#: git-submodule.sh:857
 #, sh-format
-msgid "Unable to fetch in submodule path '$prefix$sm_path'"
+msgid "Unable to fetch in submodule path '$displaypath'"
 msgstr ""
 
-#: git-submodule.sh:791
+#: git-submodule.sh:871
 #, sh-format
-msgid "Unable to rebase '$sha1' in submodule path '$prefix$sm_path'"
+msgid "Unable to rebase '$sha1' in submodule path '$displaypath'"
 msgstr ""
 
-#: git-submodule.sh:792
+#: git-submodule.sh:872
 #, sh-format
-msgid "Submodule path '$prefix$sm_path': rebased into '$sha1'"
+msgid "Submodule path '$displaypath': rebased into '$sha1'"
 msgstr ""
 
-#: git-submodule.sh:797
+#: git-submodule.sh:877
 #, sh-format
-msgid "Unable to merge '$sha1' in submodule path '$prefix$sm_path'"
+msgid "Unable to merge '$sha1' in submodule path '$displaypath'"
 msgstr ""
 
-#: git-submodule.sh:798
+#: git-submodule.sh:878
 #, sh-format
-msgid "Submodule path '$prefix$sm_path': merged in '$sha1'"
+msgid "Submodule path '$displaypath': merged in '$sha1'"
 msgstr ""
 
-#: git-submodule.sh:803
+#: git-submodule.sh:883
 #, sh-format
-msgid "Unable to checkout '$sha1' in submodule path '$prefix$sm_path'"
+msgid ""
+"Execution of '$command $sha1' failed in submodule  path '$prefix$sm_path'"
 msgstr ""
 
-#: git-submodule.sh:804
+#: git-submodule.sh:884
 #, sh-format
-msgid "Submodule path '$prefix$sm_path': checked out '$sha1'"
+msgid "Submodule path '$prefix$sm_path': '$command $sha1'"
 msgstr ""
 
-#: git-submodule.sh:831
+#: git-submodule.sh:889
 #, sh-format
-msgid "Failed to recurse into submodule path '$prefix$sm_path'"
+msgid "Unable to checkout '$sha1' in submodule path '$displaypath'"
 msgstr ""
 
-#: git-submodule.sh:939
+#: git-submodule.sh:890
+#, sh-format
+msgid "Submodule path '$displaypath': checked out '$sha1'"
+msgstr ""
+
+#: git-submodule.sh:917
+#, sh-format
+msgid "Failed to recurse into submodule path '$displaypath'"
+msgstr ""
+
+#: git-submodule.sh:1025
 msgid "The --cached option cannot be used with the --files option"
 msgstr ""
 
 #. unexpected type
-#: git-submodule.sh:979
+#: git-submodule.sh:1066
 #, sh-format
 msgid "unexpected mode $mod_dst"
 msgstr ""
 
-#: git-submodule.sh:997
+#: git-submodule.sh:1086
 #, sh-format
-msgid "  Warn: $name doesn't contain commit $sha1_src"
+msgid "  Warn: $display_name doesn't contain commit $sha1_src"
 msgstr ""
 
-#: git-submodule.sh:1000
+#: git-submodule.sh:1089
 #, sh-format
-msgid "  Warn: $name doesn't contain commit $sha1_dst"
+msgid "  Warn: $display_name doesn't contain commit $sha1_dst"
 msgstr ""
 
-#: git-submodule.sh:1003
+#: git-submodule.sh:1092
 #, sh-format
-msgid "  Warn: $name doesn't contain commits $sha1_src and $sha1_dst"
+msgid "  Warn: $display_name doesn't contain commits $sha1_src and $sha1_dst"
 msgstr ""
 
-#: git-submodule.sh:1028
+#: git-submodule.sh:1117
 msgid "blob"
 msgstr ""
 
-#: git-submodule.sh:1066
+#: git-submodule.sh:1155
 msgid "Submodules changed but not updated:"
 msgstr ""
 
-#: git-submodule.sh:1068
+#: git-submodule.sh:1157
 msgid "Submodule changes to be committed:"
 msgstr ""
 
-#: git-submodule.sh:1153
+#: git-submodule.sh:1242
 #, sh-format
 msgid "Failed to recurse into submodule path '$sm_path'"
 msgstr ""
 
-#: git-submodule.sh:1216
+#: git-submodule.sh:1306
 #, sh-format
-msgid "Synchronizing submodule url for '$prefix$sm_path'"
+msgid "Synchronizing submodule url for '$displaypath'"
 msgstr ""
diff --git a/po/sv.po b/po/sv.po
index 1d4ea2e3..12dfca9 100644
--- a/po/sv.po
+++ b/po/sv.po
@@ -5,10 +5,10 @@
 #
 msgid ""
 msgstr ""
-"Project-Id-Version: git 1.8.3\n"
+"Project-Id-Version: git 1.8.4\n"
 "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
-"POT-Creation-Date: 2013-04-10 15:16+0800\n"
-"PO-Revision-Date: 2013-04-11 11:56+0100\n"
+"POT-Creation-Date: 2013-08-06 14:10+0800\n"
+"PO-Revision-Date: 2013-08-06 12:37+0100\n"
 "Last-Translator: Peter Krefting <peter@softwolves.pp.se>\n"
 "Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
 "Language: sv\n"
@@ -17,7 +17,7 @@
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: advice.c:53
+#: advice.c:57
 #, c-format
 msgid "hint: %.*s\n"
 msgstr "tips: %.*s\n"
@@ -26,7 +26,7 @@
 #. * Message used both when 'git commit' fails and when
 #. * other commands doing a merge do.
 #.
-#: advice.c:83
+#: advice.c:87
 msgid ""
 "Fix them up in the work tree,\n"
 "and then use 'git add/rm <file>' as\n"
@@ -65,7 +65,7 @@
 msgid "archive format"
 msgstr "arkivformat"
 
-#: archive.c:324 builtin/log.c:1117
+#: archive.c:324 builtin/log.c:1173
 msgid "prefix"
 msgstr "prefix"
 
@@ -73,11 +73,11 @@
 msgid "prepend prefix to each pathname in the archive"
 msgstr "lägg till prefix till varje sökväg i arkivet"
 
-#: archive.c:326 builtin/archive.c:88 builtin/blame.c:2366
-#: builtin/blame.c:2367 builtin/config.c:55 builtin/fast-export.c:659
-#: builtin/fast-export.c:661 builtin/grep.c:715 builtin/hash-object.c:77
-#: builtin/ls-files.c:497 builtin/ls-files.c:500 builtin/notes.c:536
-#: builtin/notes.c:693 builtin/read-tree.c:107 parse-options.h:149
+#: archive.c:326 builtin/archive.c:88 builtin/blame.c:2292
+#: builtin/blame.c:2293 builtin/config.c:56 builtin/fast-export.c:673
+#: builtin/fast-export.c:675 builtin/grep.c:714 builtin/hash-object.c:77
+#: builtin/ls-files.c:496 builtin/ls-files.c:499 builtin/notes.c:408
+#: builtin/notes.c:565 builtin/read-tree.c:108 parse-options.h:152
 msgid "file"
 msgstr "fil"
 
@@ -109,7 +109,7 @@
 msgid "list supported archive formats"
 msgstr "visa understödda arkivformat"
 
-#: archive.c:345 builtin/archive.c:90 builtin/clone.c:86
+#: archive.c:345 builtin/archive.c:90 builtin/clone.c:85
 msgid "repo"
 msgstr "arkiv"
 
@@ -117,7 +117,7 @@
 msgid "retrieve the archive from remote repository <repo>"
 msgstr "hämta arkivet från fjärrarkivet <arkiv>"
 
-#: archive.c:347 builtin/archive.c:92 builtin/notes.c:615
+#: archive.c:347 builtin/archive.c:92 builtin/notes.c:487
 msgid "command"
 msgstr "kommando"
 
@@ -133,17 +133,88 @@
 "Negativa mönster ignoreras i git-attribut\n"
 "Använd '\\!' för att inleda med ett utropstecken."
 
-#: branch.c:201
+#: branch.c:60
+#, c-format
+msgid "Not setting branch %s as its own upstream."
+msgstr "Ställer inte in grenen %s som sin egen uppströmsgren."
+
+#: branch.c:82
+#, c-format
+msgid "Branch %s set up to track remote branch %s from %s by rebasing."
+msgstr ""
+"Grenen %s ställdes in att spåra fjärrgrenen %s från %s genom ombasering."
+
+#: branch.c:83
+#, c-format
+msgid "Branch %s set up to track remote branch %s from %s."
+msgstr "Grenen %s ställdes in att spåra fjärrgrenen %s från %s."
+
+#: branch.c:87
+#, c-format
+msgid "Branch %s set up to track local branch %s by rebasing."
+msgstr "Grenen %s ställdes in att spåra den lokala grenen %s genom ombasering."
+
+#: branch.c:88
+#, c-format
+msgid "Branch %s set up to track local branch %s."
+msgstr "Grenen %s ställdes in att spåra den lokala grenen %s."
+
+#: branch.c:92
+#, c-format
+msgid "Branch %s set up to track remote ref %s by rebasing."
+msgstr "Grenen %s ställdes in att spåra fjärreferensen %s genom ombasering."
+
+#: branch.c:93
+#, c-format
+msgid "Branch %s set up to track remote ref %s."
+msgstr "Grenen %s ställdes in att spåra fjärreferensen %s."
+
+#: branch.c:97
+#, c-format
+msgid "Branch %s set up to track local ref %s by rebasing."
+msgstr ""
+"Grenen %s ställdes in att spåra den lokala referensen %s genom ombasering."
+
+#: branch.c:98
+#, c-format
+msgid "Branch %s set up to track local ref %s."
+msgstr "Grenen %s ställdes in att spåra den lokala referensen %s."
+
+#: branch.c:118
+#, c-format
+msgid "Tracking not set up: name too long: %s"
+msgstr "Spårning har inte ställts in: namnet för långt: %s"
+
+#: branch.c:137
+#, c-format
+msgid "Not tracking: ambiguous information for ref %s"
+msgstr "Spårar inte: tvetydig information för referensen %s"
+
+#: branch.c:182
+#, c-format
+msgid "'%s' is not a valid branch name."
+msgstr "\"%s\" är inte ett giltigt grennamn."
+
+#: branch.c:187
+#, c-format
+msgid "A branch named '%s' already exists."
+msgstr "Det finns redan en gren som heter \"%s\""
+
+#: branch.c:195
+msgid "Cannot force update the current branch."
+msgstr "Kan inte tvinga uppdatering av aktuell gren."
+
+#: branch.c:216
 #, c-format
 msgid "Cannot setup tracking information; starting point '%s' is not a branch."
 msgstr "Kan inte ställa in spårning; startpunkten \"%s\" är inte en gren."
 
-#: branch.c:203
+#: branch.c:218
 #, c-format
 msgid "the requested upstream branch '%s' does not exist"
 msgstr "den efterfrågade uppströmsgrenen \"%s\" finns inte"
 
-#: branch.c:205
+#: branch.c:220
 msgid ""
 "\n"
 "If you are planning on basing your work on an upstream\n"
@@ -163,6 +234,29 @@
 "spåra dess fjärrmotsvarighet kan du använda \"git push -u\"\n"
 "för att ställa in uppströmskonfigurationen när du sänder in."
 
+#: branch.c:265
+#, c-format
+msgid "Not a valid object name: '%s'."
+msgstr "Objektnamnet är inte giltigt: \"%s\"."
+
+#: branch.c:285
+#, c-format
+msgid "Ambiguous object name: '%s'."
+msgstr "Objektnamnet är tvetydigt: \"%s\"."
+
+#: branch.c:290
+#, c-format
+msgid "Not a valid branch point: '%s'."
+msgstr "Avgreningspunkten är inte giltig: \"%s\""
+
+#: branch.c:296
+msgid "Failed to lock ref for update"
+msgstr "Misslyckades låsa referens för uppdatering"
+
+#: branch.c:314
+msgid "Failed to write ref"
+msgstr "Misslyckades skriva referens"
+
 #: bundle.c:36
 #, c-format
 msgid "'%s' does not look like a v2 bundle file"
@@ -173,7 +267,7 @@
 msgid "unrecognized header: %s%s (%d)"
 msgstr "okänt huvud: %s%s (%d)"
 
-#: bundle.c:89 builtin/commit.c:676
+#: bundle.c:89 builtin/commit.c:697
 #, c-format
 msgid "could not open '%s'"
 msgstr "kunde inte öppna \"%s\""
@@ -182,9 +276,9 @@
 msgid "Repository lacks these prerequisite commits:"
 msgstr "Arkivet saknar dessa nödvändiga incheckningar:"
 
-#: bundle.c:164 sequencer.c:651 sequencer.c:1083 builtin/log.c:300
-#: builtin/log.c:754 builtin/log.c:1350 builtin/log.c:1566 builtin/merge.c:349
-#: builtin/shortlog.c:157
+#: bundle.c:164 sequencer.c:661 sequencer.c:1111 builtin/log.c:331
+#: builtin/log.c:801 builtin/log.c:1399 builtin/log.c:1625 builtin/merge.c:364
+#: builtin/shortlog.c:156
 msgid "revision walk setup failed"
 msgstr "misslyckades skapa revisionstraversering"
 
@@ -210,7 +304,7 @@
 msgid "rev-list died"
 msgstr "rev-list dog"
 
-#: bundle.c:300 builtin/log.c:1246 builtin/shortlog.c:260
+#: bundle.c:300 builtin/log.c:1310 builtin/shortlog.c:259
 #, c-format
 msgid "unrecognized argument: %s"
 msgstr "okänt argument: %s"
@@ -241,12 +335,12 @@
 msgid "index-pack died"
 msgstr "index-pack dog"
 
-#: commit.c:50
+#: commit.c:53
 #, c-format
 msgid "could not parse %s"
 msgstr "kunde inte tolka %s"
 
-#: commit.c:52
+#: commit.c:55
 #, c-format
 msgid "%s %s is not a commit!"
 msgstr "%s %s är inte en incheckning!"
@@ -255,16 +349,16 @@
 msgid "memory exhausted"
 msgstr "minnet slut"
 
-#: connected.c:39
+#: connected.c:60
 msgid "Could not run 'git rev-list'"
 msgstr "Kunde inte köra \"git rev-list\""
 
-#: connected.c:48
+#: connected.c:80
 #, c-format
 msgid "failed write to rev-list: %s"
 msgstr "kunde inte skriva till rev-list: %s"
 
-#: connected.c:56
+#: connected.c:88
 #, c-format
 msgid "failed to close rev-list's stdin: %s"
 msgstr "kunde inte stänga rev-list:s standard in: %s"
@@ -360,7 +454,7 @@
 "Hittade fel i konfigurationsvariabeln \"diff.dirstat\":\n"
 "%s"
 
-#: diff.c:3480
+#: diff.c:3487
 #, c-format
 msgid ""
 "Failed to parse --dirstat/-X option parameter:\n"
@@ -369,7 +463,7 @@
 "Misslyckades tolka argument till flaggan --dirstat/-X;\n"
 "%s"
 
-#: diff.c:3494
+#: diff.c:3501
 #, c-format
 msgid "Failed to parse --submodule option parameter: '%s'"
 msgstr "Misslyckades tolka argument till flaggan --submodule: \"%s\""
@@ -411,20 +505,20 @@
 msgid "'%s': short read %s"
 msgstr "\"%s\": kort läsning %s"
 
-#: help.c:212
+#: help.c:210
 #, c-format
 msgid "available git commands in '%s'"
 msgstr "git-kommandon tillgängliga i \"%s\""
 
-#: help.c:219
+#: help.c:217
 msgid "git commands available from elsewhere on your $PATH"
 msgstr "git-kommandon från andra platser i din $PATH"
 
-#: help.c:235
+#: help.c:233
 msgid "The most commonly used git commands are:"
 msgstr "De mest använda git-kommandona är:"
 
-#: help.c:292
+#: help.c:290
 #, c-format
 msgid ""
 "'%s' appears to be a git command, but we were not\n"
@@ -433,11 +527,11 @@
 "\"%s\" verkar vara ett git-kommando, men vi kan inte\n"
 "köra det. Kanske git-%s är trasigt?"
 
-#: help.c:349
+#: help.c:347
 msgid "Uh oh. Your system reports no Git commands at all."
 msgstr "Oj då. Ditt system rapporterar inga Git-kommandon alls."
 
-#: help.c:371
+#: help.c:369
 #, c-format
 msgid ""
 "WARNING: You called a Git command named '%s', which does not exist.\n"
@@ -446,17 +540,17 @@
 "VARNING: Du anropade ett Git-kommando vid namn \"%s\", som inte finns.\n"
 "Fortsätter under förutsättningen att du menade \"%s\""
 
-#: help.c:376
+#: help.c:374
 #, c-format
 msgid "in %0.1f seconds automatically..."
 msgstr "automatiskt om %0.1f sekunder..."
 
-#: help.c:383
+#: help.c:381
 #, c-format
 msgid "git: '%s' is not a git command. See 'git --help'."
 msgstr "git: \"%s\" är inte ett git-kommando. Se \"git --help\"."
 
-#: help.c:387
+#: help.c:385 help.c:444
 msgid ""
 "\n"
 "Did you mean this?"
@@ -470,12 +564,17 @@
 "\n"
 "Menade du ett av dessa?"
 
+#: help.c:440
+#, c-format
+msgid "%s: %s - %s"
+msgstr "%s: %s - %s"
+
 #: merge.c:56
 msgid "failed to read the cache"
 msgstr "misslyckads läsa cachen"
 
-#: merge.c:110 builtin/checkout.c:362 builtin/checkout.c:563
-#: builtin/clone.c:635
+#: merge.c:110 builtin/checkout.c:365 builtin/checkout.c:566
+#: builtin/clone.c:656
 msgid "unable to write new index file"
 msgstr "kunde inte skriva ny indexfil"
 
@@ -489,70 +588,70 @@
 msgid "addinfo_cache failed for path '%s'"
 msgstr "addinfo_cache misslyckades för sökvägen \"%s\""
 
-#: merge-recursive.c:268
+#: merge-recursive.c:269
 msgid "error building trees"
 msgstr "fel vid byggande av träd"
 
-#: merge-recursive.c:672
+#: merge-recursive.c:673
 #, c-format
 msgid "failed to create path '%s'%s"
 msgstr "misslyckades skapa sökvägen \"%s\"%s"
 
-#: merge-recursive.c:683
+#: merge-recursive.c:684
 #, c-format
 msgid "Removing %s to make room for subdirectory\n"
 msgstr "Tar bort %s för att göra plats för underkatalog\n"
 
 #. something else exists
 #. .. but not some other error (who really cares what?)
-#: merge-recursive.c:697 merge-recursive.c:718
+#: merge-recursive.c:698 merge-recursive.c:719
 msgid ": perhaps a D/F conflict?"
 msgstr ": kanske en K/F-konflikt?"
 
-#: merge-recursive.c:708
+#: merge-recursive.c:709
 #, c-format
 msgid "refusing to lose untracked file at '%s'"
 msgstr "vägrar förlora ospårad fil vid \"%s\""
 
-#: merge-recursive.c:748
+#: merge-recursive.c:749
 #, c-format
 msgid "cannot read object %s '%s'"
 msgstr "kan inte läsa objektet %s: \"%s\""
 
-#: merge-recursive.c:750
+#: merge-recursive.c:751
 #, c-format
 msgid "blob expected for %s '%s'"
 msgstr "blob förväntades för %s \"%s\""
 
-#: merge-recursive.c:773 builtin/clone.c:303
+#: merge-recursive.c:774 builtin/clone.c:312
 #, c-format
 msgid "failed to open '%s'"
 msgstr "misslyckades öppna \"%s\""
 
-#: merge-recursive.c:781
+#: merge-recursive.c:782
 #, c-format
 msgid "failed to symlink '%s'"
 msgstr "misslyckades ta skapa symboliska länken \"%s\""
 
-#: merge-recursive.c:784
+#: merge-recursive.c:785
 #, c-format
 msgid "do not know what to do with %06o %s '%s'"
 msgstr "vet inte hur %06o %s \"%s\" skall hanteras"
 
-#: merge-recursive.c:922
+#: merge-recursive.c:923
 msgid "Failed to execute internal merge"
 msgstr "Misslyckades exekvera intern sammanslagning"
 
-#: merge-recursive.c:926
+#: merge-recursive.c:927
 #, c-format
 msgid "Unable to add %s to database"
 msgstr "Kunde inte lägga till %s till databasen"
 
-#: merge-recursive.c:942
+#: merge-recursive.c:943
 msgid "unsupported object type in the tree"
 msgstr "objekttyp som ej stöds upptäcktes i trädet"
 
-#: merge-recursive.c:1021 merge-recursive.c:1035
+#: merge-recursive.c:1022 merge-recursive.c:1036
 #, c-format
 msgid ""
 "CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s left "
@@ -561,7 +660,7 @@
 "KONFLIKT (%s/radera): %s raderad i %s och %s i %s. Versionen %s av %s lämnad "
 "i trädet."
 
-#: merge-recursive.c:1027 merge-recursive.c:1040
+#: merge-recursive.c:1028 merge-recursive.c:1041
 #, c-format
 msgid ""
 "CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s left "
@@ -570,20 +669,20 @@
 "KONFLIKT (%s/radera): %s raderad i %s och %s i %s. Versionen %s av %s lämnad "
 "i trädet vid %s."
 
-#: merge-recursive.c:1081
+#: merge-recursive.c:1082
 msgid "rename"
 msgstr "namnbyte"
 
-#: merge-recursive.c:1081
+#: merge-recursive.c:1082
 msgid "renamed"
 msgstr "namnbytt"
 
-#: merge-recursive.c:1137
+#: merge-recursive.c:1138
 #, c-format
 msgid "%s is a directory in %s adding as %s instead"
 msgstr "%s är en katalog i %s lägger till som %s istället"
 
-#: merge-recursive.c:1159
+#: merge-recursive.c:1160
 #, c-format
 msgid ""
 "CONFLICT (rename/rename): Rename \"%s\"->\"%s\" in branch \"%s\" rename \"%s"
@@ -592,148 +691,169 @@
 "KONFLIKT (namnbyte/namnbyte): Namnbyte \"%s\"->\"%s\" på grenen \"%s\" "
 "namnbyte \"%s\"->\"%s\" i \"%s\"%s"
 
-#: merge-recursive.c:1164
+#: merge-recursive.c:1165
 msgid " (left unresolved)"
 msgstr " (lämnad olöst)"
 
-#: merge-recursive.c:1218
+#: merge-recursive.c:1219
 #, c-format
 msgid "CONFLICT (rename/rename): Rename %s->%s in %s. Rename %s->%s in %s"
 msgstr ""
 "KONFLIKT (namnbyte/namnbyte): Namnbyte %s->%s i %s. Namnbyte %s->%s i %s"
 
-#: merge-recursive.c:1248
+#: merge-recursive.c:1249
 #, c-format
 msgid "Renaming %s to %s and %s to %s instead"
 msgstr "Byter namn på %s till %s och %s till %s istället"
 
-#: merge-recursive.c:1447
+#: merge-recursive.c:1448
 #, c-format
 msgid "CONFLICT (rename/add): Rename %s->%s in %s. %s added in %s"
 msgstr "KONFLIKT (namnbyte/tillägg): Namnbyte %s->%s i %s. %s tillagd i %s"
 
-#: merge-recursive.c:1457
+#: merge-recursive.c:1458
 #, c-format
 msgid "Adding merged %s"
 msgstr "Lägger till sammanslagen %s"
 
-#: merge-recursive.c:1462 merge-recursive.c:1660
+#: merge-recursive.c:1463 merge-recursive.c:1661
 #, c-format
 msgid "Adding as %s instead"
 msgstr "Lägger till som %s iställer"
 
-#: merge-recursive.c:1513
+#: merge-recursive.c:1514
 #, c-format
 msgid "cannot read object %s"
 msgstr "kan inte läsa objektet %s"
 
-#: merge-recursive.c:1516
+#: merge-recursive.c:1517
 #, c-format
 msgid "object %s is not a blob"
 msgstr "objektet %s är inte en blob"
 
-#: merge-recursive.c:1564
+#: merge-recursive.c:1565
 msgid "modify"
 msgstr "ändra"
 
-#: merge-recursive.c:1564
+#: merge-recursive.c:1565
 msgid "modified"
 msgstr "ändrad"
 
-#: merge-recursive.c:1574
+#: merge-recursive.c:1575
 msgid "content"
 msgstr "innehåll"
 
-#: merge-recursive.c:1581
+#: merge-recursive.c:1582
 msgid "add/add"
 msgstr "tillägg/tillägg"
 
-#: merge-recursive.c:1615
+#: merge-recursive.c:1616
 #, c-format
 msgid "Skipped %s (merged same as existing)"
 msgstr "Hoppade över %s (sammanslagen samma som befintlig)"
 
-#: merge-recursive.c:1629
+#: merge-recursive.c:1630
 #, c-format
 msgid "Auto-merging %s"
 msgstr "Slår ihop %s automatiskt"
 
-#: merge-recursive.c:1633 git-submodule.sh:1029
+#: merge-recursive.c:1634 git-submodule.sh:1118
 msgid "submodule"
 msgstr "undermodul"
 
-#: merge-recursive.c:1634
+#: merge-recursive.c:1635
 #, c-format
 msgid "CONFLICT (%s): Merge conflict in %s"
 msgstr "KONFLIKT (%s): Sammanslagningskonflikt i %s"
 
-#: merge-recursive.c:1724
+#: merge-recursive.c:1725
 #, c-format
 msgid "Removing %s"
 msgstr "Tar bort %s"
 
-#: merge-recursive.c:1749
+#: merge-recursive.c:1750
 msgid "file/directory"
 msgstr "fil/katalog"
 
-#: merge-recursive.c:1755
+#: merge-recursive.c:1756
 msgid "directory/file"
 msgstr "katalog/fil"
 
-#: merge-recursive.c:1760
+#: merge-recursive.c:1761
 #, c-format
 msgid "CONFLICT (%s): There is a directory with name %s in %s. Adding %s as %s"
 msgstr ""
 "KONFLIKT (%s): Det finns en katalog med namnet %s i %s. Lägger till %s som %s"
 
-#: merge-recursive.c:1770
+#: merge-recursive.c:1771
 #, c-format
 msgid "Adding %s"
 msgstr "Lägger till %s"
 
-#: merge-recursive.c:1787
+#: merge-recursive.c:1788
 msgid "Fatal merge failure, shouldn't happen."
 msgstr "Ödesdigert sammanslagningsfel, borde inte inträffa."
 
-#: merge-recursive.c:1806
+#: merge-recursive.c:1807
 msgid "Already up-to-date!"
 msgstr "Redan à jour!"
 
-#: merge-recursive.c:1815
+#: merge-recursive.c:1816
 #, c-format
 msgid "merging of trees %s and %s failed"
 msgstr "sammanslagning av träden %s och %s misslyckades"
 
-#: merge-recursive.c:1845
+#: merge-recursive.c:1846
 #, c-format
 msgid "Unprocessed path??? %s"
 msgstr "Obehandlad sökväg??? %s"
 
-#: merge-recursive.c:1890
+#: merge-recursive.c:1891
 msgid "Merging:"
 msgstr "Slår ihop:"
 
-#: merge-recursive.c:1903
+#: merge-recursive.c:1904
 #, c-format
 msgid "found %u common ancestor:"
 msgid_plural "found %u common ancestors:"
 msgstr[0] "hittade %u gemensam förfader:"
 msgstr[1] "hittade %u gemensamma förfäder:"
 
-#: merge-recursive.c:1940
+#: merge-recursive.c:1941
 msgid "merge returned no commit"
 msgstr "sammanslagningen returnerade ingen incheckning"
 
-#: merge-recursive.c:1997
+#: merge-recursive.c:1998
 #, c-format
 msgid "Could not parse object '%s'"
 msgstr "Kunde inte tolka objektet \"%s\""
 
-#: merge-recursive.c:2009 builtin/merge.c:658
+#: merge-recursive.c:2010 builtin/merge.c:672
 msgid "Unable to write index."
 msgstr "Kunde inte skriva indexet."
 
-#: object.c:195
+#: notes-utils.c:40
+msgid "Cannot commit uninitialized/unreferenced notes tree"
+msgstr "Kan inte checka in oinitierat/orefererat anteckningsträd"
+
+#: notes-utils.c:81
+#, c-format
+msgid "Bad notes.rewriteMode value: '%s'"
+msgstr "Felaktigt värde för notes.rewriteMode: '%s'"
+
+#: notes-utils.c:91
+#, c-format
+msgid "Refusing to rewrite notes in %s (outside of refs/notes/)"
+msgstr "Vägrar skriva över anteckningar i %s (utanför refs/notes/)"
+
+#. TRANSLATORS: The first %s is the name of the
+#. environment variable, the second %s is its value
+#: notes-utils.c:118
+#, c-format
+msgid "Bad %s value: '%s'"
+msgstr "Felaktigt värde på %s: \"%s\""
+
+#: object.c:204
 #, c-format
 msgid "unable to parse object: %s"
 msgstr "kunde inte tolka objektet: %s"
@@ -773,18 +893,18 @@
 msgid "'%s' is beyond a symbolic link"
 msgstr "\"%s\" är på andra sidan av en symbolisk länk"
 
-#: remote.c:1781
+#: remote.c:1788
 #, c-format
 msgid "Your branch is ahead of '%s' by %d commit.\n"
 msgid_plural "Your branch is ahead of '%s' by %d commits.\n"
 msgstr[0] "Din gren ligger före \"%s\" med %d incheckning.\n"
 msgstr[1] "Din gren ligger före \"%s\" med %d incheckningar.\n"
 
-#: remote.c:1787
+#: remote.c:1794
 msgid "  (use \"git push\" to publish your local commits)\n"
 msgstr "  (använd \"git push\" för att publicera dina lokala incheckningar)\n"
 
-#: remote.c:1790
+#: remote.c:1797
 #, c-format
 msgid "Your branch is behind '%s' by %d commit, and can be fast-forwarded.\n"
 msgid_plural ""
@@ -794,11 +914,11 @@
 msgstr[1] ""
 "Din gren ligger efter \"%s\" med %d incheckningar, och kan snabbspolas.\n"
 
-#: remote.c:1798
+#: remote.c:1805
 msgid "  (use \"git pull\" to update your local branch)\n"
 msgstr "  (använd \"git pull\" för att uppdatera din lokala gren)\n"
 
-#: remote.c:1801
+#: remote.c:1808
 #, c-format
 msgid ""
 "Your branch and '%s' have diverged,\n"
@@ -813,18 +933,27 @@
 "Din gren och \"%s\" har divergerat,\n"
 "och har %d respektive %d olika incheckningar.\n"
 
-#: remote.c:1811
+#: remote.c:1818
 msgid "  (use \"git pull\" to merge the remote branch into yours)\n"
 msgstr "  (använd \"git pull\" för att slå ihop fjärrgrenen med din egen)\n"
 
-#: sequencer.c:206 builtin/merge.c:776 builtin/merge.c:889 builtin/merge.c:999
-#: builtin/merge.c:1009
+#: run-command.c:80
+msgid "open /dev/null failed"
+msgstr "misslyckades öppna /dev/null"
+
+#: run-command.c:82
+#, c-format
+msgid "dup2(%d,%d) failed"
+msgstr "dup2(%d,%d) misslyckades"
+
+#: sequencer.c:206 builtin/merge.c:790 builtin/merge.c:903
+#: builtin/merge.c:1013 builtin/merge.c:1023
 #, c-format
 msgid "Could not open '%s' for writing"
 msgstr "Kunde inte öppna \"%s\" för skrivning"
 
-#: sequencer.c:208 builtin/merge.c:335 builtin/merge.c:779
-#: builtin/merge.c:1001 builtin/merge.c:1014
+#: sequencer.c:208 builtin/merge.c:350 builtin/merge.c:793
+#: builtin/merge.c:1015 builtin/merge.c:1028
 #, c-format
 msgid "Could not write to '%s'"
 msgstr "Kunde inte skriva till \"%s\""
@@ -847,7 +976,7 @@
 "med \"git add <sökvägar>\" eller \"git rm <sökvägar>\"\n"
 "och checka in resultatet med \"git commit\""
 
-#: sequencer.c:245 sequencer.c:859 sequencer.c:942
+#: sequencer.c:245 sequencer.c:869 sequencer.c:952
 #, c-format
 msgid "Could not write to %s"
 msgstr "Kunde inte skriva till %s"
@@ -870,205 +999,237 @@
 msgstr "Checka in dina ändringar eller använd \"stash\" för att fortsätta."
 
 #. TRANSLATORS: %s will be "revert" or "cherry-pick"
-#: sequencer.c:319
+#: sequencer.c:324
 #, c-format
 msgid "%s: Unable to write new index file"
 msgstr "%s: Kunde inte skriva ny indexfil"
 
-#: sequencer.c:350
+#: sequencer.c:355
 msgid "Could not resolve HEAD commit\n"
 msgstr "Kunde inte bestämma HEAD:s incheckning\n"
 
-#: sequencer.c:371
+#: sequencer.c:377
 msgid "Unable to update cache tree\n"
 msgstr "Kan inte uppdatera cacheträd\n"
 
-#: sequencer.c:416
+#: sequencer.c:422
 #, c-format
 msgid "Could not parse commit %s\n"
 msgstr "Kunde inte tolka incheckningen %s\n"
 
-#: sequencer.c:421
+#: sequencer.c:427
 #, c-format
 msgid "Could not parse parent commit %s\n"
 msgstr "Kunde inte tolka föräldraincheckningen %s\n"
 
-#: sequencer.c:487
+#: sequencer.c:493
 msgid "Your index file is unmerged."
 msgstr "Din indexfil har inte slagits ihop."
 
-#: sequencer.c:506
+#: sequencer.c:512
 #, c-format
 msgid "Commit %s is a merge but no -m option was given."
 msgstr "Incheckning %s är en sammanslagning, men flaggan -m angavs inte."
 
-#: sequencer.c:514
+#: sequencer.c:520
 #, c-format
 msgid "Commit %s does not have parent %d"
 msgstr "Incheckning %s har inte förälder %d"
 
-#: sequencer.c:518
+#: sequencer.c:524
 #, c-format
 msgid "Mainline was specified but commit %s is not a merge."
 msgstr "Huvudlinje angavs, men incheckningen %s är inte en sammanslagning"
 
 #. TRANSLATORS: The first %s will be "revert" or
 #. "cherry-pick", the second %s a SHA1
-#: sequencer.c:531
+#: sequencer.c:537
 #, c-format
 msgid "%s: cannot parse parent commit %s"
 msgstr "%s: kan inte tolka föräldraincheckningen %s"
 
-#: sequencer.c:535
+#: sequencer.c:541
 #, c-format
 msgid "Cannot get commit message for %s"
 msgstr "Kan inte hämta incheckningsmeddelande för %s"
 
-#: sequencer.c:621
+#: sequencer.c:627
 #, c-format
 msgid "could not revert %s... %s"
 msgstr "kunde inte ångra %s... %s"
 
-#: sequencer.c:622
+#: sequencer.c:628
 #, c-format
 msgid "could not apply %s... %s"
 msgstr "kunde inte tillämpa %s... %s"
 
-#: sequencer.c:654
+#: sequencer.c:664
 msgid "empty commit set passed"
 msgstr "den angivna uppsättningen incheckningar är tom"
 
-#: sequencer.c:662
+#: sequencer.c:672
 #, c-format
 msgid "git %s: failed to read the index"
 msgstr "git %s: misslyckades läsa indexet"
 
-#: sequencer.c:667
+#: sequencer.c:677
 #, c-format
 msgid "git %s: failed to refresh the index"
 msgstr "git %s: misslyckades uppdatera indexet"
 
-#: sequencer.c:725
+#: sequencer.c:735
 #, c-format
 msgid "Cannot %s during a %s"
 msgstr "kan inte %s under en %s"
 
-#: sequencer.c:747
+#: sequencer.c:757
 #, c-format
 msgid "Could not parse line %d."
 msgstr "Kan inte tolka rad %d."
 
-#: sequencer.c:752
+#: sequencer.c:762
 msgid "No commits parsed."
 msgstr "Inga incheckningar lästes."
 
-#: sequencer.c:765
+#: sequencer.c:775
 #, c-format
 msgid "Could not open %s"
 msgstr "Kunde inte öppna %s"
 
-#: sequencer.c:769
+#: sequencer.c:779
 #, c-format
 msgid "Could not read %s."
 msgstr "kunde inte läsa %s."
 
-#: sequencer.c:776
+#: sequencer.c:786
 #, c-format
 msgid "Unusable instruction sheet: %s"
 msgstr "Oanvändbart manus: %s"
 
-#: sequencer.c:804
+#: sequencer.c:814
 #, c-format
 msgid "Invalid key: %s"
 msgstr "Felaktig nyckel: %s"
 
-#: sequencer.c:807
+#: sequencer.c:817
 #, c-format
 msgid "Invalid value for %s: %s"
 msgstr "Felaktigt värde för %s: %s"
 
-#: sequencer.c:819
+#: sequencer.c:829
 #, c-format
 msgid "Malformed options sheet: %s"
 msgstr "Trasigt manus: %s"
 
-#: sequencer.c:840
+#: sequencer.c:850
 msgid "a cherry-pick or revert is already in progress"
 msgstr "en \"cherry-pick\" eller \"revert\" pågår redan"
 
-#: sequencer.c:841
+#: sequencer.c:851
 msgid "try \"git cherry-pick (--continue | --quit | --abort)\""
 msgstr "testa \"git cherry-pick (--continue | --quit | --abort)\""
 
-#: sequencer.c:845
+#: sequencer.c:855
 #, c-format
 msgid "Could not create sequencer directory %s"
 msgstr "Kunde inte skapa \"sequencer\"-katalogen \"%s\""
 
-#: sequencer.c:861 sequencer.c:946
+#: sequencer.c:871 sequencer.c:956
 #, c-format
 msgid "Error wrapping up %s."
 msgstr "Fel vid ombrytning av %s."
 
-#: sequencer.c:880 sequencer.c:1014
+#: sequencer.c:890 sequencer.c:1024
 msgid "no cherry-pick or revert in progress"
 msgstr "ingen \"cherry-pick\" eller \"revert\" pågår"
 
-#: sequencer.c:882
+#: sequencer.c:892
 msgid "cannot resolve HEAD"
 msgstr "kan inte bestämma HEAD"
 
-#: sequencer.c:884
+#: sequencer.c:894
 msgid "cannot abort from a branch yet to be born"
 msgstr "kan inte avbryta från en gren som ännu inte är född"
 
-#: sequencer.c:906 builtin/apply.c:4060
+#: sequencer.c:916 builtin/apply.c:4061
 #, c-format
 msgid "cannot open %s: %s"
 msgstr "kan inte öppna %s: %s"
 
-#: sequencer.c:909
+#: sequencer.c:919
 #, c-format
 msgid "cannot read %s: %s"
 msgstr "kan inte läsa %s: %s"
 
-#: sequencer.c:910
+#: sequencer.c:920
 msgid "unexpected end of file"
 msgstr "oväntat filslut"
 
-#: sequencer.c:916
+#: sequencer.c:926
 #, c-format
 msgid "stored pre-cherry-pick HEAD file '%s' is corrupt"
 msgstr "sparad HEAD-fil från före \"cherry-pick\", \"%s\", är trasig"
 
-#: sequencer.c:939
+#: sequencer.c:949
 #, c-format
 msgid "Could not format %s."
 msgstr "Kunde inte formatera %s."
 
-#: sequencer.c:1101
+#: sequencer.c:1092
+#, c-format
+msgid "%s: can't cherry-pick a %s"
+msgstr "%s: kan inte göra \"cherry-pick\" på typen \"%s\""
+
+#: sequencer.c:1095
+#, c-format
+msgid "%s: bad revision"
+msgstr "%s: felaktig revision"
+
+#: sequencer.c:1129
 msgid "Can't revert as initial commit"
 msgstr "Kan inte ångra som första incheckning"
 
-#: sequencer.c:1102
+#: sequencer.c:1130
 msgid "Can't cherry-pick into empty head"
 msgstr "Kan inte göra \"cherry-pick\" i ett tomt huvud"
 
-#: sha1_name.c:1036
+#: sha1_name.c:440
+msgid ""
+"Git normally never creates a ref that ends with 40 hex characters\n"
+"because it will be ignored when you just specify 40-hex. These refs\n"
+"may be created by mistake. For example,\n"
+"\n"
+"  git checkout -b $br $(git rev-parse ...)\n"
+"\n"
+"where \"$br\" is somehow empty and a 40-hex ref is created. Please\n"
+"examine these refs and maybe delete them. Turn this message off by\n"
+"running \"git config advice.objectNameWarning false\""
+msgstr ""
+"Git skapar normalt aldrig referenser som slutar med 40 hexadecimala\n"
+"tecken, då detta ignoreras när du anger 40-hex enbart. Dessa\n"
+"referenser kan skapas av misstag. Till exempel, för\n"
+"\n"
+"  git checkout -b $br $(git rev-parse ...)\n"
+"\n"
+"där \"$br\" på något sätt blivit tomt och en 40-hex-referens skapats.\n"
+"Undersök referenserna och ta kanske bort dem. Stäng av meddelandet\n"
+"genom att köra \"git config advice.objectNameWarning false\""
+
+#: sha1_name.c:1097
 msgid "HEAD does not point to a branch"
 msgstr "HEAD pekar inte på en gren"
 
-#: sha1_name.c:1039
+#: sha1_name.c:1100
 #, c-format
 msgid "No such branch: '%s'"
 msgstr "Okänd gren: \"%s\""
 
-#: sha1_name.c:1041
+#: sha1_name.c:1102
 #, c-format
 msgid "No upstream configured for branch '%s'"
 msgstr "Ingen standarduppström angiven för grenen \"%s\""
 
-#: sha1_name.c:1044
+#: sha1_name.c:1106
 #, c-format
 msgid "Upstream branch '%s' not stored as a remote-tracking branch"
 msgstr "Uppströmsgrenen \"%s\" är inte lagrad som en fjärrspårande gren"
@@ -1078,232 +1239,232 @@
 msgid "unable to access '%s': %s"
 msgstr "kan inte komma åt \"%s\": %s"
 
-#: wrapper.c:423
+#: wrapper.c:429
 #, c-format
 msgid "unable to access '%s'"
 msgstr "kan inte komma åt \"%s\""
 
-#: wrapper.c:434
+#: wrapper.c:440
 #, c-format
 msgid "unable to look up current user in the passwd file: %s"
 msgstr "kan inte slå upp aktuell användare i passwd-filen: %s"
 
-#: wrapper.c:435
+#: wrapper.c:441
 msgid "no such user"
 msgstr "okänd användare"
 
-#: wt-status.c:140
+#: wt-status.c:141
 msgid "Unmerged paths:"
 msgstr "Ej sammanslagna sökvägar:"
 
-#: wt-status.c:167 wt-status.c:194
+#: wt-status.c:168 wt-status.c:195
 #, c-format
 msgid "  (use \"git reset %s <file>...\" to unstage)"
 msgstr "  (använd \"git reset %s <fil>...\" för att ta bort från kö)"
 
-#: wt-status.c:169 wt-status.c:196
+#: wt-status.c:170 wt-status.c:197
 msgid "  (use \"git rm --cached <file>...\" to unstage)"
 msgstr "  (använd \"git rm --cached <fil>...\" för att ta bort från kö)"
 
-#: wt-status.c:173
+#: wt-status.c:174
 msgid "  (use \"git add <file>...\" to mark resolution)"
 msgstr "  (använd \"git add <fil>...\" för att ange lösning)"
 
-#: wt-status.c:175 wt-status.c:179
+#: wt-status.c:176 wt-status.c:180
 msgid "  (use \"git add/rm <file>...\" as appropriate to mark resolution)"
 msgstr "  (använd \"git add/rm <fil>...\" som lämpligt för att ange lösning)"
 
-#: wt-status.c:177
+#: wt-status.c:178
 msgid "  (use \"git rm <file>...\" to mark resolution)"
 msgstr "  (använd \"git rm <fil>...\" för att ange lösning)"
 
-#: wt-status.c:188
+#: wt-status.c:189
 msgid "Changes to be committed:"
 msgstr "Ändringar att checka in:"
 
-#: wt-status.c:206
+#: wt-status.c:207
 msgid "Changes not staged for commit:"
 msgstr "Ändringar ej i incheckningskön:"
 
-#: wt-status.c:210
+#: wt-status.c:211
 msgid "  (use \"git add <file>...\" to update what will be committed)"
 msgstr ""
 "  (använd \"git add <fil>...\" för att uppdatera vad som skall checkas in)"
 
-#: wt-status.c:212
+#: wt-status.c:213
 msgid "  (use \"git add/rm <file>...\" to update what will be committed)"
 msgstr ""
 "  (använd \"git add/rm <fil>...\" för att uppdatera vad som skall checkas in)"
 
-#: wt-status.c:213
+#: wt-status.c:214
 msgid ""
 "  (use \"git checkout -- <file>...\" to discard changes in working directory)"
 msgstr ""
 "  (använd \"git checkout -- <fil>...\" för att förkasta ändringar i "
 "arbetskatalogen)"
 
-#: wt-status.c:215
+#: wt-status.c:216
 msgid "  (commit or discard the untracked or modified content in submodules)"
 msgstr ""
 "  (checka in eller förkasta ospårat eller ändrat innehåll i undermoduler)"
 
-#: wt-status.c:227
+#: wt-status.c:228
 #, c-format
 msgid "  (use \"git %s <file>...\" to include in what will be committed)"
 msgstr ""
 "  (använd \"git %s <fil>...\" för att ta med i det som skall checkas in)"
 
-#: wt-status.c:244
+#: wt-status.c:245
 msgid "bug"
 msgstr "programfel"
 
-#: wt-status.c:249
+#: wt-status.c:250
 msgid "both deleted:"
 msgstr "borttaget av bägge:"
 
-#: wt-status.c:250
+#: wt-status.c:251
 msgid "added by us:"
 msgstr "tillagt av oss:"
 
-#: wt-status.c:251
+#: wt-status.c:252
 msgid "deleted by them:"
 msgstr "borttaget av dem:"
 
-#: wt-status.c:252
+#: wt-status.c:253
 msgid "added by them:"
 msgstr "tillagt av dem:"
 
-#: wt-status.c:253
+#: wt-status.c:254
 msgid "deleted by us:"
 msgstr "borttaget av oss:"
 
-#: wt-status.c:254
+#: wt-status.c:255
 msgid "both added:"
 msgstr "tillagt av bägge:"
 
-#: wt-status.c:255
+#: wt-status.c:256
 msgid "both modified:"
 msgstr "ändrat av bägge:"
 
-#: wt-status.c:285
+#: wt-status.c:286
 msgid "new commits, "
 msgstr "nya incheckningar, "
 
-#: wt-status.c:287
+#: wt-status.c:288
 msgid "modified content, "
 msgstr "ändrat innehåll, "
 
-#: wt-status.c:289
+#: wt-status.c:290
 msgid "untracked content, "
 msgstr "ospårat innehåll, "
 
-#: wt-status.c:306
+#: wt-status.c:307
 #, c-format
 msgid "new file:   %s"
 msgstr "ny fil:     %s"
 
-#: wt-status.c:309
+#: wt-status.c:310
 #, c-format
 msgid "copied:     %s -> %s"
 msgstr "kopierad:   %s -> %s"
 
-#: wt-status.c:312
+#: wt-status.c:313
 #, c-format
 msgid "deleted:    %s"
 msgstr "borttagen:  %s"
 
-#: wt-status.c:315
+#: wt-status.c:316
 #, c-format
 msgid "modified:   %s"
 msgstr "ändrad:     %s"
 
-#: wt-status.c:318
+#: wt-status.c:319
 #, c-format
 msgid "renamed:    %s -> %s"
 msgstr "namnbyte:   %s -> %s"
 
-#: wt-status.c:321
+#: wt-status.c:322
 #, c-format
 msgid "typechange: %s"
 msgstr "typbyte:    %s"
 
-#: wt-status.c:324
+#: wt-status.c:325
 #, c-format
 msgid "unknown:    %s"
 msgstr "okänd:      %s"
 
-#: wt-status.c:327
+#: wt-status.c:328
 #, c-format
 msgid "unmerged:   %s"
 msgstr "osammansl.: %s"
 
-#: wt-status.c:330
+#: wt-status.c:331
 #, c-format
 msgid "bug: unhandled diff status %c"
 msgstr "programfel: diff-status %c ej hanterad"
 
-#: wt-status.c:805
+#: wt-status.c:803
 msgid "You have unmerged paths."
 msgstr "Du har ej sammanslagna sökvägar."
 
-#: wt-status.c:808 wt-status.c:960
+#: wt-status.c:806
 msgid "  (fix conflicts and run \"git commit\")"
 msgstr "  (rätta konflikter och kör \"git commit\")"
 
-#: wt-status.c:811
+#: wt-status.c:809
 msgid "All conflicts fixed but you are still merging."
 msgstr "Alla konflikter har rättats men du är fortfarande i en sammanslagning."
 
-#: wt-status.c:814
+#: wt-status.c:812
 msgid "  (use \"git commit\" to conclude merge)"
 msgstr "  (använd \"git commit\" för att slutföra sammanslagningen)"
 
-#: wt-status.c:824
+#: wt-status.c:822
 msgid "You are in the middle of an am session."
 msgstr "Du är i mitten av en körning av \"git am\"."
 
-#: wt-status.c:827
+#: wt-status.c:825
 msgid "The current patch is empty."
 msgstr "Aktuell patch är tom."
 
-#: wt-status.c:831
-msgid "  (fix conflicts and then run \"git am --resolved\")"
-msgstr "  (rätta konflikter och kör sedan \"git am --resolved\")"
+#: wt-status.c:829
+msgid "  (fix conflicts and then run \"git am --continue\")"
+msgstr "  (rätta konflikter och kör sedan \"git am --continue\")"
 
-#: wt-status.c:833
+#: wt-status.c:831
 msgid "  (use \"git am --skip\" to skip this patch)"
 msgstr "  (använd \"git am --skip\" för att hoppa över patchen)"
 
-#: wt-status.c:835
+#: wt-status.c:833
 msgid "  (use \"git am --abort\" to restore the original branch)"
 msgstr "  (använd \"git am --abort\" för att återställa ursprungsgrenen)"
 
-#: wt-status.c:895 wt-status.c:912
+#: wt-status.c:893 wt-status.c:910
 #, c-format
 msgid "You are currently rebasing branch '%s' on '%s'."
 msgstr "Du håller på att ombasera grenen \"%s\" ovanpå \"%s\"."
 
-#: wt-status.c:900 wt-status.c:917
+#: wt-status.c:898 wt-status.c:915
 msgid "You are currently rebasing."
 msgstr "Du håller på med en ombasering."
 
-#: wt-status.c:903
+#: wt-status.c:901
 msgid "  (fix conflicts and then run \"git rebase --continue\")"
 msgstr "  (rätta konflikter och kör sedan \"git rebase --continue\")"
 
-#: wt-status.c:905
+#: wt-status.c:903
 msgid "  (use \"git rebase --skip\" to skip this patch)"
 msgstr "  (använd \"git rebase --skip\" för att hoppa över patchen)"
 
-#: wt-status.c:907
+#: wt-status.c:905
 msgid "  (use \"git rebase --abort\" to check out the original branch)"
 msgstr "  (använd \"git rebase --abort\" för att checka ut ursprungsgrenen)"
 
-#: wt-status.c:920
+#: wt-status.c:918
 msgid "  (all conflicts fixed: run \"git rebase --continue\")"
 msgstr "  (alla konflikter rättade: kör \"git rebase --continue\")"
 
-#: wt-status.c:924
+#: wt-status.c:922
 #, c-format
 msgid ""
 "You are currently splitting a commit while rebasing branch '%s' on '%s'."
@@ -1311,42 +1472,52 @@
 "Du håller på att dela upp en incheckning medan du ombaserar grenen \"%s\" "
 "ovanpå \"%s\"."
 
-#: wt-status.c:929
+#: wt-status.c:927
 msgid "You are currently splitting a commit during a rebase."
 msgstr "Du håller på att dela upp en incheckning i en ombasering."
 
-#: wt-status.c:932
+#: wt-status.c:930
 msgid "  (Once your working directory is clean, run \"git rebase --continue\")"
 msgstr "  (Så fort din arbetskatalog är ren, kör \"git rebase --continue\")"
 
-#: wt-status.c:936
+#: wt-status.c:934
 #, c-format
 msgid "You are currently editing a commit while rebasing branch '%s' on '%s'."
 msgstr ""
 "Du håller på att redigera en incheckning medan du ombaserar grenen \"%s\" "
 "ovanpå \"%s\"."
 
-#: wt-status.c:941
+#: wt-status.c:939
 msgid "You are currently editing a commit during a rebase."
 msgstr "Du håller på att redigera en incheckning under en ombasering."
 
-#: wt-status.c:944
+#: wt-status.c:942
 msgid "  (use \"git commit --amend\" to amend the current commit)"
 msgstr ""
 "  (använd \"git commit --amend\" för att lägga till på aktuell incheckning)"
 
-#: wt-status.c:946
+#: wt-status.c:944
 msgid ""
 "  (use \"git rebase --continue\" once you are satisfied with your changes)"
 msgstr "  (använd \"git rebase --continue\" när du är nöjd med dina ändringar)"
 
-#: wt-status.c:956
+#: wt-status.c:954
 msgid "You are currently cherry-picking."
 msgstr "Du håller på med en \"cherry-pick\"."
 
+#: wt-status.c:958
+msgid "  (fix conflicts and run \"git cherry-pick --continue\")"
+msgstr "  (rätta konflikter och kör sedan \"git cherry-pick --continue\")"
+
+#: wt-status.c:961
+msgid "  (all conflicts fixed: run \"git cherry-pick --continue\")"
+msgstr "  (alla konflikter rättade: kör \"git cherry-pick --continue\")"
+
 #: wt-status.c:963
-msgid "  (all conflicts fixed: run \"git commit\")"
-msgstr "  (alla konflikter har rättats: kör \"git commit\")"
+msgid "  (use \"git cherry-pick --abort\" to cancel the cherry-pick operation)"
+msgstr ""
+"  (använd \"git cherry-pick --abort\" för att avbryta \"cherry-pick\"-"
+"operationen)"
 
 #: wt-status.c:972
 #, c-format
@@ -1379,74 +1550,76 @@
 msgstr ""
 "  (använd \"git bisect reset\" för att komma tillbaka till ursprungsgrenen)"
 
-#: wt-status.c:1175
+#: wt-status.c:1173
 msgid "On branch "
 msgstr "På grenen "
 
-#: wt-status.c:1186
+#: wt-status.c:1180
+msgid "rebase in progress; onto "
+msgstr "ombasering pågår; ovanpå"
+
+#: wt-status.c:1187
 msgid "HEAD detached at "
 msgstr "HEAD frånkopplad vid "
 
-#: wt-status.c:1188
+#: wt-status.c:1189
 msgid "HEAD detached from "
 msgstr "HEAD frånkopplad från "
 
-#: wt-status.c:1191
+#: wt-status.c:1192
 msgid "Not currently on any branch."
 msgstr "Inte på någon gren för närvarande."
 
-#: wt-status.c:1208
+#: wt-status.c:1209
 msgid "Initial commit"
 msgstr "Första incheckning"
 
-#: wt-status.c:1222
+#: wt-status.c:1223
 msgid "Untracked files"
 msgstr "Ospårade filer"
 
-#: wt-status.c:1224
+#: wt-status.c:1225
 msgid "Ignored files"
 msgstr "Ignorerade filer"
 
-#: wt-status.c:1228
+#: wt-status.c:1229
 #, c-format
-msgid "It took %.2f seconds to enumerate untracked files.  'status -uno'"
-msgstr "Det tog %.2f sekunder att räkna ospårade filer. \"status -uno\""
-
-#: wt-status.c:1232
-msgid "may speed it up, but you have to be careful not to forget to add"
-msgstr "kanske gör det snabbare, men du måste vara försiktig så att du"
-
-#: wt-status.c:1235
-msgid "new files yourself (see 'git help status')."
-msgstr "inte glömmer lägga till filer själv (se \"git help status\")"
+msgid ""
+"It took %.2f seconds to enumerate untracked files. 'status -uno'\n"
+"may speed it up, but you have to be careful not to forget to add\n"
+"new files yourself (see 'git help status')."
+msgstr ""
+"Det tog %.2f sekunder att räkna upp ospårade filer. \"status -uno\"\n"
+"kan gå snabbare, men du måste vara försiktig så du inte glömmer\n"
+"lägga till nya filer själv (se \"git help status\")."
 
 # %s är nästa sträng eller tom.
-#: wt-status.c:1238
+#: wt-status.c:1235
 #, c-format
 msgid "Untracked files not listed%s"
 msgstr "Ospårade filer visas ej%s"
 
-#: wt-status.c:1240
+#: wt-status.c:1237
 msgid " (use -u option to show untracked files)"
 msgstr " (använd flaggan -u för att visa ospårade filer)"
 
-#: wt-status.c:1246
+#: wt-status.c:1243
 msgid "No changes"
 msgstr "Inga ändringar"
 
-#: wt-status.c:1251
+#: wt-status.c:1248
 #, c-format
 msgid "no changes added to commit (use \"git add\" and/or \"git commit -a\")\n"
 msgstr ""
 "inga ändringar att checka in (använd \"git add\" och/eller \"git commit -a"
 "\")\n"
 
-#: wt-status.c:1254
+#: wt-status.c:1251
 #, c-format
 msgid "no changes added to commit\n"
 msgstr "inga ändringar att checka in\n"
 
-#: wt-status.c:1257
+#: wt-status.c:1254
 #, c-format
 msgid ""
 "nothing added to commit but untracked files present (use \"git add\" to "
@@ -1455,52 +1628,52 @@
 "inget köat för incheckning, men ospårade filer finns (spåra med \"git add"
 "\")\n"
 
-#: wt-status.c:1260
+#: wt-status.c:1257
 #, c-format
 msgid "nothing added to commit but untracked files present\n"
 msgstr "inget köat för incheckning, men ospårade filer finns\n"
 
-#: wt-status.c:1263
+#: wt-status.c:1260
 #, c-format
 msgid "nothing to commit (create/copy files and use \"git add\" to track)\n"
 msgstr "inget att checka in (skapa/kopiera filer och spåra med \"git add\")\n"
 
-#: wt-status.c:1266 wt-status.c:1271
+#: wt-status.c:1263 wt-status.c:1268
 #, c-format
 msgid "nothing to commit\n"
 msgstr "inget att checka in\n"
 
-#: wt-status.c:1269
+#: wt-status.c:1266
 #, c-format
 msgid "nothing to commit (use -u to show untracked files)\n"
 msgstr "inget att checka in (använd -u för att visa ospårade filer)\n"
 
-#: wt-status.c:1273
+#: wt-status.c:1270
 #, c-format
 msgid "nothing to commit, working directory clean\n"
 msgstr "inget att checka in, arbetskatalogen ren\n"
 
-#: wt-status.c:1381
+#: wt-status.c:1378
 msgid "HEAD (no branch)"
 msgstr "HEAD (ingen gren)"
 
-#: wt-status.c:1387
+#: wt-status.c:1384
 msgid "Initial commit on "
 msgstr "Första incheckning på "
 
-#: wt-status.c:1402
+#: wt-status.c:1399
 msgid "behind "
 msgstr "efter "
 
-#: wt-status.c:1405 wt-status.c:1408
+#: wt-status.c:1402 wt-status.c:1405
 msgid "ahead "
 msgstr "före "
 
-#: wt-status.c:1410
+#: wt-status.c:1407
 msgid ", behind "
 msgstr ", efter "
 
-#: compat/precompose_utf8.c:58 builtin/clone.c:342
+#: compat/precompose_utf8.c:58 builtin/clone.c:351
 #, c-format
 msgid "failed to unlink '%s'"
 msgstr "misslyckades ta bort länken \"%s\""
@@ -1509,125 +1682,6 @@
 msgid "git add [options] [--] <pathspec>..."
 msgstr "git add [flaggor] [--] <sökväg>..."
 
-#: builtin/add.c:63
-#, c-format
-msgid "unexpected diff status %c"
-msgstr "diff-status %c förväntades inte"
-
-#: builtin/add.c:68 builtin/commit.c:233
-msgid "updating files failed"
-msgstr "misslyckades uppdatera filer"
-
-#: builtin/add.c:78
-#, c-format
-msgid "remove '%s'\n"
-msgstr "ta bort \"%s\"\n"
-
-#: builtin/add.c:148
-msgid "Unstaged changes after refreshing the index:"
-msgstr "Ospårade ändringar efter att ha uppdaterat indexet:"
-
-#: builtin/add.c:151 builtin/add.c:460 builtin/rm.c:275
-#, c-format
-msgid "pathspec '%s' did not match any files"
-msgstr "sökvägsangivelsen \"%s\" motsvarade inte några filer"
-
-#: builtin/add.c:234
-msgid "Could not read the index"
-msgstr "Kunde inte läsa indexet"
-
-#: builtin/add.c:244
-#, c-format
-msgid "Could not open '%s' for writing."
-msgstr "Kunde inte öppna \"%s\" för skrivning"
-
-#: builtin/add.c:248
-msgid "Could not write patch"
-msgstr "Kunde inte skriva patch"
-
-#: builtin/add.c:253
-#, c-format
-msgid "Could not stat '%s'"
-msgstr "Kunde inte ta status på \"%s\""
-
-#: builtin/add.c:255
-msgid "Empty patch. Aborted."
-msgstr "Tom patch. Avbryter."
-
-#: builtin/add.c:261
-#, c-format
-msgid "Could not apply '%s'"
-msgstr "Kunde inte tillämpa \"%s\""
-
-#: builtin/add.c:271
-msgid "The following paths are ignored by one of your .gitignore files:\n"
-msgstr "Följande sökvägar ignoreras av en av dina .gitignore-filer:\n"
-
-#: builtin/add.c:277 builtin/clean.c:161 builtin/fetch.c:78 builtin/mv.c:63
-#: builtin/prune-packed.c:76 builtin/push.c:425 builtin/remote.c:1253
-#: builtin/rm.c:206
-msgid "dry run"
-msgstr "testkörning"
-
-#: builtin/add.c:278 builtin/apply.c:4409 builtin/check-ignore.c:19
-#: builtin/commit.c:1152 builtin/count-objects.c:95 builtin/fsck.c:613
-#: builtin/log.c:1514 builtin/mv.c:62 builtin/read-tree.c:112
-msgid "be verbose"
-msgstr "var pratsam"
-
-#: builtin/add.c:280
-msgid "interactive picking"
-msgstr "plocka interaktivt"
-
-#: builtin/add.c:281 builtin/checkout.c:1060 builtin/reset.c:258
-msgid "select hunks interactively"
-msgstr "välj stycken interaktivt"
-
-#: builtin/add.c:282
-msgid "edit current diff and apply"
-msgstr "redigera aktuell diff och applicera"
-
-#: builtin/add.c:283
-msgid "allow adding otherwise ignored files"
-msgstr "tillåt lägga till annars ignorerade filer"
-
-#: builtin/add.c:284
-msgid "update tracked files"
-msgstr "uppdatera spårade filer"
-
-#: builtin/add.c:285
-msgid "record only the fact that the path will be added later"
-msgstr "registrera endast att sökvägen kommer läggas till senare"
-
-#: builtin/add.c:286
-msgid "add changes from all tracked and untracked files"
-msgstr "lägg till ändringar från alla spårade och ospårade filer"
-
-#: builtin/add.c:287
-msgid "don't add, only refresh the index"
-msgstr "lägg inte till, uppdatera endast indexet"
-
-#: builtin/add.c:288
-msgid "just skip files which cannot be added because of errors"
-msgstr "hoppa bara över filer som inte kan läggas till på grund av fel"
-
-#: builtin/add.c:289
-msgid "check if - even missing - files are ignored in dry run"
-msgstr "se om - även saknade - filer ignoreras i testkörning"
-
-#: builtin/add.c:311
-#, c-format
-msgid "Use -f if you really want to add them.\n"
-msgstr "Använd -f om du verkligen vill lägga till dem.\n"
-
-#: builtin/add.c:312
-msgid "no files added"
-msgstr "inga filer har lagts till"
-
-#: builtin/add.c:318
-msgid "adding files failed"
-msgstr "misslyckades lägga till filer"
-
 #.
 #. * To be consistent with "git add -p" and most Git
 #. * commands, we should default to being tree-wide, but
@@ -1638,7 +1692,7 @@
 #. * to tree-wide, keeping the warning for a while, and
 #. * eventually we can drop the warning.
 #.
-#: builtin/add.c:335
+#: builtin/add.c:58
 #, c-format
 msgid ""
 "The behavior of 'git add %s (or %s)' with no path argument from a\n"
@@ -1655,7 +1709,7 @@
 "  (or git add %s .)\n"
 "\n"
 "With the current Git version, the command is restricted to the current "
-"directory."
+"directory.\n"
 msgstr ""
 "Beteendet för \"git add %s (eller %s)\" utan sökvägsargument från en\n"
 "underkatalog i ett träd kommer ändras i Git 2.0 och bör inte längre "
@@ -1670,32 +1724,184 @@
 "  git add %s .\n"
 "  (eller git add %s .)\n"
 "\n"
-"I nuvarande version av Git begränsas kommandot till aktuell katalog."
+"I nuvarande version av Git begränsas kommandot till aktuell katalog.\n"
 
-#: builtin/add.c:381
+#: builtin/add.c:100
+#, c-format
+msgid ""
+"You ran 'git add' with neither '-A (--all)' or '--ignore-removal',\n"
+"whose behaviour will change in Git 2.0 with respect to paths you removed.\n"
+"Paths like '%s' that are\n"
+"removed from your working tree are ignored with this version of Git.\n"
+"\n"
+"* 'git add --ignore-removal <pathspec>', which is the current default,\n"
+"  ignores paths you removed from your working tree.\n"
+"\n"
+"* 'git add --all <pathspec>' will let you also record the removals.\n"
+"\n"
+"Run 'git status' to check the paths you removed from your working tree.\n"
+msgstr ""
+"Du körde \"git add\" utan varken \"-A (--all)\" eller \"--ignore-removal\".\n"
+"Beteendet kommer ändras i Git 2.0 vad gäller sökvägar du tagit bort.\n"
+"Sökvägar som \"%s\", som har\n"
+"tagits bort från din arbetskatalog ignoreras i den här versionen av Git.\n"
+"\n"
+"* \"git add --ignore-removal <sökväg>\", som är förvalet just nu,\n"
+"  ignorerar sökvägar du har tagit bort från arbetskatalogen.\n"
+"\n"
+"* \"git add --all <sökväg>\" låter dig även registrera borttagningarna.\n"
+"\n"
+"Kör \"git status\" för att kontrollera sökvägarna du tagit bort från\n"
+"arbetskatalogen.\n"
+
+#: builtin/add.c:144
+#, c-format
+msgid "unexpected diff status %c"
+msgstr "diff-status %c förväntades inte"
+
+#: builtin/add.c:149 builtin/commit.c:252
+msgid "updating files failed"
+msgstr "misslyckades uppdatera filer"
+
+#: builtin/add.c:163
+#, c-format
+msgid "remove '%s'\n"
+msgstr "ta bort \"%s\"\n"
+
+#: builtin/add.c:253
+msgid "Unstaged changes after refreshing the index:"
+msgstr "Ospårade ändringar efter att ha uppdaterat indexet:"
+
+#: builtin/add.c:256 builtin/add.c:573 builtin/rm.c:337
+#, c-format
+msgid "pathspec '%s' did not match any files"
+msgstr "sökvägsangivelsen \"%s\" motsvarade inte några filer"
+
+#: builtin/add.c:339
+msgid "Could not read the index"
+msgstr "Kunde inte läsa indexet"
+
+#: builtin/add.c:350
+#, c-format
+msgid "Could not open '%s' for writing."
+msgstr "Kunde inte öppna \"%s\" för skrivning"
+
+#: builtin/add.c:354
+msgid "Could not write patch"
+msgstr "Kunde inte skriva patch"
+
+#: builtin/add.c:359
+#, c-format
+msgid "Could not stat '%s'"
+msgstr "Kunde inte ta status på \"%s\""
+
+#: builtin/add.c:361
+msgid "Empty patch. Aborted."
+msgstr "Tom patch. Avbryter."
+
+#: builtin/add.c:367
+#, c-format
+msgid "Could not apply '%s'"
+msgstr "Kunde inte tillämpa \"%s\""
+
+#: builtin/add.c:377
+msgid "The following paths are ignored by one of your .gitignore files:\n"
+msgstr "Följande sökvägar ignoreras av en av dina .gitignore-filer:\n"
+
+#: builtin/add.c:394 builtin/clean.c:875 builtin/fetch.c:78 builtin/mv.c:63
+#: builtin/prune-packed.c:73 builtin/push.c:451 builtin/remote.c:1253
+#: builtin/rm.c:268
+msgid "dry run"
+msgstr "testkörning"
+
+#: builtin/add.c:395 builtin/apply.c:4410 builtin/check-ignore.c:19
+#: builtin/commit.c:1220 builtin/count-objects.c:95 builtin/fsck.c:613
+#: builtin/log.c:1573 builtin/mv.c:62 builtin/read-tree.c:113
+msgid "be verbose"
+msgstr "var pratsam"
+
+#: builtin/add.c:397
+msgid "interactive picking"
+msgstr "plocka interaktivt"
+
+#: builtin/add.c:398 builtin/checkout.c:1073 builtin/reset.c:261
+msgid "select hunks interactively"
+msgstr "välj stycken interaktivt"
+
+#: builtin/add.c:399
+msgid "edit current diff and apply"
+msgstr "redigera aktuell diff och applicera"
+
+#: builtin/add.c:400
+msgid "allow adding otherwise ignored files"
+msgstr "tillåt lägga till annars ignorerade filer"
+
+#: builtin/add.c:401
+msgid "update tracked files"
+msgstr "uppdatera spårade filer"
+
+#: builtin/add.c:402
+msgid "record only the fact that the path will be added later"
+msgstr "registrera endast att sökvägen kommer läggas till senare"
+
+#: builtin/add.c:403
+msgid "add changes from all tracked and untracked files"
+msgstr "lägg till ändringar från alla spårade och ospårade filer"
+
+#. takes no arguments
+#: builtin/add.c:406
+msgid "ignore paths removed in the working tree (same as --no-all)"
+msgstr "ignorera sökvägar borttagna i arbetskatalogen (samma som --no-all)"
+
+#: builtin/add.c:408
+msgid "don't add, only refresh the index"
+msgstr "lägg inte till, uppdatera endast indexet"
+
+#: builtin/add.c:409
+msgid "just skip files which cannot be added because of errors"
+msgstr "hoppa bara över filer som inte kan läggas till på grund av fel"
+
+#: builtin/add.c:410
+msgid "check if - even missing - files are ignored in dry run"
+msgstr "se om - även saknade - filer ignoreras i testkörning"
+
+#: builtin/add.c:432
+#, c-format
+msgid "Use -f if you really want to add them.\n"
+msgstr "Använd -f om du verkligen vill lägga till dem.\n"
+
+#: builtin/add.c:433
+msgid "no files added"
+msgstr "inga filer har lagts till"
+
+#: builtin/add.c:439
+msgid "adding files failed"
+msgstr "misslyckades lägga till filer"
+
+#: builtin/add.c:478
 msgid "-A and -u are mutually incompatible"
 msgstr "-A och -u är ömsesidigt inkompatibla"
 
-#: builtin/add.c:383
+#: builtin/add.c:496
 msgid "Option --ignore-missing can only be used together with --dry-run"
 msgstr "Flaggan --ignore-missing kan endast användas tillsammans med --dry-run"
 
-#: builtin/add.c:414
+#: builtin/add.c:526
 #, c-format
 msgid "Nothing specified, nothing added.\n"
 msgstr "Inget angivet, inget tillagt.\n"
 
-#: builtin/add.c:415
+#: builtin/add.c:527
 #, c-format
 msgid "Maybe you wanted to say 'git add .'?\n"
 msgstr "Kanske menade du att skriva \"git add .\"?\n"
 
-#: builtin/add.c:421 builtin/check-ignore.c:67 builtin/clean.c:204
-#: builtin/commit.c:293 builtin/mv.c:82 builtin/rm.c:235
+#: builtin/add.c:533 builtin/check-ignore.c:161 builtin/clean.c:919
+#: builtin/commit.c:312 builtin/mv.c:82 builtin/rm.c:297
 msgid "index file corrupt"
 msgstr "indexfilen trasig"
 
-#: builtin/add.c:481 builtin/apply.c:4505 builtin/mv.c:229 builtin/rm.c:370
+#: builtin/add.c:605 builtin/apply.c:4506 builtin/mv.c:229 builtin/rm.c:432
 msgid "Unable to write new index file"
 msgstr "Kunde inte skriva ny indexfil"
 
@@ -1879,293 +2085,293 @@
 msgid "cannot checkout %s"
 msgstr "kan inte checka ut %s"
 
-#: builtin/apply.c:3140 builtin/apply.c:3149 builtin/apply.c:3193
+#: builtin/apply.c:3140 builtin/apply.c:3149 builtin/apply.c:3194
 #, c-format
 msgid "read of %s failed"
 msgstr "misslyckades läsa %s"
 
-#: builtin/apply.c:3173 builtin/apply.c:3395
+#: builtin/apply.c:3174 builtin/apply.c:3396
 #, c-format
 msgid "path %s has been renamed/deleted"
 msgstr "sökvägen %s har ändrat namn/tagits bort"
 
-#: builtin/apply.c:3254 builtin/apply.c:3409
+#: builtin/apply.c:3255 builtin/apply.c:3410
 #, c-format
 msgid "%s: does not exist in index"
 msgstr "%s: finns inte i indexet"
 
-#: builtin/apply.c:3258 builtin/apply.c:3401 builtin/apply.c:3423
+#: builtin/apply.c:3259 builtin/apply.c:3402 builtin/apply.c:3424
 #, c-format
 msgid "%s: %s"
 msgstr "%s: %s"
 
-#: builtin/apply.c:3263 builtin/apply.c:3417
+#: builtin/apply.c:3264 builtin/apply.c:3418
 #, c-format
 msgid "%s: does not match index"
 msgstr "%s: motsvarar inte indexet"
 
-#: builtin/apply.c:3365
+#: builtin/apply.c:3366
 msgid "removal patch leaves file contents"
 msgstr "patch för borttagning lämnar kvar filinnehåll"
 
-#: builtin/apply.c:3434
+#: builtin/apply.c:3435
 #, c-format
 msgid "%s: wrong type"
 msgstr "%s: fel typ"
 
-#: builtin/apply.c:3436
+#: builtin/apply.c:3437
 #, c-format
 msgid "%s has type %o, expected %o"
 msgstr "%s har typen %o, förväntade %o"
 
-#: builtin/apply.c:3537
+#: builtin/apply.c:3538
 #, c-format
 msgid "%s: already exists in index"
 msgstr "%s: finns redan i indexet"
 
-#: builtin/apply.c:3540
+#: builtin/apply.c:3541
 #, c-format
 msgid "%s: already exists in working directory"
 msgstr "%s: finns redan i arbetskatalogen"
 
-#: builtin/apply.c:3560
+#: builtin/apply.c:3561
 #, c-format
 msgid "new mode (%o) of %s does not match old mode (%o)"
 msgstr "nytt läge (%o) för %s motsvarar inte gammalt läge (%o)"
 
-#: builtin/apply.c:3565
+#: builtin/apply.c:3566
 #, c-format
 msgid "new mode (%o) of %s does not match old mode (%o) of %s"
 msgstr "nytt läge (%o) för %s motsvarar inte gammalt läge (%o) för %s"
 
-#: builtin/apply.c:3573
+#: builtin/apply.c:3574
 #, c-format
 msgid "%s: patch does not apply"
 msgstr "%s: patchen kan inte tillämpas"
 
-#: builtin/apply.c:3586
+#: builtin/apply.c:3587
 #, c-format
 msgid "Checking patch %s..."
 msgstr "Kontrollerar patchen %s..."
 
-#: builtin/apply.c:3679 builtin/checkout.c:215 builtin/reset.c:124
+#: builtin/apply.c:3680 builtin/checkout.c:216 builtin/reset.c:127
 #, c-format
 msgid "make_cache_entry failed for path '%s'"
 msgstr "make_cache_entry misslyckades för sökvägen \"%s\""
 
-#: builtin/apply.c:3822
+#: builtin/apply.c:3823
 #, c-format
 msgid "unable to remove %s from index"
 msgstr "kan inte ta bort %s från indexet"
 
-#: builtin/apply.c:3850
+#: builtin/apply.c:3851
 #, c-format
-msgid "corrupt patch for subproject %s"
-msgstr "trasig patch för underprojektet %s"
+msgid "corrupt patch for submodule %s"
+msgstr "trasig patch för undermodulen %s"
 
-#: builtin/apply.c:3854
+#: builtin/apply.c:3855
 #, c-format
 msgid "unable to stat newly created file '%s'"
 msgstr "kan inte ta status på nyligen skapade filen \"%s\""
 
-#: builtin/apply.c:3859
+#: builtin/apply.c:3860
 #, c-format
 msgid "unable to create backing store for newly created file %s"
 msgstr "kan inte skapa säkerhetsminne för nyligen skapade filen %s"
 
-#: builtin/apply.c:3862 builtin/apply.c:3970
+#: builtin/apply.c:3863 builtin/apply.c:3971
 #, c-format
 msgid "unable to add cache entry for %s"
 msgstr "kan inte lägga till cachepost för %s"
 
-#: builtin/apply.c:3895
+#: builtin/apply.c:3896
 #, c-format
 msgid "closing file '%s'"
 msgstr "stänger filen \"%s\""
 
-#: builtin/apply.c:3944
+#: builtin/apply.c:3945
 #, c-format
 msgid "unable to write file '%s' mode %o"
 msgstr "kan inte skriva filen \"%s\" läge %o"
 
-#: builtin/apply.c:4031
+#: builtin/apply.c:4032
 #, c-format
 msgid "Applied patch %s cleanly."
 msgstr "Tillämpade patchen %s rent."
 
-#: builtin/apply.c:4039
+#: builtin/apply.c:4040
 msgid "internal error"
 msgstr "internt fel"
 
 #. Say this even without --verbose
-#: builtin/apply.c:4042
+#: builtin/apply.c:4043
 #, c-format
 msgid "Applying patch %%s with %d reject..."
 msgid_plural "Applying patch %%s with %d rejects..."
 msgstr[0] "Tillämpade patchen %%s med %d refuserad..."
 msgstr[1] "Tillämpade patchen %%s med %d refuserade..."
 
-#: builtin/apply.c:4052
+#: builtin/apply.c:4053
 #, c-format
 msgid "truncating .rej filename to %.*s.rej"
 msgstr "trunkerar .rej-filnamnet till %.*s.rej"
 
-#: builtin/apply.c:4073
+#: builtin/apply.c:4074
 #, c-format
 msgid "Hunk #%d applied cleanly."
 msgstr "Stycke %d tillämpades rent."
 
-#: builtin/apply.c:4076
+#: builtin/apply.c:4077
 #, c-format
 msgid "Rejected hunk #%d."
 msgstr "Refuserar stycke %d."
 
-#: builtin/apply.c:4226
+#: builtin/apply.c:4227
 msgid "unrecognized input"
 msgstr "indata känns inte igen"
 
-#: builtin/apply.c:4237
+#: builtin/apply.c:4238
 msgid "unable to read index file"
 msgstr "kan inte läsa indexfilen"
 
-#: builtin/apply.c:4356 builtin/apply.c:4359 builtin/clone.c:92
+#: builtin/apply.c:4357 builtin/apply.c:4360 builtin/clone.c:91
 #: builtin/fetch.c:63
 msgid "path"
 msgstr "sökväg"
 
-#: builtin/apply.c:4357
+#: builtin/apply.c:4358
 msgid "don't apply changes matching the given path"
 msgstr "tillämpa inte ändringar som motsvarar given sökväg"
 
-#: builtin/apply.c:4360
+#: builtin/apply.c:4361
 msgid "apply changes matching the given path"
 msgstr "tillämpa ändringar som motsvarar given sökväg"
 
-#: builtin/apply.c:4362
+#: builtin/apply.c:4363
 msgid "num"
 msgstr "antal"
 
-#: builtin/apply.c:4363
+#: builtin/apply.c:4364
 msgid "remove <num> leading slashes from traditional diff paths"
 msgstr "ta bort <antal> inledande snedstreck från traditionella diff-sökvägar"
 
-#: builtin/apply.c:4366
+#: builtin/apply.c:4367
 msgid "ignore additions made by the patch"
 msgstr "ignorera tillägg gjorda av patchen"
 
-#: builtin/apply.c:4368
+#: builtin/apply.c:4369
 msgid "instead of applying the patch, output diffstat for the input"
 msgstr "istället för att tillämpa patchen, skriv ut diffstat för indata"
 
-#: builtin/apply.c:4372
+#: builtin/apply.c:4373
 msgid "show number of added and deleted lines in decimal notation"
 msgstr "visa antal tillagda och borttagna rader decimalt"
 
-#: builtin/apply.c:4374
+#: builtin/apply.c:4375
 msgid "instead of applying the patch, output a summary for the input"
 msgstr "istället för att tillämpa patchen, skriv ut en summering av indata"
 
-#: builtin/apply.c:4376
+#: builtin/apply.c:4377
 msgid "instead of applying the patch, see if the patch is applicable"
 msgstr "istället för att tillämpa patchen, se om patchen kan tillämpas"
 
-#: builtin/apply.c:4378
+#: builtin/apply.c:4379
 msgid "make sure the patch is applicable to the current index"
 msgstr "se till att patchen kan tillämpas på aktuellt index"
 
-#: builtin/apply.c:4380
+#: builtin/apply.c:4381
 msgid "apply a patch without touching the working tree"
 msgstr "tillämpa en patch utan att röra arbetskatalogen"
 
-#: builtin/apply.c:4382
+#: builtin/apply.c:4383
 msgid "also apply the patch (use with --stat/--summary/--check)"
 msgstr "tillämpa också patchen (använd med --stat/--summary/--check)"
 
-#: builtin/apply.c:4384
+#: builtin/apply.c:4385
 msgid "attempt three-way merge if a patch does not apply"
 msgstr "försök en trevägssammanslagning om patchen inte kan tillämpas"
 
-#: builtin/apply.c:4386
+#: builtin/apply.c:4387
 msgid "build a temporary index based on embedded index information"
 msgstr "bygg ett temporärt index baserat på inbyggd indexinformation"
 
-#: builtin/apply.c:4388 builtin/checkout-index.c:197 builtin/ls-files.c:463
+#: builtin/apply.c:4389 builtin/checkout-index.c:197 builtin/ls-files.c:462
 msgid "paths are separated with NUL character"
 msgstr "sökvägar avdelas med NUL-tecken"
 
-#: builtin/apply.c:4391
+#: builtin/apply.c:4392
 msgid "ensure at least <n> lines of context match"
 msgstr "se till att åtminstone <n> rader sammanhang är lika"
 
-#: builtin/apply.c:4392
+#: builtin/apply.c:4393
 msgid "action"
 msgstr "åtgärd"
 
-#: builtin/apply.c:4393
+#: builtin/apply.c:4394
 msgid "detect new or modified lines that have whitespace errors"
 msgstr "detektera nya eller ändrade rader som har fel i blanktecken"
 
-#: builtin/apply.c:4396 builtin/apply.c:4399
+#: builtin/apply.c:4397 builtin/apply.c:4400
 msgid "ignore changes in whitespace when finding context"
 msgstr "ignorera ändringar i blanktecken för sammanhang"
 
-#: builtin/apply.c:4402
+#: builtin/apply.c:4403
 msgid "apply the patch in reverse"
 msgstr "tillämpa patchen baklänges"
 
-#: builtin/apply.c:4404
+#: builtin/apply.c:4405
 msgid "don't expect at least one line of context"
 msgstr "förvänta inte minst en rad sammanhang"
 
-#: builtin/apply.c:4406
+#: builtin/apply.c:4407
 msgid "leave the rejected hunks in corresponding *.rej files"
 msgstr "lämna refuserade stycken i motsvarande *.rej-filer"
 
-#: builtin/apply.c:4408
+#: builtin/apply.c:4409
 msgid "allow overlapping hunks"
 msgstr "tillåt överlappande stycken"
 
-#: builtin/apply.c:4411
+#: builtin/apply.c:4412
 msgid "tolerate incorrectly detected missing new-line at the end of file"
 msgstr "tolerera felaktigt detekterade saknade nyradstecken vid filslut"
 
-#: builtin/apply.c:4414
+#: builtin/apply.c:4415
 msgid "do not trust the line counts in the hunk headers"
 msgstr "lite inte på antalet linjer i styckehuvuden"
 
-#: builtin/apply.c:4416
+#: builtin/apply.c:4417
 msgid "root"
 msgstr "rot"
 
-#: builtin/apply.c:4417
+#: builtin/apply.c:4418
 msgid "prepend <root> to all filenames"
 msgstr "lägg till <rot> i alla filnamn"
 
-#: builtin/apply.c:4439
+#: builtin/apply.c:4440
 msgid "--3way outside a repository"
 msgstr "--3way utanför arkiv"
 
-#: builtin/apply.c:4447
+#: builtin/apply.c:4448
 msgid "--index outside a repository"
 msgstr "--index utanför arkiv"
 
-#: builtin/apply.c:4450
+#: builtin/apply.c:4451
 msgid "--cached outside a repository"
 msgstr "--cached utanför arkiv"
 
-#: builtin/apply.c:4466
+#: builtin/apply.c:4467
 #, c-format
 msgid "can't open patch '%s'"
 msgstr "kan inte öppna patchen \"%s\""
 
-#: builtin/apply.c:4480
+#: builtin/apply.c:4481
 #, c-format
 msgid "squelched %d whitespace error"
 msgid_plural "squelched %d whitespace errors"
 msgstr[0] "undertryckte %d fel i blanksteg"
 msgstr[1] "undertryckte %d fel i blanksteg"
 
-#: builtin/apply.c:4486 builtin/apply.c:4496
+#: builtin/apply.c:4487 builtin/apply.c:4497
 #, c-format
 msgid "%d line adds whitespace errors."
 msgid_plural "%d lines add whitespace errors."
@@ -2219,103 +2425,103 @@
 msgid "update BISECT_HEAD instead of checking out the current commit"
 msgstr "uppdatera BISECT_HEAD istället för att checka ut aktuell incheckning"
 
-#: builtin/blame.c:25
+#: builtin/blame.c:26
 msgid "git blame [options] [rev-opts] [rev] [--] file"
 msgstr "git blame [flaggor] [rev-flaggor] [rev] [--] fil"
 
-#: builtin/blame.c:30 builtin/shortlog.c:15
+#: builtin/blame.c:31
 msgid "[rev-opts] are documented in git-rev-list(1)"
 msgstr "[rev-flaggor] dokumenteras i git-rev-list(1)"
 
-#: builtin/blame.c:2350
+#: builtin/blame.c:2276
 msgid "Show blame entries as we find them, incrementally"
 msgstr "Visa klandringsposter när vi hittar dem, interaktivt"
 
-#: builtin/blame.c:2351
+#: builtin/blame.c:2277
 msgid "Show blank SHA-1 for boundary commits (Default: off)"
 msgstr "Visa blank SHA-1 för gränsincheckningar (Standard: av)"
 
-#: builtin/blame.c:2352
+#: builtin/blame.c:2278
 msgid "Do not treat root commits as boundaries (Default: off)"
 msgstr "Behandla inte rotincheckningar som gränser (Standard: av)"
 
-#: builtin/blame.c:2353
+#: builtin/blame.c:2279
 msgid "Show work cost statistics"
 msgstr "Visa statistik över arbetskostnad"
 
-#: builtin/blame.c:2354
+#: builtin/blame.c:2280
 msgid "Show output score for blame entries"
 msgstr "Visa utdatapoäng för klandringsposter"
 
-#: builtin/blame.c:2355
+#: builtin/blame.c:2281
 msgid "Show original filename (Default: auto)"
 msgstr "Visa originalfilnamn (Standard: auto)"
 
-#: builtin/blame.c:2356
+#: builtin/blame.c:2282
 msgid "Show original linenumber (Default: off)"
 msgstr "Visa ursprungligt radnummer (Standard: av)"
 
-#: builtin/blame.c:2357
+#: builtin/blame.c:2283
 msgid "Show in a format designed for machine consumption"
 msgstr "Visa i ett format avsett för maskinkonsumtion"
 
-#: builtin/blame.c:2358
+#: builtin/blame.c:2284
 msgid "Show porcelain format with per-line commit information"
 msgstr "Visa porslinsformat med per-rad-incheckningsinformation"
 
-#: builtin/blame.c:2359
+#: builtin/blame.c:2285
 msgid "Use the same output mode as git-annotate (Default: off)"
 msgstr "Använd samma utdataläge som git-annotate (Standard: av)"
 
-#: builtin/blame.c:2360
+#: builtin/blame.c:2286
 msgid "Show raw timestamp (Default: off)"
 msgstr "Visa rå tidsstämpel (Standard: av)"
 
-#: builtin/blame.c:2361
+#: builtin/blame.c:2287
 msgid "Show long commit SHA1 (Default: off)"
 msgstr "Visa lång inchecknings-SHA1 (Standard: av)"
 
-#: builtin/blame.c:2362
+#: builtin/blame.c:2288
 msgid "Suppress author name and timestamp (Default: off)"
 msgstr "Undertryck författarnamn och tidsstämpel (Standard: av)"
 
-#: builtin/blame.c:2363
+#: builtin/blame.c:2289
 msgid "Show author email instead of name (Default: off)"
 msgstr "Visa författarens e-post istället för namn (Standard: av)"
 
-#: builtin/blame.c:2364
+#: builtin/blame.c:2290
 msgid "Ignore whitespace differences"
 msgstr "Ignorera ändringar i blanksteg"
 
-#: builtin/blame.c:2365
+#: builtin/blame.c:2291
 msgid "Spend extra cycles to find better match"
 msgstr "Slösa extra cykler med att hitta bättre träff"
 
-#: builtin/blame.c:2366
+#: builtin/blame.c:2292
 msgid "Use revisions from <file> instead of calling git-rev-list"
 msgstr "Använd revisioner från <fil> istället för att anropa git-rev-list"
 
-#: builtin/blame.c:2367
+#: builtin/blame.c:2293
 msgid "Use <file>'s contents as the final image"
 msgstr "Använd <fil>s innehåll som slutgiltig bild"
 
-#: builtin/blame.c:2368 builtin/blame.c:2369
+#: builtin/blame.c:2294 builtin/blame.c:2295
 msgid "score"
 msgstr "poäng"
 
-#: builtin/blame.c:2368
+#: builtin/blame.c:2294
 msgid "Find line copies within and across files"
 msgstr "Hitta kopierade rader inuti och mellan filer"
 
-#: builtin/blame.c:2369
+#: builtin/blame.c:2295
 msgid "Find line movements within and across files"
 msgstr "Hitta flyttade rader inuti och mellan filer"
 
-#: builtin/blame.c:2370
+#: builtin/blame.c:2296
 msgid "n,m"
 msgstr "n,m"
 
-#: builtin/blame.c:2370
+#: builtin/blame.c:2296
 msgid "Process only line range n,m, counting from 1"
 msgstr "Behandla endast radintervallet n,m, med början på 1"
 
@@ -2335,7 +2541,7 @@
 msgid "git branch [options] (-m | -M) [<oldbranch>] <newbranch>"
 msgstr "git branch [flaggor] (-m | -M) [<gammal_gren>] <ny_gren>"
 
-#: builtin/branch.c:146
+#: builtin/branch.c:150
 #, c-format
 msgid ""
 "deleting branch '%s' that has been merged to\n"
@@ -2344,7 +2550,7 @@
 "tar bort grenen \"%s\" som har slagits ihop med\n"
 "         \"%s\", men ännu inte slagits ihop med HEAD."
 
-#: builtin/branch.c:150
+#: builtin/branch.c:154
 #, c-format
 msgid ""
 "not deleting branch '%s' that is not yet merged to\n"
@@ -2353,12 +2559,12 @@
 "tar inte bort grenen \"%s\" som inte har slagits ihop med\n"
 "         \"%s\", trots att den har slagits ihop med HEAD."
 
-#: builtin/branch.c:164
+#: builtin/branch.c:168
 #, c-format
 msgid "Couldn't look up commit object for '%s'"
 msgstr "Kunde inte slå upp incheckningsobjekt för \"%s\""
 
-#: builtin/branch.c:168
+#: builtin/branch.c:172
 #, c-format
 msgid ""
 "The branch '%s' is not fully merged.\n"
@@ -2367,332 +2573,332 @@
 "Grenen \"%s\" har inte slagits samman i sin helhet.\n"
 "Om du är säker på att du vill ta bort den, kör \"git branch -D %s\"."
 
-#: builtin/branch.c:181
+#: builtin/branch.c:185
 msgid "Update of config-file failed"
 msgstr "Misslyckades uppdatera konfigurationsfil"
 
-#: builtin/branch.c:209
+#: builtin/branch.c:213
 msgid "cannot use -a with -d"
 msgstr "kan inte ange -a med -d"
 
-#: builtin/branch.c:215
+#: builtin/branch.c:219
 msgid "Couldn't look up commit object for HEAD"
 msgstr "Kunde inte slå upp incheckningsobjekt för HEAD"
 
-#: builtin/branch.c:223
+#: builtin/branch.c:227
 #, c-format
 msgid "Cannot delete the branch '%s' which you are currently on."
 msgstr "Kan inte ta bort grenen \"%s\" som du befinner dig på för närvarande."
 
-#: builtin/branch.c:236
+#: builtin/branch.c:240
 #, c-format
 msgid "remote branch '%s' not found."
 msgstr "fjärrgrenen \"%s\" hittades inte."
 
-#: builtin/branch.c:237
+#: builtin/branch.c:241
 #, c-format
 msgid "branch '%s' not found."
 msgstr "grenen \"%s\" hittades inte."
 
-#: builtin/branch.c:251
+#: builtin/branch.c:255
 #, c-format
 msgid "Error deleting remote branch '%s'"
 msgstr "Fel vid borttagning av fjärrgrenen \"%s\""
 
-#: builtin/branch.c:252
+#: builtin/branch.c:256
 #, c-format
 msgid "Error deleting branch '%s'"
 msgstr "Fel vid borttagning av grenen \"%s\""
 
-#: builtin/branch.c:259
+#: builtin/branch.c:263
 #, c-format
 msgid "Deleted remote branch %s (was %s).\n"
 msgstr "Tog bort fjärrgrenen %s (var %s).\n"
 
-#: builtin/branch.c:260
+#: builtin/branch.c:264
 #, c-format
 msgid "Deleted branch %s (was %s).\n"
 msgstr "Tog bort grenen %s (var %s).\n"
 
-#: builtin/branch.c:362
+#: builtin/branch.c:366
 #, c-format
 msgid "branch '%s' does not point at a commit"
 msgstr "grenen \"%s\" pekar inte på en incheckning"
 
-#: builtin/branch.c:434
+#: builtin/branch.c:453
 #, c-format
 msgid "[%s: behind %d]"
 msgstr "[%s: bakom %d] "
 
-#: builtin/branch.c:436
+#: builtin/branch.c:455
 #, c-format
 msgid "[behind %d]"
 msgstr "[bakom %d] "
 
-#: builtin/branch.c:440
+#: builtin/branch.c:459
 #, c-format
 msgid "[%s: ahead %d]"
 msgstr "[%s: före %d] "
 
-#: builtin/branch.c:442
+#: builtin/branch.c:461
 #, c-format
 msgid "[ahead %d]"
 msgstr "[före %d] "
 
-#: builtin/branch.c:445
+#: builtin/branch.c:464
 #, c-format
 msgid "[%s: ahead %d, behind %d]"
 msgstr "[%s: före %d, bakom %d] "
 
-#: builtin/branch.c:448
+#: builtin/branch.c:467
 #, c-format
 msgid "[ahead %d, behind %d]"
 msgstr "[före %d, bakom %d] "
 
-#: builtin/branch.c:470
+#: builtin/branch.c:490
 msgid " **** invalid ref ****"
 msgstr " **** ogiltig ref ****"
 
-#: builtin/branch.c:562
+#: builtin/branch.c:582
 #, c-format
 msgid "(no branch, rebasing %s)"
 msgstr "(ingen gren, ombaserar %s)"
 
-#: builtin/branch.c:565
+#: builtin/branch.c:585
 #, c-format
 msgid "(no branch, bisect started on %s)"
 msgstr "(ingen gren, \"bisect\" startad på %s)"
 
-#: builtin/branch.c:568
+#: builtin/branch.c:588
 #, c-format
 msgid "(detached from %s)"
 msgstr "(frånkopplad från %s)"
 
-#: builtin/branch.c:571
+#: builtin/branch.c:591
 msgid "(no branch)"
 msgstr "(ingen gren)"
 
-#: builtin/branch.c:617
+#: builtin/branch.c:637
 #, c-format
 msgid "object '%s' does not point to a commit"
 msgstr "objektet \"%s\" pekar på en incheckning"
 
-#: builtin/branch.c:649
+#: builtin/branch.c:669
 msgid "some refs could not be read"
 msgstr "vissa referenser kunde inte läsas"
 
-#: builtin/branch.c:662
+#: builtin/branch.c:682
 msgid "cannot rename the current branch while not on any."
 msgstr ""
 "kunde inte byta namn på aktuell gren när du inte befinner dig på någon."
 
-#: builtin/branch.c:672
+#: builtin/branch.c:692
 #, c-format
 msgid "Invalid branch name: '%s'"
 msgstr "Felaktigt namn på gren: \"%s\""
 
-#: builtin/branch.c:687
+#: builtin/branch.c:707
 msgid "Branch rename failed"
 msgstr "Misslyckades byta namn på gren"
 
-#: builtin/branch.c:691
+#: builtin/branch.c:711
 #, c-format
 msgid "Renamed a misnamed branch '%s' away"
 msgstr "Bytte bort namn på en felaktigt namngiven gren \"%s\""
 
-#: builtin/branch.c:695
+#: builtin/branch.c:715
 #, c-format
 msgid "Branch renamed to %s, but HEAD is not updated!"
 msgstr "Grenen namnbytt till %s, men HEAD har inte uppdaterats!"
 
-#: builtin/branch.c:702
+#: builtin/branch.c:722
 msgid "Branch is renamed, but update of config-file failed"
 msgstr "Grenen namnbytt, men misslyckades uppdatera konfigurationsfilen"
 
-#: builtin/branch.c:717
+#: builtin/branch.c:737
 #, c-format
 msgid "malformed object name %s"
 msgstr "felformat objektnamn %s"
 
-#: builtin/branch.c:741
+#: builtin/branch.c:761
 #, c-format
 msgid "could not write branch description template: %s"
 msgstr "kunde inte skriva grenbeskrivningsmall: %s"
 
-#: builtin/branch.c:771
+#: builtin/branch.c:791
 msgid "Generic options"
 msgstr "Allmänna flaggor"
 
-#: builtin/branch.c:773
+#: builtin/branch.c:793
 msgid "show hash and subject, give twice for upstream branch"
 msgstr "visa hash och ärenderad, ange två gånger för uppströmsgren"
 
-#: builtin/branch.c:774
+#: builtin/branch.c:794
 msgid "suppress informational messages"
 msgstr "undertryck informationsmeddelanden"
 
-#: builtin/branch.c:775
+#: builtin/branch.c:795
 msgid "set up tracking mode (see git-pull(1))"
 msgstr "ställ in spårningsläge (se git-pull(1))"
 
-#: builtin/branch.c:777
+#: builtin/branch.c:797
 msgid "change upstream info"
 msgstr "ändra uppströmsinformation"
 
-#: builtin/branch.c:781
+#: builtin/branch.c:801
 msgid "use colored output"
 msgstr "använd färgad utdata"
 
-#: builtin/branch.c:782
+#: builtin/branch.c:802
 msgid "act on remote-tracking branches"
 msgstr "arbeta på fjärrspårande grenar"
 
-#: builtin/branch.c:785 builtin/branch.c:791 builtin/branch.c:812
-#: builtin/branch.c:818 builtin/commit.c:1368 builtin/commit.c:1369
-#: builtin/commit.c:1370 builtin/commit.c:1371 builtin/tag.c:468
+#: builtin/branch.c:805 builtin/branch.c:811 builtin/branch.c:832
+#: builtin/branch.c:838 builtin/commit.c:1433 builtin/commit.c:1434
+#: builtin/commit.c:1435 builtin/commit.c:1436 builtin/tag.c:468
 msgid "commit"
 msgstr "incheckning"
 
-#: builtin/branch.c:786 builtin/branch.c:792
+#: builtin/branch.c:806 builtin/branch.c:812
 msgid "print only branches that contain the commit"
 msgstr "visa endast grenar som innehåller incheckningen"
 
-#: builtin/branch.c:798
+#: builtin/branch.c:818
 msgid "Specific git-branch actions:"
 msgstr "Specifika git-branch-åtgärder:"
 
-#: builtin/branch.c:799
+#: builtin/branch.c:819
 msgid "list both remote-tracking and local branches"
 msgstr "visa både fjärrspårande och lokala grenar"
 
-#: builtin/branch.c:801
+#: builtin/branch.c:821
 msgid "delete fully merged branch"
 msgstr "ta bort helt sammanslagen gren"
 
-#: builtin/branch.c:802
+#: builtin/branch.c:822
 msgid "delete branch (even if not merged)"
 msgstr "ta bort gren (även om inte helt sammanslagen)"
 
-#: builtin/branch.c:803
+#: builtin/branch.c:823
 msgid "move/rename a branch and its reflog"
 msgstr "flytta/ta bort en gren och dess reflogg"
 
-#: builtin/branch.c:804
+#: builtin/branch.c:824
 msgid "move/rename a branch, even if target exists"
 msgstr "flytta/ta bort en gren, även om målet finns"
 
-#: builtin/branch.c:805
+#: builtin/branch.c:825
 msgid "list branch names"
 msgstr "lista namn på grenar"
 
-#: builtin/branch.c:806
+#: builtin/branch.c:826
 msgid "create the branch's reflog"
 msgstr "skapa grenens reflogg"
 
-#: builtin/branch.c:808
+#: builtin/branch.c:828
 msgid "edit the description for the branch"
 msgstr "redigera beskrivning för grenen"
 
-#: builtin/branch.c:809
+#: builtin/branch.c:829
 msgid "force creation (when already exists)"
 msgstr "tvinga skapande (när den redan finns)"
 
-#: builtin/branch.c:812
+#: builtin/branch.c:832
 msgid "print only not merged branches"
 msgstr "visa endast ej sammanslagna grenar"
 
-#: builtin/branch.c:818
+#: builtin/branch.c:838
 msgid "print only merged branches"
 msgstr "visa endast sammanslagna grenar"
 
-#: builtin/branch.c:822
+#: builtin/branch.c:842
 msgid "list branches in columns"
 msgstr "visa grenar i spalter"
 
-#: builtin/branch.c:835
+#: builtin/branch.c:855
 msgid "Failed to resolve HEAD as a valid ref."
 msgstr "Misslyckades slå upp HEAD som giltig referens"
 
-#: builtin/branch.c:840 builtin/clone.c:609
+#: builtin/branch.c:860 builtin/clone.c:630
 msgid "HEAD not found below refs/heads!"
 msgstr "HEAD hittades inte under refs/heads!"
 
-#: builtin/branch.c:863
+#: builtin/branch.c:883
 msgid "--column and --verbose are incompatible"
 msgstr "--column och --verbose är inkompatibla"
 
-#: builtin/branch.c:869 builtin/branch.c:908
+#: builtin/branch.c:889 builtin/branch.c:928
 msgid "branch name required"
 msgstr "grennamn krävs"
 
-#: builtin/branch.c:884
+#: builtin/branch.c:904
 msgid "Cannot give description to detached HEAD"
 msgstr "Kan inte beskriva frånkopplad HEAD"
 
-#: builtin/branch.c:889
+#: builtin/branch.c:909
 msgid "cannot edit description of more than one branch"
 msgstr "kan inte redigera beskrivning för mer än en gren"
 
-#: builtin/branch.c:896
+#: builtin/branch.c:916
 #, c-format
 msgid "No commit on branch '%s' yet."
 msgstr "Inga incheckningar på grenen \"%s\" ännu"
 
-#: builtin/branch.c:899
+#: builtin/branch.c:919
 #, c-format
 msgid "No branch named '%s'."
 msgstr "Ingen gren vid namnet \"%s\"."
 
-#: builtin/branch.c:914
+#: builtin/branch.c:934
 msgid "too many branches for a rename operation"
 msgstr "för många grenar för namnbyte"
 
-#: builtin/branch.c:919
+#: builtin/branch.c:939
 msgid "too many branches to set new upstream"
 msgstr "för många grenar för att byta uppström"
 
-#: builtin/branch.c:923
+#: builtin/branch.c:943
 #, c-format
 msgid ""
 "could not set upstream of HEAD to %s when it does not point to any branch."
 msgstr ""
 "kunde inte sätta uppström för HEAD till %s när det inte pekar mot någon gren."
 
-#: builtin/branch.c:926 builtin/branch.c:948 builtin/branch.c:970
+#: builtin/branch.c:946 builtin/branch.c:968 builtin/branch.c:990
 #, c-format
 msgid "no such branch '%s'"
 msgstr "okänd gren \"%s\""
 
-#: builtin/branch.c:930
+#: builtin/branch.c:950
 #, c-format
 msgid "branch '%s' does not exist"
 msgstr "grenen \"%s\" finns inte"
 
-#: builtin/branch.c:942
+#: builtin/branch.c:962
 msgid "too many branches to unset upstream"
 msgstr "för många grenar för att ta bort uppström"
 
-#: builtin/branch.c:946
+#: builtin/branch.c:966
 msgid "could not unset upstream of HEAD when it does not point to any branch."
 msgstr ""
 "kunde inte ta bort uppström för HEAD när det inte pekar mot någon gren."
 
-#: builtin/branch.c:952
+#: builtin/branch.c:972
 #, c-format
 msgid "Branch '%s' has no upstream information"
 msgstr "Grenen \"%s\" har ingen uppströmsinformation"
 
-#: builtin/branch.c:967
+#: builtin/branch.c:987
 msgid "it does not make sense to create 'HEAD' manually"
 msgstr "kan inte skapa \"HEAD\" manuellt"
 
-#: builtin/branch.c:973
+#: builtin/branch.c:993
 msgid "-a and -r options to 'git branch' do not make sense with a branch name"
 msgstr ""
 "flaggorna -a och -r på \"git branch\" kan inte anges tillsammans med ett "
 "grennamn"
 
-#: builtin/branch.c:976
+#: builtin/branch.c:996
 #, c-format
 msgid ""
 "The --set-upstream flag is deprecated and will be removed. Consider using --"
@@ -2701,7 +2907,7 @@
 "Flaggan --set-upstream rekommenderas ej och kommer tas bort. Använd --track "
 "eller --set-upstream-to\n"
 
-#: builtin/branch.c:993
+#: builtin/branch.c:1013
 #, c-format
 msgid ""
 "\n"
@@ -2712,12 +2918,12 @@
 "Om du vill göra så att \"%s\" spårar \"%s\" gör du så här:\n"
 "\n"
 
-#: builtin/branch.c:994
+#: builtin/branch.c:1014
 #, c-format
 msgid "    git branch -d %s\n"
 msgstr "    git branch -d %s\n"
 
-#: builtin/branch.c:995
+#: builtin/branch.c:1015
 #, c-format
 msgid "    git branch --set-upstream-to %s\n"
 msgstr "    git branch --set-upstream-to %s\n"
@@ -2735,43 +2941,43 @@
 msgid "Need a repository to unbundle."
 msgstr "Behöver ett arkiv för att packa upp ett paket (bundle)."
 
-#: builtin/cat-file.c:247
+#: builtin/cat-file.c:285
 msgid "git cat-file (-t|-s|-e|-p|<type>|--textconv) <object>"
 msgstr "git cat-file (-t|-s|-e|-p|<typ>|--textconv) <objekt>"
 
-#: builtin/cat-file.c:248
+#: builtin/cat-file.c:286
 msgid "git cat-file (--batch|--batch-check) < <list_of_objects>"
 msgstr "git cat-file (--batch|--batch-check) < <objektlista>"
 
-#: builtin/cat-file.c:266
+#: builtin/cat-file.c:323
 msgid "<type> can be one of: blob, tree, commit, tag"
 msgstr "<typ> kan vara en av: blob, tree, commit, tag"
 
-#: builtin/cat-file.c:267
+#: builtin/cat-file.c:324
 msgid "show object type"
 msgstr "visa objekttyp"
 
-#: builtin/cat-file.c:268
+#: builtin/cat-file.c:325
 msgid "show object size"
 msgstr "visa objektstorlek"
 
-#: builtin/cat-file.c:270
+#: builtin/cat-file.c:327
 msgid "exit with zero when there's no error"
 msgstr "avsluta med noll när det inte uppstått något fel"
 
-#: builtin/cat-file.c:271
+#: builtin/cat-file.c:328
 msgid "pretty-print object's content"
 msgstr "visa objektets innehåll snyggt"
 
-#: builtin/cat-file.c:273
+#: builtin/cat-file.c:330
 msgid "for blob objects, run textconv on object's content"
 msgstr "för blob-objekt, kör textconv på objektets innehåll"
 
-#: builtin/cat-file.c:275
+#: builtin/cat-file.c:332
 msgid "show info and content of objects fed from the standard input"
 msgstr "visa information och innehåll för objekt som listas på standard in"
 
-#: builtin/cat-file.c:278
+#: builtin/cat-file.c:335
 msgid "show info about objects fed from the standard input"
 msgstr "visa information för objekt som listas på standard in"
 
@@ -2799,30 +3005,55 @@
 msgid "input paths are terminated by a null character"
 msgstr "sökvägar avdelas med null-tecken"
 
-#: builtin/check-ignore.c:18 builtin/checkout.c:1041 builtin/gc.c:177
+#: builtin/check-ignore.c:18 builtin/checkout.c:1054 builtin/gc.c:177
 msgid "suppress progress reporting"
 msgstr "undertryck förloppsrapportering"
 
-#: builtin/check-ignore.c:151
+#: builtin/check-ignore.c:26
+msgid "show non-matching input paths"
+msgstr "visa indatasökvägar som inte träffas"
+
+#: builtin/check-ignore.c:143
 msgid "cannot specify pathnames with --stdin"
 msgstr "kan inte ange sökvägsnamn med --stdin"
 
-#: builtin/check-ignore.c:154
+#: builtin/check-ignore.c:146
 msgid "-z only makes sense with --stdin"
 msgstr "-z kan endast användas tillsammans med --stdin"
 
-#: builtin/check-ignore.c:156
+#: builtin/check-ignore.c:148
 msgid "no path specified"
 msgstr "ingen sökväg angavs"
 
-#: builtin/check-ignore.c:160
+#: builtin/check-ignore.c:152
 msgid "--quiet is only valid with a single pathname"
 msgstr "--quiet kan endast användas med ett enkelt sökvägsnamn"
 
-#: builtin/check-ignore.c:162
+#: builtin/check-ignore.c:154
 msgid "cannot have both --quiet and --verbose"
 msgstr "kan inte använda både --quiet och --verbose"
 
+#: builtin/check-ignore.c:157
+msgid "--non-matching is only valid with --verbose"
+msgstr "--non-matching är endast giltig med --verbose"
+
+#: builtin/check-mailmap.c:8
+msgid "git check-mailmap [options] <contact>..."
+msgstr "git check-mailmap [flaggor] <kontakt>..."
+
+#: builtin/check-mailmap.c:13
+msgid "also read contacts from stdin"
+msgstr "läs även kontakter från standard in"
+
+#: builtin/check-mailmap.c:24
+#, c-format
+msgid "unable to parse contact: %s"
+msgstr "kunde inte tolka kontakt: %s"
+
+#: builtin/check-mailmap.c:47
+msgid "no contacts specified"
+msgstr "inga kontakter angavs"
+
 #: builtin/checkout-index.c:126
 msgid "git checkout-index [options] [--] [<file>...]"
 msgstr "git checkout-index [flaggor] [--] [<fil>...]"
@@ -2875,106 +3106,106 @@
 msgid "git checkout [options] [<branch>] -- <file>..."
 msgstr "git checkout [flaggor] [<gren>] -- <fil>..."
 
-#: builtin/checkout.c:116 builtin/checkout.c:149
+#: builtin/checkout.c:117 builtin/checkout.c:150
 #, c-format
 msgid "path '%s' does not have our version"
 msgstr "sökvägen \"%s\" har inte vår version"
 
-#: builtin/checkout.c:118 builtin/checkout.c:151
+#: builtin/checkout.c:119 builtin/checkout.c:152
 #, c-format
 msgid "path '%s' does not have their version"
 msgstr "sökvägen \"%s\" har inte deras version"
 
-#: builtin/checkout.c:134
+#: builtin/checkout.c:135
 #, c-format
 msgid "path '%s' does not have all necessary versions"
 msgstr "sökvägen \"%s\" innehåller inte alla nödvändiga versioner"
 
-#: builtin/checkout.c:178
+#: builtin/checkout.c:179
 #, c-format
 msgid "path '%s' does not have necessary versions"
 msgstr "sökvägen \"%s\" innehåller inte nödvändiga versioner"
 
-#: builtin/checkout.c:195
+#: builtin/checkout.c:196
 #, c-format
 msgid "path '%s': cannot merge"
 msgstr "sökväg \"%s\": kan inte slå ihop"
 
-#: builtin/checkout.c:212
+#: builtin/checkout.c:213
 #, c-format
 msgid "Unable to add merge result for '%s'"
 msgstr "Kunde inte lägga till sammanslagningsresultat för \"%s\""
 
-#: builtin/checkout.c:236 builtin/checkout.c:239 builtin/checkout.c:242
-#: builtin/checkout.c:245
+#: builtin/checkout.c:237 builtin/checkout.c:240 builtin/checkout.c:243
+#: builtin/checkout.c:246
 #, c-format
 msgid "'%s' cannot be used with updating paths"
 msgstr "\"%s\" kan inte användas vid uppdatering av sökvägar"
 
-#: builtin/checkout.c:248 builtin/checkout.c:251
+#: builtin/checkout.c:249 builtin/checkout.c:252
 #, c-format
 msgid "'%s' cannot be used with %s"
 msgstr "\"%s\" kan inte användas med %s"
 
-#: builtin/checkout.c:254
+#: builtin/checkout.c:255
 #, c-format
 msgid "Cannot update paths and switch to branch '%s' at the same time."
 msgstr "Kan inte uppdatera sökvägar och växla till grenen \"%s\" samtidigt."
 
-#: builtin/checkout.c:265 builtin/checkout.c:455
+#: builtin/checkout.c:266 builtin/checkout.c:458
 msgid "corrupt index file"
 msgstr "indexfilen är trasig"
 
-#: builtin/checkout.c:326 builtin/checkout.c:333
+#: builtin/checkout.c:329 builtin/checkout.c:336
 #, c-format
 msgid "path '%s' is unmerged"
 msgstr "sökvägen \"%s\" har inte slagits ihop"
 
-#: builtin/checkout.c:477
+#: builtin/checkout.c:480
 msgid "you need to resolve your current index first"
 msgstr "du måste lösa ditt befintliga index först"
 
-#: builtin/checkout.c:598
+#: builtin/checkout.c:601
 #, c-format
 msgid "Can not do reflog for '%s'\n"
 msgstr "Kan inte skapa referenslog för \"%s\"\n"
 
-#: builtin/checkout.c:631
+#: builtin/checkout.c:639
 msgid "HEAD is now at"
 msgstr "HEAD är nu på"
 
-#: builtin/checkout.c:638
+#: builtin/checkout.c:646
 #, c-format
 msgid "Reset branch '%s'\n"
 msgstr "Återställ gren \"%s\"\n"
 
-#: builtin/checkout.c:641
+#: builtin/checkout.c:649
 #, c-format
 msgid "Already on '%s'\n"
 msgstr "Redan på \"%s\"\n"
 
-#: builtin/checkout.c:645
+#: builtin/checkout.c:653
 #, c-format
 msgid "Switched to and reset branch '%s'\n"
 msgstr "Växlade till och nollställde grenen \"%s\"\n"
 
-#: builtin/checkout.c:647 builtin/checkout.c:984
+#: builtin/checkout.c:655 builtin/checkout.c:997
 #, c-format
 msgid "Switched to a new branch '%s'\n"
 msgstr "Växlade till en ny gren \"%s\"\n"
 
-#: builtin/checkout.c:649
+#: builtin/checkout.c:657
 #, c-format
 msgid "Switched to branch '%s'\n"
 msgstr "Växlade till grenen \"%s\"\n"
 
-#: builtin/checkout.c:705
+#: builtin/checkout.c:713
 #, c-format
 msgid " ... and %d more.\n"
 msgstr " ... och %d till.\n"
 
 #. The singular version
-#: builtin/checkout.c:711
+#: builtin/checkout.c:719
 #, c-format
 msgid ""
 "Warning: you are leaving %d commit behind, not connected to\n"
@@ -2997,7 +3228,7 @@
 "\n"
 "%s\n"
 
-#: builtin/checkout.c:729
+#: builtin/checkout.c:737
 #, c-format
 msgid ""
 "If you want to keep them by creating a new branch, this may be a good time\n"
@@ -3012,132 +3243,136 @@
 " git branch nytt_grennamn %s\n"
 "\n"
 
-#: builtin/checkout.c:759
+#: builtin/checkout.c:767
 msgid "internal error in revision walk"
 msgstr "internt fel vid genomgång av revisioner (revision walk)"
 
-#: builtin/checkout.c:763
+#: builtin/checkout.c:771
 msgid "Previous HEAD position was"
 msgstr "Tidigare position för HEAD var"
 
-#: builtin/checkout.c:790 builtin/checkout.c:979
+#: builtin/checkout.c:798 builtin/checkout.c:992
 msgid "You are on a branch yet to be born"
 msgstr "Du är på en gren som ännu inte är född"
 
 #. case (1)
-#: builtin/checkout.c:915
+#: builtin/checkout.c:928
 #, c-format
 msgid "invalid reference: %s"
 msgstr "felaktig referens: %s"
 
 #. case (1): want a tree
-#: builtin/checkout.c:954
+#: builtin/checkout.c:967
 #, c-format
 msgid "reference is not a tree: %s"
 msgstr "referensen är inte ett träd: %s"
 
-#: builtin/checkout.c:993
+#: builtin/checkout.c:1006
 msgid "paths cannot be used with switching branches"
 msgstr "sökvägar kan inte användas vid byte av gren"
 
-#: builtin/checkout.c:996 builtin/checkout.c:1000
+#: builtin/checkout.c:1009 builtin/checkout.c:1013
 #, c-format
 msgid "'%s' cannot be used with switching branches"
 msgstr "\"%s\" kan inte användas vid byte av gren"
 
-#: builtin/checkout.c:1004 builtin/checkout.c:1007 builtin/checkout.c:1012
-#: builtin/checkout.c:1015
+#: builtin/checkout.c:1017 builtin/checkout.c:1020 builtin/checkout.c:1025
+#: builtin/checkout.c:1028
 #, c-format
 msgid "'%s' cannot be used with '%s'"
 msgstr "\"%s\" kan inte användas med \"%s\""
 
-#: builtin/checkout.c:1020
+#: builtin/checkout.c:1033
 #, c-format
 msgid "Cannot switch branch to a non-commit '%s'"
 msgstr "Kan inte växla gren till icke-incheckningen \"%s\""
 
-#: builtin/checkout.c:1042 builtin/checkout.c:1044 builtin/clone.c:90
+#: builtin/checkout.c:1055 builtin/checkout.c:1057 builtin/clone.c:89
 #: builtin/remote.c:169 builtin/remote.c:171
 msgid "branch"
 msgstr "gren"
 
-#: builtin/checkout.c:1043
+#: builtin/checkout.c:1056
 msgid "create and checkout a new branch"
 msgstr "skapa och checka ut en ny gren"
 
-#: builtin/checkout.c:1045
+#: builtin/checkout.c:1058
 msgid "create/reset and checkout a branch"
 msgstr "skapa/nollställ och checka ut en gren"
 
-#: builtin/checkout.c:1046
+#: builtin/checkout.c:1059
 msgid "create reflog for new branch"
 msgstr "skapa reflogg för ny gren"
 
-#: builtin/checkout.c:1047
+#: builtin/checkout.c:1060
 msgid "detach the HEAD at named commit"
 msgstr "koppla från HEAD vid namngiven incheckning"
 
-#: builtin/checkout.c:1048
+#: builtin/checkout.c:1061
 msgid "set upstream info for new branch"
 msgstr "sätt uppströmsinformation för ny gren"
 
-#: builtin/checkout.c:1050
+#: builtin/checkout.c:1063
 msgid "new branch"
 msgstr "ny gren"
 
-#: builtin/checkout.c:1050
+#: builtin/checkout.c:1063
 msgid "new unparented branch"
 msgstr "ny gren utan förälder"
 
-#: builtin/checkout.c:1051
+#: builtin/checkout.c:1064
 msgid "checkout our version for unmerged files"
 msgstr "checka ut vår version för ej sammanslagna filer"
 
-#: builtin/checkout.c:1053
+#: builtin/checkout.c:1066
 msgid "checkout their version for unmerged files"
 msgstr "checka ut deras version för ej sammanslagna filer"
 
-#: builtin/checkout.c:1055
+#: builtin/checkout.c:1068
 msgid "force checkout (throw away local modifications)"
 msgstr "tvinga utcheckning (kasta bort lokala ändringar)"
 
-#: builtin/checkout.c:1056
+#: builtin/checkout.c:1069
 msgid "perform a 3-way merge with the new branch"
 msgstr "utför en 3-vägssammanslagning för den nya grenen"
 
-#: builtin/checkout.c:1057 builtin/merge.c:217
+#: builtin/checkout.c:1070 builtin/merge.c:232
 msgid "update ignored files (default)"
 msgstr "uppdatera ignorerade filer (standard)"
 
-#: builtin/checkout.c:1058 builtin/log.c:1149 parse-options.h:245
+#: builtin/checkout.c:1071 builtin/log.c:1208 parse-options.h:249
 msgid "style"
 msgstr "stil"
 
-#: builtin/checkout.c:1059
+#: builtin/checkout.c:1072
 msgid "conflict style (merge or diff3)"
 msgstr "konfliktstil (merge eller diff3)"
 
-#: builtin/checkout.c:1062
+#: builtin/checkout.c:1075
+msgid "do not limit pathspecs to sparse entries only"
+msgstr "begränsa inte sökvägar till endast glesa poster"
+
+#: builtin/checkout.c:1077
 msgid "second guess 'git checkout no-such-branch'"
 msgstr "förutspå \"git checkout gren-saknas\""
 
-#: builtin/checkout.c:1086
+#: builtin/checkout.c:1101
 msgid "-b, -B and --orphan are mutually exclusive"
 msgstr "-b, -B och --orphan är ömsesidigt uteslutande"
 
-#: builtin/checkout.c:1103
+#: builtin/checkout.c:1118
 msgid "--track needs a branch name"
 msgstr "--track behöver ett namn på en gren"
 
-#: builtin/checkout.c:1110
+#: builtin/checkout.c:1125
 msgid "Missing branch name; try -b"
 msgstr "Grennamn saknas; försök med -b"
 
-#: builtin/checkout.c:1145
+#: builtin/checkout.c:1160
 msgid "invalid path specification"
 msgstr "felaktig sökvägsangivelse"
 
-#: builtin/checkout.c:1152
+#: builtin/checkout.c:1167
 #, c-format
 msgid ""
 "Cannot update paths and switch to branch '%s' at the same time.\n"
@@ -3146,12 +3381,12 @@
 "Kan inte uppdatera sökvägar och växla till grenen \"%s\" samtidigt.\n"
 "Ville du checka ut \"%s\" som inte kan lösas som en utcheckning?"
 
-#: builtin/checkout.c:1157
+#: builtin/checkout.c:1172
 #, c-format
 msgid "git checkout: --detach does not take a path argument '%s'"
 msgstr "git checkout: --detach tar inte en sökväg som argument \"%s\""
 
-#: builtin/checkout.c:1161
+#: builtin/checkout.c:1176
 msgid ""
 "git checkout: --ours/--theirs, --force and --merge are incompatible when\n"
 "checking out of the index."
@@ -3159,218 +3394,321 @@
 "git checkout: --ours/--theirs, --force och --merge är inkompatibla när\n"
 "du checkar ut från indexet."
 
-#: builtin/clean.c:20
-msgid "git clean [-d] [-f] [-n] [-q] [-e <pattern>] [-x | -X] [--] <paths>..."
+#: builtin/clean.c:25
+msgid ""
+"git clean [-d] [-f] [-i] [-n] [-q] [-e <pattern>] [-x | -X] [--] <paths>..."
 msgstr ""
-"git clean [-d] [-f] [-n] [-q] [-e <mönster>] [-x | -X] [--] <sökvägar>..."
+"git clean [-d] [-f] [-i] [-n] [-q] [-e <mönster>] [-x | -X] [--] "
+"<sökvägar>..."
 
-#: builtin/clean.c:24
+#: builtin/clean.c:29
 #, c-format
 msgid "Removing %s\n"
 msgstr "Tar bort %s\n"
 
-#: builtin/clean.c:25
+#: builtin/clean.c:30
 #, c-format
 msgid "Would remove %s\n"
 msgstr "Skulle ta bort %s\n"
 
-#: builtin/clean.c:26
+#: builtin/clean.c:31
 #, c-format
 msgid "Skipping repository %s\n"
 msgstr "Hoppar över arkivet %s\n"
 
-#: builtin/clean.c:27
+#: builtin/clean.c:32
 #, c-format
 msgid "Would skip repository %s\n"
 msgstr "Skulle hoppa över arkivet %s\n"
 
-#: builtin/clean.c:28
+#: builtin/clean.c:33
 #, c-format
 msgid "failed to remove %s"
 msgstr "misslyckades ta bort %s"
 
-#: builtin/clean.c:160
+#: builtin/clean.c:293
+msgid ""
+"Prompt help:\n"
+"1          - select a numbered item\n"
+"foo        - select item based on unique prefix\n"
+"           - (empty) select nothing"
+msgstr ""
+"Kommandohjälp:\n"
+"1          - markera en numrerad post\n"
+"foo        - markera post baserad på unikt prefix\n"
+"           - (tomt) markera ingenting"
+
+#: builtin/clean.c:297
+msgid ""
+"Prompt help:\n"
+"1          - select a single item\n"
+"3-5        - select a range of items\n"
+"2-3,6-9    - select multiple ranges\n"
+"foo        - select item based on unique prefix\n"
+"-...       - unselect specified items\n"
+"*          - choose all items\n"
+"           - (empty) finish selecting"
+msgstr ""
+"Kommandohjälp:\n"
+"1          - markera en ensam post\n"
+"3-5        - markera ett intervall med poster\n"
+"2-3,6-9    - markera flera intervall\n"
+"foo        - markera post baserad på unikt prefix\n"
+"-...       - avmarkera specifika poster\n"
+"*          - välj alla poster\n"
+"           - (tomt) avsluta markering"
+
+#: builtin/clean.c:515
+#, c-format
+msgid "Huh (%s)?"
+msgstr "Vadå (%s)?"
+
+#: builtin/clean.c:658
+#, c-format
+msgid "Input ignore patterns>> "
+msgstr "Ange ignoreringsmönster>>"
+
+#: builtin/clean.c:695
+#, c-format
+msgid "WARNING: Cannot find items matched by: %s"
+msgstr "VARNING: Hittar inte poster som motsvarar: %s"
+
+#: builtin/clean.c:716
+msgid "Select items to delete"
+msgstr "Välj poster att ta bort"
+
+#: builtin/clean.c:756
+#, c-format
+msgid "remove %s? "
+msgstr "ta bort %s?"
+
+#: builtin/clean.c:781
+msgid "Bye."
+msgstr "Hej då."
+
+#: builtin/clean.c:789
+msgid ""
+"clean               - start cleaning\n"
+"filter by pattern   - exclude items from deletion\n"
+"select by numbers   - select items to be deleted by numbers\n"
+"ask each            - confirm each deletion (like \"rm -i\")\n"
+"quit                - stop cleaning\n"
+"help                - this screen\n"
+"?                   - help for prompt selection"
+msgstr ""
+"clean               - börja städa\n"
+"filter by pattern   - uteslut poster från borttagning\n"
+"select by numbers   - markera poster som ska tas bort med siffror\n"
+"ask each            - bekräfta varje borttagning (som \"rm -i\")\n"
+"quit                - sluta städa\n"
+"help                - denna skärm\n"
+"?                   - hjälp för kommandoval"
+
+#: builtin/clean.c:816
+msgid "*** Commands ***"
+msgstr "*** Kommandon ***"
+
+#: builtin/clean.c:817
+msgid "What now"
+msgstr "Vad nu"
+
+#: builtin/clean.c:825
+msgid "Would remove the following item:"
+msgid_plural "Would remove the following items:"
+msgstr[0] "Skulle ta bort följande post:"
+msgstr[1] "Skulle ta bort följande poster:"
+
+#: builtin/clean.c:842
+msgid "No more files to clean, exiting."
+msgstr "Inga fler filer att städa, avslutar."
+
+#: builtin/clean.c:874
 msgid "do not print names of files removed"
 msgstr "skriv inte ut namn på borttagna filer"
 
-#: builtin/clean.c:162
+#: builtin/clean.c:876
 msgid "force"
 msgstr "tvinga"
 
-#: builtin/clean.c:164
+#: builtin/clean.c:877
+msgid "interactive cleaning"
+msgstr "städa interaktivt"
+
+#: builtin/clean.c:879
 msgid "remove whole directories"
 msgstr "ta bort hela kataloger"
 
-#: builtin/clean.c:165 builtin/describe.c:412 builtin/grep.c:717
-#: builtin/ls-files.c:494 builtin/name-rev.c:231 builtin/show-ref.c:182
+#: builtin/clean.c:880 builtin/describe.c:420 builtin/grep.c:716
+#: builtin/ls-files.c:493 builtin/name-rev.c:315 builtin/show-ref.c:186
 msgid "pattern"
 msgstr "mönster"
 
-#: builtin/clean.c:166
+#: builtin/clean.c:881
 msgid "add <pattern> to ignore rules"
 msgstr "lägg till <mönster> till ignoreringsregler"
 
-#: builtin/clean.c:167
+#: builtin/clean.c:882
 msgid "remove ignored files, too"
 msgstr "ta även bort ignorerade filer"
 
-#: builtin/clean.c:169
+#: builtin/clean.c:884
 msgid "remove only ignored files"
 msgstr "ta endast bort ignorerade filer"
 
-#: builtin/clean.c:187
+#: builtin/clean.c:902
 msgid "-x and -X cannot be used together"
 msgstr "-x och -X kan inte användas samtidigt"
 
-#: builtin/clean.c:191
+#: builtin/clean.c:906
 msgid ""
-"clean.requireForce set to true and neither -n nor -f given; refusing to clean"
-msgstr ""
-"clean.requireForce satt till true, men varken -n eller -f angavs; vägrar "
-"städa"
-
-#: builtin/clean.c:194
-msgid ""
-"clean.requireForce defaults to true and neither -n nor -f given; refusing to "
+"clean.requireForce set to true and neither -i, -n nor -f given; refusing to "
 "clean"
 msgstr ""
-"clean.requireForce har standardvärdet true, men varken -n eller -f angavs; "
-"vägrar städa"
+"clean.requireForce satt till true, men varken -i, -n eller -f angavs; vägrar "
+"städa"
 
-#: builtin/clone.c:37
+#: builtin/clean.c:909
+msgid ""
+"clean.requireForce defaults to true and neither -i, -n nor -f given; "
+"refusing to clean"
+msgstr ""
+"clean.requireForce har standardvärdet true och varken -i, -n eller -f "
+"angavs; vägrar städa"
+
+#: builtin/clone.c:36
 msgid "git clone [options] [--] <repo> [<dir>]"
 msgstr "git clone [flaggor] [--] <arkiv> [<kat>]"
 
-#: builtin/clone.c:65 builtin/fetch.c:82 builtin/merge.c:214
-#: builtin/push.c:436
+#: builtin/clone.c:64 builtin/fetch.c:82 builtin/merge.c:229
+#: builtin/push.c:462
 msgid "force progress reporting"
 msgstr "tvinga förloppsrapportering"
 
-#: builtin/clone.c:67
+#: builtin/clone.c:66
 msgid "don't create a checkout"
 msgstr "skapa inte någon utcheckning"
 
-#: builtin/clone.c:68 builtin/clone.c:70 builtin/init-db.c:488
+#: builtin/clone.c:67 builtin/clone.c:69 builtin/init-db.c:488
 msgid "create a bare repository"
 msgstr "skapa ett naket (\"bare\") arkiv"
 
-#: builtin/clone.c:73
+#: builtin/clone.c:72
 msgid "create a mirror repository (implies bare)"
 msgstr "skapa ett spegelarkiv (implicerar \"bare\")"
 
-#: builtin/clone.c:75
+#: builtin/clone.c:74
 msgid "to clone from a local repository"
 msgstr "för att klona från ett lokalt arkiv"
 
-#: builtin/clone.c:77
+#: builtin/clone.c:76
 msgid "don't use local hardlinks, always copy"
 msgstr "skapa inte lokala hårda länkar, kopiera alltid"
 
-#: builtin/clone.c:79
+#: builtin/clone.c:78
 msgid "setup as shared repository"
 msgstr "skapa som ett delat arkiv"
 
-#: builtin/clone.c:81 builtin/clone.c:83
+#: builtin/clone.c:80 builtin/clone.c:82
 msgid "initialize submodules in the clone"
 msgstr "initiera undermoduler i klonen"
 
-#: builtin/clone.c:84 builtin/init-db.c:485
+#: builtin/clone.c:83 builtin/init-db.c:485
 msgid "template-directory"
 msgstr "mallkatalog"
 
-#: builtin/clone.c:85 builtin/init-db.c:486
+#: builtin/clone.c:84 builtin/init-db.c:486
 msgid "directory from which templates will be used"
 msgstr "katalog att använda mallar från"
 
-#: builtin/clone.c:87
+#: builtin/clone.c:86
 msgid "reference repository"
 msgstr "referensarkiv"
 
-#: builtin/clone.c:88 builtin/column.c:26 builtin/merge-file.c:44
+#: builtin/clone.c:87 builtin/column.c:26 builtin/merge-file.c:44
 msgid "name"
 msgstr "namn"
 
-#: builtin/clone.c:89
+#: builtin/clone.c:88
 msgid "use <name> instead of 'origin' to track upstream"
 msgstr "använd <namn> istället för \"origin\" för att spåra uppströms"
 
-#: builtin/clone.c:91
+#: builtin/clone.c:90
 msgid "checkout <branch> instead of the remote's HEAD"
 msgstr "checka ut <gren> istället för fjärrens HEAD"
 
-#: builtin/clone.c:93
+#: builtin/clone.c:92
 msgid "path to git-upload-pack on the remote"
 msgstr "sökväg till git-upload-pack på fjärren"
 
-#: builtin/clone.c:94 builtin/fetch.c:83 builtin/grep.c:662
+#: builtin/clone.c:93 builtin/fetch.c:83 builtin/grep.c:661
 msgid "depth"
 msgstr "djup"
 
-#: builtin/clone.c:95
+#: builtin/clone.c:94
 msgid "create a shallow clone of that depth"
 msgstr "skapa en grund klon på detta djup"
 
-#: builtin/clone.c:97
+#: builtin/clone.c:96
 msgid "clone only one branch, HEAD or --branch"
 msgstr "klona endast en gren, HEAD eller --branch"
 
-#: builtin/clone.c:98 builtin/init-db.c:494
+#: builtin/clone.c:97 builtin/init-db.c:494
 msgid "gitdir"
 msgstr "gitkat"
 
-#: builtin/clone.c:99 builtin/init-db.c:495
+#: builtin/clone.c:98 builtin/init-db.c:495
 msgid "separate git dir from working tree"
 msgstr "separera gitkatalogen från arbetskatalogen"
 
-#: builtin/clone.c:100
+#: builtin/clone.c:99
 msgid "key=value"
 msgstr "nyckel=värde"
 
-#: builtin/clone.c:101
+#: builtin/clone.c:100
 msgid "set config inside the new repository"
 msgstr "ställ in konfiguration i det nya arkivet"
 
-#: builtin/clone.c:244
+#: builtin/clone.c:253
 #, c-format
-msgid "reference repository '%s' is not a local directory."
-msgstr "referensarkivet \"%s\" är inte en lokal katalog."
+msgid "reference repository '%s' is not a local repository."
+msgstr "referensarkivet \"%s\" är inte ett lokalt arkiv."
 
-#: builtin/clone.c:307
+#: builtin/clone.c:316
 #, c-format
 msgid "failed to create directory '%s'"
 msgstr "misslyckades skapa katalogen \"%s\""
 
-#: builtin/clone.c:309 builtin/diff.c:77
+#: builtin/clone.c:318 builtin/diff.c:77
 #, c-format
 msgid "failed to stat '%s'"
 msgstr "misslyckades ta status på \"%s\""
 
-#: builtin/clone.c:311
+#: builtin/clone.c:320
 #, c-format
 msgid "%s exists and is not a directory"
 msgstr "%s finns och är ingen katalog"
 
-#: builtin/clone.c:325
+#: builtin/clone.c:334
 #, c-format
 msgid "failed to stat %s\n"
 msgstr "misslyckades ta status på %s\n"
 
-#: builtin/clone.c:347
+#: builtin/clone.c:356
 #, c-format
 msgid "failed to create link '%s'"
 msgstr "misslyckades skapa länken \"%s\""
 
-#: builtin/clone.c:351
+#: builtin/clone.c:360
 #, c-format
 msgid "failed to copy file to '%s'"
 msgstr "misslyckades kopiera filen till \"%s\""
 
-#: builtin/clone.c:374
+#: builtin/clone.c:383
 #, c-format
 msgid "done.\n"
 msgstr "klart.\n"
 
-#: builtin/clone.c:387
+#: builtin/clone.c:396
 msgid ""
 "Clone succeeded, but checkout failed.\n"
 "You can inspect what was checked out with 'git status'\n"
@@ -3380,91 +3718,105 @@
 "Du kan inspektera det som checkades ut med \"git status\"\n"
 "och försöka checka ut igen med \"git checkout -f HEAD\"\n"
 
-#: builtin/clone.c:466
+#: builtin/clone.c:475
 #, c-format
 msgid "Could not find remote branch %s to clone."
 msgstr "Kunde inte hitta fjärrgrenen %s för att klona."
 
-#: builtin/clone.c:540
+#: builtin/clone.c:555
+#, c-format
+msgid "Checking connectivity... "
+msgstr "Kontrollerar anslutning..."
+
+#: builtin/clone.c:558
 msgid "remote did not send all necessary objects"
 msgstr "fjärren sände inte alla nödvändiga objekt"
 
-#: builtin/clone.c:600
+#: builtin/clone.c:560
+#, c-format
+msgid "done\n"
+msgstr "klart\n"
+
+#: builtin/clone.c:621
 msgid "remote HEAD refers to nonexistent ref, unable to checkout.\n"
 msgstr ""
 "HEAD hos fjärren pekar på en obefintlig referens, kan inte checka ut.\n"
 
-#: builtin/clone.c:631
+#: builtin/clone.c:652
 msgid "unable to checkout working tree"
 msgstr "kunde inte checka ut arbetskatalogen"
 
-#: builtin/clone.c:739
+#: builtin/clone.c:760
 msgid "Too many arguments."
 msgstr "För många argument."
 
-#: builtin/clone.c:743
+#: builtin/clone.c:764
 msgid "You must specify a repository to clone."
 msgstr "Du måste ange ett arkiv att klona."
 
-#: builtin/clone.c:754
+#: builtin/clone.c:775
 #, c-format
 msgid "--bare and --origin %s options are incompatible."
 msgstr "flaggorna --bare och --origin %s är inkompatibla."
 
-#: builtin/clone.c:757
+#: builtin/clone.c:778
 msgid "--bare and --separate-git-dir are incompatible."
 msgstr "flaggorna --bare och --separate-git-dir är inkompatibla."
 
-#: builtin/clone.c:770
+#: builtin/clone.c:791
 #, c-format
 msgid "repository '%s' does not exist"
 msgstr "arkivet \"%s\" finns inte"
 
-#: builtin/clone.c:775
+#: builtin/clone.c:796
 msgid "--depth is ignored in local clones; use file:// instead."
 msgstr "--depth ignoreras i lokala kloningar; använd file:// istället"
 
-#: builtin/clone.c:785
+#: builtin/clone.c:798
+msgid "--local is ignored"
+msgstr "--local ignoreras"
+
+#: builtin/clone.c:808
 #, c-format
 msgid "destination path '%s' already exists and is not an empty directory."
 msgstr "destinationssökvägen \"%s\" finns redan och är inte en tom katalog."
 
-#: builtin/clone.c:795
+#: builtin/clone.c:818
 #, c-format
 msgid "working tree '%s' already exists."
 msgstr "arbetsträdet \"%s\" finns redan."
 
-#: builtin/clone.c:808 builtin/clone.c:820
+#: builtin/clone.c:831 builtin/clone.c:843
 #, c-format
 msgid "could not create leading directories of '%s'"
 msgstr "kunde inte skapa inledande kataloger för \"%s\""
 
-#: builtin/clone.c:811
+#: builtin/clone.c:834
 #, c-format
 msgid "could not create work tree dir '%s'."
 msgstr "kunde inte skapa arbetskatalogen \"%s\""
 
-#: builtin/clone.c:830
+#: builtin/clone.c:853
 #, c-format
 msgid "Cloning into bare repository '%s'...\n"
 msgstr "Klonar till ett naket arkiv \"%s\"...\n"
 
-#: builtin/clone.c:832
+#: builtin/clone.c:855
 #, c-format
 msgid "Cloning into '%s'...\n"
 msgstr "Klonar till \"%s\"...\n"
 
-#: builtin/clone.c:867
+#: builtin/clone.c:890
 #, c-format
 msgid "Don't know how to clone %s"
 msgstr "Vet inte hur man klonar %s"
 
-#: builtin/clone.c:916
+#: builtin/clone.c:942
 #, c-format
 msgid "Remote branch %s not found in upstream %s"
 msgstr "Fjärrgrenen %s hittades inte i uppströmsarkivet %s"
 
-#: builtin/clone.c:923
+#: builtin/clone.c:949
 msgid "You appear to have cloned an empty repository."
 msgstr "Du verkar ha klonat ett tomt arkiv."
 
@@ -3500,15 +3852,15 @@
 msgid "--command must be the first argument"
 msgstr "--command måste vara första argument"
 
-#: builtin/commit.c:34
+#: builtin/commit.c:35
 msgid "git commit [options] [--] <pathspec>..."
 msgstr "git commit [flaggor] [--] <sökväg>..."
 
-#: builtin/commit.c:39
+#: builtin/commit.c:40
 msgid "git status [options] [--] <pathspec>..."
 msgstr "git status [flaggor] [--] <sökväg>..."
 
-#: builtin/commit.c:44
+#: builtin/commit.c:45
 msgid ""
 "Your name and email address were configured automatically based\n"
 "on your username and hostname. Please check that they are accurate.\n"
@@ -3533,7 +3885,7 @@
 "\n"
 "    git commit --amend --reset-author\n"
 
-#: builtin/commit.c:56
+#: builtin/commit.c:57
 msgid ""
 "You asked to amend the most recent commit, but doing so would make\n"
 "it empty. You can repeat your command with --allow-empty, or you can\n"
@@ -3543,109 +3895,127 @@
 "blir den tom. Du kan köra kommandot på nytt med --allow-empty, eller\n"
 "så kan du ta bort incheckningen helt med \"git reset HEAD^\".\n"
 
-#: builtin/commit.c:61
+#: builtin/commit.c:62
 msgid ""
 "The previous cherry-pick is now empty, possibly due to conflict resolution.\n"
 "If you wish to commit it anyway, use:\n"
 "\n"
 "    git commit --allow-empty\n"
 "\n"
-"Otherwise, please use 'git reset'\n"
 msgstr ""
 "Den tidigare \"cherry-pick\":en är nu tom, kanske på grund av en löst\n"
 "konflikt. Om du vill checka in den ändå använder du:\n"
 "\n"
 "    git commit --allow-empty\n"
 "\n"
-"Annars använder du \"git reset\"\n"
 
-#: builtin/commit.c:260
+#: builtin/commit.c:69
+msgid "Otherwise, please use 'git reset'\n"
+msgstr "Använd annars \"git reset\"\n"
+
+#: builtin/commit.c:72
+msgid ""
+"If you wish to skip this commit, use:\n"
+"\n"
+"    git reset\n"
+"\n"
+"Then \"git cherry-pick --continue\" will resume cherry-picking\n"
+"the remaining commits.\n"
+msgstr ""
+"Om du vill hoppa över incheckningen, använd:\n"
+"\n"
+"    git reset\n"
+"\n"
+"\"git cherry-pick --continue\" kommer därefter att återuppta\n"
+"cherry-pick för återstående incheckningar.\n"
+
+#: builtin/commit.c:279
 msgid "failed to unpack HEAD tree object"
 msgstr "misslyckades packa upp HEAD:s trädobjekt"
 
-#: builtin/commit.c:302
+#: builtin/commit.c:321
 msgid "unable to create temporary index"
 msgstr "kunde inte skapa temporär indexfil"
 
-#: builtin/commit.c:308
+#: builtin/commit.c:327
 msgid "interactive add failed"
 msgstr "interaktiv tilläggning misslyckades"
 
-#: builtin/commit.c:341 builtin/commit.c:362 builtin/commit.c:412
+#: builtin/commit.c:360 builtin/commit.c:381 builtin/commit.c:431
 msgid "unable to write new_index file"
 msgstr "kunde inte skriva filen new_index"
 
-#: builtin/commit.c:393
+#: builtin/commit.c:412
 msgid "cannot do a partial commit during a merge."
 msgstr "kan inte utföra en delvis incheckning under en sammanslagning."
 
-#: builtin/commit.c:395
+#: builtin/commit.c:414
 msgid "cannot do a partial commit during a cherry-pick."
 msgstr "kan inte utföra en delvis incheckning under en cherry-pick."
 
-#: builtin/commit.c:405
+#: builtin/commit.c:424
 msgid "cannot read the index"
 msgstr "kan inte läsa indexet"
 
-#: builtin/commit.c:425
+#: builtin/commit.c:444
 msgid "unable to write temporary index file"
 msgstr "kunde inte skriva temporär indexfil"
 
-#: builtin/commit.c:513 builtin/commit.c:519
+#: builtin/commit.c:535 builtin/commit.c:541
 #, c-format
 msgid "invalid commit: %s"
 msgstr "felaktig incheckning: %s"
 
-#: builtin/commit.c:542
+#: builtin/commit.c:563
 msgid "malformed --author parameter"
 msgstr "felformad \"--author\"-flagga"
 
-#: builtin/commit.c:562
+#: builtin/commit.c:583
 #, c-format
 msgid "Malformed ident string: '%s'"
 msgstr "Felaktig indragningssträng: \"%s\""
 
-#: builtin/commit.c:600 builtin/commit.c:633 builtin/commit.c:956
+#: builtin/commit.c:621 builtin/commit.c:654 builtin/commit.c:982
 #, c-format
 msgid "could not lookup commit %s"
 msgstr "kunde inte slå upp incheckningen %s"
 
-#: builtin/commit.c:612 builtin/shortlog.c:272
+#: builtin/commit.c:633 builtin/shortlog.c:271
 #, c-format
 msgid "(reading log message from standard input)\n"
 msgstr "(läser loggmeddelande från standard in)\n"
 
-#: builtin/commit.c:614
+#: builtin/commit.c:635
 msgid "could not read log from standard input"
 msgstr "kunde inte läsa logg från standard in"
 
-#: builtin/commit.c:618
+#: builtin/commit.c:639
 #, c-format
 msgid "could not read log file '%s'"
 msgstr "kunde inte läsa loggfilen \"%s\""
 
-#: builtin/commit.c:624
+#: builtin/commit.c:645
 msgid "commit has empty message"
 msgstr "incheckningen har ett tomt meddelande"
 
-#: builtin/commit.c:640
+#: builtin/commit.c:661
 msgid "could not read MERGE_MSG"
 msgstr "kunde inte läsa MERGE_MSG"
 
-#: builtin/commit.c:644
+#: builtin/commit.c:665
 msgid "could not read SQUASH_MSG"
 msgstr "kunde inte läsa SQUASH_MSG"
 
-#: builtin/commit.c:648
+#: builtin/commit.c:669
 #, c-format
 msgid "could not read '%s'"
 msgstr "kunde inte läsa \"%s\""
 
-#: builtin/commit.c:709
+#: builtin/commit.c:730
 msgid "could not write commit template"
 msgstr "kunde inte skriva incheckningsmall"
 
-#: builtin/commit.c:720
+#: builtin/commit.c:741
 #, c-format
 msgid ""
 "\n"
@@ -3660,7 +4030,7 @@
 "\t%s\n"
 "och försöker igen.\n"
 
-#: builtin/commit.c:725
+#: builtin/commit.c:746
 #, c-format
 msgid ""
 "\n"
@@ -3675,7 +4045,7 @@
 "\t%s\n"
 "och försöker igen.\n"
 
-#: builtin/commit.c:737
+#: builtin/commit.c:758
 #, c-format
 msgid ""
 "Please enter the commit message for your changes. Lines starting\n"
@@ -3685,7 +4055,7 @@
 "med \"%c\" kommer ignoreras, och ett tomt meddelande avbryter "
 "incheckningen.\n"
 
-#: builtin/commit.c:742
+#: builtin/commit.c:763
 #, c-format
 msgid ""
 "Please enter the commit message for your changes. Lines starting\n"
@@ -3696,139 +4066,139 @@
 "med \"%c\" kommer behållas; du kan själv ta bort dem om du vill.\n"
 "Ett tomt meddelande avbryter incheckningen.\n"
 
-#: builtin/commit.c:755
+#: builtin/commit.c:776
 #, c-format
 msgid "%sAuthor:    %s"
 msgstr "%sFörfattare: %s"
 
-#: builtin/commit.c:762
+#: builtin/commit.c:783
 #, c-format
 msgid "%sCommitter: %s"
 msgstr "%sIncheckare: %s"
 
-#: builtin/commit.c:782
+#: builtin/commit.c:803
 msgid "Cannot read index"
 msgstr "Kan inte läsa indexet"
 
-#: builtin/commit.c:819
+#: builtin/commit.c:845
 msgid "Error building trees"
 msgstr "Fel vid byggande av träd"
 
-#: builtin/commit.c:834 builtin/tag.c:359
+#: builtin/commit.c:860 builtin/tag.c:359
 #, c-format
 msgid "Please supply the message using either -m or -F option.\n"
 msgstr "Ange meddelandet en av flaggorna -m eller -F.\n"
 
-#: builtin/commit.c:931
+#: builtin/commit.c:957
 #, c-format
 msgid "No existing author found with '%s'"
 msgstr "Hittade ingen befintlig författare med \"%s\""
 
-#: builtin/commit.c:946 builtin/commit.c:1140
+#: builtin/commit.c:972 builtin/commit.c:1208
 #, c-format
 msgid "Invalid untracked files mode '%s'"
 msgstr "Ogiltigt läge för ospårade filer: \"%s\""
 
-#: builtin/commit.c:976
+#: builtin/commit.c:1009
+msgid "--long and -z are incompatible"
+msgstr "--long och -z är inkompatibla"
+
+#: builtin/commit.c:1039
 msgid "Using both --reset-author and --author does not make sense"
 msgstr "Kan inte använda både --reset-author och --author"
 
-#: builtin/commit.c:987
+#: builtin/commit.c:1050
 msgid "You have nothing to amend."
 msgstr "Du har inget att utöka."
 
-#: builtin/commit.c:990
+#: builtin/commit.c:1053
 msgid "You are in the middle of a merge -- cannot amend."
 msgstr "Du är i mitten av en sammanslagning -- kan inte utöka."
 
-#: builtin/commit.c:992
+#: builtin/commit.c:1055
 msgid "You are in the middle of a cherry-pick -- cannot amend."
 msgstr "Du är i mitten av en cherry-pick -- kan inte utöka."
 
-#: builtin/commit.c:995
+#: builtin/commit.c:1058
 msgid "Options --squash and --fixup cannot be used together"
 msgstr "Flaggorna --squash och --fixup kan inte användas samtidigt"
 
-#: builtin/commit.c:1005
+#: builtin/commit.c:1068
 msgid "Only one of -c/-C/-F/--fixup can be used."
 msgstr "Endast en av -c/-C/-F/--fixup kan användas."
 
-#: builtin/commit.c:1007
+#: builtin/commit.c:1070
 msgid "Option -m cannot be combined with -c/-C/-F/--fixup."
 msgstr "Flaggan -m kan inte kombineras med -c/-C/-F/--fixup."
 
-#: builtin/commit.c:1015
+#: builtin/commit.c:1078
 msgid "--reset-author can be used only with -C, -c or --amend."
 msgstr "--reset-author kan endast användas med -C, -c eller --amend."
 
-#: builtin/commit.c:1032
+#: builtin/commit.c:1095
 msgid "Only one of --include/--only/--all/--interactive/--patch can be used."
 msgstr ""
 "Endast en av --include/--only/--all/--interactive/--patch kan användas."
 
-#: builtin/commit.c:1034
+#: builtin/commit.c:1097
 msgid "No paths with --include/--only does not make sense."
 msgstr "Du måste ange sökvägar tillsammans med --include/--only."
 
-#: builtin/commit.c:1036
+#: builtin/commit.c:1099
 msgid "Clever... amending the last one with dirty index."
 msgstr "Smart... utöka den senaste med smutsigt index."
 
-#: builtin/commit.c:1038
+#: builtin/commit.c:1101
 msgid "Explicit paths specified without -i nor -o; assuming --only paths..."
 msgstr "Explicita sökvägar angavs utan -i eller -o; antar --only sökvägar..."
 
-#: builtin/commit.c:1048 builtin/tag.c:575
+#: builtin/commit.c:1111 builtin/tag.c:575
 #, c-format
 msgid "Invalid cleanup mode %s"
 msgstr "Felaktigt städningsläge %s"
 
-#: builtin/commit.c:1053
+#: builtin/commit.c:1116
 msgid "Paths with -a does not make sense."
 msgstr "Kan inte ange sökvägar med -a."
 
-#: builtin/commit.c:1059 builtin/commit.c:1194
-msgid "--long and -z are incompatible"
-msgstr "--long och -z är inkompatibla"
-
-#: builtin/commit.c:1154 builtin/commit.c:1390
+#: builtin/commit.c:1222 builtin/commit.c:1455
 msgid "show status concisely"
-msgstr "vis koncis status"
+msgstr "visa koncis status"
 
-#: builtin/commit.c:1156 builtin/commit.c:1392
+#: builtin/commit.c:1224 builtin/commit.c:1457
 msgid "show branch information"
 msgstr "visa information om gren"
 
-#: builtin/commit.c:1158 builtin/commit.c:1394 builtin/push.c:426
+#: builtin/commit.c:1226 builtin/commit.c:1459 builtin/push.c:452
 msgid "machine-readable output"
 msgstr "maskinläsbar utdata"
 
-#: builtin/commit.c:1161 builtin/commit.c:1396
+#: builtin/commit.c:1229 builtin/commit.c:1461
 msgid "show status in long format (default)"
 msgstr "visa status i långt format (standard)"
 
-#: builtin/commit.c:1164 builtin/commit.c:1399
+#: builtin/commit.c:1232 builtin/commit.c:1464
 msgid "terminate entries with NUL"
 msgstr "terminera poster med NUL"
 
-#: builtin/commit.c:1166 builtin/commit.c:1402 builtin/fast-export.c:653
-#: builtin/fast-export.c:656 builtin/tag.c:459
+#: builtin/commit.c:1234 builtin/commit.c:1467 builtin/fast-export.c:667
+#: builtin/fast-export.c:670 builtin/tag.c:459
 msgid "mode"
 msgstr "läge"
 
-#: builtin/commit.c:1167 builtin/commit.c:1402
+#: builtin/commit.c:1235 builtin/commit.c:1467
 msgid "show untracked files, optional modes: all, normal, no. (Default: all)"
 msgstr "visa ospårade filer, valfria lägen: alla, normal, no. (Standard: all)"
 
-#: builtin/commit.c:1170
+#: builtin/commit.c:1238
 msgid "show ignored files"
 msgstr "visa ignorerade filer"
 
-#: builtin/commit.c:1171 parse-options.h:151
+#: builtin/commit.c:1239 parse-options.h:154
 msgid "when"
 msgstr "när"
 
-#: builtin/commit.c:1172
+#: builtin/commit.c:1240
 msgid ""
 "ignore changes to submodules, optional when: all, dirty, untracked. "
 "(Default: all)"
@@ -3836,217 +4206,217 @@
 "ignorera ändringar i undermoduler, valfritt när: all, dirty, untracked. "
 "(Default: all)"
 
-#: builtin/commit.c:1174
+#: builtin/commit.c:1242
 msgid "list untracked files in columns"
 msgstr "visa ospårade filer i spalter"
 
-#: builtin/commit.c:1248
+#: builtin/commit.c:1313
 msgid "couldn't look up newly created commit"
 msgstr "kunde inte slå upp en precis skapad incheckning"
 
-#: builtin/commit.c:1250
+#: builtin/commit.c:1315
 msgid "could not parse newly created commit"
 msgstr "kunde inte tolka en precis skapad incheckning"
 
-#: builtin/commit.c:1291
+#: builtin/commit.c:1356
 msgid "detached HEAD"
 msgstr "frånkopplad HEAD"
 
-#: builtin/commit.c:1293
+#: builtin/commit.c:1358
 msgid " (root-commit)"
 msgstr " (rotincheckning)"
 
-#: builtin/commit.c:1360
+#: builtin/commit.c:1425
 msgid "suppress summary after successful commit"
 msgstr "undertryck sammanfattning efter framgångsrik incheckning"
 
-#: builtin/commit.c:1361
+#: builtin/commit.c:1426
 msgid "show diff in commit message template"
 msgstr "visa diff i mallen för incheckningsmeddelandet"
 
-#: builtin/commit.c:1363
+#: builtin/commit.c:1428
 msgid "Commit message options"
 msgstr "Alternativ för incheckningsmeddelande"
 
-#: builtin/commit.c:1364 builtin/tag.c:457
+#: builtin/commit.c:1429 builtin/tag.c:457
 msgid "read message from file"
 msgstr "läs meddelande från fil"
 
-#: builtin/commit.c:1365
+#: builtin/commit.c:1430
 msgid "author"
 msgstr "författare"
 
-#: builtin/commit.c:1365
+#: builtin/commit.c:1430
 msgid "override author for commit"
 msgstr "överstyr författare för incheckningen"
 
-#: builtin/commit.c:1366 builtin/gc.c:178
+#: builtin/commit.c:1431 builtin/gc.c:178
 msgid "date"
 msgstr "datum"
 
-#: builtin/commit.c:1366
+#: builtin/commit.c:1431
 msgid "override date for commit"
 msgstr "överstyr datum för inchecknignen"
 
-#: builtin/commit.c:1367 builtin/merge.c:208 builtin/notes.c:533
-#: builtin/notes.c:690 builtin/tag.c:455
+#: builtin/commit.c:1432 builtin/merge.c:223 builtin/notes.c:405
+#: builtin/notes.c:562 builtin/tag.c:455
 msgid "message"
 msgstr "meddelande"
 
-#: builtin/commit.c:1367
+#: builtin/commit.c:1432
 msgid "commit message"
 msgstr "incheckningsmeddelande"
 
-#: builtin/commit.c:1368
+#: builtin/commit.c:1433
 msgid "reuse and edit message from specified commit"
 msgstr "återanvänd och redigera meddelande från angiven incheckning"
 
-#: builtin/commit.c:1369
+#: builtin/commit.c:1434
 msgid "reuse message from specified commit"
 msgstr "återanvänd meddelande från angiven incheckning"
 
-#: builtin/commit.c:1370
+#: builtin/commit.c:1435
 msgid "use autosquash formatted message to fixup specified commit"
 msgstr ""
 "använd autosquash-formaterat meddelande för att fixa angiven incheckning"
 
-#: builtin/commit.c:1371
+#: builtin/commit.c:1436
 msgid "use autosquash formatted message to squash specified commit"
 msgstr ""
 "använd autosquash-formaterat meddelande för att slå ihop med angiven "
 "incheckning"
 
-#: builtin/commit.c:1372
+#: builtin/commit.c:1437
 msgid "the commit is authored by me now (used with -C/-c/--amend)"
 msgstr "jag är nu författare av incheckningen (används med -C/-c/--amend)"
 
-#: builtin/commit.c:1373 builtin/log.c:1104 builtin/revert.c:109
+#: builtin/commit.c:1438 builtin/log.c:1160 builtin/revert.c:111
 msgid "add Signed-off-by:"
 msgstr "lägg till Signed-off-by:"
 
-#: builtin/commit.c:1374
+#: builtin/commit.c:1439
 msgid "use specified template file"
 msgstr "använd angiven mallfil"
 
-#: builtin/commit.c:1375
+#: builtin/commit.c:1440
 msgid "force edit of commit"
 msgstr "tvinga redigering av incheckning"
 
-#: builtin/commit.c:1376
+#: builtin/commit.c:1441
 msgid "default"
 msgstr "standard"
 
-#: builtin/commit.c:1376 builtin/tag.c:460
+#: builtin/commit.c:1441 builtin/tag.c:460
 msgid "how to strip spaces and #comments from message"
 msgstr "hur blanksteg och #kommentarer skall tas bort från meddelande"
 
-#: builtin/commit.c:1377
+#: builtin/commit.c:1442
 msgid "include status in commit message template"
 msgstr "inkludera status i mallen för incheckningsmeddelandet"
 
-#: builtin/commit.c:1378 builtin/merge.c:215 builtin/tag.c:461
+#: builtin/commit.c:1443 builtin/merge.c:230 builtin/tag.c:461
 msgid "key id"
 msgstr "nyckel-id"
 
-#: builtin/commit.c:1379 builtin/merge.c:216
+#: builtin/commit.c:1444 builtin/merge.c:231
 msgid "GPG sign commit"
 msgstr "GPG-signera incheckning"
 
 #. end commit message options
-#: builtin/commit.c:1382
+#: builtin/commit.c:1447
 msgid "Commit contents options"
 msgstr "Alternativ för incheckningens innehåll"
 
-#: builtin/commit.c:1383
+#: builtin/commit.c:1448
 msgid "commit all changed files"
 msgstr "checka in alla ändrade filer"
 
-#: builtin/commit.c:1384
+#: builtin/commit.c:1449
 msgid "add specified files to index for commit"
 msgstr "lägg till angivna filer till indexet för incheckning"
 
-#: builtin/commit.c:1385
+#: builtin/commit.c:1450
 msgid "interactively add files"
 msgstr "lägg till filer interaktivt"
 
-#: builtin/commit.c:1386
+#: builtin/commit.c:1451
 msgid "interactively add changes"
 msgstr "lägg till ändringar interaktivt"
 
-#: builtin/commit.c:1387
+#: builtin/commit.c:1452
 msgid "commit only specified files"
 msgstr "checka endast in angivna filer"
 
-#: builtin/commit.c:1388
+#: builtin/commit.c:1453
 msgid "bypass pre-commit hook"
 msgstr "förbigå pre-commit-krok"
 
-#: builtin/commit.c:1389
+#: builtin/commit.c:1454
 msgid "show what would be committed"
 msgstr "visa vad som skulle checkas in"
 
-#: builtin/commit.c:1400
+#: builtin/commit.c:1465
 msgid "amend previous commit"
 msgstr "lägg till föregående incheckning"
 
-#: builtin/commit.c:1401
+#: builtin/commit.c:1466
 msgid "bypass post-rewrite hook"
 msgstr "förbigå post-rewrite-krok"
 
-#: builtin/commit.c:1406
+#: builtin/commit.c:1471
 msgid "ok to record an empty change"
 msgstr "ok att registrera en tom ändring"
 
-#: builtin/commit.c:1409
+#: builtin/commit.c:1474
 msgid "ok to record a change with an empty message"
 msgstr "ok att registrera en ändring med tomt meddelande"
 
-#: builtin/commit.c:1441
+#: builtin/commit.c:1507
 msgid "could not parse HEAD commit"
 msgstr "kunde inte tolka HEAD:s incheckning"
 
-#: builtin/commit.c:1479 builtin/merge.c:510
+#: builtin/commit.c:1545 builtin/merge.c:525
 #, c-format
 msgid "could not open '%s' for reading"
 msgstr "kunde inte öppna \"%s\" för läsning"
 
-#: builtin/commit.c:1486
+#: builtin/commit.c:1552
 #, c-format
 msgid "Corrupt MERGE_HEAD file (%s)"
 msgstr "Trasig MERGE_HEAD-fil (%s)"
 
-#: builtin/commit.c:1493
+#: builtin/commit.c:1559
 msgid "could not read MERGE_MODE"
 msgstr "kunde inte läsa MERGE_MODE"
 
-#: builtin/commit.c:1512
+#: builtin/commit.c:1578
 #, c-format
 msgid "could not read commit message: %s"
 msgstr "kunde inte läsa incheckningsmeddelande: %s"
 
-#: builtin/commit.c:1526
+#: builtin/commit.c:1592
 #, c-format
 msgid "Aborting commit; you did not edit the message.\n"
 msgstr "Avbryter incheckning; meddelandet inte redigerat.\n"
 
-#: builtin/commit.c:1531
+#: builtin/commit.c:1597
 #, c-format
 msgid "Aborting commit due to empty commit message.\n"
 msgstr "Avbryter på grund av tomt incheckningsmeddelande.\n"
 
-#: builtin/commit.c:1546 builtin/merge.c:847 builtin/merge.c:872
+#: builtin/commit.c:1612 builtin/merge.c:861 builtin/merge.c:886
 msgid "failed to write commit object"
 msgstr "kunde inte skriva incheckningsobjekt"
 
-#: builtin/commit.c:1567
+#: builtin/commit.c:1633
 msgid "cannot lock HEAD ref"
 msgstr "kunde inte låsa HEAD-referens"
 
-#: builtin/commit.c:1571
+#: builtin/commit.c:1637
 msgid "cannot update HEAD ref"
 msgstr "kunde inte uppdatera HEAD-referens"
 
-#: builtin/commit.c:1582
+#: builtin/commit.c:1648
 msgid ""
 "Repository has been updated, but unable to write\n"
 "new_index file. Check that disk is not full or quota is\n"
@@ -4061,171 +4431,183 @@
 msgid "git config [options]"
 msgstr "git config [flaggor]"
 
-#: builtin/config.c:51
+#: builtin/config.c:52
 msgid "Config file location"
 msgstr "Konfigurationsfilens plats"
 
-#: builtin/config.c:52
+#: builtin/config.c:53
 msgid "use global config file"
 msgstr "använd global konfigurationsfil"
 
-#: builtin/config.c:53
+#: builtin/config.c:54
 msgid "use system config file"
 msgstr "använd systemets konfigurationsfil"
 
-#: builtin/config.c:54
+#: builtin/config.c:55
 msgid "use repository config file"
 msgstr "använd arkivets konfigurationsfil"
 
-#: builtin/config.c:55
+#: builtin/config.c:56
 msgid "use given config file"
 msgstr "använd angiven konfigurationsil"
 
-#: builtin/config.c:56
+#: builtin/config.c:57
+msgid "blob-id"
+msgstr "blob-id"
+
+#: builtin/config.c:57
+msgid "read config from given blob object"
+msgstr "läs konfiguration från givet blob-objekt"
+
+#: builtin/config.c:58
 msgid "Action"
 msgstr "Åtgärd"
 
-#: builtin/config.c:57
+#: builtin/config.c:59
 msgid "get value: name [value-regex]"
 msgstr "hämta värde: namn [värde-reguttr]"
 
-#: builtin/config.c:58
+#: builtin/config.c:60
 msgid "get all values: key [value-regex]"
 msgstr "hämta alla värden: nyckel [värde-reguttr]"
 
-#: builtin/config.c:59
+#: builtin/config.c:61
 msgid "get values for regexp: name-regex [value-regex]"
 msgstr "hämta värden för reguttr: namn-reguttr [värde-reguttr]"
 
-#: builtin/config.c:60
+#: builtin/config.c:62
 msgid "replace all matching variables: name value [value_regex]"
 msgstr "ersätt alla motsvarande variabler: namn värde [värde-reguttr]"
 
-#: builtin/config.c:61
+#: builtin/config.c:63
 msgid "add a new variable: name value"
 msgstr "lägg till en ny variabel: namn värde"
 
-#: builtin/config.c:62
+#: builtin/config.c:64
 msgid "remove a variable: name [value-regex]"
 msgstr "ta bort en variabel: namn [värde-reguttr]"
 
-#: builtin/config.c:63
+#: builtin/config.c:65
 msgid "remove all matches: name [value-regex]"
 msgstr "ta bort alla träffar: namn [värde-reguttr]"
 
-#: builtin/config.c:64
+#: builtin/config.c:66
 msgid "rename section: old-name new-name"
 msgstr "byt namn på sektion: gammalt-namn nytt-namn"
 
-#: builtin/config.c:65
+#: builtin/config.c:67
 msgid "remove a section: name"
 msgstr "ta bort en sektion: namn"
 
-#: builtin/config.c:66
+#: builtin/config.c:68
 msgid "list all"
 msgstr "visa alla"
 
-#: builtin/config.c:67
+#: builtin/config.c:69
 msgid "open an editor"
 msgstr "öppna textredigeringsprogram"
 
-#: builtin/config.c:68 builtin/config.c:69
+#: builtin/config.c:70 builtin/config.c:71
 msgid "slot"
 msgstr "plats"
 
-#: builtin/config.c:68
+#: builtin/config.c:70
 msgid "find the color configured: [default]"
 msgstr "hitta den inställda färgen: [default]"
 
-#: builtin/config.c:69
+#: builtin/config.c:71
 msgid "find the color setting: [stdout-is-tty]"
 msgstr "hitta färginställningen: [stdout-is-tty]"
 
-#: builtin/config.c:70
+#: builtin/config.c:72
 msgid "Type"
 msgstr "Typ"
 
-#: builtin/config.c:71
+#: builtin/config.c:73
 msgid "value is \"true\" or \"false\""
 msgstr "värdet är \"true\" eller \"false\""
 
-#: builtin/config.c:72
+#: builtin/config.c:74
 msgid "value is decimal number"
 msgstr "värdet är ett decimalt tal"
 
-#: builtin/config.c:73
+#: builtin/config.c:75
 msgid "value is --bool or --int"
 msgstr "värdet är --bool eller --int"
 
-#: builtin/config.c:74
+#: builtin/config.c:76
 msgid "value is a path (file or directory name)"
 msgstr "värdet är en sökväg (fil- eller katalognamn)"
 
-#: builtin/config.c:75
+#: builtin/config.c:77
 msgid "Other"
 msgstr "Andra"
 
-#: builtin/config.c:76
+#: builtin/config.c:78
 msgid "terminate values with NUL byte"
 msgstr "terminera värden med NUL-byte"
 
-#: builtin/config.c:77
+#: builtin/config.c:79
 msgid "respect include directives on lookup"
 msgstr "respektera inkluderingsdirektiv vid uppslag"
 
 #: builtin/count-objects.c:82
-msgid "git count-objects [-v]"
-msgstr "git count-objects [-v]"
+msgid "git count-objects [-v] [-H | --human-readable]"
+msgstr "git count-objects [-v] [-H | --human-readable]"
 
-#: builtin/describe.c:15
+#: builtin/count-objects.c:97
+msgid "print sizes in human readable format"
+msgstr "skriv storlekar i människoläsbart format"
+
+#: builtin/describe.c:16
 msgid "git describe [options] <committish>*"
 msgstr "git describe [flaggor] <incheckning-igt>*"
 
-#: builtin/describe.c:16
+#: builtin/describe.c:17
 msgid "git describe [options] --dirty"
 msgstr "git describe [flaggor] --dirty"
 
-#: builtin/describe.c:233
+#: builtin/describe.c:237
 #, c-format
 msgid "annotated tag %s not available"
 msgstr "den annoterade taggen %s inte tillgänglig"
 
-#: builtin/describe.c:237
+#: builtin/describe.c:241
 #, c-format
 msgid "annotated tag %s has no embedded name"
 msgstr "den annoterade taggen %s har inget inbäddat namn"
 
-#: builtin/describe.c:239
+#: builtin/describe.c:243
 #, c-format
 msgid "tag '%s' is really '%s' here"
 msgstr "taggen \"%s\" är i verkligheten \"%s\" här"
 
-#: builtin/describe.c:266
+#: builtin/describe.c:270
 #, c-format
 msgid "Not a valid object name %s"
 msgstr "Objektnamnet är inte giltigt: %s"
 
-#: builtin/describe.c:269
+#: builtin/describe.c:273
 #, c-format
 msgid "%s is not a valid '%s' object"
 msgstr "%s är inte ett giltigt \"%s\"-objekt"
 
-#: builtin/describe.c:286
+#: builtin/describe.c:290
 #, c-format
 msgid "no tag exactly matches '%s'"
 msgstr "ingen tagg motsvarar \"%s\" exakt"
 
-#: builtin/describe.c:288
+#: builtin/describe.c:292
 #, c-format
 msgid "searching to describe %s\n"
 msgstr "söker för att beskriva %s\n"
 
-#: builtin/describe.c:328
+#: builtin/describe.c:332
 #, c-format
 msgid "finished search at %s\n"
 msgstr "avslutade sökning på %s\n"
 
-#: builtin/describe.c:352
+#: builtin/describe.c:359
 #, c-format
 msgid ""
 "No annotated tags can describe '%s'.\n"
@@ -4234,7 +4616,7 @@
 "Inga annoterade taggar kan beskriva \"%s\".\n"
 "Det finns dock oannoterade taggar: testa --tags."
 
-#: builtin/describe.c:356
+#: builtin/describe.c:363
 #, c-format
 msgid ""
 "No tags can describe '%s'.\n"
@@ -4243,12 +4625,12 @@
 "Inga taggar kan beskriva \"%s\".\n"
 "Testa --always, eller skapa några taggar."
 
-#: builtin/describe.c:377
+#: builtin/describe.c:384
 #, c-format
 msgid "traversed %lu commits\n"
 msgstr "traverserade %lu incheckningar\n"
 
-#: builtin/describe.c:380
+#: builtin/describe.c:387
 #, c-format
 msgid ""
 "more than %i tags found; listed %i most recent\n"
@@ -4257,59 +4639,63 @@
 "mer än %i taggar hittades; listar de %i senaste\n"
 "gav upp sökningen vid %s\n"
 
-#: builtin/describe.c:402
+#: builtin/describe.c:409
 msgid "find the tag that comes after the commit"
 msgstr "hitta taggen som kommer efter incheckningen"
 
-#: builtin/describe.c:403
+#: builtin/describe.c:410
 msgid "debug search strategy on stderr"
 msgstr "felsök sökstrategin på standard fel"
 
-#: builtin/describe.c:404
+#: builtin/describe.c:411
 msgid "use any ref"
 msgstr "använd alla referenser"
 
-#: builtin/describe.c:405
+#: builtin/describe.c:412
 msgid "use any tag, even unannotated"
 msgstr "använd alla taggar, även oannoterade"
 
-#: builtin/describe.c:406
+#: builtin/describe.c:413
 msgid "always use long format"
 msgstr "använd alltid långt format"
 
-#: builtin/describe.c:409
+#: builtin/describe.c:414
+msgid "only follow first parent"
+msgstr "följ endast första föräldern"
+
+#: builtin/describe.c:417
 msgid "only output exact matches"
 msgstr "skriv endast ut exakta träffar"
 
-#: builtin/describe.c:411
+#: builtin/describe.c:419
 msgid "consider <n> most recent tags (default: 10)"
 msgstr "överväg de <n> nyaste taggarna (standard: 10)"
 
-#: builtin/describe.c:413
+#: builtin/describe.c:421
 msgid "only consider tags matching <pattern>"
 msgstr "överväg endast taggar som motsvarar <mönster>"
 
-#: builtin/describe.c:415 builtin/name-rev.c:238
+#: builtin/describe.c:423 builtin/name-rev.c:322
 msgid "show abbreviated commit object as fallback"
 msgstr "visa förkortade incheckningsobjekt som standard"
 
-#: builtin/describe.c:416
+#: builtin/describe.c:424
 msgid "mark"
 msgstr "märke"
 
-#: builtin/describe.c:417
+#: builtin/describe.c:425
 msgid "append <mark> on dirty working tree (default: \"-dirty\")"
 msgstr "lägg till <märke> på lortigt arbetsträd (standard: \"-dirty\")"
 
-#: builtin/describe.c:435
+#: builtin/describe.c:443
 msgid "--long is incompatible with --abbrev=0"
 msgstr "--long är inkompatibel med --abbrev=0"
 
-#: builtin/describe.c:461
+#: builtin/describe.c:469
 msgid "No names found, cannot describe anything."
 msgstr "Inga namn hittades, kan inte beskriva något."
 
-#: builtin/describe.c:481
+#: builtin/describe.c:489
 msgid "--dirty is incompatible with committishes"
 msgstr "--dirty är inkompatibelt med \"committish\"-värden"
 
@@ -4318,31 +4704,26 @@
 msgid "'%s': not a regular file or symlink"
 msgstr "\"%s\": inte en normal fil eller symbolisk länk"
 
-#: builtin/diff.c:228
+#: builtin/diff.c:230
 #, c-format
 msgid "invalid option: %s"
 msgstr "ogiltig flagga: %s"
 
-#: builtin/diff.c:305
+#: builtin/diff.c:307
 msgid "Not a git repository"
 msgstr "Inte ett git-arkiv"
 
-#: builtin/diff.c:348
+#: builtin/diff.c:350
 #, c-format
 msgid "invalid object '%s' given."
 msgstr "objektet \"%s\" som angavs är felaktigt."
 
-#: builtin/diff.c:353
-#, c-format
-msgid "more than %d trees given: '%s'"
-msgstr "mer än %d träd angavs: \"%s\""
-
-#: builtin/diff.c:363
+#: builtin/diff.c:359
 #, c-format
 msgid "more than two blobs given: '%s'"
 msgstr "mer än två blobbar angavs: \"%s\""
 
-#: builtin/diff.c:371
+#: builtin/diff.c:366
 #, c-format
 msgid "unhandled object '%s' given."
 msgstr "ej hanterat objekt \"%s\" angavs."
@@ -4351,39 +4732,39 @@
 msgid "git fast-export [rev-list-opts]"
 msgstr "git fast-export [rev-list-flaggor]"
 
-#: builtin/fast-export.c:652
+#: builtin/fast-export.c:666
 msgid "show progress after <n> objects"
 msgstr "visa förlopp efter <n> objekt"
 
-#: builtin/fast-export.c:654
+#: builtin/fast-export.c:668
 msgid "select handling of signed tags"
 msgstr "välj hantering av signerade taggar"
 
-#: builtin/fast-export.c:657
+#: builtin/fast-export.c:671
 msgid "select handling of tags that tag filtered objects"
 msgstr "välj hantering av taggar som har taggfiltrerade objekt"
 
-#: builtin/fast-export.c:660
+#: builtin/fast-export.c:674
 msgid "Dump marks to this file"
 msgstr "Dump märken till filen"
 
-#: builtin/fast-export.c:662
+#: builtin/fast-export.c:676
 msgid "Import marks from this file"
 msgstr "Importera märken från filen"
 
-#: builtin/fast-export.c:664
+#: builtin/fast-export.c:678
 msgid "Fake a tagger when tags lack one"
 msgstr "Fejka taggare när taggen saknar en"
 
-#: builtin/fast-export.c:666
+#: builtin/fast-export.c:680
 msgid "Output full tree for each commit"
 msgstr "Skriv ut hela trädet för varje incheckning"
 
-#: builtin/fast-export.c:668
+#: builtin/fast-export.c:682
 msgid "Use the done feature to terminate the stream"
 msgstr "Använd done-funktionen för att avsluta strömmen"
 
-#: builtin/fast-export.c:669
+#: builtin/fast-export.c:683
 msgid "Skip output of blob data"
 msgstr "Hoppa över skrivning av blob-data"
 
@@ -4459,7 +4840,7 @@
 msgid "convert to a complete repository"
 msgstr "konvertera till komplett arkiv"
 
-#: builtin/fetch.c:88 builtin/log.c:1121
+#: builtin/fetch.c:88 builtin/log.c:1177
 msgid "dir"
 msgstr "kat"
 
@@ -4471,76 +4852,76 @@
 msgid "default mode for recursion"
 msgstr "standardläge för rekursion"
 
-#: builtin/fetch.c:204
+#: builtin/fetch.c:220
 msgid "Couldn't find remote ref HEAD"
 msgstr "Kunde inte hitta fjärr-referensen HEAD"
 
-#: builtin/fetch.c:257
+#: builtin/fetch.c:273
 #, c-format
 msgid "object %s not found"
 msgstr "objektet %s hittades inte"
 
-#: builtin/fetch.c:262
+#: builtin/fetch.c:278
 msgid "[up to date]"
 msgstr "[àjour]"
 
-#: builtin/fetch.c:276
+#: builtin/fetch.c:292
 #, c-format
 msgid "! %-*s %-*s -> %s  (can't fetch in current branch)"
 msgstr "! %-*s %-*s -> %s  (kan inte hämta i aktuell gren)"
 
-#: builtin/fetch.c:277 builtin/fetch.c:363
+#: builtin/fetch.c:293 builtin/fetch.c:379
 msgid "[rejected]"
 msgstr "[refuserad]"
 
-#: builtin/fetch.c:288
+#: builtin/fetch.c:304
 msgid "[tag update]"
 msgstr "[uppdaterad tagg]"
 
-#: builtin/fetch.c:290 builtin/fetch.c:325 builtin/fetch.c:343
+#: builtin/fetch.c:306 builtin/fetch.c:341 builtin/fetch.c:359
 msgid "  (unable to update local ref)"
 msgstr "  (kunde inte uppdatera lokal ref)"
 
-#: builtin/fetch.c:308
+#: builtin/fetch.c:324
 msgid "[new tag]"
 msgstr "[ny tagg]"
 
-#: builtin/fetch.c:311
+#: builtin/fetch.c:327
 msgid "[new branch]"
 msgstr "[ny gren]"
 
-#: builtin/fetch.c:314
+#: builtin/fetch.c:330
 msgid "[new ref]"
 msgstr "[ny ref]"
 
-#: builtin/fetch.c:359
+#: builtin/fetch.c:375
 msgid "unable to update local ref"
 msgstr "kunde inte uppdatera lokal ref"
 
-#: builtin/fetch.c:359
+#: builtin/fetch.c:375
 msgid "forced update"
 msgstr "tvingad uppdatering"
 
-#: builtin/fetch.c:365
+#: builtin/fetch.c:381
 msgid "(non-fast-forward)"
 msgstr "(ej snabbspolad)"
 
-#: builtin/fetch.c:396 builtin/fetch.c:688
+#: builtin/fetch.c:412 builtin/fetch.c:718
 #, c-format
 msgid "cannot open %s: %s\n"
 msgstr "kan inte öppna %s: %s\n"
 
-#: builtin/fetch.c:405
+#: builtin/fetch.c:421
 #, c-format
 msgid "%s did not send all necessary objects\n"
 msgstr "%s sände inte alla nödvändiga objekt\n"
 
-#: builtin/fetch.c:491
+#: builtin/fetch.c:520
 #, c-format
 msgid "From %.*s\n"
 msgstr "Från %.*s\n"
 
-#: builtin/fetch.c:502
+#: builtin/fetch.c:531
 #, c-format
 msgid ""
 "some local refs could not be updated; try running\n"
@@ -4549,55 +4930,55 @@
 "vissa lokala referenser kunde inte uppdateras; testa att köra\n"
 " \"git remote prune %s\" för att ta bort gamla grenar som står i konflikt"
 
-#: builtin/fetch.c:552
+#: builtin/fetch.c:581
 #, c-format
 msgid "   (%s will become dangling)"
 msgstr "   (%s kommer bli dinglande)"
 
-#: builtin/fetch.c:553
+#: builtin/fetch.c:582
 #, c-format
 msgid "   (%s has become dangling)"
 msgstr "   (%s har blivit dinglande)"
 
-#: builtin/fetch.c:560
+#: builtin/fetch.c:589
 msgid "[deleted]"
 msgstr "[borttagen]"
 
-#: builtin/fetch.c:561 builtin/remote.c:1055
+#: builtin/fetch.c:590 builtin/remote.c:1055
 msgid "(none)"
 msgstr "(ingen)"
 
-#: builtin/fetch.c:678
+#: builtin/fetch.c:708
 #, c-format
 msgid "Refusing to fetch into current branch %s of non-bare repository"
 msgstr "Vägrar hämta till aktuell gren %s i ett icke-naket arkiv"
 
-#: builtin/fetch.c:712
+#: builtin/fetch.c:742
 #, c-format
 msgid "Don't know how to fetch from %s"
 msgstr "Vet inte hur man hämtar från %s"
 
-#: builtin/fetch.c:789
+#: builtin/fetch.c:823
 #, c-format
 msgid "Option \"%s\" value \"%s\" is not valid for %s"
 msgstr "Flaggan \"%s\" och värdet \"%s\" är inte giltigt för %s"
 
-#: builtin/fetch.c:792
+#: builtin/fetch.c:826
 #, c-format
 msgid "Option \"%s\" is ignored for %s\n"
 msgstr "Flaggan \"%s\" ignoreras för %s\n"
 
-#: builtin/fetch.c:894
+#: builtin/fetch.c:928
 #, c-format
 msgid "Fetching %s\n"
 msgstr "Hämtar %s\n"
 
-#: builtin/fetch.c:896 builtin/remote.c:100
+#: builtin/fetch.c:930 builtin/remote.c:100
 #, c-format
 msgid "Could not fetch %s"
 msgstr "Kunde inte hämta %s"
 
-#: builtin/fetch.c:915
+#: builtin/fetch.c:949
 msgid ""
 "No remote repository specified.  Please, specify either a URL or a\n"
 "remote name from which new revisions should be fetched."
@@ -4605,32 +4986,32 @@
 "Inget fjärrarkiv angavs. Ange antingen en URL eller namnet på ett\n"
 "fjärrarkiv som nya incheckningar skall hämtas från."
 
-#: builtin/fetch.c:935
+#: builtin/fetch.c:969
 msgid "You need to specify a tag name."
 msgstr "Du måste ange namnet på en tagg."
 
-#: builtin/fetch.c:981
+#: builtin/fetch.c:1015
 msgid "--depth and --unshallow cannot be used together"
 msgstr "--depth och --unshallow kan inte användas samtidigt"
 
-#: builtin/fetch.c:983
+#: builtin/fetch.c:1017
 msgid "--unshallow on a complete repository does not make sense"
 msgstr "--unshallow kan inte användas på ett komplett arkiv"
 
-#: builtin/fetch.c:1002
+#: builtin/fetch.c:1036
 msgid "fetch --all does not take a repository argument"
 msgstr "fetch --all tar inte namnet på ett arkiv som argument"
 
-#: builtin/fetch.c:1004
+#: builtin/fetch.c:1038
 msgid "fetch --all does not make sense with refspecs"
 msgstr "fetch --all kan inte anges med referensspecifikationer"
 
-#: builtin/fetch.c:1015
+#: builtin/fetch.c:1049
 #, c-format
 msgid "No such remote or remote group: %s"
 msgstr "Fjärren eller fjärrgruppen finns inte: %s"
 
-#: builtin/fetch.c:1023
+#: builtin/fetch.c:1057
 msgid "Fetching a group and specifying refspecs does not make sense"
 msgstr "Kan inte hämta från grupp och ange referensspecifikationer"
 
@@ -4639,29 +5020,29 @@
 msgstr ""
 "git fmt-merge-msg [-m <meddelande>] [--log[=<n>]|--no-log] [--file <fil>]"
 
-#: builtin/fmt-merge-msg.c:659 builtin/fmt-merge-msg.c:662 builtin/grep.c:701
-#: builtin/merge.c:188 builtin/show-branch.c:656 builtin/show-ref.c:175
-#: builtin/tag.c:446 parse-options.h:133 parse-options.h:239
+#: builtin/fmt-merge-msg.c:663 builtin/fmt-merge-msg.c:666 builtin/grep.c:700
+#: builtin/merge.c:203 builtin/show-branch.c:655 builtin/show-ref.c:179
+#: builtin/tag.c:446 parse-options.h:133 parse-options.h:243
 msgid "n"
 msgstr "n"
 
-#: builtin/fmt-merge-msg.c:660
+#: builtin/fmt-merge-msg.c:664
 msgid "populate log with at most <n> entries from shortlog"
 msgstr "fyll i loggen med som mest <n> poster från shortlog"
 
-#: builtin/fmt-merge-msg.c:663
+#: builtin/fmt-merge-msg.c:667
 msgid "alias for --log (deprecated)"
 msgstr "alias för --log (avråds)"
 
-#: builtin/fmt-merge-msg.c:666
+#: builtin/fmt-merge-msg.c:670
 msgid "text"
 msgstr "text"
 
-#: builtin/fmt-merge-msg.c:667
+#: builtin/fmt-merge-msg.c:671
 msgid "use <text> as start of message"
 msgstr "inled meddelande med <text>"
 
-#: builtin/fmt-merge-msg.c:668
+#: builtin/fmt-merge-msg.c:672
 msgid "file to read from"
 msgstr "fil att läsa från"
 
@@ -4800,220 +5181,220 @@
 msgid "grep: failed to create thread: %s"
 msgstr "grep: misslyckades skapa tråd. %s"
 
-#: builtin/grep.c:365
+#: builtin/grep.c:364
 #, c-format
 msgid "Failed to chdir: %s"
 msgstr "Kunde inte byta katalog (chdir): %s"
 
-#: builtin/grep.c:443 builtin/grep.c:478
+#: builtin/grep.c:442 builtin/grep.c:477
 #, c-format
 msgid "unable to read tree (%s)"
 msgstr "kunde inte läsa träd (%s)"
 
-#: builtin/grep.c:493
+#: builtin/grep.c:492
 #, c-format
 msgid "unable to grep from object of type %s"
 msgstr "Kunde inte \"grep\" från objekt av typen %s"
 
-#: builtin/grep.c:551
+#: builtin/grep.c:550
 #, c-format
 msgid "switch `%c' expects a numerical value"
 msgstr "flaggan \"%c\" antar ett numeriskt värde"
 
-#: builtin/grep.c:568
+#: builtin/grep.c:567
 #, c-format
 msgid "cannot open '%s'"
 msgstr "kan inte öppna \"%s\""
 
-#: builtin/grep.c:643
+#: builtin/grep.c:642
 msgid "search in index instead of in the work tree"
 msgstr "sök i indexet istället för i arbetskatalogen"
 
-#: builtin/grep.c:645
+#: builtin/grep.c:644
 msgid "find in contents not managed by git"
 msgstr "sök i innehål som inte hanteras av git"
 
-#: builtin/grep.c:647
+#: builtin/grep.c:646
 msgid "search in both tracked and untracked files"
 msgstr "sök i både spårade och ospårade filer"
 
-#: builtin/grep.c:649
+#: builtin/grep.c:648
 msgid "search also in ignored files"
 msgstr "sök även i ignorerade filer"
 
-#: builtin/grep.c:652
+#: builtin/grep.c:651
 msgid "show non-matching lines"
-msgstr "vis rader som inte träffas"
+msgstr "visa rader som inte träffas"
 
-#: builtin/grep.c:654
+#: builtin/grep.c:653
 msgid "case insensitive matching"
 msgstr "skiftlägesokänslig sökning"
 
-#: builtin/grep.c:656
+#: builtin/grep.c:655
 msgid "match patterns only at word boundaries"
 msgstr "matcha endast mönster vid ordgränser"
 
-#: builtin/grep.c:658
+#: builtin/grep.c:657
 msgid "process binary files as text"
 msgstr "hantera binärfiler som text"
 
-#: builtin/grep.c:660
+#: builtin/grep.c:659
 msgid "don't match patterns in binary files"
 msgstr "träffa inte mönster i binärfiler"
 
-#: builtin/grep.c:663
+#: builtin/grep.c:662
 msgid "descend at most <depth> levels"
 msgstr "gå som mest ned <djup> nivåer"
 
-#: builtin/grep.c:667
+#: builtin/grep.c:666
 msgid "use extended POSIX regular expressions"
 msgstr "använd utökade POSIX-reguljära uttryck"
 
-#: builtin/grep.c:670
+#: builtin/grep.c:669
 msgid "use basic POSIX regular expressions (default)"
 msgstr "använd grundläggande POSIX-reguljära uttryck (standard)"
 
-#: builtin/grep.c:673
+#: builtin/grep.c:672
 msgid "interpret patterns as fixed strings"
 msgstr "tolka mönster som fixerade strängar"
 
-#: builtin/grep.c:676
+#: builtin/grep.c:675
 msgid "use Perl-compatible regular expressions"
 msgstr "använd Perlkompatibla reguljära uttryck"
 
-#: builtin/grep.c:679
+#: builtin/grep.c:678
 msgid "show line numbers"
 msgstr "visa radnummer"
 
-#: builtin/grep.c:680
+#: builtin/grep.c:679
 msgid "don't show filenames"
 msgstr "visa inte filnamn"
 
-#: builtin/grep.c:681
+#: builtin/grep.c:680
 msgid "show filenames"
 msgstr "visa filnamn"
 
-#: builtin/grep.c:683
+#: builtin/grep.c:682
 msgid "show filenames relative to top directory"
 msgstr "visa filnamn relativa till toppkatalogen"
 
-#: builtin/grep.c:685
+#: builtin/grep.c:684
 msgid "show only filenames instead of matching lines"
 msgstr "visa endast filnamn istället för träffade rader"
 
-#: builtin/grep.c:687
+#: builtin/grep.c:686
 msgid "synonym for --files-with-matches"
 msgstr "synonym för --files-with-matches"
 
-#: builtin/grep.c:690
+#: builtin/grep.c:689
 msgid "show only the names of files without match"
 msgstr "visa endast namn på filer utan träffar"
 
-#: builtin/grep.c:692
+#: builtin/grep.c:691
 msgid "print NUL after filenames"
 msgstr "skriv NUL efter filnamn"
 
-#: builtin/grep.c:694
+#: builtin/grep.c:693
 msgid "show the number of matches instead of matching lines"
 msgstr "visa antal träffar istället för träffade rader"
 
-#: builtin/grep.c:695
+#: builtin/grep.c:694
 msgid "highlight matches"
 msgstr "ljusmarkera träffar"
 
-#: builtin/grep.c:697
+#: builtin/grep.c:696
 msgid "print empty line between matches from different files"
 msgstr "skriv tomma rader mellan träffar från olika filer"
 
-#: builtin/grep.c:699
+#: builtin/grep.c:698
 msgid "show filename only once above matches from same file"
 msgstr "visa filnamn endast en gång ovanför träffar från samma fil"
 
-#: builtin/grep.c:702
+#: builtin/grep.c:701
 msgid "show <n> context lines before and after matches"
 msgstr "visa <n> rader sammanhang före och efter träffar"
 
-#: builtin/grep.c:705
+#: builtin/grep.c:704
 msgid "show <n> context lines before matches"
 msgstr "visa <n> rader sammanhang före träffar"
 
-#: builtin/grep.c:707
+#: builtin/grep.c:706
 msgid "show <n> context lines after matches"
 msgstr "visa <n> rader sammanhang efter träffar"
 
-#: builtin/grep.c:708
+#: builtin/grep.c:707
 msgid "shortcut for -C NUM"
 msgstr "genväg för -C NUM"
 
-#: builtin/grep.c:711
+#: builtin/grep.c:710
 msgid "show a line with the function name before matches"
 msgstr "visa en rad med funktionsnamnet före träffen"
 
-#: builtin/grep.c:713
+#: builtin/grep.c:712
 msgid "show the surrounding function"
 msgstr "visa den omkringliggande funktionen"
 
-#: builtin/grep.c:716
+#: builtin/grep.c:715
 msgid "read patterns from file"
 msgstr "läs mönster från fil"
 
-#: builtin/grep.c:718
+#: builtin/grep.c:717
 msgid "match <pattern>"
 msgstr "träffa <mönster>"
 
-#: builtin/grep.c:720
+#: builtin/grep.c:719
 msgid "combine patterns specified with -e"
 msgstr "kombinera mönster som anges med -e"
 
-#: builtin/grep.c:732
+#: builtin/grep.c:731
 msgid "indicate hit with exit status without output"
 msgstr "ange träff med slutstatuskod utan utdata"
 
-#: builtin/grep.c:734
+#: builtin/grep.c:733
 msgid "show only matches from files that match all patterns"
 msgstr "visa endast träffar från filer som träffar alla mönster"
 
-#: builtin/grep.c:736
+#: builtin/grep.c:735
 msgid "show parse tree for grep expression"
 msgstr "visa analysträd för grep-uttryck"
 
-#: builtin/grep.c:740
+#: builtin/grep.c:739
 msgid "pager"
 msgstr "bläddrare"
 
-#: builtin/grep.c:740
+#: builtin/grep.c:739
 msgid "show matching files in the pager"
 msgstr "visa träffade filer i filbläddraren"
 
-#: builtin/grep.c:743
+#: builtin/grep.c:742
 msgid "allow calling of grep(1) (ignored by this build)"
 msgstr "tillåt anropa grep(1) (ignoreras av detta bygge)"
 
-#: builtin/grep.c:744 builtin/show-ref.c:184
+#: builtin/grep.c:743 builtin/show-ref.c:188
 msgid "show usage"
 msgstr "visa användning"
 
-#: builtin/grep.c:811
+#: builtin/grep.c:810
 msgid "no pattern given."
 msgstr "inget mönster angavs."
 
-#: builtin/grep.c:866
+#: builtin/grep.c:865
 msgid "--open-files-in-pager only works on the worktree"
 msgstr "--open-files-in-pager fungerar endast i arbetskatalogen"
 
-#: builtin/grep.c:889
+#: builtin/grep.c:888
 msgid "--cached or --untracked cannot be used with --no-index."
 msgstr "--cached och --untracked kan inte användas med --no-index."
 
-#: builtin/grep.c:894
+#: builtin/grep.c:893
 msgid "--no-index or --untracked cannot be used with revs."
 msgstr "--no-index och --untracked kan inte användas med revisioner."
 
-#: builtin/grep.c:897
+#: builtin/grep.c:896
 msgid "--[no-]exclude-standard cannot be used for tracked contents."
 msgstr "--[no-]exclude-standard kan inte användas för spårat innehåll."
 
-#: builtin/grep.c:905
+#: builtin/grep.c:904
 msgid "both --cached and trees are given."
 msgstr "både --cached och träd angavs."
 
@@ -5053,10 +5434,14 @@
 msgid "process file as it were from this path"
 msgstr "hantera filen som om den kom från sökvägen"
 
-#: builtin/help.c:42
+#: builtin/help.c:41
 msgid "print all available commands"
 msgstr "visa alla tillgängliga kommandon"
 
+#: builtin/help.c:42
+msgid "print list of useful guides"
+msgstr "lista användbara vägledningar"
+
 #: builtin/help.c:43
 msgid "show man page"
 msgstr "visa manualsida"
@@ -5070,8 +5455,8 @@
 msgstr "visa info-sida"
 
 #: builtin/help.c:52
-msgid "git help [--all] [--man|--web|--info] [command]"
-msgstr "git help [--all] [--man|--web|--info] [kommando]"
+msgid "git help [--all] [--guides] [--man|--web|--info] [command]"
+msgstr "git help [--all] [--guides] [--man|--web|--info] [kommando]"
 
 #: builtin/help.c:64
 #, c-format
@@ -5127,290 +5512,322 @@
 msgid "no info viewer handled the request"
 msgstr "ingen info-visare hanterade förfrågan"
 
-#: builtin/help.c:429 builtin/help.c:436
+#: builtin/help.c:420
+msgid "Defining attributes per path"
+msgstr "Definierar attribut per sökväg"
+
+#: builtin/help.c:421
+msgid "A Git glossary"
+msgstr "En Git-ordlista"
+
+#: builtin/help.c:422
+msgid "Specifies intentionally untracked files to ignore"
+msgstr "Ange avsiktligen ospårade filer att ignorera"
+
+#: builtin/help.c:423
+msgid "Defining submodule properties"
+msgstr "Ange egenskaper för undermoduler"
+
+#: builtin/help.c:424
+msgid "Specifying revisions and ranges for Git"
+msgstr "Ange versioner och intervall i Git"
+
+#: builtin/help.c:425
+msgid "A tutorial introduction to Git (for version 1.5.1 or newer)"
+msgstr "Introduktion till Git (för version 1.5.1 och senare)"
+
+#: builtin/help.c:426
+msgid "An overview of recommended workflows with Git"
+msgstr "Översikt över rekommenderade arbetsflöden med Git"
+
+#: builtin/help.c:438
+msgid "The common Git guides are:\n"
+msgstr "De vanliga Git-vägledningarna är:\n"
+
+#: builtin/help.c:460 builtin/help.c:476
 #, c-format
 msgid "usage: %s%s"
 msgstr "användning: %s%s"
 
-#: builtin/help.c:452
+#: builtin/help.c:492
 #, c-format
 msgid "`git %s' is aliased to `%s'"
 msgstr "\"git %s\" är ett alias för \"%s\""
 
-#: builtin/index-pack.c:182
+#: builtin/index-pack.c:184
 #, c-format
 msgid "object type mismatch at %s"
 msgstr "objekttyp stämmer inte överens vid %s"
 
-#: builtin/index-pack.c:202
+#: builtin/index-pack.c:204
 msgid "object of unexpected type"
 msgstr "objekt av oväntad typ"
 
-#: builtin/index-pack.c:239
+#: builtin/index-pack.c:244
 #, c-format
 msgid "cannot fill %d byte"
 msgid_plural "cannot fill %d bytes"
 msgstr[0] "kan inte fylla %d byte"
 msgstr[1] "kan inte fylla %d byte"
 
-#: builtin/index-pack.c:249
+#: builtin/index-pack.c:254
 msgid "early EOF"
 msgstr "tidigt filslut"
 
-#: builtin/index-pack.c:250
+#: builtin/index-pack.c:255
 msgid "read error on input"
 msgstr "indataläsfel"
 
-#: builtin/index-pack.c:262
+#: builtin/index-pack.c:267
 msgid "used more bytes than were available"
 msgstr "använde fler byte än tillgängligt"
 
-#: builtin/index-pack.c:269
+#: builtin/index-pack.c:274
 msgid "pack too large for current definition of off_t"
 msgstr "paket för stort för nuvarande definition av off_t"
 
-#: builtin/index-pack.c:285
+#: builtin/index-pack.c:290
 #, c-format
 msgid "unable to create '%s'"
 msgstr "kunde inte skapa \"%s\""
 
-#: builtin/index-pack.c:290
+#: builtin/index-pack.c:295
 #, c-format
 msgid "cannot open packfile '%s'"
 msgstr "kan inte öppna paketfilen \"%s\""
 
-#: builtin/index-pack.c:304
+#: builtin/index-pack.c:309
 msgid "pack signature mismatch"
 msgstr "paketsignatur stämmer inte överens"
 
-#: builtin/index-pack.c:306
+#: builtin/index-pack.c:311
 #, c-format
 msgid "pack version %<PRIu32> unsupported"
 msgstr "paketversion %<PRIu32> stöds ej"
 
-#: builtin/index-pack.c:324
+#: builtin/index-pack.c:329
 #, c-format
 msgid "pack has bad object at offset %lu: %s"
 msgstr "paketet har felaktigt objekt vid index %lu: %s"
 
-#: builtin/index-pack.c:446
+#: builtin/index-pack.c:451
 #, c-format
 msgid "inflate returned %d"
 msgstr "inflate returnerade %d"
 
-#: builtin/index-pack.c:495
+#: builtin/index-pack.c:500
 msgid "offset value overflow for delta base object"
 msgstr "indexvärdespill för deltabasobjekt"
 
-#: builtin/index-pack.c:503
+#: builtin/index-pack.c:508
 msgid "delta base offset is out of bound"
 msgstr "deltabasindex utanför gränsen"
 
-#: builtin/index-pack.c:511
+#: builtin/index-pack.c:516
 #, c-format
 msgid "unknown object type %d"
 msgstr "okänd objekttyp %d"
 
-#: builtin/index-pack.c:542
+#: builtin/index-pack.c:547
 msgid "cannot pread pack file"
 msgstr "kan inte utföra \"pread\" på paketfil"
 
-#: builtin/index-pack.c:544
+#: builtin/index-pack.c:549
 #, c-format
 msgid "premature end of pack file, %lu byte missing"
 msgid_plural "premature end of pack file, %lu bytes missing"
 msgstr[0] "för tidigt slut på paketfilen, %lu byte saknas"
 msgstr[1] "för tidigt slut på paketfilen, %lu byte saknas"
 
-#: builtin/index-pack.c:570
+#: builtin/index-pack.c:575
 msgid "serious inflate inconsistency"
 msgstr "allvarlig inflate-inkonsekvens"
 
-#: builtin/index-pack.c:661 builtin/index-pack.c:667 builtin/index-pack.c:690
-#: builtin/index-pack.c:724 builtin/index-pack.c:733
+#: builtin/index-pack.c:666 builtin/index-pack.c:672 builtin/index-pack.c:695
+#: builtin/index-pack.c:729 builtin/index-pack.c:738
 #, c-format
 msgid "SHA1 COLLISION FOUND WITH %s !"
 msgstr "SHA1-KOLLISION UPPTÄCKT VID %s !"
 
-#: builtin/index-pack.c:664 builtin/pack-objects.c:170
+#: builtin/index-pack.c:669 builtin/pack-objects.c:170
 #: builtin/pack-objects.c:262
 #, c-format
 msgid "unable to read %s"
 msgstr "kunde inte läsa %s"
 
-#: builtin/index-pack.c:730
+#: builtin/index-pack.c:735
 #, c-format
 msgid "cannot read existing object %s"
 msgstr "kan inte läsa befintligt objekt %s"
 
-#: builtin/index-pack.c:744
+#: builtin/index-pack.c:749
 #, c-format
 msgid "invalid blob object %s"
 msgstr "ogiltigt blob-objekt %s"
 
-#: builtin/index-pack.c:759
+#: builtin/index-pack.c:763
 #, c-format
 msgid "invalid %s"
 msgstr "ogiltigt %s"
 
-#: builtin/index-pack.c:761
+#: builtin/index-pack.c:766
 msgid "Error in object"
 msgstr "Fel i objekt"
 
-#: builtin/index-pack.c:763
+#: builtin/index-pack.c:768
 #, c-format
 msgid "Not all child objects of %s are reachable"
 msgstr "Inte alla barnobjekt för %s kan nås"
 
-#: builtin/index-pack.c:833 builtin/index-pack.c:863
+#: builtin/index-pack.c:838 builtin/index-pack.c:868
 msgid "failed to apply delta"
 msgstr "misslyckades tillämpa delta"
 
-#: builtin/index-pack.c:1004
+#: builtin/index-pack.c:1009
 msgid "Receiving objects"
 msgstr "Tar emot objekt"
 
-#: builtin/index-pack.c:1004
+#: builtin/index-pack.c:1009
 msgid "Indexing objects"
 msgstr "Skapar index för objekt"
 
-#: builtin/index-pack.c:1030
+#: builtin/index-pack.c:1035
 msgid "pack is corrupted (SHA1 mismatch)"
 msgstr "paketet är trasigt (SHA1 stämmer inte)"
 
-#: builtin/index-pack.c:1035
+#: builtin/index-pack.c:1040
 msgid "cannot fstat packfile"
 msgstr "kan inte utföra \"fstat\" på paketfil"
 
-#: builtin/index-pack.c:1038
+#: builtin/index-pack.c:1043
 msgid "pack has junk at the end"
 msgstr "paket har skräp i slutet"
 
-#: builtin/index-pack.c:1049
+#: builtin/index-pack.c:1054
 msgid "confusion beyond insanity in parse_pack_objects()"
 msgstr "förvirrad bortom vanvett i parse_pack_objects()"
 
-#: builtin/index-pack.c:1072
+#: builtin/index-pack.c:1077
 msgid "Resolving deltas"
 msgstr "Analyserar delta"
 
-#: builtin/index-pack.c:1082
+#: builtin/index-pack.c:1087
 #, c-format
 msgid "unable to create thread: %s"
 msgstr "kunde inte skapa tråd: %s"
 
-#: builtin/index-pack.c:1124
+#: builtin/index-pack.c:1129
 msgid "confusion beyond insanity"
 msgstr "förvirrad bortom vanvett"
 
-#: builtin/index-pack.c:1132
+#: builtin/index-pack.c:1137
 #, c-format
 msgid "completed with %d local objects"
 msgstr "slutfördes med %d lokala objekt"
 
-#: builtin/index-pack.c:1142
+#: builtin/index-pack.c:1147
 #, c-format
 msgid "Unexpected tail checksum for %s (disk corruption?)"
 msgstr "Oväntad svanschecksumma för %s (trasig disk?)"
 
-#: builtin/index-pack.c:1146
+#: builtin/index-pack.c:1151
 #, c-format
 msgid "pack has %d unresolved delta"
 msgid_plural "pack has %d unresolved deltas"
 msgstr[0] "paketet har %d oanalyserat delta"
 msgstr[1] "paketet har %d oanalyserade delta"
 
-#: builtin/index-pack.c:1171
+#: builtin/index-pack.c:1176
 #, c-format
 msgid "unable to deflate appended object (%d)"
 msgstr "kunde inte utföra \"deflate\" på tillagt objekt (%d)"
 
-#: builtin/index-pack.c:1250
+#: builtin/index-pack.c:1255
 #, c-format
 msgid "local object %s is corrupt"
 msgstr "lokalt objekt %s är trasigt"
 
-#: builtin/index-pack.c:1274
+#: builtin/index-pack.c:1279
 msgid "error while closing pack file"
 msgstr "fel vid stängning av paketfil"
 
-#: builtin/index-pack.c:1287
+#: builtin/index-pack.c:1292
 #, c-format
 msgid "cannot write keep file '%s'"
 msgstr "kan inte ta skriva \"keep\"-fil \"%s\""
 
-#: builtin/index-pack.c:1295
+#: builtin/index-pack.c:1300
 #, c-format
 msgid "cannot close written keep file '%s'"
 msgstr "akn inte stänga skriven \"keep\"-fil \"%s\""
 
-#: builtin/index-pack.c:1308
+#: builtin/index-pack.c:1313
 msgid "cannot store pack file"
 msgstr "kan inte spara paketfil"
 
-#: builtin/index-pack.c:1319
+#: builtin/index-pack.c:1324
 msgid "cannot store index file"
 msgstr "kan inte spara indexfil"
 
-#: builtin/index-pack.c:1352
+#: builtin/index-pack.c:1357
 #, c-format
 msgid "bad pack.indexversion=%<PRIu32>"
 msgstr "felaktig pack.indexversion=%<PRIu32>"
 
-#: builtin/index-pack.c:1358
+#: builtin/index-pack.c:1363
 #, c-format
 msgid "invalid number of threads specified (%d)"
 msgstr "felaktigt antal trådar angivet (%d)"
 
-#: builtin/index-pack.c:1362 builtin/index-pack.c:1535
+#: builtin/index-pack.c:1367 builtin/index-pack.c:1545
 #, c-format
 msgid "no threads support, ignoring %s"
 msgstr "trådstöd saknas, ignorerar %s"
 
-#: builtin/index-pack.c:1420
+#: builtin/index-pack.c:1425
 #, c-format
 msgid "Cannot open existing pack file '%s'"
 msgstr "Kan inte öppna befintlig paketfil \"%s\""
 
-#: builtin/index-pack.c:1422
+#: builtin/index-pack.c:1427
 #, c-format
 msgid "Cannot open existing pack idx file for '%s'"
 msgstr "Kan inte öppna befintligt paket-idx-fil för \"%s\""
 
-#: builtin/index-pack.c:1469
+#: builtin/index-pack.c:1474
 #, c-format
 msgid "non delta: %d object"
 msgid_plural "non delta: %d objects"
 msgstr[0] "icke-delta: %d objekt"
 msgstr[1] "icke-delta: %d objekt"
 
-#: builtin/index-pack.c:1476
+#: builtin/index-pack.c:1481
 #, c-format
 msgid "chain length = %d: %lu object"
 msgid_plural "chain length = %d: %lu objects"
 msgstr[0] "kedjelängd = %d: %lu objekt"
 msgstr[1] "kedjelängd = %d: %lu objekt"
 
-#: builtin/index-pack.c:1503
+#: builtin/index-pack.c:1509
 msgid "Cannot come back to cwd"
 msgstr "Kan inte gå tillbaka till arbetskatalogen (cwd)"
 
-#: builtin/index-pack.c:1547 builtin/index-pack.c:1550
-#: builtin/index-pack.c:1562 builtin/index-pack.c:1566
+#: builtin/index-pack.c:1557 builtin/index-pack.c:1560
+#: builtin/index-pack.c:1572 builtin/index-pack.c:1576
 #, c-format
 msgid "bad %s"
 msgstr "felaktig %s"
 
-#: builtin/index-pack.c:1580
+#: builtin/index-pack.c:1590
 msgid "--fix-thin cannot be used without --stdin"
 msgstr "--fix-thin kan inte användas med --stdin"
 
-#: builtin/index-pack.c:1584 builtin/index-pack.c:1594
+#: builtin/index-pack.c:1594 builtin/index-pack.c:1604
 #, c-format
 msgid "packfile name '%s' does not end with '.pack'"
 msgstr "paketfilnamnet \"%s\" slutar inte med \".pack\""
 
-#: builtin/index-pack.c:1603
+#: builtin/index-pack.c:1613
 msgid "--verify with no packfile name given"
 msgstr "--verify angavs utan paketfilnamn"
 
@@ -5546,7 +5963,7 @@
 msgid "specify that the git repository is to be shared amongst several users"
 msgstr "ange att git-arkivet skall delas bland flera användare"
 
-#: builtin/init-db.c:493 builtin/prune-packed.c:77
+#: builtin/init-db.c:493 builtin/prune-packed.c:75
 msgid "be quiet"
 msgstr "var tyst"
 
@@ -5578,340 +5995,353 @@
 msgid "Cannot access work tree '%s'"
 msgstr "Kan inte komma åt arbetskatalogen \"%s\""
 
-#: builtin/log.c:40
-msgid "git log [<options>] [<since>..<until>] [[--] <path>...]\n"
-msgstr "git log [<flaggor>] [<sedan>..<till>] [[--] <sökväg>...]\n"
-
 #: builtin/log.c:41
+msgid "git log [<options>] [<revision range>] [[--] <path>...]\n"
+msgstr "git log [<flaggor>] [<versionsintervall>] [[--] <sökväg>...]\n"
+
+#: builtin/log.c:42
 msgid "   or: git show [options] <object>..."
 msgstr "     eller: git show [flaggor] <objekt>..."
 
-#: builtin/log.c:103
+#: builtin/log.c:124
 msgid "suppress diff output"
 msgstr "undertryck diff-utdata"
 
-#: builtin/log.c:104
+#: builtin/log.c:125
 msgid "show source"
 msgstr "visa källkod"
 
-#: builtin/log.c:105
+#: builtin/log.c:126
 msgid "Use mail map file"
 msgstr "Använd e-postmappningsfil"
 
-#: builtin/log.c:106
+#: builtin/log.c:127
 msgid "decorate options"
 msgstr "dekoreringsflaggor"
 
-#: builtin/log.c:199
+#: builtin/log.c:230
 #, c-format
 msgid "Final output: %d %s\n"
 msgstr "Slututdata: %d %s\n"
 
-#: builtin/log.c:422 builtin/log.c:514
+#: builtin/log.c:453 builtin/log.c:545
 #, c-format
 msgid "Could not read object %s"
 msgstr "Kunde inte läsa objektet %s"
 
-#: builtin/log.c:538
+#: builtin/log.c:569
 #, c-format
 msgid "Unknown type: %d"
 msgstr "Okänd typ: %d"
 
-#: builtin/log.c:630
+#: builtin/log.c:669
 msgid "format.headers without value"
 msgstr "format.headers utan värde"
 
-#: builtin/log.c:704
+#: builtin/log.c:751
 msgid "name of output directory is too long"
 msgstr "namnet på utdatakatalogen är för långt"
 
-#: builtin/log.c:720
+#: builtin/log.c:767
 #, c-format
 msgid "Cannot open patch file %s"
 msgstr "Kan inte öppna patchfilen %s"
 
-#: builtin/log.c:734
+#: builtin/log.c:781
 msgid "Need exactly one range."
 msgstr "Behöver precis ett intervall."
 
-#: builtin/log.c:742
+#: builtin/log.c:789
 msgid "Not a range."
 msgstr "Inte ett intervall."
 
-#: builtin/log.c:815
+#: builtin/log.c:891
 msgid "Cover letter needs email format"
 msgstr "Omslagsbrevet behöver e-postformat"
 
-#: builtin/log.c:888
+#: builtin/log.c:967
 #, c-format
 msgid "insane in-reply-to: %s"
 msgstr "tokigt in-reply-to: %s"
 
-#: builtin/log.c:916
+#: builtin/log.c:995
 msgid "git format-patch [options] [<since> | <revision range>]"
 msgstr "git format-patch [flaggor] [<sedan> | <revisionsintervall>]"
 
-#: builtin/log.c:961
+#: builtin/log.c:1040
 msgid "Two output directories?"
 msgstr "Två utdatakataloger?"
 
-#: builtin/log.c:1099
+#: builtin/log.c:1155
 msgid "use [PATCH n/m] even with a single patch"
 msgstr "använd [PATCH n/m] även för en ensam patch"
 
-#: builtin/log.c:1102
+#: builtin/log.c:1158
 msgid "use [PATCH] even with multiple patches"
 msgstr "använd [PATCH] även för flera patchar"
 
-#: builtin/log.c:1106
+#: builtin/log.c:1162
 msgid "print patches to standard out"
 msgstr "skriv patcharna på stnadard ut"
 
-#: builtin/log.c:1108
+#: builtin/log.c:1164
 msgid "generate a cover letter"
 msgstr "generera ett följebrev"
 
-#: builtin/log.c:1110
+#: builtin/log.c:1166
 msgid "use simple number sequence for output file names"
 msgstr "använd enkel nummersekvens för utdatafilnamn"
 
-#: builtin/log.c:1111
+#: builtin/log.c:1167
 msgid "sfx"
 msgstr "sfx"
 
-#: builtin/log.c:1112
+#: builtin/log.c:1168
 msgid "use <sfx> instead of '.patch'"
 msgstr "använd <sfx> istället för \".patch\""
 
-#: builtin/log.c:1114
+#: builtin/log.c:1170
 msgid "start numbering patches at <n> instead of 1"
 msgstr "börja numrera patchar på <n> istället för 1"
 
-#: builtin/log.c:1116
+#: builtin/log.c:1172
 msgid "mark the series as Nth re-roll"
 msgstr "markera serien som N:te försök"
 
-#: builtin/log.c:1118
+#: builtin/log.c:1174
 msgid "Use [<prefix>] instead of [PATCH]"
 msgstr "Använd [<prefix>] istället för [PATCH]"
 
-#: builtin/log.c:1121
+#: builtin/log.c:1177
 msgid "store resulting files in <dir>"
 msgstr "spara filerna i <katalog>"
 
-#: builtin/log.c:1124
+#: builtin/log.c:1180
 msgid "don't strip/add [PATCH]"
 msgstr "ta inte bort eller lägg till [PATCH]"
 
-#: builtin/log.c:1127
+#: builtin/log.c:1183
 msgid "don't output binary diffs"
 msgstr "skriv inte binära diffar"
 
-#: builtin/log.c:1129
+#: builtin/log.c:1185
 msgid "don't include a patch matching a commit upstream"
 msgstr "ta inte med patchar som motsvarar en uppströmsincheckning"
 
-#: builtin/log.c:1131
+#: builtin/log.c:1187
 msgid "show patch format instead of default (patch + stat)"
 msgstr "visa patchformat istället för standard (patch + stat)"
 
-#: builtin/log.c:1133
+#: builtin/log.c:1189
 msgid "Messaging"
 msgstr "E-post"
 
-#: builtin/log.c:1134
+#: builtin/log.c:1190
 msgid "header"
 msgstr "huvud"
 
-#: builtin/log.c:1135
+#: builtin/log.c:1191
 msgid "add email header"
 msgstr "lägg till e-posthuvud"
 
-#: builtin/log.c:1136 builtin/log.c:1138
+#: builtin/log.c:1192 builtin/log.c:1194
 msgid "email"
 msgstr "epost"
 
-#: builtin/log.c:1136
+#: builtin/log.c:1192
 msgid "add To: header"
 msgstr "Lägg till mottagarhuvud (\"To:\")"
 
-#: builtin/log.c:1138
+#: builtin/log.c:1194
 msgid "add Cc: header"
 msgstr "Lägg till kopiehuvud (\"Cc:\")"
 
-#: builtin/log.c:1140
+#: builtin/log.c:1196
+msgid "ident"
+msgstr "ident"
+
+#: builtin/log.c:1197
+msgid "set From address to <ident> (or committer ident if absent)"
+msgstr "sätt Från-adress till <ident> (eller incheckare om ident saknas)"
+
+#: builtin/log.c:1199
 msgid "message-id"
 msgstr "meddelande-id"
 
-#: builtin/log.c:1141
+#: builtin/log.c:1200
 msgid "make first mail a reply to <message-id>"
 msgstr "Gör det första brevet ett svar till <meddelande-id>"
 
-#: builtin/log.c:1142 builtin/log.c:1145
+#: builtin/log.c:1201 builtin/log.c:1204
 msgid "boundary"
 msgstr "gräns"
 
-#: builtin/log.c:1143
+#: builtin/log.c:1202
 msgid "attach the patch"
 msgstr "bifoga patchen"
 
-#: builtin/log.c:1146
+#: builtin/log.c:1205
 msgid "inline the patch"
 msgstr "gör patchen ett inline-objekt"
 
-#: builtin/log.c:1150
+#: builtin/log.c:1209
 msgid "enable message threading, styles: shallow, deep"
 msgstr "aktivera brevtrådning, typer: shallow, deep"
 
-#: builtin/log.c:1152
+#: builtin/log.c:1211
 msgid "signature"
 msgstr "signatur"
 
-#: builtin/log.c:1153
+#: builtin/log.c:1212
 msgid "add a signature"
 msgstr "lägg till signatur"
 
-#: builtin/log.c:1155
+#: builtin/log.c:1214
 msgid "don't print the patch filenames"
 msgstr "visa inte filnamn för patchar"
 
-#: builtin/log.c:1239
+#: builtin/log.c:1288
+#, c-format
+msgid "invalid ident line: %s"
+msgstr "ogiltig ident-rad: %s"
+
+#: builtin/log.c:1303
 msgid "-n and -k are mutually exclusive."
 msgstr "-n och -k kan inte användas samtidigt."
 
-#: builtin/log.c:1241
+#: builtin/log.c:1305
 msgid "--subject-prefix and -k are mutually exclusive."
 msgstr "--subject-prefix och -k kan inte användas samtidigt."
 
-#: builtin/log.c:1249
+#: builtin/log.c:1313
 msgid "--name-only does not make sense"
 msgstr "kan inte använda --name-only"
 
-#: builtin/log.c:1251
+#: builtin/log.c:1315
 msgid "--name-status does not make sense"
 msgstr "kan inte använda --name-status"
 
-#: builtin/log.c:1253
+#: builtin/log.c:1317
 msgid "--check does not make sense"
 msgstr "kan inte använda --check"
 
-#: builtin/log.c:1276
+#: builtin/log.c:1340
 msgid "standard output, or directory, which one?"
 msgstr "standard ut, eller katalog, vilken skall det vara?"
 
-#: builtin/log.c:1278
+#: builtin/log.c:1342
 #, c-format
 msgid "Could not create directory '%s'"
 msgstr "Kunde inte skapa katalogen \"%s\""
 
-#: builtin/log.c:1431
+#: builtin/log.c:1490
 msgid "Failed to create output files"
 msgstr "Misslyckades skapa utdatafiler"
 
-#: builtin/log.c:1480
+#: builtin/log.c:1539
 msgid "git cherry [-v] [<upstream> [<head> [<limit>]]]"
 msgstr "git cherry [-v] [<uppström> [<huvud> [<gräns>]]]"
 
-#: builtin/log.c:1535
+#: builtin/log.c:1594
 #, c-format
 msgid ""
 "Could not find a tracked remote branch, please specify <upstream> manually.\n"
 msgstr "Kunde inte hitta en spårad fjärrgren, ange <uppström> manuellt.\n"
 
-#: builtin/log.c:1548 builtin/log.c:1550 builtin/log.c:1562
+#: builtin/log.c:1607 builtin/log.c:1609 builtin/log.c:1621
 #, c-format
 msgid "Unknown commit %s"
 msgstr "Okänd incheckning %s"
 
-#: builtin/ls-files.c:409
+#: builtin/ls-files.c:408
 msgid "git ls-files [options] [<file>...]"
 msgstr "git ls-files [flaggor] [<fil>...]"
 
-#: builtin/ls-files.c:466
+#: builtin/ls-files.c:465
 msgid "identify the file status with tags"
 msgstr "identifiera filstatus med taggar"
 
-#: builtin/ls-files.c:468
+#: builtin/ls-files.c:467
 msgid "use lowercase letters for 'assume unchanged' files"
 msgstr "använd små bokstäver för \"anta oförändrade\"-filer"
 
-#: builtin/ls-files.c:470
+#: builtin/ls-files.c:469
 msgid "show cached files in the output (default)"
 msgstr "visa cachade filer i utdata (standard)"
 
-#: builtin/ls-files.c:472
+#: builtin/ls-files.c:471
 msgid "show deleted files in the output"
 msgstr "visa borttagna filer i utdata"
 
-#: builtin/ls-files.c:474
+#: builtin/ls-files.c:473
 msgid "show modified files in the output"
 msgstr "visa modifierade filer i utdata"
 
-#: builtin/ls-files.c:476
+#: builtin/ls-files.c:475
 msgid "show other files in the output"
 msgstr "visa andra filer i utdata"
 
-#: builtin/ls-files.c:478
+#: builtin/ls-files.c:477
 msgid "show ignored files in the output"
 msgstr "visa ignorerade filer i utdata"
 
-#: builtin/ls-files.c:481
+#: builtin/ls-files.c:480
 msgid "show staged contents' object name in the output"
 msgstr "visa köat innehålls objektnamn i utdata"
 
-#: builtin/ls-files.c:483
+#: builtin/ls-files.c:482
 msgid "show files on the filesystem that need to be removed"
 msgstr "visa filer i filsystemet som behöver tas bort"
 
-#: builtin/ls-files.c:485
+#: builtin/ls-files.c:484
 msgid "show 'other' directories' name only"
 msgstr "visa endast namn för \"andra\" kataloger"
 
-#: builtin/ls-files.c:488
+#: builtin/ls-files.c:487
 msgid "don't show empty directories"
 msgstr "visa inte tomma kataloger"
 
-#: builtin/ls-files.c:491
+#: builtin/ls-files.c:490
 msgid "show unmerged files in the output"
 msgstr "visa ej sammanslagna filer i utdata"
 
-#: builtin/ls-files.c:493
+#: builtin/ls-files.c:492
 msgid "show resolve-undo information"
 msgstr "visa \"resolve-undo\"-information"
 
-#: builtin/ls-files.c:495
+#: builtin/ls-files.c:494
 msgid "skip files matching pattern"
 msgstr "hoppa över filer som motsvarar mönster"
 
-#: builtin/ls-files.c:498
+#: builtin/ls-files.c:497
 msgid "exclude patterns are read from <file>"
 msgstr "exkludera mönster som läses från <fil>"
 
-#: builtin/ls-files.c:501
+#: builtin/ls-files.c:500
 msgid "read additional per-directory exclude patterns in <file>"
 msgstr "läs ytterligare per-katalog-exkluderingsmönster från <fil>"
 
-#: builtin/ls-files.c:503
+#: builtin/ls-files.c:502
 msgid "add the standard git exclusions"
 msgstr "lägg till git:s standardexkluderingar"
 
-#: builtin/ls-files.c:506
+#: builtin/ls-files.c:505
 msgid "make the output relative to the project top directory"
 msgstr "gör utdata relativ till projektets toppkatalog"
 
-#: builtin/ls-files.c:509
+#: builtin/ls-files.c:508
 msgid "if any <file> is not in the index, treat this as an error"
 msgstr "om en <fil> inte är indexet, betrakta det som ett fel"
 
-#: builtin/ls-files.c:510
+#: builtin/ls-files.c:509
 msgid "tree-ish"
 msgstr "träd-igt"
 
-#: builtin/ls-files.c:511
+#: builtin/ls-files.c:510
 msgid "pretend that paths removed since <tree-ish> are still present"
 msgstr "låtsas att sökvägar borttagna sedan <träd-igt> fortfarande finns"
 
-#: builtin/ls-files.c:513
+#: builtin/ls-files.c:512
 msgid "show debugging data"
 msgstr "visa felsökningsutdata"
 
@@ -5963,170 +6393,170 @@
 msgid "git merge --abort"
 msgstr "git merge --abort"
 
-#: builtin/merge.c:90
+#: builtin/merge.c:98
 msgid "switch `m' requires a value"
 msgstr "flaggan \"m\" behöver ett värde"
 
-#: builtin/merge.c:127
+#: builtin/merge.c:135
 #, c-format
 msgid "Could not find merge strategy '%s'.\n"
 msgstr "Kunde inte hitta sammanslagningsstrategin \"%s\".\n"
 
-#: builtin/merge.c:128
+#: builtin/merge.c:136
 #, c-format
 msgid "Available strategies are:"
 msgstr "Tillgängliga strategier är:"
 
-#: builtin/merge.c:133
+#: builtin/merge.c:141
 #, c-format
 msgid "Available custom strategies are:"
 msgstr "Tillgängliga skräddarsydda strategier är:"
 
-#: builtin/merge.c:183
+#: builtin/merge.c:198
 msgid "do not show a diffstat at the end of the merge"
 msgstr "visa inte en diffstat när sammanslagningen är färdig"
 
-#: builtin/merge.c:186
+#: builtin/merge.c:201
 msgid "show a diffstat at the end of the merge"
 msgstr "visa en diffstat när sammanslagningen är färdig"
 
-#: builtin/merge.c:187
+#: builtin/merge.c:202
 msgid "(synonym to --stat)"
 msgstr "(synonym till --stat)"
 
-#: builtin/merge.c:189
+#: builtin/merge.c:204
 msgid "add (at most <n>) entries from shortlog to merge commit message"
 msgstr ""
 "lägg till (som mest <n>) poster från shortlog till incheckningsmeddelandet"
 
-#: builtin/merge.c:192
+#: builtin/merge.c:207
 msgid "create a single commit instead of doing a merge"
 msgstr "skapa en ensam incheckning istället för en sammanslagning"
 
-#: builtin/merge.c:194
+#: builtin/merge.c:209
 msgid "perform a commit if the merge succeeds (default)"
 msgstr "utför en incheckning om sammanslagningen lyckades (standard)"
 
-#: builtin/merge.c:196
+#: builtin/merge.c:211
 msgid "edit message before committing"
 msgstr "redigera meddelande innan incheckning"
 
-#: builtin/merge.c:198
+#: builtin/merge.c:212
 msgid "allow fast-forward (default)"
 msgstr "tillåt snabbspolning (standard)"
 
-#: builtin/merge.c:200
+#: builtin/merge.c:214
 msgid "abort if fast-forward is not possible"
 msgstr "avbryt om snabbspolning inte är möjlig"
 
-#: builtin/merge.c:203
+#: builtin/merge.c:218
 msgid "Verify that the named commit has a valid GPG signature"
 msgstr "Bekräfta att den namngivna incheckningen har en giltig GPG-signatur"
 
-#: builtin/merge.c:204 builtin/notes.c:866 builtin/revert.c:112
+#: builtin/merge.c:219 builtin/notes.c:738 builtin/revert.c:114
 msgid "strategy"
 msgstr "strategi"
 
-#: builtin/merge.c:205
+#: builtin/merge.c:220
 msgid "merge strategy to use"
 msgstr "sammanslagninsstrategi att använda"
 
-#: builtin/merge.c:206
+#: builtin/merge.c:221
 msgid "option=value"
 msgstr "alternativ=värde"
 
-#: builtin/merge.c:207
+#: builtin/merge.c:222
 msgid "option for selected merge strategy"
 msgstr "alternativ för vald sammanslagningsstrategi"
 
-#: builtin/merge.c:209
+#: builtin/merge.c:224
 msgid "merge commit message (for a non-fast-forward merge)"
 msgstr "incheckningsmeddelande för (icke snabbspolande) sammanslagning"
 
-#: builtin/merge.c:213
+#: builtin/merge.c:228
 msgid "abort the current in-progress merge"
 msgstr "avbryt den pågående sammanslagningen"
 
-#: builtin/merge.c:242
+#: builtin/merge.c:257
 msgid "could not run stash."
 msgstr "kunde köra stash."
 
-#: builtin/merge.c:247
+#: builtin/merge.c:262
 msgid "stash failed"
 msgstr "stash misslyckades"
 
-#: builtin/merge.c:252
+#: builtin/merge.c:267
 #, c-format
 msgid "not a valid object: %s"
 msgstr "inte ett giltigt objekt: %s"
 
-#: builtin/merge.c:271 builtin/merge.c:288
+#: builtin/merge.c:286 builtin/merge.c:303
 msgid "read-tree failed"
 msgstr "read-tree misslyckades"
 
-#: builtin/merge.c:318
+#: builtin/merge.c:333
 msgid " (nothing to squash)"
 msgstr " (inget att platta till)"
 
-#: builtin/merge.c:331
+#: builtin/merge.c:346
 #, c-format
 msgid "Squash commit -- not updating HEAD\n"
 msgstr "Tillplattningsincheckning -- uppdaterar inte HEAD\n"
 
-#: builtin/merge.c:363
+#: builtin/merge.c:378
 msgid "Writing SQUASH_MSG"
 msgstr "Skriver SQUASH_MSG"
 
-#: builtin/merge.c:365
+#: builtin/merge.c:380
 msgid "Finishing SQUASH_MSG"
 msgstr "Avslutar SQUASH_MSG"
 
-#: builtin/merge.c:388
+#: builtin/merge.c:403
 #, c-format
 msgid "No merge message -- not updating HEAD\n"
 msgstr "Inget sammanslagningsmeddelande -- uppdaterar inte HEAD\n"
 
-#: builtin/merge.c:438
+#: builtin/merge.c:453
 #, c-format
 msgid "'%s' does not point to a commit"
 msgstr "\"%s\" verkar inte peka på en incheckning"
 
-#: builtin/merge.c:550
+#: builtin/merge.c:565
 #, c-format
 msgid "Bad branch.%s.mergeoptions string: %s"
 msgstr "Felaktig branch.%s.mergeoptions-sträng: %s"
 
-#: builtin/merge.c:643
+#: builtin/merge.c:657
 msgid "git write-tree failed to write a tree"
 msgstr "git write-tree misslyckades skriva ett träd"
 
-#: builtin/merge.c:671
+#: builtin/merge.c:685
 msgid "Not handling anything other than two heads merge."
 msgstr "Hanterar inte något annat än en sammanslagning av två huvuden."
 
-#: builtin/merge.c:685
+#: builtin/merge.c:699
 #, c-format
 msgid "Unknown option for merge-recursive: -X%s"
 msgstr "Felaktig flagga för merge-recursive: -X%s"
 
-#: builtin/merge.c:699
+#: builtin/merge.c:713
 #, c-format
 msgid "unable to write %s"
 msgstr "kunde inte skriva %s"
 
-#: builtin/merge.c:788
+#: builtin/merge.c:802
 #, c-format
 msgid "Could not read from '%s'"
 msgstr "Kunde inte läsa från \"%s\""
 
-#: builtin/merge.c:797
+#: builtin/merge.c:811
 #, c-format
 msgid "Not committing merge; use 'git commit' to complete the merge.\n"
 msgstr ""
 "Checkar inte in sammanslagningen; använd \"git commit\" för att slutföra "
 "den.\n"
 
-#: builtin/merge.c:803
+#: builtin/merge.c:817
 #, c-format
 msgid ""
 "Please enter a commit message to explain why this merge is necessary,\n"
@@ -6142,53 +6572,48 @@
 "Rader som inleds med \"%c\" kommer ignoreras, och ett tomt meddelande\n"
 "avbryter incheckningen.\n"
 
-#: builtin/merge.c:827
+#: builtin/merge.c:841
 msgid "Empty commit message."
 msgstr "Tomt incheckningsmeddelande."
 
-#: builtin/merge.c:839
+#: builtin/merge.c:853
 #, c-format
 msgid "Wonderful.\n"
 msgstr "Underbart.\n"
 
-#: builtin/merge.c:904
+#: builtin/merge.c:918
 #, c-format
 msgid "Automatic merge failed; fix conflicts and then commit the result.\n"
 msgstr ""
 "Kunde inte slå ihop automatiskt; fixa konflikter och checka in resultatet.\n"
 
-#: builtin/merge.c:920
+#: builtin/merge.c:934
 #, c-format
 msgid "'%s' is not a commit"
 msgstr "\"%s\" är inte en incheckning"
 
-#: builtin/merge.c:961
+#: builtin/merge.c:975
 msgid "No current branch."
 msgstr "Inte på någon gren."
 
-#: builtin/merge.c:963
+#: builtin/merge.c:977
 msgid "No remote for the current branch."
 msgstr "Ingen fjärr för aktuell gren."
 
-#: builtin/merge.c:965
+#: builtin/merge.c:979
 msgid "No default upstream defined for the current branch."
 msgstr "Ingen standarduppström angiven för aktuell gren."
 
-#: builtin/merge.c:970
+#: builtin/merge.c:984
 #, c-format
-msgid "No remote tracking branch for %s from %s"
+msgid "No remote-tracking branch for %s from %s"
 msgstr "Ingen fjärrspårande gren för %s från %s"
 
-#: builtin/merge.c:1057 builtin/merge.c:1214
-#, c-format
-msgid "%s - not something we can merge"
-msgstr "%s - inte något vi kan slå ihop"
-
-#: builtin/merge.c:1125
+#: builtin/merge.c:1140
 msgid "There is no merge to abort (MERGE_HEAD missing)."
 msgstr "Det finns ingen sammanslagning att avbryta (MERGE_HEAD saknas)."
 
-#: builtin/merge.c:1141 git-pull.sh:31
+#: builtin/merge.c:1156 git-pull.sh:31
 msgid ""
 "You have not concluded your merge (MERGE_HEAD exists).\n"
 "Please, commit your changes before you can merge."
@@ -6196,11 +6621,11 @@
 "Du har inte avslutat sammanslagningen (MERGE_HEAD finns).\n"
 "Checka in dina ändringar innan du kan slå ihop."
 
-#: builtin/merge.c:1144 git-pull.sh:34
+#: builtin/merge.c:1159 git-pull.sh:34
 msgid "You have not concluded your merge (MERGE_HEAD exists)."
 msgstr "Du har inte avslutat sammanslagningen (MERGE_HEAD finns)."
 
-#: builtin/merge.c:1148
+#: builtin/merge.c:1163
 msgid ""
 "You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists).\n"
 "Please, commit your changes before you can merge."
@@ -6208,102 +6633,103 @@
 "Du har inte avslutat din \"cherry-pick\" (CHERRY_PICK_HEAD finns).\n"
 "Checka in dina ändringar innan du kan slå ihop."
 
-#: builtin/merge.c:1151
+#: builtin/merge.c:1166
 msgid "You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists)."
 msgstr "Du har inte avslutat din \"cherry-pick\" (CHERRY_PICK_HEAD finns)."
 
-#: builtin/merge.c:1160
+#: builtin/merge.c:1175
 msgid "You cannot combine --squash with --no-ff."
 msgstr "Du kan inte kombinera --squash med --no-ff."
 
-#: builtin/merge.c:1165
-msgid "You cannot combine --no-ff with --ff-only."
-msgstr "Du kan inte kombinera --no-ff med --ff-only."
-
-#: builtin/merge.c:1172
+#: builtin/merge.c:1184
 msgid "No commit specified and merge.defaultToUpstream not set."
 msgstr "Ingen incheckning angiven och merge.defaultToUpstream är ej satt."
 
-#: builtin/merge.c:1204
+#: builtin/merge.c:1216
 msgid "Can merge only exactly one commit into empty head"
 msgstr "Kan endast slå ihop en enda incheckning i ett tomt huvud."
 
-#: builtin/merge.c:1207
+#: builtin/merge.c:1219
 msgid "Squash commit into empty head not supported yet"
 msgstr "Stöder inte en tillplattningsincheckning på ett tomt huvud ännu"
 
-#: builtin/merge.c:1209
+#: builtin/merge.c:1221
 msgid "Non-fast-forward commit does not make sense into an empty head"
 msgstr "Icke-snabbspolad incheckning kan inte användas med ett tomt huvud"
 
-#: builtin/merge.c:1265
+#: builtin/merge.c:1226
+#, c-format
+msgid "%s - not something we can merge"
+msgstr "%s - inte något vi kan slå ihop"
+
+#: builtin/merge.c:1277
 #, c-format
 msgid "Commit %s has an untrusted GPG signature, allegedly by %s."
 msgstr ""
 "Incheckningen %s har en obetrodd GPG-signatur som påstås vara gjord av %s."
 
-#: builtin/merge.c:1268
+#: builtin/merge.c:1280
 #, c-format
 msgid "Commit %s has a bad GPG signature allegedly by %s."
 msgstr ""
 "Incheckningen %s har en felaktig GPG-signatur som påstås vara gjord av %s."
 
 #. 'N'
-#: builtin/merge.c:1271
+#: builtin/merge.c:1283
 #, c-format
 msgid "Commit %s does not have a GPG signature."
 msgstr "Incheckning %s har inte någon GPG-signatur."
 
-#: builtin/merge.c:1274
+#: builtin/merge.c:1286
 #, c-format
 msgid "Commit %s has a good GPG signature by %s\n"
 msgstr "Incheckningen %s har en korrekt GPG-signatur av %s\n"
 
-#: builtin/merge.c:1358
+#: builtin/merge.c:1370
 #, c-format
 msgid "Updating %s..%s\n"
 msgstr "Uppdaterar %s..%s\n"
 
-#: builtin/merge.c:1397
+#: builtin/merge.c:1409
 #, c-format
 msgid "Trying really trivial in-index merge...\n"
 msgstr "Försöker riktigt enkel sammanslagning i indexet...\n"
 
-#: builtin/merge.c:1404
+#: builtin/merge.c:1416
 #, c-format
 msgid "Nope.\n"
 msgstr "Nej.\n"
 
-#: builtin/merge.c:1436
+#: builtin/merge.c:1448
 msgid "Not possible to fast-forward, aborting."
 msgstr "Kan inte snabbspola, avbryter."
 
-#: builtin/merge.c:1459 builtin/merge.c:1538
+#: builtin/merge.c:1471 builtin/merge.c:1550
 #, c-format
 msgid "Rewinding the tree to pristine...\n"
 msgstr "Återspolar trädet till orört...\n"
 
-#: builtin/merge.c:1463
+#: builtin/merge.c:1475
 #, c-format
 msgid "Trying merge strategy %s...\n"
 msgstr "Försöker sammanslagninsstrategin %s...\n"
 
-#: builtin/merge.c:1529
+#: builtin/merge.c:1541
 #, c-format
 msgid "No merge strategy handled the merge.\n"
 msgstr "Ingen sammanslagningsstrategi hanterade sammanslagningen.\n"
 
-#: builtin/merge.c:1531
+#: builtin/merge.c:1543
 #, c-format
 msgid "Merge with strategy %s failed.\n"
 msgstr "Sammanslagning med strategin %s misslyckades.\n"
 
-#: builtin/merge.c:1540
+#: builtin/merge.c:1552
 #, c-format
 msgid "Using the %s to prepare resolving by hand.\n"
 msgstr "Använder %s för att förbereda lösning för hand.\n"
 
-#: builtin/merge.c:1552
+#: builtin/merge.c:1564
 #, c-format
 msgid "Automatic merge went well; stopped before committing as requested\n"
 msgstr ""
@@ -6470,47 +6896,51 @@
 msgid "renaming '%s' failed"
 msgstr "misslyckades byta namn på \"%s\""
 
-#: builtin/name-rev.c:175
+#: builtin/name-rev.c:259
 msgid "git name-rev [options] <commit>..."
 msgstr "git name-rev [flaggor] <incheckning>..."
 
-#: builtin/name-rev.c:176
+#: builtin/name-rev.c:260
 msgid "git name-rev [options] --all"
 msgstr "git name-rev [flaggor] --all"
 
-#: builtin/name-rev.c:177
+#: builtin/name-rev.c:261
 msgid "git name-rev [options] --stdin"
 msgstr "git name-rev [flaggor] --stdin"
 
-#: builtin/name-rev.c:229
+#: builtin/name-rev.c:313
 msgid "print only names (no SHA-1)"
 msgstr "skriv endast namn (ingen SHA-1)"
 
-#: builtin/name-rev.c:230
+#: builtin/name-rev.c:314
 msgid "only use tags to name the commits"
 msgstr "använd endast taggar för att namnge incheckningar"
 
-#: builtin/name-rev.c:232
+#: builtin/name-rev.c:316
 msgid "only use refs matching <pattern>"
 msgstr "använd endast referenser som motsvarar <mönster>"
 
-#: builtin/name-rev.c:234
+#: builtin/name-rev.c:318
 msgid "list all commits reachable from all refs"
 msgstr "lista alla incheckningar som kan nås alla referenser"
 
-#: builtin/name-rev.c:235
+#: builtin/name-rev.c:319
 msgid "read from stdin"
 msgstr "läs från standard in"
 
-#: builtin/name-rev.c:236
+#: builtin/name-rev.c:320
 msgid "allow to print `undefined` names"
 msgstr "tillåt att skriva \"odefinierade\" namn"
 
-#: builtin/notes.c:26
+#: builtin/name-rev.c:326
+msgid "dereference tags in the input (internal use)"
+msgstr "avreferera taggar i indata (används internt)"
+
+#: builtin/notes.c:24
 msgid "git notes [--ref <notes_ref>] [list [<object>]]"
 msgstr "git notes [--ref <anteckningsref>] [list [<objekt>]]"
 
-#: builtin/notes.c:27
+#: builtin/notes.c:25
 msgid ""
 "git notes [--ref <notes_ref>] add [-f] [-m <msg> | -F <file> | (-c | -C) "
 "<object>] [<object>]"
@@ -6518,12 +6948,12 @@
 "git notes [--ref <anteckningsref>] add [-f] [-m <medd> | -F <fil> | (-c | -"
 "C) <objekt>] [<objekt>]"
 
-#: builtin/notes.c:28
+#: builtin/notes.c:26
 msgid "git notes [--ref <notes_ref>] copy [-f] <from-object> <to-object>"
 msgstr ""
 "git notes [--ref <anteckningsref>] copy [-f] <från-objekt> <till-objekt>"
 
-#: builtin/notes.c:29
+#: builtin/notes.c:27
 msgid ""
 "git notes [--ref <notes_ref>] append [-m <msg> | -F <file> | (-c | -C) "
 "<object>] [<object>]"
@@ -6531,221 +6961,200 @@
 "git notes [--ref <anteckningsref>] append [-m <medd> | -F <fil> | (-c | -C) "
 "<objekt>] [<objekt>]"
 
-#: builtin/notes.c:30
+#: builtin/notes.c:28
 msgid "git notes [--ref <notes_ref>] edit [<object>]"
 msgstr "git notes [--ref <anteckningsref>] edit [<objekt>]"
 
-#: builtin/notes.c:31
+#: builtin/notes.c:29
 msgid "git notes [--ref <notes_ref>] show [<object>]"
 msgstr "git notes [--ref <anteckningsref>] show [<objekt>]"
 
-#: builtin/notes.c:32
+#: builtin/notes.c:30
 msgid ""
 "git notes [--ref <notes_ref>] merge [-v | -q] [-s <strategy> ] <notes_ref>"
 msgstr ""
 "git notes [--ref <anteckningsref>] merge [-v | -q] [-s <strategi> ] "
 "<anteckningsref>"
 
-#: builtin/notes.c:33
+#: builtin/notes.c:31
 msgid "git notes merge --commit [-v | -q]"
 msgstr "git notes merge --commit [-v | -q]"
 
-#: builtin/notes.c:34
+#: builtin/notes.c:32
 msgid "git notes merge --abort [-v | -q]"
 msgstr "git notes merge --abort [-v | -q]"
 
-#: builtin/notes.c:35
+#: builtin/notes.c:33
 msgid "git notes [--ref <notes_ref>] remove [<object>...]"
 msgstr "git notes [--ref <anteckningsref>] remove [<objekt>...]"
 
-#: builtin/notes.c:36
+#: builtin/notes.c:34
 msgid "git notes [--ref <notes_ref>] prune [-n | -v]"
 msgstr "git notes [--ref <anteckningsref>] prune [-n | -v]"
 
-#: builtin/notes.c:37
+#: builtin/notes.c:35
 msgid "git notes [--ref <notes_ref>] get-ref"
 msgstr "git notes [--ref <anteckningsref>] get-ref"
 
-#: builtin/notes.c:42
+#: builtin/notes.c:40
 msgid "git notes [list [<object>]]"
 msgstr "git notes [list [<objekt>]]"
 
-#: builtin/notes.c:47
+#: builtin/notes.c:45
 msgid "git notes add [<options>] [<object>]"
 msgstr "git notes add [<flaggor>] [<objekt>]"
 
-#: builtin/notes.c:52
+#: builtin/notes.c:50
 msgid "git notes copy [<options>] <from-object> <to-object>"
 msgstr "git notes copy [<flaggor>] <från-objekt> <till-objekt>"
 
-#: builtin/notes.c:53
+#: builtin/notes.c:51
 msgid "git notes copy --stdin [<from-object> <to-object>]..."
 msgstr "git notes copy --stdin [<från-objekt> <till-objekt>]..."
 
-#: builtin/notes.c:58
+#: builtin/notes.c:56
 msgid "git notes append [<options>] [<object>]"
 msgstr "git notes append [<flaggor>] [<objekt>]"
 
-#: builtin/notes.c:63
+#: builtin/notes.c:61
 msgid "git notes edit [<object>]"
 msgstr "git notes edit [<objekt>]"
 
-#: builtin/notes.c:68
+#: builtin/notes.c:66
 msgid "git notes show [<object>]"
 msgstr "git notes show [<objekt>]"
 
-#: builtin/notes.c:73
+#: builtin/notes.c:71
 msgid "git notes merge [<options>] <notes_ref>"
 msgstr "git notes merge [<flaggor>] <anteckningsref>"
 
-#: builtin/notes.c:74
+#: builtin/notes.c:72
 msgid "git notes merge --commit [<options>]"
 msgstr "git notes merge --commit [<flaggor>]"
 
-#: builtin/notes.c:75
+#: builtin/notes.c:73
 msgid "git notes merge --abort [<options>]"
 msgstr "git notes merge --abort [<flaggor>]"
 
-#: builtin/notes.c:80
+#: builtin/notes.c:78
 msgid "git notes remove [<object>]"
 msgstr "git notes remove [<objekt>]"
 
-#: builtin/notes.c:85
+#: builtin/notes.c:83
 msgid "git notes prune [<options>]"
 msgstr "git notes prune [<flaggor>]"
 
-#: builtin/notes.c:90
+#: builtin/notes.c:88
 msgid "git notes get-ref"
 msgstr "git notes get-ref"
 
-#: builtin/notes.c:139
+#: builtin/notes.c:137
 #, c-format
 msgid "unable to start 'show' for object '%s'"
 msgstr "kunde inte starta \"show\" för objektet \"%s\""
 
-#: builtin/notes.c:143
+#: builtin/notes.c:141
 msgid "could not read 'show' output"
 msgstr "kunde inte läsa utdata från \"show\""
 
-#: builtin/notes.c:151
+#: builtin/notes.c:149
 #, c-format
 msgid "failed to finish 'show' for object '%s'"
 msgstr "kunde inte avsluta \"show\" för objektet \"%s\""
 
-#: builtin/notes.c:169 builtin/tag.c:341
+#: builtin/notes.c:167 builtin/tag.c:341
 #, c-format
 msgid "could not create file '%s'"
 msgstr "kunde inte skapa filen \"%s\""
 
-#: builtin/notes.c:188
+#: builtin/notes.c:186
 msgid "Please supply the note contents using either -m or -F option"
 msgstr "Ange innehåll för anteckningen med antingen -m eller -F"
 
-#: builtin/notes.c:209 builtin/notes.c:972
+#: builtin/notes.c:207 builtin/notes.c:844
 #, c-format
 msgid "Removing note for object %s\n"
 msgstr "Tar bort anteckning för objektet %s\n"
 
-#: builtin/notes.c:214
+#: builtin/notes.c:212
 msgid "unable to write note object"
 msgstr "kunde inte skriva anteckningsobjekt"
 
-#: builtin/notes.c:216
+#: builtin/notes.c:214
 #, c-format
 msgid "The note contents has been left in %s"
 msgstr "Anteckningens innehåll har lämnats kvar i %s"
 
-#: builtin/notes.c:250 builtin/tag.c:540
+#: builtin/notes.c:248 builtin/tag.c:540
 #, c-format
 msgid "cannot read '%s'"
 msgstr "kunde inte läsa \"%s\""
 
-#: builtin/notes.c:252 builtin/tag.c:543
+#: builtin/notes.c:250 builtin/tag.c:543
 #, c-format
 msgid "could not open or read '%s'"
 msgstr "kunde inte öppna eller läsa \"%s\""
 
-#: builtin/notes.c:271 builtin/notes.c:444 builtin/notes.c:446
-#: builtin/notes.c:506 builtin/notes.c:560 builtin/notes.c:643
-#: builtin/notes.c:648 builtin/notes.c:723 builtin/notes.c:765
-#: builtin/notes.c:967 builtin/tag.c:556
+#: builtin/notes.c:269 builtin/notes.c:316 builtin/notes.c:318
+#: builtin/notes.c:378 builtin/notes.c:432 builtin/notes.c:515
+#: builtin/notes.c:520 builtin/notes.c:595 builtin/notes.c:637
+#: builtin/notes.c:839 builtin/tag.c:556
 #, c-format
 msgid "Failed to resolve '%s' as a valid ref."
 msgstr "Kunde inte slå upp \"%s\" som en giltig referens."
 
-#: builtin/notes.c:274
+#: builtin/notes.c:272
 #, c-format
 msgid "Failed to read object '%s'."
 msgstr "Kunde inte läsa objektet \"%s\"."
 
-#: builtin/notes.c:298
-msgid "Cannot commit uninitialized/unreferenced notes tree"
-msgstr "Kan inte checka in oinitierat/orefererat anteckningsträd"
-
-#: builtin/notes.c:339
-#, c-format
-msgid "Bad notes.rewriteMode value: '%s'"
-msgstr "Felaktigt värde för notes.rewriteMode: '%s'"
-
-#: builtin/notes.c:349
-#, c-format
-msgid "Refusing to rewrite notes in %s (outside of refs/notes/)"
-msgstr "Vägrar skriva över anteckningar i %s (utanför refs/notes/)"
-
-#. TRANSLATORS: The first %s is the name of the
-#. environment variable, the second %s is its value
-#: builtin/notes.c:376
-#, c-format
-msgid "Bad %s value: '%s'"
-msgstr "Felaktigt värde på %s: \"%s\""
-
-#: builtin/notes.c:440
+#: builtin/notes.c:312
 #, c-format
 msgid "Malformed input line: '%s'."
 msgstr "Felaktig indatarad: \"%s\"."
 
-#: builtin/notes.c:455
+#: builtin/notes.c:327
 #, c-format
 msgid "Failed to copy notes from '%s' to '%s'"
 msgstr "Misslyckades kopiera anteckningar från \"%s\" till \"%s\""
 
-#: builtin/notes.c:499 builtin/notes.c:553 builtin/notes.c:626
-#: builtin/notes.c:638 builtin/notes.c:711 builtin/notes.c:758
-#: builtin/notes.c:1032
+#: builtin/notes.c:371 builtin/notes.c:425 builtin/notes.c:498
+#: builtin/notes.c:510 builtin/notes.c:583 builtin/notes.c:630
+#: builtin/notes.c:904
 msgid "too many parameters"
 msgstr "för många parametrar"
 
-#: builtin/notes.c:512 builtin/notes.c:771
+#: builtin/notes.c:384 builtin/notes.c:643
 #, c-format
 msgid "No note found for object %s."
 msgstr "Inga anteckningar hittades för objektet %s."
 
-#: builtin/notes.c:534 builtin/notes.c:691
+#: builtin/notes.c:406 builtin/notes.c:563
 msgid "note contents as a string"
 msgstr "anteckningsinnehåll som sträng"
 
-#: builtin/notes.c:537 builtin/notes.c:694
+#: builtin/notes.c:409 builtin/notes.c:566
 msgid "note contents in a file"
 msgstr "anteckningsinnehåll i en fil"
 
-#: builtin/notes.c:539 builtin/notes.c:542 builtin/notes.c:696
-#: builtin/notes.c:699 builtin/tag.c:474
+#: builtin/notes.c:411 builtin/notes.c:414 builtin/notes.c:568
+#: builtin/notes.c:571 builtin/tag.c:474
 msgid "object"
 msgstr "objekt"
 
-#: builtin/notes.c:540 builtin/notes.c:697
+#: builtin/notes.c:412 builtin/notes.c:569
 msgid "reuse and edit specified note object"
 msgstr "återanvänd och redigera angivet anteckningsobjekt"
 
-#: builtin/notes.c:543 builtin/notes.c:700
+#: builtin/notes.c:415 builtin/notes.c:572
 msgid "reuse specified note object"
 msgstr "återanvänd angivet anteckningsobjekt"
 
-#: builtin/notes.c:545 builtin/notes.c:613
+#: builtin/notes.c:417 builtin/notes.c:485
 msgid "replace existing notes"
 msgstr "ersätt befintliga anteckningar"
 
-#: builtin/notes.c:579
+#: builtin/notes.c:451
 #, c-format
 msgid ""
 "Cannot add notes. Found existing notes for object %s. Use '-f' to overwrite "
@@ -6754,24 +7163,24 @@
 "Kan inte lägga till anteckningar. Hittade befintliga anteckningar för "
 "objektet %s. Använd \"-f\" för att skriva över befintliga anteckningar"
 
-#: builtin/notes.c:584 builtin/notes.c:661
+#: builtin/notes.c:456 builtin/notes.c:533
 #, c-format
 msgid "Overwriting existing notes for object %s\n"
 msgstr "Skriver över befintliga anteckningar för objektet %s\n"
 
-#: builtin/notes.c:614
+#: builtin/notes.c:486
 msgid "read objects from stdin"
 msgstr "läs objekt från standard in"
 
-#: builtin/notes.c:616
+#: builtin/notes.c:488
 msgid "load rewriting config for <command> (implies --stdin)"
 msgstr "läs omskrivningsinställning för <kommando> (implicerar --stdin)"
 
-#: builtin/notes.c:634
+#: builtin/notes.c:506
 msgid "too few parameters"
 msgstr "för få parametrar"
 
-#: builtin/notes.c:655
+#: builtin/notes.c:527
 #, c-format
 msgid ""
 "Cannot copy notes. Found existing notes for object %s. Use '-f' to overwrite "
@@ -6780,12 +7189,12 @@
 "Kan inte kopiera anteckningar. Hittade befintliga anteckningar för objektet "
 "%s. Använd \"-f\" för att skriva över befintliga anteckningar"
 
-#: builtin/notes.c:667
+#: builtin/notes.c:539
 #, c-format
 msgid "Missing notes on source object %s. Cannot copy."
 msgstr "Anteckningar på källobjektet %s saknas. Kan inte kopiera."
 
-#: builtin/notes.c:716
+#: builtin/notes.c:588
 #, c-format
 msgid ""
 "The -m/-F/-c/-C options have been deprecated for the 'edit' subcommand.\n"
@@ -6794,15 +7203,15 @@
 "Flaggorna -m/-F/-c/-C rekommenderas inte för underkommandot \"edit\".\n"
 "Använd \"git notes add -f -m/-F/-c/-C\" istället.\n"
 
-#: builtin/notes.c:863
+#: builtin/notes.c:735
 msgid "General options"
 msgstr "Allmänna flaggor"
 
-#: builtin/notes.c:865
+#: builtin/notes.c:737
 msgid "Merge options"
 msgstr "Flaggor för sammanslagning"
 
-#: builtin/notes.c:867
+#: builtin/notes.c:739
 msgid ""
 "resolve notes conflicts using the given strategy (manual/ours/theirs/union/"
 "cat_sort_uniq)"
@@ -6810,46 +7219,46 @@
 "läs konflikter i anteckningar med angiven strategi (manual/ours/theirs/union/"
 "cat_sort_uniq)"
 
-#: builtin/notes.c:869
+#: builtin/notes.c:741
 msgid "Committing unmerged notes"
 msgstr "Checkar in ej sammanslagna anteckningar"
 
-#: builtin/notes.c:871
+#: builtin/notes.c:743
 msgid "finalize notes merge by committing unmerged notes"
 msgstr ""
 "färdigställ sammanslagning av anteckningar genom att checka in ej "
 "sammanslagna anteckningar"
 
-#: builtin/notes.c:873
+#: builtin/notes.c:745
 msgid "Aborting notes merge resolution"
 msgstr "Avbryt lösning av sammanslagning av anteckningar"
 
-#: builtin/notes.c:875
+#: builtin/notes.c:747
 msgid "abort notes merge"
 msgstr "avbryt sammanslagning av anteckningar"
 
-#: builtin/notes.c:970
+#: builtin/notes.c:842
 #, c-format
 msgid "Object %s has no note\n"
 msgstr "Objektet %s har ingen anteckning\n"
 
-#: builtin/notes.c:982
+#: builtin/notes.c:854
 msgid "attempt to remove non-existent note is not an error"
 msgstr "försök att ta bort icke-existerande anteckningar är inte ett fel"
 
-#: builtin/notes.c:985
+#: builtin/notes.c:857
 msgid "read object names from the standard input"
 msgstr "läs objektnamn från standard in"
 
-#: builtin/notes.c:1066
+#: builtin/notes.c:938
 msgid "notes_ref"
 msgstr "anteckningar-ref"
 
-#: builtin/notes.c:1067
+#: builtin/notes.c:939
 msgid "use notes from <notes_ref>"
 msgstr "använd anteckningar från <anteckningsref>"
 
-#: builtin/notes.c:1102 builtin/remote.c:1598
+#: builtin/notes.c:974 builtin/remote.c:1598
 #, c-format
 msgid "Unknown subcommand: %s"
 msgstr "Okänt underkommando: %s"
@@ -7085,7 +7494,7 @@
 "    git push %s %s\n"
 "%s"
 
-#: builtin/push.c:121
+#: builtin/push.c:117
 #, c-format
 msgid ""
 "You are not currently on a branch.\n"
@@ -7100,7 +7509,7 @@
 "\n"
 "    git push %s HEAD:<namn-på-fjärrgren>\n"
 
-#: builtin/push.c:128
+#: builtin/push.c:131
 #, c-format
 msgid ""
 "The current branch %s has no upstream branch.\n"
@@ -7113,12 +7522,12 @@
 "\n"
 "    git push --set-upstream %s %s\n"
 
-#: builtin/push.c:136
+#: builtin/push.c:139
 #, c-format
 msgid "The current branch %s has multiple upstream branches, refusing to push."
 msgstr "Den aktuella grenen %s har flera uppströmsgrenar, vägrar sända."
 
-#: builtin/push.c:139
+#: builtin/push.c:142
 #, c-format
 msgid ""
 "You are pushing to remote '%s', which is not the upstream of\n"
@@ -7129,7 +7538,7 @@
 "aktuella grenen \"%s\", utan att tala om för mig vad som\n"
 "skall sändas för att uppdatera fjärrgrenen."
 
-#: builtin/push.c:151
+#: builtin/push.c:165
 msgid ""
 "push.default is unset; its implicit value is changing in\n"
 "Git 2.0 from 'matching' to 'simple'. To squelch this message\n"
@@ -7163,26 +7572,26 @@
 "liknande läget \"current\" istället för \"simple\" om du ibland använder\n"
 "äldre versioner av Git.)"
 
-#: builtin/push.c:199
+#: builtin/push.c:225
 msgid ""
 "You didn't specify any refspecs to push, and push.default is \"nothing\"."
 msgstr ""
 "Du angav inga referensspecifikationer att sända, och push.default är "
 "\"nothing\"."
 
-#: builtin/push.c:206
+#: builtin/push.c:232
 msgid ""
 "Updates were rejected because the tip of your current branch is behind\n"
-"its remote counterpart. Merge the remote changes (e.g. 'git pull')\n"
-"before pushing again.\n"
+"its remote counterpart. Integrate the remote changes (e.g.\n"
+"'git pull ...') before pushing again.\n"
 "See the 'Note about fast-forwards' in 'git push --help' for details."
 msgstr ""
 "Uppdateringar avvisades då änden på din befintliga gren är bakom\n"
-"dess fjärrmotsvarighet. Slå ihop fjärrändringarna (t.ex. \"git pull\")\n"
-"innan du sänder igen.\n"
+"dess fjärrmotsvarighet. Integrera fjärrändringarna (t.ex\n"
+"\"git pull ....\") innan du sänder igen.\n"
 "Se avsnittet \"Note about fast-forward\" i \"git push --help\" för detaljer."
 
-#: builtin/push.c:212
+#: builtin/push.c:238
 msgid ""
 "Updates were rejected because a pushed branch tip is behind its remote\n"
 "counterpart. If you did not intend to push that branch, you may want to\n"
@@ -7196,37 +7605,37 @@
 "endast\n"
 "sända aktuell gren."
 
-#: builtin/push.c:218
+#: builtin/push.c:244
 msgid ""
 "Updates were rejected because a pushed branch tip is behind its remote\n"
-"counterpart. Check out this branch and merge the remote changes\n"
-"(e.g. 'git pull') before pushing again.\n"
+"counterpart. Check out this branch and integrate the remote changes\n"
+"(e.g. 'git pull ...') before pushing again.\n"
 "See the 'Note about fast-forwards' in 'git push --help' for details."
 msgstr ""
 "Uppdateringar avvisades då änden på en gren som sänds in är bakom dess\n"
-"fjärrmotsvarighet. Checka ut grenen och slå ihop fjärrändringarna (t.ex.\n"
-"\"git pull\") innan du sänder igen.\n"
+"fjärrmotsvarighet. Checka ut grenen och integrera fjärrändringarna (t.ex.\n"
+"\"git pull ...\") innan du sänder igen.\n"
 "Se avsnittet \"Note about fast-forward\" i \"git push --help\" för detaljer."
 
-#: builtin/push.c:224
+#: builtin/push.c:250
 msgid ""
 "Updates were rejected because the remote contains work that you do\n"
 "not have locally. This is usually caused by another repository pushing\n"
-"to the same ref. You may want to first merge the remote changes (e.g.,\n"
-"'git pull') before pushing again.\n"
+"to the same ref. You may want to first integrate the remote changes\n"
+"(e.g., 'git pull ...') before pushing again.\n"
 "See the 'Note about fast-forwards' in 'git push --help' for details."
 msgstr ""
 "Uppdateringar avvisades då fjärren innehåller ändringar som du inte\n"
 "har lokalt. Det beror oftast på att ett annat arkiv har sänt in samma\n"
-"referenser. Det kan vara en idé att först slå ihop fjärrändringarna\n"
-"(t.ex. \"git pull\") innan du sänder igen.\n"
+"referenser. Det kan vara en idé att först integrera fjärrändringarna\n"
+"(t.ex. \"git pull ...\") innan du sänder igen.\n"
 "Se avsnittet \"Note about fast-forwards\" i \"git push --help\" för detaljer."
 
-#: builtin/push.c:231
+#: builtin/push.c:257
 msgid "Updates were rejected because the tag already exists in the remote."
 msgstr "Uppdateringarna avvisades eftersom taggen redan finns på fjärren."
 
-#: builtin/push.c:234
+#: builtin/push.c:260
 msgid ""
 "You cannot update a remote ref that points at a non-commit object,\n"
 "or update a remote ref to make it point at a non-commit object,\n"
@@ -7237,22 +7646,22 @@
 "pekar på något som inte är en incheckning, utan att använda flaggan\n"
 "\"--force\".\n"
 
-#: builtin/push.c:294
+#: builtin/push.c:320
 #, c-format
 msgid "Pushing to %s\n"
 msgstr "Sänder till %s\n"
 
-#: builtin/push.c:298
+#: builtin/push.c:324
 #, c-format
 msgid "failed to push some refs to '%s'"
 msgstr "misslyckades sända vissa referenser till \"%s\""
 
-#: builtin/push.c:331
+#: builtin/push.c:357
 #, c-format
 msgid "bad repository '%s'"
 msgstr "felaktigt arkiv \"%s\""
 
-#: builtin/push.c:332
+#: builtin/push.c:358
 msgid ""
 "No configured push destination.\n"
 "Either specify the URL from the command-line or configure a remote "
@@ -7273,87 +7682,87 @@
 "\n"
 "    git push <namn>\n"
 
-#: builtin/push.c:347
+#: builtin/push.c:373
 msgid "--all and --tags are incompatible"
 msgstr "--all och --tags är inkompatibla"
 
-#: builtin/push.c:348
+#: builtin/push.c:374
 msgid "--all can't be combined with refspecs"
 msgstr "--all kan inte kombineras med referensspecifikationer"
 
-#: builtin/push.c:353
+#: builtin/push.c:379
 msgid "--mirror and --tags are incompatible"
 msgstr "--mirror och --tags är inkompatibla"
 
-#: builtin/push.c:354
+#: builtin/push.c:380
 msgid "--mirror can't be combined with refspecs"
 msgstr "--mirror kan inte kombineras med referensspecifikationer"
 
-#: builtin/push.c:359
+#: builtin/push.c:385
 msgid "--all and --mirror are incompatible"
 msgstr "--all och --mirror är inkompatibla"
 
-#: builtin/push.c:419
+#: builtin/push.c:445
 msgid "repository"
 msgstr "arkiv"
 
-#: builtin/push.c:420
+#: builtin/push.c:446
 msgid "push all refs"
 msgstr "sänd alla referenser"
 
-#: builtin/push.c:421
+#: builtin/push.c:447
 msgid "mirror all refs"
 msgstr "spegla alla referenser"
 
-#: builtin/push.c:423
+#: builtin/push.c:449
 msgid "delete refs"
 msgstr "ta bort referenser"
 
-#: builtin/push.c:424
+#: builtin/push.c:450
 msgid "push tags (can't be used with --all or --mirror)"
 msgstr "sänd taggar (kan inte användas med --all eller --mirror)"
 
-#: builtin/push.c:427
+#: builtin/push.c:453
 msgid "force updates"
 msgstr "tvinga uppdateringar"
 
-#: builtin/push.c:428
+#: builtin/push.c:454
 msgid "check"
 msgstr "kontrollera"
 
-#: builtin/push.c:429
+#: builtin/push.c:455
 msgid "control recursive pushing of submodules"
 msgstr "styr rekursiv insändning av undermoduler"
 
-#: builtin/push.c:431
+#: builtin/push.c:457
 msgid "use thin pack"
 msgstr "använd tunna paket"
 
-#: builtin/push.c:432 builtin/push.c:433
+#: builtin/push.c:458 builtin/push.c:459
 msgid "receive pack program"
 msgstr "program för att ta emot paket"
 
-#: builtin/push.c:434
+#: builtin/push.c:460
 msgid "set upstream for git pull/status"
 msgstr "ställ in uppström för git pull/status"
 
-#: builtin/push.c:437
+#: builtin/push.c:463
 msgid "prune locally removed refs"
 msgstr "ta bort lokalt borttagna referenser"
 
-#: builtin/push.c:439
+#: builtin/push.c:465
 msgid "bypass pre-push hook"
 msgstr "förbigå pre-push-krok"
 
-#: builtin/push.c:440
+#: builtin/push.c:466
 msgid "push missing but relevant tags"
 msgstr "sänd in saknade men relevanta taggar"
 
-#: builtin/push.c:450
+#: builtin/push.c:476
 msgid "--delete is incompatible with --all, --mirror and --tags"
 msgstr "--delete är imkompatibel med --all, --mirror och --tags"
 
-#: builtin/push.c:452
+#: builtin/push.c:478
 msgid "--delete doesn't make sense without any refs"
 msgstr "--delete kan inte användas utan referenser"
 
@@ -7367,70 +7776,80 @@
 "[-u [--exclude-per-directory=<gitignore>] | -i]] [--no-sparse-checkout] [--"
 "index-output=<fil>] (--empty | <träd-igt1> [<träd-igt2> [<träd-igt3>]])"
 
-#: builtin/read-tree.c:108
+#: builtin/read-tree.c:109
 msgid "write resulting index to <file>"
 msgstr "skriv resulterande index till <fil>"
 
-#: builtin/read-tree.c:111
+#: builtin/read-tree.c:112
 msgid "only empty the index"
 msgstr "töm bara indexet"
 
-#: builtin/read-tree.c:113
+#: builtin/read-tree.c:114
 msgid "Merging"
 msgstr "Sammanslagning"
 
-#: builtin/read-tree.c:115
+#: builtin/read-tree.c:116
 msgid "perform a merge in addition to a read"
 msgstr "utför en sammanslagning i tillägg till en läsning"
 
-#: builtin/read-tree.c:117
+#: builtin/read-tree.c:118
 msgid "3-way merge if no file level merging required"
 msgstr "3-vägssammanslagning om sammanslagning på filnivå ej krävs"
 
-#: builtin/read-tree.c:119
+#: builtin/read-tree.c:120
 msgid "3-way merge in presence of adds and removes"
 msgstr "3-vägssammanslagning när det finns tillägg och borttagningar"
 
-#: builtin/read-tree.c:121
+#: builtin/read-tree.c:122
 msgid "same as -m, but discard unmerged entries"
 msgstr "som -m, men kasta bort ej sammanslagna poster"
 
-#: builtin/read-tree.c:122
+#: builtin/read-tree.c:123
 msgid "<subdirectory>/"
 msgstr "<underkatalog>/"
 
-#: builtin/read-tree.c:123
+#: builtin/read-tree.c:124
 msgid "read the tree into the index under <subdirectory>/"
 msgstr "läs in trädet i indexet under <underkatalog>/"
 
-#: builtin/read-tree.c:126
+#: builtin/read-tree.c:127
 msgid "update working tree with merge result"
 msgstr "uppdatera arbetskatalogen med resultatet från sammanslagningen"
 
-#: builtin/read-tree.c:128
+#: builtin/read-tree.c:129
 msgid "gitignore"
 msgstr "gitignore"
 
-#: builtin/read-tree.c:129
+#: builtin/read-tree.c:130
 msgid "allow explicitly ignored files to be overwritten"
 msgstr "tillåt explicit ignorerade filer att skrivas över"
 
-#: builtin/read-tree.c:132
+#: builtin/read-tree.c:133
 msgid "don't check the working tree after merging"
 msgstr "kontrollera inte arbetskatalogen efter sammanslagning"
 
-#: builtin/read-tree.c:133
+#: builtin/read-tree.c:134
 msgid "don't update the index or the work tree"
 msgstr "uppdatera inte indexet eller arbetskatalogen"
 
-#: builtin/read-tree.c:135
+#: builtin/read-tree.c:136
 msgid "skip applying sparse checkout filter"
 msgstr "hoppa över att applicera filter för gles utcheckning"
 
-#: builtin/read-tree.c:137
+#: builtin/read-tree.c:138
 msgid "debug unpack-trees"
 msgstr "felsök unpack-trees"
 
+#: builtin/reflog.c:500
+#, c-format
+msgid "%s' for '%s' is not a valid timestamp"
+msgstr "\"%s\" för \"%s\" är inte en giltig tidsstämpel"
+
+#: builtin/reflog.c:616 builtin/reflog.c:621
+#, c-format
+msgid "'%s' is not a valid timestamp"
+msgstr "\"%s\" är inte en giltig tidsstämpel"
+
 #: builtin/remote.c:11
 msgid "git remote [-v | --verbose]"
 msgstr "git remote [-v | --verbose]"
@@ -8004,96 +8423,96 @@
 msgid "Failed to find tree of %s."
 msgstr "Kunde inte hitta träder för %s."
 
-#: builtin/reset.c:98
+#: builtin/reset.c:99
 #, c-format
 msgid "HEAD is now at %s"
 msgstr "HEAD är nu på %s"
 
-#: builtin/reset.c:169
+#: builtin/reset.c:172
 #, c-format
 msgid "Cannot do a %s reset in the middle of a merge."
 msgstr "Kan inte utföra en %s återställning mitt i en sammanslagning."
 
-#: builtin/reset.c:248
+#: builtin/reset.c:251
 msgid "be quiet, only report errors"
 msgstr "var tyst, rapportera endast fel"
 
-#: builtin/reset.c:250
+#: builtin/reset.c:253
 msgid "reset HEAD and index"
 msgstr "återställ HEAD och index"
 
-#: builtin/reset.c:251
+#: builtin/reset.c:254
 msgid "reset only HEAD"
 msgstr "återställ endast HEAD"
 
-#: builtin/reset.c:253 builtin/reset.c:255
+#: builtin/reset.c:256 builtin/reset.c:258
 msgid "reset HEAD, index and working tree"
 msgstr "återställ HEAD, index och arbetskatalog"
 
-#: builtin/reset.c:257
+#: builtin/reset.c:260
 msgid "reset HEAD but keep local changes"
 msgstr "återställ HEAD men behåll lokala ändringar"
 
-#: builtin/reset.c:275
+#: builtin/reset.c:278
 #, c-format
 msgid "Failed to resolve '%s' as a valid revision."
 msgstr "Kunde inte slå upp \"%s\" som en giltig revision."
 
-#: builtin/reset.c:278 builtin/reset.c:286
+#: builtin/reset.c:281 builtin/reset.c:289
 #, c-format
 msgid "Could not parse object '%s'."
 msgstr "Kan inte tolka objektet \"%s\""
 
-#: builtin/reset.c:283
+#: builtin/reset.c:286
 #, c-format
 msgid "Failed to resolve '%s' as a valid tree."
 msgstr "Kunde inte slå upp \"%s\" som ett giltigt träd."
 
-#: builtin/reset.c:292
+#: builtin/reset.c:295
 msgid "--patch is incompatible with --{hard,mixed,soft}"
 msgstr "--patch är inkompatibel med --{hard,mixed,soft}"
 
-#: builtin/reset.c:301
+#: builtin/reset.c:304
 msgid "--mixed with paths is deprecated; use 'git reset -- <paths>' instead."
 msgstr ""
 "--mixed rekommenderas inte med sökvägar; använd \"git reset -- <sökvägar>\"."
 
-#: builtin/reset.c:303
+#: builtin/reset.c:306
 #, c-format
 msgid "Cannot do %s reset with paths."
 msgstr "Kan inte göra %s återställning med sökvägar."
 
-#: builtin/reset.c:313
+#: builtin/reset.c:316
 #, c-format
 msgid "%s reset is not allowed in a bare repository"
 msgstr "%s återställning tillåts inte i ett naket arkiv"
 
-#: builtin/reset.c:333
+#: builtin/reset.c:336
 #, c-format
 msgid "Could not reset index file to revision '%s'."
 msgstr "Kunde inte återställa indexfilen till versionen \"%s\"."
 
-#: builtin/reset.c:339
+#: builtin/reset.c:342
 msgid "Unstaged changes after reset:"
 msgstr "Oköade ändringar efter återställning:"
 
-#: builtin/reset.c:344
+#: builtin/reset.c:347
 msgid "Could not write new index file."
 msgstr "Kunde inte skriva ny indexfil."
 
-#: builtin/rev-parse.c:339
+#: builtin/rev-parse.c:345
 msgid "git rev-parse --parseopt [options] -- [<args>...]"
 msgstr "git rev-parse --parseopt [options] -- [<argument>...]"
 
-#: builtin/rev-parse.c:344
+#: builtin/rev-parse.c:350
 msgid "keep the `--` passed as an arg"
 msgstr "behåll \"--\" sänt som argument"
 
-#: builtin/rev-parse.c:346
+#: builtin/rev-parse.c:352
 msgid "stop parsing after the first non-option argument"
 msgstr "sluta tolka efter första argument som inte är flagga"
 
-#: builtin/rev-parse.c:464
+#: builtin/rev-parse.c:470
 msgid ""
 "git rev-parse --parseopt [options] -- [<args>...]\n"
 "   or: git rev-parse --sq-quote [<arg>...]\n"
@@ -8109,192 +8528,216 @@
 "varianten."
 
 #: builtin/revert.c:22
-msgid "git revert [options] <commit-ish>"
-msgstr "git revert [flaggor] <incheckning-igt>"
+msgid "git revert [options] <commit-ish>..."
+msgstr "git revert [flaggor] <incheckning-igt>..."
 
 #: builtin/revert.c:23
 msgid "git revert <subcommand>"
 msgstr "git revert <underkommando>"
 
 #: builtin/revert.c:28
-msgid "git cherry-pick [options] <commit-ish>"
-msgstr "git cherry-pick [flaggor] <incheckning-igt>"
+msgid "git cherry-pick [options] <commit-ish>..."
+msgstr "git cherry-pick [flaggor] <incheckning-igt>..."
 
 #: builtin/revert.c:29
 msgid "git cherry-pick <subcommand>"
 msgstr "git cherry-pick <underkommando>"
 
-#: builtin/revert.c:70 builtin/revert.c:92
+#: builtin/revert.c:71 builtin/revert.c:94
 #, c-format
 msgid "%s: %s cannot be used with %s"
 msgstr "%s: %s kan inte användas med %s"
 
-#: builtin/revert.c:103
+#: builtin/revert.c:105
 msgid "end revert or cherry-pick sequence"
 msgstr "avsluta revert- eller cherry-pick-sekvens"
 
-#: builtin/revert.c:104
+#: builtin/revert.c:106
 msgid "resume revert or cherry-pick sequence"
 msgstr "återuppta revert- eller cherry-pick-sekvens"
 
-#: builtin/revert.c:105
+#: builtin/revert.c:107
 msgid "cancel revert or cherry-pick sequence"
 msgstr "avbryt revert- eller cherry-pick-sekvens"
 
-#: builtin/revert.c:106
+#: builtin/revert.c:108
 msgid "don't automatically commit"
 msgstr "checka inte in automatiskt"
 
-#: builtin/revert.c:107
+#: builtin/revert.c:109
 msgid "edit the commit message"
 msgstr "redigera incheckningsmeddelandet"
 
-#: builtin/revert.c:110
+#: builtin/revert.c:112
 msgid "parent number"
 msgstr "nummer på förälder"
 
-#: builtin/revert.c:112
+#: builtin/revert.c:114
 msgid "merge strategy"
 msgstr "sammanslagninsstrategi"
 
-#: builtin/revert.c:113
+#: builtin/revert.c:115
 msgid "option"
 msgstr "alternativ"
 
-#: builtin/revert.c:114
+#: builtin/revert.c:116
 msgid "option for merge strategy"
 msgstr "alternativ för sammanslagningsstrategi"
 
-#: builtin/revert.c:125
+#: builtin/revert.c:127
 msgid "append commit name"
 msgstr "lägg till incheckningsnamn"
 
-#: builtin/revert.c:126
+#: builtin/revert.c:128
 msgid "allow fast-forward"
 msgstr "tillåt snabbspolning"
 
-#: builtin/revert.c:127
+#: builtin/revert.c:129
 msgid "preserve initially empty commits"
 msgstr "behåll incheckningar som börjar som tomma"
 
-#: builtin/revert.c:128
+#: builtin/revert.c:130
 msgid "allow commits with empty messages"
 msgstr "tillåt incheckningar med tomt meddelande"
 
-#: builtin/revert.c:129
+#: builtin/revert.c:131
 msgid "keep redundant, empty commits"
 msgstr "behåll redundanta, tomma incheckningar"
 
-#: builtin/revert.c:133
+#: builtin/revert.c:135
 msgid "program error"
 msgstr "programfel"
 
-#: builtin/revert.c:223
+#: builtin/revert.c:225
 msgid "revert failed"
 msgstr "\"revert\" misslyckades"
 
-#: builtin/revert.c:238
+#: builtin/revert.c:240
 msgid "cherry-pick failed"
 msgstr "\"cherry-pick\" misslyckades"
 
-#: builtin/rm.c:15
+#: builtin/rm.c:16
 msgid "git rm [options] [--] <file>..."
 msgstr "git rm [flaggor] [--] <fil>..."
 
-#: builtin/rm.c:64 builtin/rm.c:186
-#, c-format
+#: builtin/rm.c:64
 msgid ""
-"submodule '%s' (or one of its nested submodules) uses a .git directory\n"
+"the following submodule (or one of its nested submodules)\n"
+"uses a .git directory:"
+msgid_plural ""
+"the following submodules (or one of its nested submodules)\n"
+"use a .git directory:"
+msgstr[0] ""
+"följande undermodul (eller en av dess nästlade undermoduler)\n"
+"använder en .git-katalog:"
+msgstr[1] ""
+"följande undermoduler (eller en av deras nästlade undermoduler)\n"
+"använder en .git-katalog:"
+
+#: builtin/rm.c:70
+msgid ""
+"\n"
 "(use 'rm -rf' if you really want to remove it including all of its history)"
 msgstr ""
-"undermodulen \"%s\" (eller en av dess undermoduler) använder en .git-"
-"katalog\n"
+"\n"
 "(använd \"rm -rf\" om du verkligen vill ta bort den och all dess historik)"
 
-#: builtin/rm.c:174
-#, c-format
+#: builtin/rm.c:230
 msgid ""
-"'%s' has staged content different from both the file and the HEAD\n"
+"the following file has staged content different from both the\n"
+"file and the HEAD:"
+msgid_plural ""
+"the following files have staged content different from both the\n"
+"file and the HEAD:"
+msgstr[0] ""
+"följande fil har köat innehåll som skiljer sig både från filen och HEAD:"
+msgstr[1] ""
+"följande filer har köat innehåll som skiljer sig både från filen och HEAD:"
+
+#: builtin/rm.c:235
+msgid ""
+"\n"
 "(use -f to force removal)"
 msgstr ""
-"\"%s\" har köat ändringar som skiljer sig både från filen och HEAD\n"
+"\n"
 "(använd -f för att tvinga borttagning)"
 
-#: builtin/rm.c:180
-#, c-format
+#: builtin/rm.c:239
+msgid "the following file has changes staged in the index:"
+msgid_plural "the following files have changes staged in the index:"
+msgstr[0] "följande fil har ändringar köade i indexet:"
+msgstr[1] "följande filer har ändringar köade i indexet:"
+
+#: builtin/rm.c:243 builtin/rm.c:254
 msgid ""
-"'%s' has changes staged in the index\n"
+"\n"
 "(use --cached to keep the file, or -f to force removal)"
 msgstr ""
-"\"%s\" har köade ändringar i indexet\n"
+"\n"
 "(använd --cached för att behålla filen eller -f för att tvinga borttagning)"
 
-#: builtin/rm.c:191
-#, c-format
-msgid ""
-"'%s' has local modifications\n"
-"(use --cached to keep the file, or -f to force removal)"
-msgstr ""
-"\"%s\" har lokala ändringar\n"
-"(använd --cached för att behålla filen eller -f för att tvinga borttagning)"
+#: builtin/rm.c:251
+msgid "the following file has local modifications:"
+msgid_plural "the following files have local modifications:"
+msgstr[0] "följande fil har lokala ändringar:"
+msgstr[1] "följande filer har lokala ändringar:"
 
-#: builtin/rm.c:207
+#: builtin/rm.c:269
 msgid "do not list removed files"
 msgstr "lista inte borttagna filer"
 
-#: builtin/rm.c:208
+#: builtin/rm.c:270
 msgid "only remove from the index"
 msgstr "ta bara bort från indexet"
 
-#: builtin/rm.c:209
+#: builtin/rm.c:271
 msgid "override the up-to-date check"
 msgstr "överstyr àjour-testet"
 
-#: builtin/rm.c:210
+#: builtin/rm.c:272
 msgid "allow recursive removal"
 msgstr "tillåt rekursiv borttagning"
 
-#: builtin/rm.c:212
+#: builtin/rm.c:274
 msgid "exit with a zero status even if nothing matched"
 msgstr "avsluta med nollstatus även om inget träffades"
 
-#: builtin/rm.c:283
+#: builtin/rm.c:345
 #, c-format
 msgid "not removing '%s' recursively without -r"
 msgstr "tar inte bort \"%s\" rekursivt utan -r"
 
-#: builtin/rm.c:322
+#: builtin/rm.c:384
 #, c-format
 msgid "git rm: unable to remove %s"
 msgstr "git rm: kan inte ta bort %s"
 
 #: builtin/shortlog.c:13
-msgid "git shortlog [-n] [-s] [-e] [-w] [rev-opts] [--] [<commit-id>... ]"
-msgstr ""
-"git shortlog [-n] [-s] [-e] [-w] [rev-flaggor] [--] [<incheckning-id>... ]"
+msgid "git shortlog [<options>] [<revision range>] [[--] [<path>...]]"
+msgstr "git shortlog [<flaggor>] [<versionsintervall>] [[--] <sökväg>...]"
 
-#: builtin/shortlog.c:133
+#: builtin/shortlog.c:131
 #, c-format
 msgid "Missing author: %s"
 msgstr "Författare saknas: %s"
 
-#: builtin/shortlog.c:229
+#: builtin/shortlog.c:228
 msgid "sort output according to the number of commits per author"
 msgstr "sortera utdata enligt antal incheckningar per författare"
 
-#: builtin/shortlog.c:231
+#: builtin/shortlog.c:230
 msgid "Suppress commit descriptions, only provides commit count"
 msgstr "Undertryck beskrivningar, visa bara antal incheckningar"
 
-#: builtin/shortlog.c:233
+#: builtin/shortlog.c:232
 msgid "Show the email address of each author"
 msgstr "Visa e-postadress för varje författare"
 
-#: builtin/shortlog.c:234
+#: builtin/shortlog.c:233
 msgid "w[,i1[,i2]]"
 msgstr "w[,i1[,i2]]"
 
-#: builtin/shortlog.c:235
+#: builtin/shortlog.c:234
 msgid "Linewrap output"
 msgstr "Radbryt utdata"
 
@@ -8314,47 +8757,47 @@
 msgid "git show-branch (-g|--reflog)[=<n>[,<base>]] [--list] [<ref>]"
 msgstr "git show-branch (-g|--reflog)[=<n>[,<bas>]] [--list] [<ref>]"
 
-#: builtin/show-branch.c:651
+#: builtin/show-branch.c:650
 msgid "show remote-tracking and local branches"
 msgstr "visa fjärrspårande och lokala grenar"
 
-#: builtin/show-branch.c:653
+#: builtin/show-branch.c:652
 msgid "show remote-tracking branches"
 msgstr "visa fjärrspårande grenar"
 
-#: builtin/show-branch.c:655
+#: builtin/show-branch.c:654
 msgid "color '*!+-' corresponding to the branch"
 msgstr "färga \"*!+-\" enligt grenen"
 
-#: builtin/show-branch.c:657
+#: builtin/show-branch.c:656
 msgid "show <n> more commits after the common ancestor"
 msgstr "visa <n> ytterligare incheckningar efter gemensam anfader"
 
-#: builtin/show-branch.c:659
+#: builtin/show-branch.c:658
 msgid "synonym to more=-1"
 msgstr "synonym till more=-1"
 
-#: builtin/show-branch.c:660
+#: builtin/show-branch.c:659
 msgid "suppress naming strings"
 msgstr "undertyck namnsträngar"
 
-#: builtin/show-branch.c:662
+#: builtin/show-branch.c:661
 msgid "include the current branch"
 msgstr "inkludera aktuell gren"
 
-#: builtin/show-branch.c:664
+#: builtin/show-branch.c:663
 msgid "name commits with their object names"
 msgstr "namnge incheckningar med deras objektnamn"
 
-#: builtin/show-branch.c:666
+#: builtin/show-branch.c:665
 msgid "show possible merge bases"
 msgstr "visa möjliga sammanslaningsbaser"
 
-#: builtin/show-branch.c:668
+#: builtin/show-branch.c:667
 msgid "show refs unreachable from any other ref"
 msgstr "visa referenser som inte kan nås från någon annan referens"
 
-#: builtin/show-branch.c:670
+#: builtin/show-branch.c:669
 msgid "show commits in topological order"
 msgstr "visa incheckningar i topologisk ordning"
 
@@ -8367,14 +8810,14 @@
 msgstr "visa sammanslagningar som endast kan nås från en spets"
 
 #: builtin/show-branch.c:676
-msgid "show commits where no parent comes before its children"
-msgstr "visa incheckningar där ingen förälder kommer före dess barn"
+msgid "topologically sort, maintaining date order where possible"
+msgstr "sortera topologiskt, behåll datumordning när möjligt"
 
-#: builtin/show-branch.c:678
+#: builtin/show-branch.c:679
 msgid "<n>[,<base>]"
 msgstr "<n>[,<bas>]"
 
-#: builtin/show-branch.c:679
+#: builtin/show-branch.c:680
 msgid "show <n> most recent ref-log entries starting at base"
 msgstr "visa <n> nyaste refloggposter med början på bas"
 
@@ -8390,35 +8833,35 @@
 msgid "git show-ref --exclude-existing[=pattern] < ref-list"
 msgstr "git show-ref --exclude-existing[=mönster] < reflista"
 
-#: builtin/show-ref.c:165
+#: builtin/show-ref.c:168
 msgid "only show tags (can be combined with heads)"
 msgstr "visa endast taggar (kan kombineras med huvuden)"
 
-#: builtin/show-ref.c:166
+#: builtin/show-ref.c:169
 msgid "only show heads (can be combined with tags)"
 msgstr "visa endast huvuden (kan kombineras med taggar)"
 
-#: builtin/show-ref.c:167
+#: builtin/show-ref.c:170
 msgid "stricter reference checking, requires exact ref path"
 msgstr "striktare referenskontroll, kräver exakt referenssökväg"
 
-#: builtin/show-ref.c:170 builtin/show-ref.c:172
-msgid "show the HEAD reference"
-msgstr "visa HEAD-referensen"
+#: builtin/show-ref.c:173 builtin/show-ref.c:176
+msgid "show the HEAD reference, even if it would be filtered out"
+msgstr "visa HEAD-refrens, även när den skulle filtreras ut"
 
-#: builtin/show-ref.c:174
+#: builtin/show-ref.c:178
 msgid "dereference tags into object IDs"
 msgstr "avreferera taggar till objekt-id"
 
-#: builtin/show-ref.c:176
+#: builtin/show-ref.c:180
 msgid "only show SHA1 hash using <n> digits"
 msgstr "visa SHA1-hash endast med <n> siffror"
 
-#: builtin/show-ref.c:180
+#: builtin/show-ref.c:184
 msgid "do not print results to stdout (useful with --verify)"
 msgstr "visa inte resultat på standard ut (användbart med --verify)"
 
-#: builtin/show-ref.c:182
+#: builtin/show-ref.c:186
 msgid "show refs from stdin that aren't in local repository"
 msgstr "visa referenser från standard in som inte finns i lokalt arkiv"
 
@@ -8833,24 +9276,33 @@
 msgid "only useful for debugging"
 msgstr "endast användbart vid felsökning"
 
-#: git.c:16
-msgid "See 'git help <command>' for more information on a specific command."
+#: git.c:17
+msgid ""
+"'git help -a' and 'git help -g' lists available subcommands and some\n"
+"concept guides. See 'git help <command>' or 'git help <concept>'\n"
+"to read about a specific subcommand or concept."
 msgstr ""
-"Se \"git help <kommando>\" för mer information om ett specifikt kommando."
+"\"git help -a\" och \"git help -g\" visar tillgängliga underkommandon och\n"
+"några konceptvägledningar. Se \"git help <kommando>\" eller \"git help\n"
+"<koncept>\" för att läsa mer om specifika underkommandon och koncept."
 
-#: parse-options.h:156
+#: parse-options.h:144
+msgid "expiry date"
+msgstr "giltig till"
+
+#: parse-options.h:159
 msgid "no-op (backward compatibility)"
 msgstr "ingen funktion (bakåtkompatibilitet)"
 
-#: parse-options.h:232
+#: parse-options.h:236
 msgid "be more verbose"
 msgstr "var mer pratsam"
 
-#: parse-options.h:234
+#: parse-options.h:238
 msgid "be more quiet"
 msgstr "var mer tyst"
 
-#: parse-options.h:240
+#: parse-options.h:244
 msgid "use <n> digits to display SHA-1s"
 msgstr "använd <n> siffror för att visa SHA-1:or"
 
@@ -8907,8 +9359,8 @@
 msgstr "Flytta eller byt namn på en fil, katalog eller symbolisk länk"
 
 #: common-cmds.h:21
-msgid "Fetch from and merge with another repository or a local branch"
-msgstr "Hämta från och slå ihop med annat arkiv eller en lokal gren"
+msgid "Fetch from and integrate with another repository or a local branch"
+msgstr "Hämta från och integrera med annat arkiv eller en lokal gren"
 
 #: common-cmds.h:22
 msgid "Update remote refs along with associated objects"
@@ -8953,11 +9405,11 @@
 #: git-am.sh:105
 #, sh-format
 msgid ""
-"When you have resolved this problem, run \"$cmdline --resolved\".\n"
+"When you have resolved this problem, run \"$cmdline --continue\".\n"
 "If you prefer to skip this patch, run \"$cmdline --skip\" instead.\n"
 "To restore the original branch and stop patching, run \"$cmdline --abort\"."
 msgstr ""
-"När du har löst problemet kör du \"$cmdline --resolved\".\n"
+"När du har löst problemet kör du \"$cmdline --continue\".\n"
 "Om du vill hoppa över patchen kör du istället \"$cmdline --skip\".\n"
 "För att återställa originalgrenen och avbryta kör du \"$cmdline --abort\"."
 
@@ -9013,25 +9465,34 @@
 "Flaggan -b/--binary har varit utan funktion länge, och\n"
 "kommer tas bort. Vi ber dig att inte använda den längre."
 
-#: git-am.sh:477
+#: git-am.sh:479
 #, sh-format
 msgid "previous rebase directory $dotest still exists but mbox given."
 msgstr "tidigare rebase-katalog $dotest finns fortfarande, men mbox angavs."
 
-#: git-am.sh:482
+#: git-am.sh:484
 msgid "Please make up your mind. --skip or --abort?"
 msgstr "Bestäm dig. --skip eller --abort?"
 
-#: git-am.sh:509
+#: git-am.sh:520
+#, sh-format
+msgid ""
+"Stray $dotest directory found.\n"
+"Use \"git am --abort\" to remove it."
+msgstr ""
+"Kvarbliven katalog $dotest hittades.\n"
+"Använd \"git am --abort\" för att ta bort den."
+
+#: git-am.sh:528
 msgid "Resolve operation not in progress, we are not resuming."
 msgstr "Lösningsoperation pågår inte, vi återupptar inte."
 
-#: git-am.sh:575
+#: git-am.sh:594
 #, sh-format
 msgid "Dirty index: cannot apply patches (dirty: $files)"
 msgstr "Smutsigt index: kan inte tillämpa patchar (smutsiga: $files)"
 
-#: git-am.sh:679
+#: git-am.sh:698
 #, sh-format
 msgid ""
 "Patch is empty.  Was it split wrong?\n"
@@ -9042,32 +9503,32 @@
 "Om du vill hoppa över patchen kör du istället \"$cmdline --skip\".\n"
 "För att återställa originalgrenen och avbryta kör du \"$cmdline --abort\"."
 
-#: git-am.sh:706
+#: git-am.sh:725
 msgid "Patch does not have a valid e-mail address."
 msgstr "Patchen har inte någon giltig e-postadress."
 
-#: git-am.sh:753
+#: git-am.sh:772
 msgid "cannot be interactive without stdin connected to a terminal."
 msgstr ""
 "kan inte vara interaktiv om standard in inte är ansluten till en terminal."
 
-#: git-am.sh:757
+#: git-am.sh:776
 msgid "Commit Body is:"
 msgstr "Incheckningskroppen är:"
 
 #. TRANSLATORS: Make sure to include [y], [n], [e], [v] and [a]
 #. in your translation. The program will only accept English
 #. input at this point.
-#: git-am.sh:764
+#: git-am.sh:783
 msgid "Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all "
 msgstr "Tillämpa? Y=ja/N=nej/E=redigera/V=visa patch/A=godta alla "
 
-#: git-am.sh:800
+#: git-am.sh:819
 #, sh-format
 msgid "Applying: $FIRSTLINE"
 msgstr "Tillämpar: $FIRSTLINE"
 
-#: git-am.sh:821
+#: git-am.sh:840
 msgid ""
 "No changes - did you forget to use 'git add'?\n"
 "If there is nothing left to stage, chances are that something else\n"
@@ -9077,7 +9538,7 @@
 "Om det inte är något kvar att köa kan det hända att något annat redan\n"
 "introducerat samma ändringar; kanske du bör hoppa över patchen."
 
-#: git-am.sh:829
+#: git-am.sh:848
 msgid ""
 "You still have unmerged paths in your index\n"
 "did you forget to use 'git add'?"
@@ -9085,16 +9546,16 @@
 "Du har fortfarande sökvägar som inte slagits samman i ditt index\n"
 "glömde du använda \"git add\"?"
 
-#: git-am.sh:845
+#: git-am.sh:864
 msgid "No changes -- Patch already applied."
 msgstr "Inga ändringar -- Patchen har redan tillämpats."
 
-#: git-am.sh:855
+#: git-am.sh:874
 #, sh-format
 msgid "Patch failed at $msgnum $FIRSTLINE"
 msgstr "Patchen misslyckades vid $msgnum $FIRSTLINE"
 
-#: git-am.sh:858
+#: git-am.sh:877
 #, sh-format
 msgid ""
 "The copy of the patch that failed is found in:\n"
@@ -9103,7 +9564,7 @@
 "En kopia av patchen som misslyckades finns i:\n"
 "   $dotest/patch"
 
-#: git-am.sh:876
+#: git-am.sh:895
 msgid "applying to an empty history"
 msgstr "tillämpar på en tom historik"
 
@@ -9203,16 +9664,16 @@
 "Du måste sedan ange åtminstone en bra och en dålig version.\n"
 "(Du kan använda \"git bisect bad\" och \"git bisect good\" för detta.)"
 
-#: git-bisect.sh:347 git-bisect.sh:474
+#: git-bisect.sh:363 git-bisect.sh:490
 msgid "We are not bisecting."
 msgstr "Vi utför ingen bisect för tillfället."
 
-#: git-bisect.sh:354
+#: git-bisect.sh:370
 #, sh-format
 msgid "'$invalid' is not a valid commit"
 msgstr "\"$invalid\" är inte en giltig incheckning"
 
-#: git-bisect.sh:363
+#: git-bisect.sh:379
 #, sh-format
 msgid ""
 "Could not check out original HEAD '$branch'.\n"
@@ -9221,25 +9682,25 @@
 "Kunde inte checka ut original-HEAD \"$branch\".\n"
 "Försök \"git bisect reset <incheckning>\"."
 
-#: git-bisect.sh:390
+#: git-bisect.sh:406
 msgid "No logfile given"
 msgstr "Ingen loggfil angiven"
 
-#: git-bisect.sh:391
+#: git-bisect.sh:407
 #, sh-format
 msgid "cannot read $file for replaying"
 msgstr "kan inte läsa $file för uppspelning"
 
-#: git-bisect.sh:408
+#: git-bisect.sh:424
 msgid "?? what are you talking about?"
 msgstr "?? vad menar du?"
 
-#: git-bisect.sh:420
+#: git-bisect.sh:436
 #, sh-format
 msgid "running $command"
 msgstr "kör $command"
 
-#: git-bisect.sh:427
+#: git-bisect.sh:443
 #, sh-format
 msgid ""
 "bisect run failed:\n"
@@ -9248,11 +9709,11 @@
 "\"bisect\"-körningen misslyckades:\n"
 "felkod $res från \"$command\" är < 0 eller >= 128"
 
-#: git-bisect.sh:453
+#: git-bisect.sh:469
 msgid "bisect run cannot continue any more"
 msgstr "\"bisect\"-körningen kan inte fortsätta längre"
 
-#: git-bisect.sh:459
+#: git-bisect.sh:475
 #, sh-format
 msgid ""
 "bisect run failed:\n"
@@ -9261,7 +9722,7 @@
 "\"bisect\"-körningen misslyckades:\n"
 "\"bisect_state $state\" avslutades med felkoden $res"
 
-#: git-bisect.sh:466
+#: git-bisect.sh:482
 msgid "bisect run success"
 msgstr "\"bisect\"-körningen lyckades"
 
@@ -9306,7 +9767,7 @@
 msgid "Cannot rebase onto multiple branches"
 msgstr "Kan inte utföra en \"rebase\" ovanpå flera grenar"
 
-#: git-rebase.sh:53
+#: git-rebase.sh:54
 msgid ""
 "When you have resolved this problem, run \"git rebase --continue\".\n"
 "If you prefer to skip this patch, run \"git rebase --skip\" instead.\n"
@@ -9317,31 +9778,50 @@
 "Om du vill hoppa över patchen kör du istället \"git rebase --skip\".\n"
 "För att återställa originalgrenen och avbryta kör du \"git rebase --abort\"."
 
+#: git-rebase.sh:156
+msgid "Applied autostash."
+msgstr "Tillämpade autostash."
+
+#: git-rebase.sh:159
+#, sh-format
+msgid "Cannot store $stash_sha1"
+msgstr "Kan inte spara $stash_sha1"
+
 #: git-rebase.sh:160
+msgid ""
+"Applying autostash resulted in conflicts.\n"
+"Your changes are safe in the stash.\n"
+"You can run \"git stash pop\" or \"git stash drop\" at any time.\n"
+msgstr ""
+"Tillämpning av autostash gav konflikter.\n"
+"Dina ändringar är säkra i stashen.\n"
+"Du kan när som helst använda \"git stash pop\" eller \"git stash drop\".\n"
+
+#: git-rebase.sh:190
 msgid "The pre-rebase hook refused to rebase."
 msgstr "Kroken pre-rebase vägrade ombaseringen."
 
-#: git-rebase.sh:165
+#: git-rebase.sh:195
 msgid "It looks like git-am is in progress. Cannot rebase."
 msgstr "Det verkar som en git-am körs. Kan inte ombasera."
 
-#: git-rebase.sh:296
+#: git-rebase.sh:329
 msgid "The --exec option must be used with the --interactive option"
 msgstr "Flaggan --exec måste användas tillsammans med flaggan --interactive"
 
-#: git-rebase.sh:301
+#: git-rebase.sh:334
 msgid "No rebase in progress?"
 msgstr "Ingen ombasering pågår?"
 
-#: git-rebase.sh:312
+#: git-rebase.sh:345
 msgid "The --edit-todo action can only be used during interactive rebase."
 msgstr "Åtgärden --edit-todo kan endast användas under interaktiv ombasering."
 
-#: git-rebase.sh:319
+#: git-rebase.sh:352
 msgid "Cannot read HEAD"
 msgstr "Kan inte läsa HEAD"
 
-#: git-rebase.sh:322
+#: git-rebase.sh:355
 msgid ""
 "You must edit all merge conflicts and then\n"
 "mark them as resolved using git add"
@@ -9349,12 +9829,12 @@
 "Du måste redigera alla sammanslagningskonflikter och\n"
 "därefter markera dem som lösta med git add"
 
-#: git-rebase.sh:340
+#: git-rebase.sh:373
 #, sh-format
 msgid "Could not move back to $head_name"
 msgstr "Kunde inte flytta tillbaka till $head_name"
 
-#: git-rebase.sh:359
+#: git-rebase.sh:392
 #, sh-format
 msgid ""
 "It seems that there is already a $state_dir_base directory, and\n"
@@ -9375,57 +9855,66 @@
 "och kör programmet igen. Jag avslutar ifall du fortfarande har\n"
 "något av värde där."
 
-#: git-rebase.sh:404
+#: git-rebase.sh:437
 #, sh-format
 msgid "invalid upstream $upstream_name"
 msgstr "ogiltig uppström $upstream_name"
 
-#: git-rebase.sh:428
+#: git-rebase.sh:461
 #, sh-format
 msgid "$onto_name: there are more than one merge bases"
 msgstr "$onto_name: mer än en sammanslagningsbas finns"
 
-#: git-rebase.sh:431 git-rebase.sh:435
+#: git-rebase.sh:464 git-rebase.sh:468
 #, sh-format
 msgid "$onto_name: there is no merge base"
 msgstr "$onto_name: ingen sammanslagningsbas finns"
 
-#: git-rebase.sh:440
+#: git-rebase.sh:473
 #, sh-format
 msgid "Does not point to a valid commit: $onto_name"
 msgstr "Peka på en giltig incheckning: $onto_name"
 
-#: git-rebase.sh:463
+#: git-rebase.sh:496
 #, sh-format
 msgid "fatal: no such branch: $branch_name"
 msgstr "ödesdigert: ingen sådan gren: $branch_name"
 
-#: git-rebase.sh:483
+#: git-rebase.sh:519
+msgid "Cannot autostash"
+msgstr "Kan inte utföra \"autostash\""
+
+#: git-rebase.sh:524
+#, sh-format
+msgid "Created autostash: $stash_abbrev"
+msgstr "Skapade autostash: $stash_abbrev"
+
+#: git-rebase.sh:528
 msgid "Please commit or stash them."
 msgstr "Checka in eller använd \"stash\" på dem."
 
-#: git-rebase.sh:501
+#: git-rebase.sh:548
 #, sh-format
 msgid "Current branch $branch_name is up to date."
 msgstr "Aktuell gren $branch_name är à jour."
 
-#: git-rebase.sh:504
+#: git-rebase.sh:552
 #, sh-format
 msgid "Current branch $branch_name is up to date, rebase forced."
 msgstr "Aktuell gren $branch_name är à jour, ombasering framtvingad."
 
-#: git-rebase.sh:515
+#: git-rebase.sh:563
 #, sh-format
 msgid "Changes from $mb to $onto:"
 msgstr "Ändringar från $mb till $onto:"
 
 #. Detach HEAD and reset the tree
-#: git-rebase.sh:524
+#: git-rebase.sh:572
 msgid "First, rewinding head to replay your work on top of it..."
 msgstr ""
 "Först, spolar tillbaka huvudet för att spela av ditt arbete ovanpå det..."
 
-#: git-rebase.sh:532
+#: git-rebase.sh:582
 #, sh-format
 msgid "Fast-forwarded $branch_name to $onto_name."
 msgstr "Snabbspolade $branch_name till $onto_name."
@@ -9458,6 +9947,11 @@
 msgid "Cannot record working tree state"
 msgstr "Kan inte registrera tillstånd för arbetskatalog"
 
+#: git-stash.sh:190
+#, sh-format
+msgid "Cannot update $ref_stash with $w_commit"
+msgstr "Kan inte uppdatera $ref_stash med $w_commit"
+
 #. TRANSLATORS: $option is an invalid option, like
 #. `--blah-blah'. The 7 spaces at the beginning of the
 #. second line correspond to "error: ". So you should line
@@ -9468,7 +9962,7 @@
 #. $ git stash save --blah-blah 2>&1 | head -n 2
 #. error: unknown option for 'stash save': --blah-blah
 #. To provide a message, use git stash save -- '--blah-blah'
-#: git-stash.sh:202
+#: git-stash.sh:241
 #, sh-format
 msgid ""
 "error: unknown option for 'stash save': $option\n"
@@ -9477,120 +9971,139 @@
 "fel: felaktig flagga för \"stash save\": $option\n"
 "     För att ange ett meddelande, använd git stash save -- \"$option\""
 
-#: git-stash.sh:223
+#: git-stash.sh:262
 msgid "No local changes to save"
 msgstr "Inga lokala ändringar att spara"
 
-#: git-stash.sh:227
+#: git-stash.sh:268
+msgid ""
+"The following untracked files would NOT be saved but need to be removed by "
+"stash save:"
+msgstr ""
+"Följande ospårade ändringar skulle INTE sparas utan måste tas bort med "
+"\"stash save\":"
+
+#: git-stash.sh:270
+msgid ""
+"Aborting. Consider using either the --force or --include-untracked option."
+msgstr ""
+"Avbryter. Överväg att använda antingen flaggan --force eller --include-"
+"untracked."
+
+#: git-stash.sh:274
 msgid "Cannot initialize stash"
 msgstr "Kan inte initiera \"stash\""
 
-#: git-stash.sh:235
+#: git-stash.sh:278
 msgid "Cannot save the current status"
 msgstr "Kan inte spara aktuell status"
 
-#: git-stash.sh:253
+#: git-stash.sh:296
 msgid "Cannot remove worktree changes"
 msgstr "Kan inte ta bort ändringar i arbetskatalogen"
 
-#: git-stash.sh:352
+#: git-stash.sh:395
 msgid "No stash found."
 msgstr "Ingen \"stash\" hittades."
 
-#: git-stash.sh:359
+#: git-stash.sh:402
 #, sh-format
 msgid "Too many revisions specified: $REV"
 msgstr "För många revisioner angivna: $REV"
 
-#: git-stash.sh:365
+#: git-stash.sh:408
 #, sh-format
 msgid "$reference is not valid reference"
 msgstr "$reference är inte en giltig referens."
 
-#: git-stash.sh:393
+#: git-stash.sh:436
 #, sh-format
 msgid "'$args' is not a stash-like commit"
 msgstr "\"$args\" är inte en \"stash\"-liknande incheckning"
 
-#: git-stash.sh:404
+#: git-stash.sh:447
 #, sh-format
 msgid "'$args' is not a stash reference"
 msgstr "\"$args\" är inte en \"stash\"-referens"
 
-#: git-stash.sh:412
+#: git-stash.sh:455
 msgid "unable to refresh index"
 msgstr "kan inte uppdatera indexet"
 
-#: git-stash.sh:416
+#: git-stash.sh:459
 msgid "Cannot apply a stash in the middle of a merge"
 msgstr "Kan inte tillämpa en \"stash\" mitt i en sammanslagning"
 
-#: git-stash.sh:424
+#: git-stash.sh:467
 msgid "Conflicts in index. Try without --index."
 msgstr "Konflikter i indexet. Testa utan --index."
 
-#: git-stash.sh:426
+#: git-stash.sh:469
 msgid "Could not save index tree"
 msgstr "Kunde inte spara indexträd"
 
-#: git-stash.sh:460
+#: git-stash.sh:503
 msgid "Cannot unstage modified files"
 msgstr "Kan inte ta bort ändrade filer ur kön"
 
-#: git-stash.sh:475
+#: git-stash.sh:518
 msgid "Index was not unstashed."
 msgstr "Indexet har inte tagits ur kön."
 
-#: git-stash.sh:492
+#: git-stash.sh:535
 #, sh-format
 msgid "Dropped ${REV} ($s)"
 msgstr "Kastade ${REV} ($s)"
 
-#: git-stash.sh:493
+#: git-stash.sh:536
 #, sh-format
 msgid "${REV}: Could not drop stash entry"
 msgstr "${REV}: Kunde inte kasta \"stash\"-post"
 
-#: git-stash.sh:500
+#: git-stash.sh:543
 msgid "No branch name specified"
 msgstr "Inget grennamn angavs"
 
-#: git-stash.sh:571
+#: git-stash.sh:615
 msgid "(To restore them type \"git stash apply\")"
 msgstr "(För att återställa dem, skriv \"git stash apply\")"
 
-#: git-submodule.sh:91
+#: git-submodule.sh:95
 #, sh-format
 msgid "cannot strip one component off url '$remoteurl'"
 msgstr "kan inte ta bort en komponent från url:en \"$remoteurl\""
 
-#: git-submodule.sh:196
+#: git-submodule.sh:237
 #, sh-format
 msgid "No submodule mapping found in .gitmodules for path '$sm_path'"
 msgstr ""
 "Hittade ingen undermodulmappning i .gitmodules för sökvägen \"$sm_path\""
 
-#: git-submodule.sh:239
+#: git-submodule.sh:281
 #, sh-format
 msgid "Clone of '$url' into submodule path '$sm_path' failed"
 msgstr "Misslyckades klona \"$url\" till undermodulsökvägen \"$sm_path\""
 
-#: git-submodule.sh:251
+#: git-submodule.sh:293
 #, sh-format
 msgid "Gitdir '$a' is part of the submodule path '$b' or vice versa"
-msgstr "Gitkatalog \"$a\" ingår i underkatalogsökvägen \"$b\" eller omvänt"
+msgstr "Gitkatalog \"$a\" ingår i undermodulsökvägen \"$b\" eller omvänt"
 
-#: git-submodule.sh:349
+#: git-submodule.sh:403
+msgid "Relative path can only be used from the toplevel of the working tree"
+msgstr "Relativ sökväg kan enfast användas från arbetskatalogens toppnivå"
+
+#: git-submodule.sh:413
 #, sh-format
 msgid "repo URL: '$repo' must be absolute or begin with ./|../"
 msgstr "arkiv-URL: \"$repo\" måste vara absolut eller börja med ./|../"
 
-#: git-submodule.sh:366
+#: git-submodule.sh:430
 #, sh-format
 msgid "'$sm_path' already exists in the index"
 msgstr "\"$sm_path\" finns redan i indexet"
 
-#: git-submodule.sh:370
+#: git-submodule.sh:434
 #, sh-format
 msgid ""
 "The following path is ignored by one of your .gitignore files:\n"
@@ -9601,22 +10114,22 @@
 "$sm_path\n"
 "Använd -f om du verkligen vill lägga till den"
 
-#: git-submodule.sh:388
+#: git-submodule.sh:452
 #, sh-format
 msgid "Adding existing repo at '$sm_path' to the index"
 msgstr "Lägger till befintligt arkiv i \"$sm_path\" i indexet"
 
-#: git-submodule.sh:390
+#: git-submodule.sh:454
 #, sh-format
 msgid "'$sm_path' already exists and is not a valid git repo"
 msgstr "\"$sm_path\" finns redan och är inte ett giltigt git-arkiv"
 
-#: git-submodule.sh:398
+#: git-submodule.sh:462
 #, sh-format
 msgid "A git directory for '$sm_name' is found locally with remote(s):"
 msgstr "En git-katalog för \"$sm_name\" hittades lokalt med fjärr(ar):"
 
-#: git-submodule.sh:400
+#: git-submodule.sh:464
 #, sh-format
 msgid ""
 "If you want to reuse this local git directory instead of cloning again from"
@@ -9624,14 +10137,14 @@
 "För att återanvända den lokala git-katalogen istället för att på nytt klona "
 "från"
 
-#: git-submodule.sh:402
+#: git-submodule.sh:466
 #, sh-format
 msgid ""
 "use the '--force' option. If the local git directory is not the correct repo"
 msgstr ""
 "använd flaggan \"--force\". Om den lokala git-katalogen inte är riktigt arkiv"
 
-#: git-submodule.sh:403
+#: git-submodule.sh:467
 #, sh-format
 msgid ""
 "or you are unsure what this means choose another name with the '--name' "
@@ -9640,210 +10153,287 @@
 "eller om du är osäker på vad det innebär, välj nytt namn med flaggan \"--name"
 "\"."
 
-#: git-submodule.sh:405
+#: git-submodule.sh:469
 #, sh-format
 msgid "Reactivating local git directory for submodule '$sm_name'."
 msgstr "Aktiverar lokal git-katalog för undermodulen \"$sm_name\" på nytt."
 
-#: git-submodule.sh:417
+#: git-submodule.sh:481
 #, sh-format
 msgid "Unable to checkout submodule '$sm_path'"
 msgstr "Kan inte checka ut undermodulen \"$sm_path\""
 
-#: git-submodule.sh:422
+#: git-submodule.sh:486
 #, sh-format
 msgid "Failed to add submodule '$sm_path'"
 msgstr "Misslyckades lägga till undermodulen \"$sm_path\""
 
-#: git-submodule.sh:431
+#: git-submodule.sh:495
 #, sh-format
 msgid "Failed to register submodule '$sm_path'"
 msgstr "Misslyckades registrera undermodulen \"$sm_path\""
 
-#: git-submodule.sh:474
+#: git-submodule.sh:539
 #, sh-format
-msgid "Entering '$prefix$sm_path'"
-msgstr "Går in i \"$prefix$sm_path\""
+msgid "Entering '$prefix$displaypath'"
+msgstr "Går in i \"$prefix$displaypath\""
 
-#: git-submodule.sh:488
+#: git-submodule.sh:554
 #, sh-format
-msgid "Stopping at '$sm_path'; script returned non-zero status."
+msgid "Stopping at '$prefix$displaypath'; script returned non-zero status."
 msgstr ""
-"Stoppar på \"$sm_path\"; skriptet returnerade en status skild från noll."
+"Stoppar på \"$prefix$displaypath\"; skriptet returnerade en status skild "
+"från noll."
 
-#: git-submodule.sh:532
+#: git-submodule.sh:600
 #, sh-format
-msgid "No url found for submodule path '$sm_path' in .gitmodules"
-msgstr "Hittade ingen url för undermodulsökvägen \"$sm_path\" i .gitmodules"
-
-#: git-submodule.sh:541
-#, sh-format
-msgid "Failed to register url for submodule path '$sm_path'"
-msgstr "Misslyckades registrera url för underkatalogsökväg \"$sm_path\""
-
-#: git-submodule.sh:543
-#, sh-format
-msgid "Submodule '$name' ($url) registered for path '$sm_path'"
-msgstr "Undermodulen \"$name\" ($url) registrerad för sökvägen \"$sm_path\""
-
-#: git-submodule.sh:551
-#, sh-format
-msgid "Failed to register update mode for submodule path '$sm_path'"
+msgid "No url found for submodule path '$displaypath' in .gitmodules"
 msgstr ""
-"Misslyckades registrera uppdateringsläge för undermodulsökväg \"$sm_path\""
+"Hittade ingen url för undermodulsökvägen \"$displaypath\" i .gitmodules"
 
-#: git-submodule.sh:588
+#: git-submodule.sh:609
+#, sh-format
+msgid "Failed to register url for submodule path '$displaypath'"
+msgstr "Misslyckades registrera url för undermodulsökväg \"$displaypath\""
+
+#: git-submodule.sh:611
+#, sh-format
+msgid "Submodule '$name' ($url) registered for path '$displaypath'"
+msgstr ""
+"Undermodulen \"$name\" ($url) registrerad för sökvägen \"$displaypath\""
+
+#: git-submodule.sh:619
+#, sh-format
+msgid "Failed to register update mode for submodule path '$displaypath'"
+msgstr ""
+"Misslyckades registrera uppdateringsläge för undermodulsökväg \"$displaypath"
+"\""
+
+#: git-submodule.sh:656
 #, sh-format
 msgid "Use '.' if you really want to deinitialize all submodules"
 msgstr "Använd \".\" om du verkligen vill avinitiera alla undermoduler"
 
-#: git-submodule.sh:603
+#: git-submodule.sh:673
 #, sh-format
-msgid "Submodule work tree '$sm_path' contains a .git directory"
-msgstr "Undermodulens arbetskatalog \"$sm_path\" innehåller katalogen \".git\""
+msgid "Submodule work tree '$displaypath' contains a .git directory"
+msgstr ""
+"Undermodulens arbetskatalog \"$displaypath\" innehåller katalogen \".git\""
 
-#: git-submodule.sh:604
+#: git-submodule.sh:674
 #, sh-format
 msgid ""
 "(use 'rm -rf' if you really want to remove it including all of its history)"
 msgstr ""
 "(använd \"rm -rf\" om du verkligen vill ta bort den och all dess historik)"
 
-#: git-submodule.sh:610
+#: git-submodule.sh:680
 #, sh-format
 msgid ""
-"Submodule work tree '$sm_path' contains local modifications; use '-f' to "
+"Submodule work tree '$displaypath' contains local modifications; use '-f' to "
 "discard them"
 msgstr ""
-"Undermodulens arbetskatalog \"$sm_path\" har lokala ändringar; \"-f\" kastar "
-"bort dem"
+"Undermodulens arbetskatalog \"$displaypath\" har lokala ändringar; \"-f\" "
+"kastar bort dem"
 
-#: git-submodule.sh:613
+#: git-submodule.sh:683
 #, sh-format
-msgid "Cleared directory '$sm_path'"
-msgstr "Rensade katalogen \"$sm_path\""
+msgid "Cleared directory '$displaypath'"
+msgstr "Rensade katalogen \"$displaypath\""
 
-#: git-submodule.sh:614
+#: git-submodule.sh:684
 #, sh-format
-msgid "Could not remove submodule work tree '$sm_path'"
-msgstr "Kunde inte ta bort underkatalogens arbetskatalog \"$sm_path\""
+msgid "Could not remove submodule work tree '$displaypath'"
+msgstr "Kunde inte ta bort undermodulens arbetskatalog \"$displaypath\""
 
-#: git-submodule.sh:617
+#: git-submodule.sh:687
 #, sh-format
-msgid "Could not create empty submodule directory '$sm_path'"
-msgstr "Kunde inte skapa tom undermodulskatalog \"$sm_path\""
+msgid "Could not create empty submodule directory '$displaypath'"
+msgstr "Kunde inte skapa tom undermodulskatalog \"$displaypath\""
 
-#: git-submodule.sh:626
+#: git-submodule.sh:696
 #, sh-format
-msgid "Submodule '$name' ($url) unregistered for path '$sm_path'"
-msgstr "Undermodulen \"$name\" ($url) avregistrerad för sökvägen \"$sm_path\""
+msgid "Submodule '$name' ($url) unregistered for path '$displaypath'"
+msgstr ""
+"Undermodulen \"$name\" ($url) avregistrerad för sökvägen \"$displaypath\""
 
-#: git-submodule.sh:731
+#: git-submodule.sh:811
 #, sh-format
 msgid ""
-"Submodule path '$prefix$sm_path' not initialized\n"
+"Submodule path '$displaypath' not initialized\n"
 "Maybe you want to use 'update --init'?"
 msgstr ""
-"Undermodulen \"$prefix$sm_path\" har inte initierats\n"
+"Undermodulen \"$displaypath\" har inte initierats\n"
 "Kanske du vill köra \"update --init\"?"
 
-#: git-submodule.sh:744
+#: git-submodule.sh:824
 #, sh-format
-msgid "Unable to find current revision in submodule path '$prefix$sm_path'"
-msgstr ""
-"Kan inte hitta aktuell revision i undermodulsökvägen \"$prefix$sm_path\""
+msgid "Unable to find current revision in submodule path '$displaypath'"
+msgstr "Kan inte hitta aktuell revision i undermodulsökvägen \"$displaypath\""
 
-#: git-submodule.sh:753
+#: git-submodule.sh:833
 #, sh-format
 msgid "Unable to fetch in submodule path '$sm_path'"
 msgstr "Kan inte hämta i undermodulsökväg \"$sm_path\""
 
-#: git-submodule.sh:777
+#: git-submodule.sh:857
 #, sh-format
-msgid "Unable to fetch in submodule path '$prefix$sm_path'"
-msgstr "Kan inte hämta i undermodulsökväg \"$prefix$sm_path\""
+msgid "Unable to fetch in submodule path '$displaypath'"
+msgstr "Kan inte hämta i undermodulsökväg \"$displaypath\""
 
-#: git-submodule.sh:791
+#: git-submodule.sh:871
 #, sh-format
-msgid "Unable to rebase '$sha1' in submodule path '$prefix$sm_path'"
-msgstr "Kan inte ombasera \"$sha1\" i undermodulsökvägen \"$prefix$sm_path\""
+msgid "Unable to rebase '$sha1' in submodule path '$displaypath'"
+msgstr "Kan inte ombasera \"$sha1\" i undermodulsökvägen \"$displaypath\""
 
-#: git-submodule.sh:792
+#: git-submodule.sh:872
 #, sh-format
-msgid "Submodule path '$prefix$sm_path': rebased into '$sha1'"
-msgstr "Undermodulsökvägen \"$prefix$sm_path\": ombaserade in i \"$sha1\""
+msgid "Submodule path '$displaypath': rebased into '$sha1'"
+msgstr "Undermodulsökvägen \"$displaypath\": ombaserade in i \"$sha1\""
 
-#: git-submodule.sh:797
+#: git-submodule.sh:877
 #, sh-format
-msgid "Unable to merge '$sha1' in submodule path '$prefix$sm_path'"
-msgstr "Kan inte slå ihop \"$sha1\" i undermodulsökvägen \"$prefix$sm_path\""
+msgid "Unable to merge '$sha1' in submodule path '$displaypath'"
+msgstr "Kan inte slå ihop \"$sha1\" i undermodulsökvägen \"$displaypath\""
 
-#: git-submodule.sh:798
+#: git-submodule.sh:878
 #, sh-format
-msgid "Submodule path '$prefix$sm_path': merged in '$sha1'"
-msgstr "Undermodulsökvägen \"$prefix$sm_path\": sammanslagen i \"$sha1\""
+msgid "Submodule path '$displaypath': merged in '$sha1'"
+msgstr "Undermodulsökvägen \"$displaypath\": sammanslagen i \"$sha1\""
 
-#: git-submodule.sh:803
+#: git-submodule.sh:883
 #, sh-format
-msgid "Unable to checkout '$sha1' in submodule path '$prefix$sm_path'"
-msgstr "Kan inte checka ut \"$sha1\" i undermodulsökvägen \"$prefix$sm_path\""
+msgid ""
+"Execution of '$command $sha1' failed in submodule  path '$prefix$sm_path'"
+msgstr ""
+"Misslyckades köra \"$command $sha1\" i undermodulsökvägen \"$prefix$sm_path\""
 
-#: git-submodule.sh:804
+#: git-submodule.sh:884
 #, sh-format
-msgid "Submodule path '$prefix$sm_path': checked out '$sha1'"
-msgstr "Undermodulsökvägen \"$prefix$sm_path\": checkade ut \"$sha1\""
+msgid "Submodule path '$prefix$sm_path': '$command $sha1'"
+msgstr "Undermodulsökvägen \"$prefix$sm_path\": \"$command $sha1\""
 
-#: git-submodule.sh:831
+#: git-submodule.sh:889
 #, sh-format
-msgid "Failed to recurse into submodule path '$prefix$sm_path'"
-msgstr "Misslyckades rekursera in i undermodulsökvägen \"$prefix$sm_path\""
+msgid "Unable to checkout '$sha1' in submodule path '$displaypath'"
+msgstr "Kan inte checka ut \"$sha1\" i undermodulsökvägen \"$displaypath\""
 
-#: git-submodule.sh:939
+#: git-submodule.sh:890
+#, sh-format
+msgid "Submodule path '$displaypath': checked out '$sha1'"
+msgstr "Undermodulsökvägen \"$displaypath\": checkade ut \"$sha1\""
+
+#: git-submodule.sh:917
+#, sh-format
+msgid "Failed to recurse into submodule path '$displaypath'"
+msgstr "Misslyckades rekursera in i undermodulsökvägen \"$displaypath\""
+
+#: git-submodule.sh:1025
 msgid "The --cached option cannot be used with the --files option"
 msgstr "Flaggan --cached kan inte användas med flaggan --files"
 
 #. unexpected type
-#: git-submodule.sh:979
+#: git-submodule.sh:1066
 #, sh-format
 msgid "unexpected mode $mod_dst"
 msgstr "oväntat läge $mod_dst"
 
-#: git-submodule.sh:997
+#: git-submodule.sh:1086
 #, sh-format
-msgid "  Warn: $name doesn't contain commit $sha1_src"
-msgstr "  Varning: $name innehåller inte incheckning $sha1_src"
+msgid "  Warn: $display_name doesn't contain commit $sha1_src"
+msgstr "  Varning: $display_name innehåller inte incheckningen $sha1_src"
 
-#: git-submodule.sh:1000
+#: git-submodule.sh:1089
 #, sh-format
-msgid "  Warn: $name doesn't contain commit $sha1_dst"
-msgstr "  Varning: $name innehåller inte incheckning $sha1_dst"
+msgid "  Warn: $display_name doesn't contain commit $sha1_dst"
+msgstr "  Varning: $display_name innehåller inte incheckningen $sha1_dst"
 
-#: git-submodule.sh:1003
+#: git-submodule.sh:1092
 #, sh-format
-msgid "  Warn: $name doesn't contain commits $sha1_src and $sha1_dst"
-msgstr "  Varning: $name innehåller inte incheckningar $sha1_src och $sha1_dst"
+msgid "  Warn: $display_name doesn't contain commits $sha1_src and $sha1_dst"
+msgstr ""
+"  Varning: $display_name innehåller inte incheckningarna $sha1_src och "
+"$sha1_dst"
 
-#: git-submodule.sh:1028
+#: git-submodule.sh:1117
 msgid "blob"
 msgstr "blob"
 
-#: git-submodule.sh:1066
+#: git-submodule.sh:1155
 msgid "Submodules changed but not updated:"
 msgstr "Undermoduler ändrade men inte uppdaterade:"
 
-#: git-submodule.sh:1068
+#: git-submodule.sh:1157
 msgid "Submodule changes to be committed:"
 msgstr "Undermodulers ändringar att checka in:"
 
-#: git-submodule.sh:1153
+#: git-submodule.sh:1242
 #, sh-format
 msgid "Failed to recurse into submodule path '$sm_path'"
 msgstr "Misslyckades rekursera in i undermodulsökvägen \"$sm_path\""
 
-#: git-submodule.sh:1216
+#: git-submodule.sh:1306
 #, sh-format
-msgid "Synchronizing submodule url for '$prefix$sm_path'"
-msgstr "Synkroniserar undermodul-url för \"$prefix$sm_path\""
+msgid "Synchronizing submodule url for '$displaypath'"
+msgstr "Synkroniserar undermodul-url för \"$displaypath\""
+
+#~ msgid "  (fix conflicts and then run \"git am --resolved\")"
+#~ msgstr "  (rätta konflikter och kör sedan \"git am --resolved\")"
+
+#~ msgid "  (all conflicts fixed: run \"git commit\")"
+#~ msgstr "  (alla konflikter har rättats: kör \"git commit\")"
+
+#~ msgid "more than %d trees given: '%s'"
+#~ msgstr "mer än %d träd angavs: \"%s\""
+
+#~ msgid "You cannot combine --no-ff with --ff-only."
+#~ msgstr "Du kan inte kombinera --no-ff med --ff-only."
+
+#~ msgid ""
+#~ "submodule '%s' (or one of its nested submodules) uses a .git directory\n"
+#~ "(use 'rm -rf' if you really want to remove it including all of its "
+#~ "history)"
+#~ msgstr ""
+#~ "undermodulen \"%s\" (eller en av dess undermoduler) använder en .git-"
+#~ "katalog\n"
+#~ "(använd \"rm -rf\" om du verkligen vill ta bort den och all dess historik)"
+
+#~ msgid ""
+#~ "'%s' has changes staged in the index\n"
+#~ "(use --cached to keep the file, or -f to force removal)"
+#~ msgstr ""
+#~ "\"%s\" har köade ändringar i indexet\n"
+#~ "(använd --cached för att behålla filen eller -f för att tvinga "
+#~ "borttagning)"
+
+#~ msgid "show commits where no parent comes before its children"
+#~ msgstr "visa incheckningar där ingen förälder kommer före dess barn"
+
+#~ msgid "show the HEAD reference"
+#~ msgstr "visa HEAD-referensen"
+
+#~ msgid "Unable to fetch in submodule path '$prefix$sm_path'"
+#~ msgstr "Kan inte hämta i undermodulsökväg \"$prefix$sm_path\""
+
+#~ msgid "Failed to recurse into submodule path '$prefix$sm_path'"
+#~ msgstr "Misslyckades rekursera in i undermodulsökvägen \"$prefix$sm_path\""
+
+#~ msgid "It took %.2f seconds to enumerate untracked files.  'status -uno'"
+#~ msgstr "Det tog %.2f sekunder att räkna ospårade filer. \"status -uno\""
+
+#~ msgid "may speed it up, but you have to be careful not to forget to add"
+#~ msgstr "kanske gör det snabbare, men du måste vara försiktig så att du"
+
+#~ msgid "new files yourself (see 'git help status')."
+#~ msgstr "inte glömmer lägga till filer själv (se \"git help status\")"
+
+#~ msgid "git shortlog [-n] [-s] [-e] [-w] [rev-opts] [--] [<commit-id>... ]"
+#~ msgstr ""
+#~ "git shortlog [-n] [-s] [-e] [-w] [rev-flaggor] [--] [<incheckning-id>... ]"
+
+#~ msgid "See 'git help <command>' for more information on a specific command."
+#~ msgstr ""
+#~ "Se \"git help <kommando>\" för mer information om ett specifikt kommando."
 
 #~ msgid "use any ref in .git/refs"
 #~ msgstr "använd alla referenser i .git/refs"
@@ -9964,9 +10554,6 @@
 #~ msgid "# Changed but not updated:"
 #~ msgstr "# Ändrade men inte uppdaterade:"
 
-#~ msgid "A branch named '%s' already exists."
-#~ msgstr "Det finns redan en gren som heter \"%s\""
-
 #~ msgid "path '%s' does not have all 3 versions"
 #~ msgstr "sökvägen \"%s\" har inte alla 3 versionerna"
 
@@ -9990,73 +10577,3 @@
 
 #~ msgid "Failed to write current notes tree to database"
 #~ msgstr "Kunde inte skriva aktuellt anteckningsträd till databasen"
-
-# FIXME: Untranslatable!
-#
-#~ msgid "Refusing to %s notes in %s (outside of refs/notes/)"
-#~ msgstr "Vägrar %s anteckningar i %s (utanför refs/notes/)"
-
-#~ msgid "add"
-#~ msgstr "add"
-
-#~ msgid "copy"
-#~ msgstr "copy"
-
-#~ msgid "show"
-#~ msgstr "show"
-
-#~ msgid "remove"
-#~ msgstr "remove"
-
-#~ msgid "prune"
-#~ msgstr "prune"
-
-#~ msgid "The current branch %s is not tracking anything."
-#~ msgstr "Den aktuella grenen %s spårar ingenting."
-
-#~ msgid "No destination configured to push to."
-#~ msgstr "Har inte ställt in någon destination att sända till."
-
-#~ msgid "Reflog action message too long: %.*s..."
-#~ msgstr "Reflog-händelsemeddelande för långt: %.*s..."
-
-#~ msgid "Could not read commit message of %s"
-#~ msgstr "Kunde inte läsa incheckningsmeddelandet för %s"
-
-#~ msgid "Could not extract author email from %s"
-#~ msgstr "Kunde inte hämta författarens e-postadress från %s"
-
-#~ msgid "Could not extract author time from %s"
-#~ msgstr "Kunde inte hämta författartid från %s"
-
-#~ msgid "No author information found in %s"
-#~ msgstr "Hittade ingen författarinformation i %s"
-
-#~ msgid "cherry-pick --ff cannot be used with --signoff"
-#~ msgstr "cherry-pick --ff kan inte användas med --signoff"
-
-#~ msgid "cherry-pick --ff cannot be used with --no-commit"
-#~ msgstr "cherry-pick --ff kan inte användas med --no-commit"
-
-#~ msgid "cherry-pick --ff cannot be used with -x"
-#~ msgstr "cherry-pick --ff kan inte användas med -x"
-
-#~ msgid "cherry-pick --ff cannot be used with --edit"
-#~ msgstr "cherry-pick --ff kan inte användas med --edit"
-
-#~ msgid "committer info too long."
-#~ msgstr "incheckarinformation för lång."
-
-#~ msgid ""
-#~ "\n"
-#~ "#\n"
-#~ "# Write a tag message\n"
-#~ "#\n"
-#~ msgstr ""
-#~ "\n"
-#~ "#\n"
-#~ "# Skriv ett taggmeddelande\n"
-#~ "#\n"
-
-#~ msgid "signing key value too long (%.10s...)"
-#~ msgstr "signeringsnyckelvärdet för långt (%.10s...)"
diff --git a/po/vi.po b/po/vi.po
index 9720880..dd2d2a7 100644
--- a/po/vi.po
+++ b/po/vi.po
@@ -1,15 +1,14 @@
 # Vietnamese translation for GIT-CORE.
-# Copyright (C) 2012-2013 Trần Ngọc Quân.
 # This file is distributed under the same license as the git-core package.
 # First translated by Trần Ngọc Quân <vnwildman@gmail.com>, 2012-2013.
 # Nguyễn Thái Ngọc Duy <pclouds@gmail.com>, 2012.
 #
 msgid ""
 msgstr ""
-"Project-Id-Version: git-v1.8.2.1-342-gfa728\n"
+"Project-Id-Version: git-v1.8.4-rc1-22-gb8ecf23\n"
 "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
-"POT-Creation-Date: 2013-04-10 15:16+0800\n"
-"PO-Revision-Date: 2013-04-11 14:21+0700\n"
+"POT-Creation-Date: 2013-08-06 14:10+0800\n"
+"PO-Revision-Date: 2013-08-06 14:28+0700\n"
 "Last-Translator: Trần Ngọc Quân <vnwildman@gmail.com>\n"
 "Language-Team: Vietnamese <translation-team-vi@lists.sourceforge.net>\n"
 "Language: vi\n"
@@ -22,7 +21,7 @@
 "X-Poedit-Basepath: ../\n"
 "X-Generator: Poedit 1.5.5\n"
 
-#: advice.c:53
+#: advice.c:57
 #, c-format
 msgid "hint: %.*s\n"
 msgstr "gợi ý: %.*s\n"
@@ -31,7 +30,7 @@
 #. * Message used both when 'git commit' fails and when
 #. * other commands doing a merge do.
 #.
-#: advice.c:83
+#: advice.c:87
 msgid ""
 "Fix them up in the work tree,\n"
 "and then use 'git add/rm <file>' as\n"
@@ -39,9 +38,9 @@
 "or use 'git commit -a'."
 msgstr ""
 "Sửa chúng trong cây làm việc,\n"
-"và sau đó dùng lệnh “git add/rm <tập-tin>” dành riêng\n"
+"và sau đó dùng lệnh \"git add/rm <tập-tin>\" dành riêng\n"
 "cho việc đánh dấu tập tin cần giải quyết và tạo lần chuyển giao,\n"
-"hoặc là dùng lệnh “git commit -a”."
+"hoặc là dùng lệnh \"git commit -a\"."
 
 #: archive.c:10
 msgid "git archive [options] <tree-ish> [<path>...]"
@@ -70,7 +69,7 @@
 msgid "archive format"
 msgstr "định dạng lưu trữ"
 
-#: archive.c:324 builtin/log.c:1117
+#: archive.c:324 builtin/log.c:1173
 msgid "prefix"
 msgstr "tiền tố"
 
@@ -78,11 +77,11 @@
 msgid "prepend prefix to each pathname in the archive"
 msgstr "nối thêm tiền tố vào từng đường dẫn tập tin trong kho lưu"
 
-#: archive.c:326 builtin/archive.c:88 builtin/blame.c:2366
-#: builtin/blame.c:2367 builtin/config.c:55 builtin/fast-export.c:659
-#: builtin/fast-export.c:661 builtin/grep.c:715 builtin/hash-object.c:77
-#: builtin/ls-files.c:497 builtin/ls-files.c:500 builtin/notes.c:536
-#: builtin/notes.c:693 builtin/read-tree.c:107 parse-options.h:149
+#: archive.c:326 builtin/archive.c:88 builtin/blame.c:2292
+#: builtin/blame.c:2293 builtin/config.c:56 builtin/fast-export.c:673
+#: builtin/fast-export.c:675 builtin/grep.c:714 builtin/hash-object.c:77
+#: builtin/ls-files.c:496 builtin/ls-files.c:499 builtin/notes.c:408
+#: builtin/notes.c:565 builtin/read-tree.c:108 parse-options.h:152
 msgid "file"
 msgstr "tập-tin"
 
@@ -96,7 +95,7 @@
 
 #: archive.c:330
 msgid "report archived files on stderr"
-msgstr "liệt kê các tập tin được lưu trữ vào stderr (đầu ra lỗi chuẩn)"
+msgstr "liệt kê các tập tin được lưu trữ vào stderr (đầu ra lỗi tiêu chuẩn)"
 
 #: archive.c:331
 msgid "store only"
@@ -114,7 +113,7 @@
 msgid "list supported archive formats"
 msgstr "liệt kê các kiểu nén được hỗ trợ"
 
-#: archive.c:345 builtin/archive.c:90 builtin/clone.c:86
+#: archive.c:345 builtin/archive.c:90 builtin/clone.c:85
 msgid "repo"
 msgstr "kho"
 
@@ -122,7 +121,7 @@
 msgid "retrieve the archive from remote repository <repo>"
 msgstr "nhận kho lưu từ kho chứa <kho> trên máy chủ"
 
-#: archive.c:347 builtin/archive.c:92 builtin/notes.c:615
+#: archive.c:347 builtin/archive.c:92 builtin/notes.c:487
 msgid "command"
 msgstr "lệnh"
 
@@ -138,19 +137,90 @@
 "Các mẫu dạng phủ định bị cấm dùng cho các thuộc tính của git\n"
 "Dùng “\\!” cho các chuỗi văn bản có dấu chấm than dẫn đầu."
 
-#: branch.c:201
+#: branch.c:60
+#, c-format
+msgid "Not setting branch %s as its own upstream."
+msgstr "Chưa cài đặt nhánh %s như là thượng nguồn (upstream) của nó."
+
+#: branch.c:82
+#, c-format
+msgid "Branch %s set up to track remote branch %s from %s by rebasing."
+msgstr ""
+"Nhánh %s cài đặt để theo dõi vết nhánh máy chủ %s từ %s bằng cách rebase."
+
+#: branch.c:83
+#, c-format
+msgid "Branch %s set up to track remote branch %s from %s."
+msgstr "Nhánh %s cài đặt để theo vết nhánh máy chủ %s từ %s."
+
+#: branch.c:87
+#, c-format
+msgid "Branch %s set up to track local branch %s by rebasing."
+msgstr "Nhánh %s cài đặt để theo vết nhánh nội bộ %s bằng cách rebase."
+
+#: branch.c:88
+#, c-format
+msgid "Branch %s set up to track local branch %s."
+msgstr "Nhánh %s cài đặt để theo vết nhánh nội bộ %s."
+
+#: branch.c:92
+#, c-format
+msgid "Branch %s set up to track remote ref %s by rebasing."
+msgstr "Nhánh %s cài đặt để theo vết nhánh máy chủ %s bằng cách rebase."
+
+#: branch.c:93
+#, c-format
+msgid "Branch %s set up to track remote ref %s."
+msgstr "Nhánh %s cài đặt để theo vết tham chiếu máy chủ %s."
+
+#: branch.c:97
+#, c-format
+msgid "Branch %s set up to track local ref %s by rebasing."
+msgstr ""
+"Nhánh %s cài đặt để theo dõi vết tham chiếu nội bộ %s bằng cách rebase."
+
+#: branch.c:98
+#, c-format
+msgid "Branch %s set up to track local ref %s."
+msgstr "Nhánh %s cài đặt để theo dõi tham chiếu nội bộ %s."
+
+#: branch.c:118
+#, c-format
+msgid "Tracking not set up: name too long: %s"
+msgstr "Theo vết chưa được cài đặt: tên quá dài: %s"
+
+#: branch.c:137
+#, c-format
+msgid "Not tracking: ambiguous information for ref %s"
+msgstr "Không theo vết: thông tin chưa rõ ràng cho tham chiếu %s"
+
+#: branch.c:182
+#, c-format
+msgid "'%s' is not a valid branch name."
+msgstr "“%s” không phải là một tên nhánh hợp lệ."
+
+#: branch.c:187
+#, c-format
+msgid "A branch named '%s' already exists."
+msgstr "Đã có nhánh mang tên “%s”."
+
+#: branch.c:195
+msgid "Cannot force update the current branch."
+msgstr "Không thể ép buộc cập nhật nhánh hiện hành."
+
+#: branch.c:216
 #, c-format
 msgid "Cannot setup tracking information; starting point '%s' is not a branch."
 msgstr ""
-"Không thể cài đặt thông tin theo vết; điểm bắt đầu '%s' không phải là một "
+"Không thể cài đặt thông tin theo vết; điểm bắt đầu “%s” không phải là một "
 "nhánh."
 
-#: branch.c:203
+#: branch.c:218
 #, c-format
 msgid "the requested upstream branch '%s' does not exist"
 msgstr "nhánh dòng ngược đã yêu cầu “%s” chưa sẵn có"
 
-#: branch.c:205
+#: branch.c:220
 msgid ""
 "\n"
 "If you are planning on basing your work on an upstream\n"
@@ -170,6 +240,29 @@
 "sẽ theo dõi bản đối chiếu máy chủ của nó, bạn cần dùng lệnh\n"
 "\"git push -u\" để đặt cấu hình dòng ngược bạn muốn push."
 
+#: branch.c:265
+#, c-format
+msgid "Not a valid object name: '%s'."
+msgstr "Không phải tên đối tượng hợp lệ: “%s”."
+
+#: branch.c:285
+#, c-format
+msgid "Ambiguous object name: '%s'."
+msgstr "Tên đối tượng chưa rõ ràng: “%s”."
+
+#: branch.c:290
+#, c-format
+msgid "Not a valid branch point: '%s'."
+msgstr "Nhánh không hợp lệ: “%s”."
+
+#: branch.c:296
+msgid "Failed to lock ref for update"
+msgstr "Gặp lỗi khi khóa tham chiếu (ref) để cập nhật"
+
+#: branch.c:314
+msgid "Failed to write ref"
+msgstr "Gặp lỗi khi ghi tham chiếu (ref)"
+
 #: bundle.c:36
 #, c-format
 msgid "'%s' does not look like a v2 bundle file"
@@ -180,7 +273,7 @@
 msgid "unrecognized header: %s%s (%d)"
 msgstr "phần đầu (header) không được thừa nhận: %s%s (%d)"
 
-#: bundle.c:89 builtin/commit.c:676
+#: bundle.c:89 builtin/commit.c:697
 #, c-format
 msgid "could not open '%s'"
 msgstr "không thể mở “%s”"
@@ -189,11 +282,11 @@
 msgid "Repository lacks these prerequisite commits:"
 msgstr "Kho chứa thiếu những lần chuyển giao (commit) cần trước hết này:"
 
-#: bundle.c:164 sequencer.c:651 sequencer.c:1083 builtin/log.c:300
-#: builtin/log.c:754 builtin/log.c:1350 builtin/log.c:1566 builtin/merge.c:349
-#: builtin/shortlog.c:157
+#: bundle.c:164 sequencer.c:661 sequencer.c:1111 builtin/log.c:331
+#: builtin/log.c:801 builtin/log.c:1399 builtin/log.c:1625 builtin/merge.c:364
+#: builtin/shortlog.c:156
 msgid "revision walk setup failed"
-msgstr "cài đặt việc di chuyển qua các điểm xét lại gặp lỗi"
+msgstr "cài đặt việc di chuyển qua các điểm xét duyệt gặp lỗi"
 
 #: bundle.c:186
 #, c-format
@@ -217,7 +310,7 @@
 msgid "rev-list died"
 msgstr "rev-list đã chết"
 
-#: bundle.c:300 builtin/log.c:1246 builtin/shortlog.c:260
+#: bundle.c:300 builtin/log.c:1310 builtin/shortlog.c:259
 #, c-format
 msgid "unrecognized argument: %s"
 msgstr "đối số không được thừa nhận: %s"
@@ -248,12 +341,12 @@
 msgid "index-pack died"
 msgstr "index-pack đã chết"
 
-#: commit.c:50
+#: commit.c:53
 #, c-format
 msgid "could not parse %s"
-msgstr "không thể phân tích %s"
+msgstr "không thể phân tích cú pháp %s"
 
-#: commit.c:52
+#: commit.c:55
 #, c-format
 msgid "%s %s is not a commit!"
 msgstr "%s %s không phải là một lần commit!"
@@ -262,16 +355,16 @@
 msgid "memory exhausted"
 msgstr "hết bộ nhớ"
 
-#: connected.c:39
+#: connected.c:60
 msgid "Could not run 'git rev-list'"
 msgstr "Không thể chạy “git rev-list”"
 
-#: connected.c:48
+#: connected.c:80
 #, c-format
 msgid "failed write to rev-list: %s"
 msgstr "gặp lỗi khi ghi vào rev-list: %s"
 
-#: connected.c:56
+#: connected.c:88
 #, c-format
 msgid "failed to close rev-list's stdin: %s"
 msgstr "gặp lỗi khi đóng đầu vào chuẩn stdin của rev-list: %s"
@@ -367,7 +460,7 @@
 "Tìm thấy các lỗi trong biến cấu hình “diff.dirstat”:\n"
 "%s"
 
-#: diff.c:3480
+#: diff.c:3487
 #, c-format
 msgid ""
 "Failed to parse --dirstat/-X option parameter:\n"
@@ -376,7 +469,7 @@
 "Gặp lỗi khi phân tích đối số tùy chọn --dirstat/-X:\n"
 "%s"
 
-#: diff.c:3494
+#: diff.c:3501
 #, c-format
 msgid "Failed to parse --submodule option parameter: '%s'"
 msgstr "Gặp lỗi khi phân tích đối số tùy chọn --submodule: “%s”"
@@ -418,20 +511,20 @@
 msgid "'%s': short read %s"
 msgstr "“%s”: đọc ngắn %s"
 
-#: help.c:212
+#: help.c:210
 #, c-format
 msgid "available git commands in '%s'"
-msgstr "các lệnh git sẵn sàng để dùng trong “%s”"
+msgstr "các lệnh git sẵn có trong thư mục “%s”:"
 
-#: help.c:219
+#: help.c:217
 msgid "git commands available from elsewhere on your $PATH"
 msgstr "các lệnh git sẵn sàng để dùng từ một nơi khác trong $PATH của bạn"
 
-#: help.c:235
+#: help.c:233
 msgid "The most commonly used git commands are:"
 msgstr "Những lệnh git hay được sử dụng nhất là:"
 
-#: help.c:292
+#: help.c:290
 #, c-format
 msgid ""
 "'%s' appears to be a git command, but we were not\n"
@@ -440,11 +533,11 @@
 "“%s” trông như là một lệnh git, nhưng chúng tôi không\n"
 "thể thực thi nó. Có lẽ là lệnh git-%s đã bị hỏng?"
 
-#: help.c:349
+#: help.c:347
 msgid "Uh oh. Your system reports no Git commands at all."
 msgstr "Ối chà. Hệ thống của bạn báo rằng chẳng có lệnh Git nào cả."
 
-#: help.c:371
+#: help.c:369
 #, c-format
 msgid ""
 "WARNING: You called a Git command named '%s', which does not exist.\n"
@@ -453,17 +546,17 @@
 "CẢNH BÁO: Bạn đã gọi lệnh Git có tên “%s”, mà nó lại không có sẵn.\n"
 "Giả định rằng ý bạn là “%s”"
 
-#: help.c:376
+#: help.c:374
 #, c-format
 msgid "in %0.1f seconds automatically..."
 msgstr "trong %0.1f giây một cách tự động..."
 
-#: help.c:383
+#: help.c:381
 #, c-format
 msgid "git: '%s' is not a git command. See 'git --help'."
 msgstr "git: “%s” không phải là một lệnh của git. Xem “git --help”."
 
-#: help.c:387
+#: help.c:385 help.c:444
 msgid ""
 "\n"
 "Did you mean this?"
@@ -477,12 +570,17 @@
 "\n"
 "Có phải ý bạn là một trong số những cái này không?"
 
+#: help.c:440
+#, c-format
+msgid "%s: %s - %s"
+msgstr "%s: %s - %s"
+
 #: merge.c:56
 msgid "failed to read the cache"
 msgstr "gặp lỗi khi đọc bộ nhớ tạm"
 
-#: merge.c:110 builtin/checkout.c:362 builtin/checkout.c:563
-#: builtin/clone.c:635
+#: merge.c:110 builtin/checkout.c:365 builtin/checkout.c:566
+#: builtin/clone.c:656
 msgid "unable to write new index file"
 msgstr "không thể ghi tập tin lưu bảng mục lục mới"
 
@@ -496,70 +594,70 @@
 msgid "addinfo_cache failed for path '%s'"
 msgstr "addinfo_cache gặp lỗi đối với đường dẫn “%s”"
 
-#: merge-recursive.c:268
+#: merge-recursive.c:269
 msgid "error building trees"
 msgstr "gặp lỗi khi xây dựng cây"
 
-#: merge-recursive.c:672
+#: merge-recursive.c:673
 #, c-format
 msgid "failed to create path '%s'%s"
 msgstr "gặp lỗi khi tạo đường dẫn “%s”%s"
 
-#: merge-recursive.c:683
+#: merge-recursive.c:684
 #, c-format
 msgid "Removing %s to make room for subdirectory\n"
 msgstr "Gỡ bỏ %s để tạo chỗ (room) cho thư mục con\n"
 
 #. something else exists
 #. .. but not some other error (who really cares what?)
-#: merge-recursive.c:697 merge-recursive.c:718
+#: merge-recursive.c:698 merge-recursive.c:719
 msgid ": perhaps a D/F conflict?"
 msgstr ": có lẽ là một xung đột D/F?"
 
-#: merge-recursive.c:708
+#: merge-recursive.c:709
 #, c-format
 msgid "refusing to lose untracked file at '%s'"
 msgstr "từ chối đóng tập tin không được theo vết tại “%s”"
 
-#: merge-recursive.c:748
+#: merge-recursive.c:749
 #, c-format
 msgid "cannot read object %s '%s'"
 msgstr "không thể đọc đối tượng %s “%s”"
 
-#: merge-recursive.c:750
+#: merge-recursive.c:751
 #, c-format
 msgid "blob expected for %s '%s'"
 msgstr "đối tượng blob được mong đợi cho %s “%s”"
 
-#: merge-recursive.c:773 builtin/clone.c:303
+#: merge-recursive.c:774 builtin/clone.c:312
 #, c-format
 msgid "failed to open '%s'"
 msgstr "gặp lỗi khi mở “%s”"
 
-#: merge-recursive.c:781
+#: merge-recursive.c:782
 #, c-format
 msgid "failed to symlink '%s'"
 msgstr "gặp lỗi khi tạo liên kết tượng trưng (symlink) “%s”"
 
-#: merge-recursive.c:784
+#: merge-recursive.c:785
 #, c-format
 msgid "do not know what to do with %06o %s '%s'"
 msgstr "không hiểu phải làm gì với %06o %s “%s”"
 
-#: merge-recursive.c:922
+#: merge-recursive.c:923
 msgid "Failed to execute internal merge"
 msgstr "Gặp lỗi khi thực hiện trộn nội bộ"
 
-#: merge-recursive.c:926
+#: merge-recursive.c:927
 #, c-format
 msgid "Unable to add %s to database"
 msgstr "Không thể thêm %s vào cơ sở dữ liệu"
 
-#: merge-recursive.c:942
+#: merge-recursive.c:943
 msgid "unsupported object type in the tree"
 msgstr "kiểu đối tượng không được hỗ trợ trong cây (tree)"
 
-#: merge-recursive.c:1021 merge-recursive.c:1035
+#: merge-recursive.c:1022 merge-recursive.c:1036
 #, c-format
 msgid ""
 "CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s left "
@@ -568,7 +666,7 @@
 "XUNG ĐỘT (%s/xóa): %s bị xóa trong %s và %s trong %s. Phiên bản %s của %s "
 "còn lại trong cây (tree)."
 
-#: merge-recursive.c:1027 merge-recursive.c:1040
+#: merge-recursive.c:1028 merge-recursive.c:1041
 #, c-format
 msgid ""
 "CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s left "
@@ -577,20 +675,20 @@
 "XUNG ĐỘT (%s/xóa): %s bị xóa trong %s và %s trong %s. Phiên bản %s của %s "
 "còn lại trong cây (tree) tại %s."
 
-#: merge-recursive.c:1081
+#: merge-recursive.c:1082
 msgid "rename"
 msgstr "đổi tên"
 
-#: merge-recursive.c:1081
+#: merge-recursive.c:1082
 msgid "renamed"
 msgstr "đã đổi tên"
 
-#: merge-recursive.c:1137
+#: merge-recursive.c:1138
 #, c-format
 msgid "%s is a directory in %s adding as %s instead"
 msgstr "%s là một thư mục trong %s thay vào đó thêm vào như là %s"
 
-#: merge-recursive.c:1159
+#: merge-recursive.c:1160
 #, c-format
 msgid ""
 "CONFLICT (rename/rename): Rename \"%s\"->\"%s\" in branch \"%s\" rename \"%s"
@@ -599,150 +697,173 @@
 "XUNG ĐỘT (đổi-tên/đổi-tên): Đổi tên \"%s\"->\"%s\" trong nhánh \"%s\" đổi "
 "tên \"%s\"->\"%s\" trong \"%s\"%s"
 
-#: merge-recursive.c:1164
+#: merge-recursive.c:1165
 msgid " (left unresolved)"
 msgstr " (cần giải quyết)"
 
-#: merge-recursive.c:1218
+#: merge-recursive.c:1219
 #, c-format
 msgid "CONFLICT (rename/rename): Rename %s->%s in %s. Rename %s->%s in %s"
 msgstr ""
 "XUNG ĐỘT (đổi-tên/đổi-tên): Đổi tên %s->%s trong %s. Đổi tên %s->%s trong %s"
 
-#: merge-recursive.c:1248
+#: merge-recursive.c:1249
 #, c-format
 msgid "Renaming %s to %s and %s to %s instead"
 msgstr "Đang đổi tên %s thành %s thay vì %s thành %s"
 
-#: merge-recursive.c:1447
+#: merge-recursive.c:1448
 #, c-format
 msgid "CONFLICT (rename/add): Rename %s->%s in %s. %s added in %s"
 msgstr ""
 "XUNG ĐỘT (đổi-tên/thêm): Đổi tên %s->%s trong %s. %s được thêm vào trong %s"
 
-#: merge-recursive.c:1457
+#: merge-recursive.c:1458
 #, c-format
 msgid "Adding merged %s"
 msgstr "Thêm hòa trộn %s"
 
-#: merge-recursive.c:1462 merge-recursive.c:1660
+#: merge-recursive.c:1463 merge-recursive.c:1661
 #, c-format
 msgid "Adding as %s instead"
 msgstr "Thay vào đó thêm vào %s"
 
-#: merge-recursive.c:1513
+#: merge-recursive.c:1514
 #, c-format
 msgid "cannot read object %s"
 msgstr "không thể đọc đối tượng %s"
 
-#: merge-recursive.c:1516
+#: merge-recursive.c:1517
 #, c-format
 msgid "object %s is not a blob"
 msgstr "đối tượng %s không phải là một blob"
 
-#: merge-recursive.c:1564
+#: merge-recursive.c:1565
 msgid "modify"
 msgstr "sửa đổi"
 
-#: merge-recursive.c:1564
+#: merge-recursive.c:1565
 msgid "modified"
 msgstr "đã sửa"
 
-#: merge-recursive.c:1574
+#: merge-recursive.c:1575
 msgid "content"
 msgstr "nội dung"
 
-#: merge-recursive.c:1581
+#: merge-recursive.c:1582
 msgid "add/add"
 msgstr "thêm/thêm"
 
-#: merge-recursive.c:1615
+#: merge-recursive.c:1616
 #, c-format
 msgid "Skipped %s (merged same as existing)"
 msgstr "Đã bỏ qua %s (đã có sẵn lần hòa trộn này)"
 
-#: merge-recursive.c:1629
+#: merge-recursive.c:1630
 #, c-format
 msgid "Auto-merging %s"
 msgstr "Tự-động-hòa-trộn %s"
 
-#: merge-recursive.c:1633 git-submodule.sh:1029
+#: merge-recursive.c:1634 git-submodule.sh:1118
 msgid "submodule"
 msgstr "mô-đun-con"
 
-#: merge-recursive.c:1634
+#: merge-recursive.c:1635
 #, c-format
 msgid "CONFLICT (%s): Merge conflict in %s"
 msgstr "XUNG ĐỘT (%s): Xung đột hòa trộn trong %s"
 
-#: merge-recursive.c:1724
+#: merge-recursive.c:1725
 #, c-format
 msgid "Removing %s"
 msgstr "Đang xóa %s"
 
-#: merge-recursive.c:1749
+#: merge-recursive.c:1750
 msgid "file/directory"
 msgstr "tập-tin/thư-mục"
 
-#: merge-recursive.c:1755
+#: merge-recursive.c:1756
 msgid "directory/file"
 msgstr "thư-mục/tập tin"
 
-#: merge-recursive.c:1760
+#: merge-recursive.c:1761
 #, c-format
 msgid "CONFLICT (%s): There is a directory with name %s in %s. Adding %s as %s"
 msgstr ""
 "XUNG ĐỘT (%s): Ở đây không có thư mục nào có tên %s trong %s. Thêm %s như là "
 "%s"
 
-#: merge-recursive.c:1770
+#: merge-recursive.c:1771
 #, c-format
 msgid "Adding %s"
 msgstr "Thêm \"%s\""
 
-#: merge-recursive.c:1787
+#: merge-recursive.c:1788
 msgid "Fatal merge failure, shouldn't happen."
 msgstr "Việc hòa trộn hỏng nghiêm trọng, không nên để xảy ra."
 
-#: merge-recursive.c:1806
+#: merge-recursive.c:1807
 msgid "Already up-to-date!"
 msgstr "Đã cập nhật rồi!"
 
-#: merge-recursive.c:1815
+#: merge-recursive.c:1816
 #, c-format
 msgid "merging of trees %s and %s failed"
 msgstr "hòa trộn cây (tree) %s và %s gặp lỗi"
 
-#: merge-recursive.c:1845
+#: merge-recursive.c:1846
 #, c-format
 msgid "Unprocessed path??? %s"
 msgstr "Đường dẫn chưa được xử lý??? %s"
 
-#: merge-recursive.c:1890
+#: merge-recursive.c:1891
 msgid "Merging:"
 msgstr "Đang trộn:"
 
-#: merge-recursive.c:1903
+#: merge-recursive.c:1904
 #, c-format
 msgid "found %u common ancestor:"
 msgid_plural "found %u common ancestors:"
 msgstr[0] "tìm thấy %u tổ tiên chung:"
 msgstr[1] "tìm thấy %u tổ tiên chung:"
 
-#: merge-recursive.c:1940
+#: merge-recursive.c:1941
 msgid "merge returned no commit"
 msgstr "hòa trộn không trả về lần chuyển giao (commit) nào"
 
-#: merge-recursive.c:1997
+#: merge-recursive.c:1998
 #, c-format
 msgid "Could not parse object '%s'"
 msgstr "Không thể phân tích đối tượng “%s”"
 
-#: merge-recursive.c:2009 builtin/merge.c:658
+#: merge-recursive.c:2010 builtin/merge.c:672
 msgid "Unable to write index."
 msgstr "Không thể ghi bảng mục lục"
 
-#: object.c:195
+#: notes-utils.c:40
+msgid "Cannot commit uninitialized/unreferenced notes tree"
+msgstr ""
+"Không thể chuyển giao (commit) chưa được khởi tạo hoặc không được tham chiếu "
+"cây ghi chú"
+
+#: notes-utils.c:81
+#, c-format
+msgid "Bad notes.rewriteMode value: '%s'"
+msgstr "Giá trị notes.rewriteMode sai: “%s”"
+
+#: notes-utils.c:91
+#, c-format
+msgid "Refusing to rewrite notes in %s (outside of refs/notes/)"
+msgstr "Từ chối ghi đè ghi chú trong %s (nằm ngoài của refs/notes/)"
+
+#. TRANSLATORS: The first %s is the name of the
+#. environment variable, the second %s is its value
+#: notes-utils.c:118
+#, c-format
+msgid "Bad %s value: '%s'"
+msgstr "Giá trị %s sai: “%s”"
+
+#: object.c:204
 #, c-format
 msgid "unable to parse object: %s"
 msgstr "không thể phân tích đối tượng: “%s”"
@@ -782,18 +903,18 @@
 msgid "'%s' is beyond a symbolic link"
 msgstr "“%s” nằm ngoài một liên kết tượng trưng"
 
-#: remote.c:1781
+#: remote.c:1788
 #, c-format
 msgid "Your branch is ahead of '%s' by %d commit.\n"
 msgid_plural "Your branch is ahead of '%s' by %d commits.\n"
 msgstr[0] "Nhánh của bạn là đầu của “%s” bởi %d lần chuyển giao (commit).\n"
 msgstr[1] "Nhánh của bạn là đầu của “%s” bởi %d lần chuyển giao (commit).\n"
 
-#: remote.c:1787
+#: remote.c:1794
 msgid "  (use \"git push\" to publish your local commits)\n"
 msgstr "  (dùng \"git push\" để xuất bản các lần chuyển giao nội bộ của bạn)\n"
 
-#: remote.c:1790
+#: remote.c:1797
 #, c-format
 msgid "Your branch is behind '%s' by %d commit, and can be fast-forwarded.\n"
 msgid_plural ""
@@ -805,11 +926,11 @@
 "Nhánh của bạn thì ở đằng sau “%s” bởi %d lần chuyển giao (commit), và có thể "
 "được fast-forward.\n"
 
-#: remote.c:1798
+#: remote.c:1805
 msgid "  (use \"git pull\" to update your local branch)\n"
 msgstr "  (dùng \"git pull\" để cập nhật nhánh nội bộ của bạn)\n"
 
-#: remote.c:1801
+#: remote.c:1808
 #, c-format
 msgid ""
 "Your branch and '%s' have diverged,\n"
@@ -825,20 +946,29 @@
 "Your branch and “%s” have diverged,\n"
 "and have %d and %d different commit each, respectively.\n"
 
-#: remote.c:1811
+#: remote.c:1818
 msgid "  (use \"git pull\" to merge the remote branch into yours)\n"
 msgstr ""
 "  (dùng \"git pull\" để hòa trộn nhánh trên máy chủ vào trong nhánh của "
 "bạn)\n"
 
-#: sequencer.c:206 builtin/merge.c:776 builtin/merge.c:889 builtin/merge.c:999
-#: builtin/merge.c:1009
+#: run-command.c:80
+msgid "open /dev/null failed"
+msgstr "gặp lỗi khi mở /dev/null"
+
+#: run-command.c:82
+#, c-format
+msgid "dup2(%d,%d) failed"
+msgstr "dup2(%d,%d) gặp lỗi"
+
+#: sequencer.c:206 builtin/merge.c:790 builtin/merge.c:903
+#: builtin/merge.c:1013 builtin/merge.c:1023
 #, c-format
 msgid "Could not open '%s' for writing"
 msgstr "Không thể mở “%s” để ghi"
 
-#: sequencer.c:208 builtin/merge.c:335 builtin/merge.c:779
-#: builtin/merge.c:1001 builtin/merge.c:1014
+#: sequencer.c:208 builtin/merge.c:350 builtin/merge.c:793
+#: builtin/merge.c:1015 builtin/merge.c:1028
 #, c-format
 msgid "Could not write to '%s'"
 msgstr "Không thể ghi vào “%s”"
@@ -861,7 +991,7 @@
 "với lệnh “git add <đường_dẫn>” hoặc “git rm <đường_dẫn>”\n"
 "và chuyển giao (commit) kết quả bằng lệnh “git commit”"
 
-#: sequencer.c:245 sequencer.c:859 sequencer.c:942
+#: sequencer.c:245 sequencer.c:869 sequencer.c:952
 #, c-format
 msgid "Could not write to %s"
 msgstr "Không thể ghi vào %s"
@@ -884,209 +1014,243 @@
 msgstr "Chuyển giao (commit) các thay đổi của bạn hay stash chúng để xử lý."
 
 #. TRANSLATORS: %s will be "revert" or "cherry-pick"
-#: sequencer.c:319
+#: sequencer.c:324
 #, c-format
 msgid "%s: Unable to write new index file"
 msgstr "%s: Không thể ghi tập tin lưu bảng mục lục mới"
 
-#: sequencer.c:350
+#: sequencer.c:355
 msgid "Could not resolve HEAD commit\n"
 msgstr "Không thể phân giải commit (lần chuyển giao) HEAD\n"
 
-#: sequencer.c:371
+#: sequencer.c:377
 msgid "Unable to update cache tree\n"
 msgstr "Không thể cập nhật cây bộ nhớ đệm\n"
 
-#: sequencer.c:416
+#: sequencer.c:422
 #, c-format
 msgid "Could not parse commit %s\n"
 msgstr "Không thể phân tích commit (lần chuyển giao) %s\n"
 
-#: sequencer.c:421
+#: sequencer.c:427
 #, c-format
 msgid "Could not parse parent commit %s\n"
 msgstr "Không thể phân tích commit (lần chuyển giao) cha mẹ %s\n"
 
-#: sequencer.c:487
+#: sequencer.c:493
 msgid "Your index file is unmerged."
 msgstr "Tập tin lưu mục lục của bạn không được hòa trộn."
 
-#: sequencer.c:506
+#: sequencer.c:512
 #, c-format
 msgid "Commit %s is a merge but no -m option was given."
 msgstr ""
 "Lần chuyển giao (commit) %s là một lần hòa trộn nhưng không đưa ra tùy chọn -"
 "m."
 
-#: sequencer.c:514
+#: sequencer.c:520
 #, c-format
 msgid "Commit %s does not have parent %d"
 msgstr "Lần chuyển giao (commit) %s không có cha mẹ %d"
 
-#: sequencer.c:518
+#: sequencer.c:524
 #, c-format
 msgid "Mainline was specified but commit %s is not a merge."
 msgstr ""
-"Luồng chính được chỉ ra nhưng lần chuyển giao (commit) %s không phải là một "
-"lần hòa trộn."
+"Luồng chính đã được chỉ ra nhưng lần chuyển giao (commit) %s không phải là "
+"một lần hòa trộn."
 
 #. TRANSLATORS: The first %s will be "revert" or
 #. "cherry-pick", the second %s a SHA1
-#: sequencer.c:531
+#: sequencer.c:537
 #, c-format
 msgid "%s: cannot parse parent commit %s"
 msgstr "%s: không thể phân tích lần chuyển giao mẹ của %s"
 
-#: sequencer.c:535
+#: sequencer.c:541
 #, c-format
 msgid "Cannot get commit message for %s"
 msgstr "Không thể lấy thông điệp lần chuyển giao (commit) cho %s"
 
-#: sequencer.c:621
+#: sequencer.c:627
 #, c-format
 msgid "could not revert %s... %s"
 msgstr "không thể revert %s... %s"
 
-#: sequencer.c:622
+#: sequencer.c:628
 #, c-format
 msgid "could not apply %s... %s"
 msgstr "không thể apply (áp dụng miếng vá) %s... %s"
 
-#: sequencer.c:654
+#: sequencer.c:664
 msgid "empty commit set passed"
 msgstr "lần chuyển giao (commit) trống rỗng đặt là hợp quy cách"
 
-#: sequencer.c:662
+#: sequencer.c:672
 #, c-format
 msgid "git %s: failed to read the index"
 msgstr "git %s: gặp lỗi đọc bảng mục lục"
 
-#: sequencer.c:667
+#: sequencer.c:677
 #, c-format
 msgid "git %s: failed to refresh the index"
 msgstr "git %s: gặp lỗi khi làm tươi mới bảng mục lục"
 
-#: sequencer.c:725
+#: sequencer.c:735
 #, c-format
 msgid "Cannot %s during a %s"
 msgstr "Không thể %s trong khi %s"
 
-#: sequencer.c:747
+#: sequencer.c:757
 #, c-format
 msgid "Could not parse line %d."
 msgstr "Không phân tích được dòng %d."
 
-#: sequencer.c:752
+#: sequencer.c:762
 msgid "No commits parsed."
 msgstr "Không có lần chuyển giao (commit) nào được phân tích."
 
-#: sequencer.c:765
+#: sequencer.c:775
 #, c-format
 msgid "Could not open %s"
 msgstr "Không thể mở %s"
 
-#: sequencer.c:769
+#: sequencer.c:779
 #, c-format
 msgid "Could not read %s."
 msgstr "Không thể đọc %s."
 
-#: sequencer.c:776
+#: sequencer.c:786
 #, c-format
 msgid "Unusable instruction sheet: %s"
 msgstr "Bảng chỉ thị không thể dùng được: %s"
 
-#: sequencer.c:804
+#: sequencer.c:814
 #, c-format
 msgid "Invalid key: %s"
 msgstr "Khóa không đúng: %s"
 
-#: sequencer.c:807
+#: sequencer.c:817
 #, c-format
 msgid "Invalid value for %s: %s"
 msgstr "Giá trị không hợp lệ %s: %s"
 
-#: sequencer.c:819
+#: sequencer.c:829
 #, c-format
 msgid "Malformed options sheet: %s"
 msgstr "Bảng tùy chọn dị hình: %s"
 
-#: sequencer.c:840
+#: sequencer.c:850
 msgid "a cherry-pick or revert is already in progress"
 msgstr "một thao tác cherry-pick hoặc revert đang được thực hiện"
 
-#: sequencer.c:841
+#: sequencer.c:851
 msgid "try \"git cherry-pick (--continue | --quit | --abort)\""
 msgstr "hãy thử \"git cherry-pick (--continue | --quit | --abort)\""
 
-#: sequencer.c:845
+#: sequencer.c:855
 #, c-format
 msgid "Could not create sequencer directory %s"
 msgstr "Không thể tạo thư mục xếp dãy %s"
 
-#: sequencer.c:861 sequencer.c:946
+#: sequencer.c:871 sequencer.c:956
 #, c-format
 msgid "Error wrapping up %s."
 msgstr "Lỗi bao bọc %s."
 
-#: sequencer.c:880 sequencer.c:1014
+#: sequencer.c:890 sequencer.c:1024
 msgid "no cherry-pick or revert in progress"
 msgstr "không cherry-pick hay revert trong tiến trình"
 
-#: sequencer.c:882
+#: sequencer.c:892
 msgid "cannot resolve HEAD"
 msgstr "không thể phân giải HEAD"
 
-#: sequencer.c:884
+#: sequencer.c:894
 msgid "cannot abort from a branch yet to be born"
 msgstr "không thể hủy bỏ từ một nhánh mà nó còn chưa được tạo ra"
 
-#: sequencer.c:906 builtin/apply.c:4060
+#: sequencer.c:916 builtin/apply.c:4061
 #, c-format
 msgid "cannot open %s: %s"
 msgstr "không thể mở %s: %s"
 
-#: sequencer.c:909
+#: sequencer.c:919
 #, c-format
 msgid "cannot read %s: %s"
 msgstr "không thể đọc %s: %s"
 
-#: sequencer.c:910
+#: sequencer.c:920
 msgid "unexpected end of file"
 msgstr "kết thúc tập tin đột xuất"
 
-#: sequencer.c:916
+#: sequencer.c:926
 #, c-format
 msgid "stored pre-cherry-pick HEAD file '%s' is corrupt"
 msgstr "tập tin HEAD “pre-cherry-pick” đã lưu “%s” bị hỏng"
 
-#: sequencer.c:939
+#: sequencer.c:949
 #, c-format
 msgid "Could not format %s."
 msgstr "Không thể định dạng %s."
 
-#: sequencer.c:1101
+#: sequencer.c:1092
+#, c-format
+msgid "%s: can't cherry-pick a %s"
+msgstr "%s: không thể cherry-pick một %s"
+
+#: sequencer.c:1095
+#, c-format
+msgid "%s: bad revision"
+msgstr "%s: điểm xét duyệt sai"
+
+#: sequencer.c:1129
 msgid "Can't revert as initial commit"
 msgstr "Không thể revert một lần chuyển giao (commit) khởi tạo"
 
-#: sequencer.c:1102
+#: sequencer.c:1130
 msgid "Can't cherry-pick into empty head"
 msgstr "Không thể cherry-pick vào một đầu (head) trống rỗng"
 
-#: sha1_name.c:1036
+#: sha1_name.c:440
+msgid ""
+"Git normally never creates a ref that ends with 40 hex characters\n"
+"because it will be ignored when you just specify 40-hex. These refs\n"
+"may be created by mistake. For example,\n"
+"\n"
+"  git checkout -b $br $(git rev-parse ...)\n"
+"\n"
+"where \"$br\" is somehow empty and a 40-hex ref is created. Please\n"
+"examine these refs and maybe delete them. Turn this message off by\n"
+"running \"git config advice.objectNameWarning false\""
+msgstr ""
+"Git thường không bao giờ tạo tham chiếu mà nó kết thúc với 40 ký tự hex\n"
+"bởi vì nó sẽ bị bỏ qua khi bạn chỉ định 40-hex. Những tham chiếu này\n"
+"có lẽ được tạo ra bởi một sai sót nào đó. Ví dụ,\n"
+"\n"
+"  git checkout -b $br $(git rev-parse ...)\n"
+"\n"
+"với \"$br\" không hiểu lý do vì sao trống rỗng và một tham chiếu 40-hex được "
+"tạo ra.\n"
+"Xin hãy kiểm tra những tham chiếu này và có thể xóa chúng đi. Tắt lời nhắn "
+"này\n"
+"bằng cách chạy lệnh \"git config advice.objectNameWarning false\""
+
+#: sha1_name.c:1097
 msgid "HEAD does not point to a branch"
 msgstr "HEAD không chỉ đến một nhánh nào cả"
 
-#: sha1_name.c:1039
+#: sha1_name.c:1100
 #, c-format
 msgid "No such branch: '%s'"
 msgstr "Không có nhánh nào như thế: “%s”"
 
-#: sha1_name.c:1041
+#: sha1_name.c:1102
 #, c-format
 msgid "No upstream configured for branch '%s'"
 msgstr "Không có thượng nguồn (upstream) được cấu hình cho nhánh “%s”"
 
-#: sha1_name.c:1044
+#: sha1_name.c:1106
 #, c-format
 msgid "Upstream branch '%s' not stored as a remote-tracking branch"
 msgstr ""
@@ -1098,239 +1262,239 @@
 msgid "unable to access '%s': %s"
 msgstr "không thể truy cập “%s”: %s"
 
-#: wrapper.c:423
+#: wrapper.c:429
 #, c-format
 msgid "unable to access '%s'"
 msgstr "không thể truy cập “%s”"
 
-#: wrapper.c:434
+#: wrapper.c:440
 #, c-format
 msgid "unable to look up current user in the passwd file: %s"
 msgstr "không tìm thấy người dùng hiện tại trong tập tin passwd: %s"
 
-#: wrapper.c:435
+#: wrapper.c:441
 msgid "no such user"
 msgstr "không có người dùng như vậy"
 
-#: wt-status.c:140
+#: wt-status.c:141
 msgid "Unmerged paths:"
 msgstr "Những đường dẫn chưa được hòa trộn:"
 
-#: wt-status.c:167 wt-status.c:194
+#: wt-status.c:168 wt-status.c:195
 #, c-format
 msgid "  (use \"git reset %s <file>...\" to unstage)"
 msgstr "  (dùng \"git reset %s <tập-tin>...\" để bỏ một stage (trạng thái))"
 
-#: wt-status.c:169 wt-status.c:196
+#: wt-status.c:170 wt-status.c:197
 msgid "  (use \"git rm --cached <file>...\" to unstage)"
 msgstr "  (dùng \"git rm --cached <tập-tin>...\" để bỏ trạng thái (stage))"
 
-#: wt-status.c:173
+#: wt-status.c:174
 msgid "  (use \"git add <file>...\" to mark resolution)"
 msgstr "  (dùng \"git add <tập-tin>...\" để đánh dấu là cần giải quyết)"
 
-#: wt-status.c:175 wt-status.c:179
+#: wt-status.c:176 wt-status.c:180
 msgid "  (use \"git add/rm <file>...\" as appropriate to mark resolution)"
 msgstr ""
 "  (dùng \"git add/rm <tập-tin>...\" như là một cách  thích hợp để đánh dấu "
 "là cần được giải quyết)"
 
-#: wt-status.c:177
+#: wt-status.c:178
 msgid "  (use \"git rm <file>...\" to mark resolution)"
 msgstr "  (dùng \"git rm <tập-tin>...\" để đánh dấu là cần giải quyết)"
 
-#: wt-status.c:188
+#: wt-status.c:189
 msgid "Changes to be committed:"
 msgstr "Những thay đổi sẽ được chuyển giao:"
 
-#: wt-status.c:206
+#: wt-status.c:207
 msgid "Changes not staged for commit:"
 msgstr ""
 "Các thay đổi không được đặt trạng thái (stage) cho lần chuyển giao (commit):"
 
-#: wt-status.c:210
+#: wt-status.c:211
 msgid "  (use \"git add <file>...\" to update what will be committed)"
 msgstr ""
 "  (dùng \"git add <tập-tin>...\" để cập nhật những gì cần chuyển giao "
 "(commit))"
 
-#: wt-status.c:212
+#: wt-status.c:213
 msgid "  (use \"git add/rm <file>...\" to update what will be committed)"
 msgstr ""
 "  (dùng \"git add/rm <tập-tin>...\" để cập nhật những gì sẽ được chuyển giao)"
 
-#: wt-status.c:213
+#: wt-status.c:214
 msgid ""
 "  (use \"git checkout -- <file>...\" to discard changes in working directory)"
 msgstr ""
 "  (dùng \"git checkout -- <tập-tin>...\" để bỏ thay đổi trong thư mục làm "
 "việc)"
 
-#: wt-status.c:215
+#: wt-status.c:216
 msgid "  (commit or discard the untracked or modified content in submodules)"
 msgstr ""
 "  (chuyển giao (commit) hoặc là loại bỏ các nội dung không-bị-theo-vết hay "
 "đã bị chỉnh sửa trong mô-đun-con)"
 
-#: wt-status.c:227
+#: wt-status.c:228
 #, c-format
 msgid "  (use \"git %s <file>...\" to include in what will be committed)"
 msgstr ""
 "  (dùng \"git %s <tập-tin>...\" để thêm vào những gì cần chuyển giao "
 "(commit))"
 
-#: wt-status.c:244
+#: wt-status.c:245
 msgid "bug"
 msgstr "lỗi"
 
-#: wt-status.c:249
+#: wt-status.c:250
 msgid "both deleted:"
 msgstr "bị xóa bởi cả hai:"
 
-#: wt-status.c:250
+#: wt-status.c:251
 msgid "added by us:"
 msgstr "được thêm vào bởi chúng ta:"
 
-#: wt-status.c:251
+#: wt-status.c:252
 msgid "deleted by them:"
 msgstr "bị xóa đi bởi họ:"
 
-#: wt-status.c:252
+#: wt-status.c:253
 msgid "added by them:"
 msgstr "được thêm vào bởi họ:"
 
-#: wt-status.c:253
+#: wt-status.c:254
 msgid "deleted by us:"
 msgstr "bị xóa bởi chúng ta:"
 
-#: wt-status.c:254
+#: wt-status.c:255
 msgid "both added:"
 msgstr "được thêm vào bởi cả hai:"
 
-#: wt-status.c:255
+#: wt-status.c:256
 msgid "both modified:"
 msgstr "bị sửa bởi cả hai:"
 
-#: wt-status.c:285
+#: wt-status.c:286
 msgid "new commits, "
 msgstr "lần chuyển giao (commit) mới, "
 
-#: wt-status.c:287
+#: wt-status.c:288
 msgid "modified content, "
 msgstr "nội dung bị sửa đổi, "
 
-#: wt-status.c:289
+#: wt-status.c:290
 msgid "untracked content, "
 msgstr "nội dung chưa được theo dõi, "
 
-#: wt-status.c:306
+#: wt-status.c:307
 #, c-format
 msgid "new file:   %s"
 msgstr "tập tin mới:   %s"
 
-#: wt-status.c:309
+#: wt-status.c:310
 #, c-format
 msgid "copied:     %s -> %s"
 msgstr "đã sao chép:     %s -> %s"
 
-#: wt-status.c:312
+#: wt-status.c:313
 #, c-format
 msgid "deleted:    %s"
 msgstr "đã xóa:    %s"
 
-#: wt-status.c:315
+#: wt-status.c:316
 #, c-format
 msgid "modified:   %s"
 msgstr "đã sửa đổi:   %s"
 
-#: wt-status.c:318
+#: wt-status.c:319
 #, c-format
 msgid "renamed:    %s -> %s"
 msgstr "đã đổi tên:    %s -> %s"
 
-#: wt-status.c:321
+#: wt-status.c:322
 #, c-format
 msgid "typechange: %s"
 msgstr "đổi-kiểu: %s"
 
-#: wt-status.c:324
+#: wt-status.c:325
 #, c-format
 msgid "unknown:    %s"
 msgstr "không hiểu:    %s"
 
-#: wt-status.c:327
+#: wt-status.c:328
 #, c-format
 msgid "unmerged:   %s"
 msgstr "chưa hòa trộn:   %s"
 
-#: wt-status.c:330
+#: wt-status.c:331
 #, c-format
 msgid "bug: unhandled diff status %c"
 msgstr "lỗi: không lấy được trạng thái lệnh diff %c"
 
-#: wt-status.c:805
+#: wt-status.c:803
 msgid "You have unmerged paths."
 msgstr "Bạn có những đường dẫn chưa được hòa trộn."
 
-#: wt-status.c:808 wt-status.c:960
+#: wt-status.c:806
 msgid "  (fix conflicts and run \"git commit\")"
 msgstr "  (sửa các xung đột sau đó chạy \"git commit\")"
 
-#: wt-status.c:811
+#: wt-status.c:809
 msgid "All conflicts fixed but you are still merging."
 msgstr "Tất cả các xung đột đã được giải quyết nhưng bạn vẫn đang hòa trộn."
 
-#: wt-status.c:814
+#: wt-status.c:812
 msgid "  (use \"git commit\" to conclude merge)"
 msgstr "  (dùng \"git commit\" để hoàn tất việc hòa trộn)"
 
-#: wt-status.c:824
+#: wt-status.c:822
 msgid "You are in the middle of an am session."
 msgstr "Bạn đang ở giữa của một phiên “am”."
 
-#: wt-status.c:827
+#: wt-status.c:825
 msgid "The current patch is empty."
 msgstr "Miếng vá hiện tại bị trống rỗng."
 
-#: wt-status.c:831
-msgid "  (fix conflicts and then run \"git am --resolved\")"
-msgstr "  (sửa các xung đột và sau đó chạy lệnh \"git am --resolved\")"
+#: wt-status.c:829
+msgid "  (fix conflicts and then run \"git am --continue\")"
+msgstr "  (sửa các xung đột và sau đó chạy lệnh \"git am --continue\")"
 
-#: wt-status.c:833
+#: wt-status.c:831
 msgid "  (use \"git am --skip\" to skip this patch)"
 msgstr "  (dùng \"git am --skip\" để bỏ qua miếng vá này)"
 
-#: wt-status.c:835
+#: wt-status.c:833
 msgid "  (use \"git am --abort\" to restore the original branch)"
 msgstr "  (dùng \"git am --abort\" để phục hồi lại nhánh nguyên thủy)"
 
-#: wt-status.c:895 wt-status.c:912
+#: wt-status.c:893 wt-status.c:910
 #, c-format
 msgid "You are currently rebasing branch '%s' on '%s'."
 msgstr "Bạn hiện nay đang thực hiện việc rebase nhánh “%s” trên “%s”."
 
-#: wt-status.c:900 wt-status.c:917
+#: wt-status.c:898 wt-status.c:915
 msgid "You are currently rebasing."
 msgstr "Bạn hiện nay đang thực hiện việc rebase (tái cấu trúc)."
 
-#: wt-status.c:903
+#: wt-status.c:901
 msgid "  (fix conflicts and then run \"git rebase --continue\")"
 msgstr "  (sửa các xung đột và sau đó chạy lệnh \"git rebase --continue\")"
 
-#: wt-status.c:905
+#: wt-status.c:903
 msgid "  (use \"git rebase --skip\" to skip this patch)"
 msgstr "  (dùng \"git rebase --skip\" để bỏ qua lần vá này)"
 
-#: wt-status.c:907
+#: wt-status.c:905
 msgid "  (use \"git rebase --abort\" to check out the original branch)"
 msgstr "  (dùng \"git rebase --abort\" để check-out nhánh nguyên thủy)"
 
-#: wt-status.c:920
+#: wt-status.c:918
 msgid "  (all conflicts fixed: run \"git rebase --continue\")"
 msgstr ""
 "  (khi tất cả các xung đột đã sửa xong: chạy lệnh \"git rebase --continue\")"
 
-#: wt-status.c:924
+#: wt-status.c:922
 #, c-format
 msgid ""
 "You are currently splitting a commit while rebasing branch '%s' on '%s'."
@@ -1338,48 +1502,59 @@
 "Bạn hiện nay đang thực hiện việc chia tách một lần chuyển giao (commit) "
 "trong khi đang rebase nhánh “%s” trên “%s”."
 
-#: wt-status.c:929
+#: wt-status.c:927
 msgid "You are currently splitting a commit during a rebase."
 msgstr ""
 "Bạn hiện tại đang cắt đôi một lần chuyển giao trong khi đang thực hiện việc "
 "rebase."
 
-#: wt-status.c:932
+#: wt-status.c:930
 msgid "  (Once your working directory is clean, run \"git rebase --continue\")"
 msgstr ""
 "  (Một khi thư mục làm việc của bạn đã gọn gàng, chạy \"git rebase --continue"
 "\")"
 
-#: wt-status.c:936
+#: wt-status.c:934
 #, c-format
 msgid "You are currently editing a commit while rebasing branch '%s' on '%s'."
 msgstr ""
 "Bạn hiện nay đang thực hiện việc sửa chữa một lần chuyển giao (commit) trong "
 "khi đang rebase nhánh “%s” trên “%s”."
 
-#: wt-status.c:941
+#: wt-status.c:939
 msgid "You are currently editing a commit during a rebase."
 msgstr "Bạn hiện đang sửa một lần chuyển giao trong khi bạn thực hiện rebase."
 
-#: wt-status.c:944
+#: wt-status.c:942
 msgid "  (use \"git commit --amend\" to amend the current commit)"
 msgstr ""
 "  (dùng \"git commit --amend\" để tu bổ lần chuyển giao (commit) hiện tại)"
 
-#: wt-status.c:946
+#: wt-status.c:944
 msgid ""
 "  (use \"git rebase --continue\" once you are satisfied with your changes)"
 msgstr ""
 "  (dùng \"git rebase --continue\" một khi bạn cảm thấy hài lòng về những "
 "thay đổi của mình)"
 
-#: wt-status.c:956
+#: wt-status.c:954
 msgid "You are currently cherry-picking."
 msgstr "Bạn hiện nay đang thực hiện việc cherry-pick."
 
+#: wt-status.c:958
+msgid "  (fix conflicts and run \"git cherry-pick --continue\")"
+msgstr ""
+"  (sửa các xung đột và sau đó chạy lệnh \"git cherry-pick --continue\")"
+
+#: wt-status.c:961
+msgid "  (all conflicts fixed: run \"git cherry-pick --continue\")"
+msgstr ""
+"  (khi tất cả các xung đột đã sửa xong: chạy lệnh \"git cherry-pick --"
+"continue\")"
+
 #: wt-status.c:963
-msgid "  (all conflicts fixed: run \"git commit\")"
-msgstr "  (khi tất cả các xung đột đã sửa xong: chạy lệnh \"git commit\")"
+msgid "  (use \"git cherry-pick --abort\" to cancel the cherry-pick operation)"
+msgstr "  (dùng \"git cherry-pick --abort\" để hủy bỏ thao tác cherry-pick)"
 
 #: wt-status.c:972
 #, c-format
@@ -1414,74 +1589,76 @@
 msgid "  (use \"git bisect reset\" to get back to the original branch)"
 msgstr "  (dùng \"git bisect reset\" để quay trở lại nhánh nguyên thủy)"
 
-#: wt-status.c:1175
+#: wt-status.c:1173
 msgid "On branch "
 msgstr "Trên nhánh "
 
-#: wt-status.c:1186
+#: wt-status.c:1180
+msgid "rebase in progress; onto "
+msgstr "rebase đang được thực hiện: lên trên"
+
+#: wt-status.c:1187
 msgid "HEAD detached at "
 msgstr "HEAD được tách rời tại"
 
-#: wt-status.c:1188
+#: wt-status.c:1189
 msgid "HEAD detached from "
 msgstr "HEAD được tách rời từ"
 
-#: wt-status.c:1191
+#: wt-status.c:1192
 msgid "Not currently on any branch."
 msgstr "Hiện tại chẳng ở nhánh nào cả."
 
-#: wt-status.c:1208
+#: wt-status.c:1209
 msgid "Initial commit"
 msgstr "Lần chuyển giao (commit) khởi đầu"
 
-#: wt-status.c:1222
+#: wt-status.c:1223
 msgid "Untracked files"
 msgstr "Những tập tin chưa được theo dõi"
 
-#: wt-status.c:1224
+#: wt-status.c:1225
 msgid "Ignored files"
 msgstr "Những tập tin bị lờ đi"
 
-#: wt-status.c:1228
+#: wt-status.c:1229
 #, c-format
-msgid "It took %.2f seconds to enumerate untracked files.  'status -uno'"
-msgstr "Cần %.2f giây để đếm các tập tin chưa được theo vết.  'status -uno'"
-
-#: wt-status.c:1232
-msgid "may speed it up, but you have to be careful not to forget to add"
+msgid ""
+"It took %.2f seconds to enumerate untracked files. 'status -uno'\n"
+"may speed it up, but you have to be careful not to forget to add\n"
+"new files yourself (see 'git help status')."
 msgstr ""
-"có thể làm nó nhanh lên, nhưng bạn phải cẩn trọng đừng quên thêm nó vào"
+"Cần %.2f giây để liệt kê tất cả các tập tin chưa được theo dõi. “status -"
+"uno”\n"
+"có lẽ làm nó nhanh hơn, nhưng bạn phải cẩn thận đừng quên mình phải\n"
+"tự thêm các tập tin mới (xem “git help status”.."
 
 #: wt-status.c:1235
-msgid "new files yourself (see 'git help status')."
-msgstr "tập tin mới của chính bạn (xem 'git help status')."
-
-#: wt-status.c:1238
 #, c-format
 msgid "Untracked files not listed%s"
 msgstr "Những tập tin không bị theo vết không được liệt kê ra %s"
 
-#: wt-status.c:1240
+#: wt-status.c:1237
 msgid " (use -u option to show untracked files)"
 msgstr " (dùng tùy chọn -u để hiển thị các tập tin chưa được theo dõi)"
 
-#: wt-status.c:1246
+#: wt-status.c:1243
 msgid "No changes"
 msgstr "Không có thay đổi nào"
 
-#: wt-status.c:1251
+#: wt-status.c:1248
 #, c-format
 msgid "no changes added to commit (use \"git add\" and/or \"git commit -a\")\n"
 msgstr ""
 "không có thay đổi nào được thêm vào commit (dùng \"git add\" và/hoặc \"git "
 "commit -a\")\n"
 
-#: wt-status.c:1254
+#: wt-status.c:1251
 #, c-format
 msgid "no changes added to commit\n"
 msgstr "không có thay đổi nào được thêm vào lần chuyển giao (commit)\n"
 
-#: wt-status.c:1257
+#: wt-status.c:1254
 #, c-format
 msgid ""
 "nothing added to commit but untracked files present (use \"git add\" to "
@@ -1490,58 +1667,58 @@
 "không có gì được thêm vào lần chuyển giao (commit) nhưng có những tập tin "
 "không được theo dấu vết hiện diện (dùng \"git add\" để đưa vào theo dõi)\n"
 
-#: wt-status.c:1260
+#: wt-status.c:1257
 #, c-format
 msgid "nothing added to commit but untracked files present\n"
 msgstr ""
 "không có gì được thêm vào lần chuyển giao (commit) nhưng có những tập tin "
 "không được theo dấu vết hiện diện\n"
 
-#: wt-status.c:1263
+#: wt-status.c:1260
 #, c-format
 msgid "nothing to commit (create/copy files and use \"git add\" to track)\n"
 msgstr ""
 " không có gì để commit (tạo/sao-chép các tập tin và dùng \"git add\" để theo "
 "dõi dấu vết)\n"
 
-#: wt-status.c:1266 wt-status.c:1271
+#: wt-status.c:1263 wt-status.c:1268
 #, c-format
 msgid "nothing to commit\n"
 msgstr "không có gì để chuyển giao (commit)\n"
 
-#: wt-status.c:1269
+#: wt-status.c:1266
 #, c-format
 msgid "nothing to commit (use -u to show untracked files)\n"
 msgstr ""
 "không có gì để chuyển giao (commit) (dùng -u để bỏ các tập tin cần theo dấu "
 "vết)\n"
 
-#: wt-status.c:1273
+#: wt-status.c:1270
 #, c-format
 msgid "nothing to commit, working directory clean\n"
 msgstr "không có gì để chuyển giao (commit), thư mục làm việc sạch sẽ\n"
 
-#: wt-status.c:1381
+#: wt-status.c:1378
 msgid "HEAD (no branch)"
 msgstr "HEAD (không nhánh)"
 
-#: wt-status.c:1387
+#: wt-status.c:1384
 msgid "Initial commit on "
 msgstr "Lần chuyển giao (commit) khởi tạo trên "
 
-#: wt-status.c:1402
+#: wt-status.c:1399
 msgid "behind "
 msgstr "đằng sau "
 
-#: wt-status.c:1405 wt-status.c:1408
+#: wt-status.c:1402 wt-status.c:1405
 msgid "ahead "
 msgstr "phía trước "
 
-#: wt-status.c:1410
+#: wt-status.c:1407
 msgid ", behind "
 msgstr ", đằng sau "
 
-#: compat/precompose_utf8.c:58 builtin/clone.c:342
+#: compat/precompose_utf8.c:58 builtin/clone.c:351
 #, c-format
 msgid "failed to unlink '%s'"
 msgstr "bỏ liên kết (unlink) %s không thành công"
@@ -1550,131 +1727,6 @@
 msgid "git add [options] [--] <pathspec>..."
 msgstr "git add [các-tùy-chọn] [--]  <pathspec>..."
 
-#: builtin/add.c:63
-#, c-format
-msgid "unexpected diff status %c"
-msgstr "trạng thái lệnh diff không như mong đợi %c"
-
-#: builtin/add.c:68 builtin/commit.c:233
-msgid "updating files failed"
-msgstr "Cập nhật tập tin gặp lỗi"
-
-#: builtin/add.c:78
-#, c-format
-msgid "remove '%s'\n"
-msgstr "gỡ bỏ “%s”\n"
-
-#: builtin/add.c:148
-msgid "Unstaged changes after refreshing the index:"
-msgstr ""
-"Các thay đổi không được lưu trạng thái sau khi làm tươi mới lại bảng mục lục:"
-
-#: builtin/add.c:151 builtin/add.c:460 builtin/rm.c:275
-#, c-format
-msgid "pathspec '%s' did not match any files"
-msgstr "pathspec “%s” không khớp với bất kỳ tập tin nào"
-
-#: builtin/add.c:234
-msgid "Could not read the index"
-msgstr "Không thể đọc bảng mục lục"
-
-#: builtin/add.c:244
-#, c-format
-msgid "Could not open '%s' for writing."
-msgstr "Không thể mở “%s” để ghi."
-
-#: builtin/add.c:248
-msgid "Could not write patch"
-msgstr "Không thể ghi ra miếng vá"
-
-#: builtin/add.c:253
-#, c-format
-msgid "Could not stat '%s'"
-msgstr "không thể lấy trạng thái về “%s”"
-
-#: builtin/add.c:255
-msgid "Empty patch. Aborted."
-msgstr "Miếng vá trống rỗng. Đã bỏ qua."
-
-#: builtin/add.c:261
-#, c-format
-msgid "Could not apply '%s'"
-msgstr "Không thể apply (áp dụng miếng vá) “%s”"
-
-#: builtin/add.c:271
-msgid "The following paths are ignored by one of your .gitignore files:\n"
-msgstr ""
-"Các đường dẫn theo sau đây sẽ bị lờ đi bởi một trong các tập tin .gitignore "
-"của bạn:\n"
-
-#: builtin/add.c:277 builtin/clean.c:161 builtin/fetch.c:78 builtin/mv.c:63
-#: builtin/prune-packed.c:76 builtin/push.c:425 builtin/remote.c:1253
-#: builtin/rm.c:206
-msgid "dry run"
-msgstr "chạy thử"
-
-#: builtin/add.c:278 builtin/apply.c:4409 builtin/check-ignore.c:19
-#: builtin/commit.c:1152 builtin/count-objects.c:95 builtin/fsck.c:613
-#: builtin/log.c:1514 builtin/mv.c:62 builtin/read-tree.c:112
-msgid "be verbose"
-msgstr "chi tiết"
-
-#: builtin/add.c:280
-msgid "interactive picking"
-msgstr "sửa bằng cách tương tác"
-
-#: builtin/add.c:281 builtin/checkout.c:1060 builtin/reset.c:258
-msgid "select hunks interactively"
-msgstr "chọn “hunks” một cách tương tác"
-
-#: builtin/add.c:282
-msgid "edit current diff and apply"
-msgstr "sửa diff hiện nay và áp dụng nó"
-
-#: builtin/add.c:283
-msgid "allow adding otherwise ignored files"
-msgstr "cho phép thêm các tập tin bị bỏ qua khác"
-
-#: builtin/add.c:284
-msgid "update tracked files"
-msgstr "cập nhật các tập tin được theo vết"
-
-#: builtin/add.c:285
-msgid "record only the fact that the path will be added later"
-msgstr "chỉ ghi lại sự việc mà đường dẫn sẽ được thêm vào sau"
-
-#: builtin/add.c:286
-msgid "add changes from all tracked and untracked files"
-msgstr ""
-"thêm các thay đổi từ tất cả các tập tin có cũng như không được theo dõi dấu "
-"vết"
-
-#: builtin/add.c:287
-msgid "don't add, only refresh the index"
-msgstr "không thêm, chỉ làm tươi mới bảng mục lục"
-
-#: builtin/add.c:288
-msgid "just skip files which cannot be added because of errors"
-msgstr "chie bỏ qua những tập tin mà nó không thể được thêm vào bởi vì gặp lỗi"
-
-#: builtin/add.c:289
-msgid "check if - even missing - files are ignored in dry run"
-msgstr ""
-"kiểm tra xem - thậm chí thiếu - tập tin bị bỏ qua trong quá trình chạy thử"
-
-#: builtin/add.c:311
-#, c-format
-msgid "Use -f if you really want to add them.\n"
-msgstr "Sử dụng tùy chọn -f nếu bạn thực sự muốn thêm chúng vào.\n"
-
-#: builtin/add.c:312
-msgid "no files added"
-msgstr "chưa có tập tin nào được thêm vào"
-
-#: builtin/add.c:318
-msgid "adding files failed"
-msgstr "thêm tập tin gặp lỗi"
-
 #.
 #. * To be consistent with "git add -p" and most Git
 #. * commands, we should default to being tree-wide, but
@@ -1685,7 +1737,7 @@
 #. * to tree-wide, keeping the warning for a while, and
 #. * eventually we can drop the warning.
 #.
-#: builtin/add.c:335
+#: builtin/add.c:58
 #, c-format
 msgid ""
 "The behavior of 'git add %s (or %s)' with no path argument from a\n"
@@ -1702,7 +1754,7 @@
 "  (or git add %s .)\n"
 "\n"
 "With the current Git version, the command is restricted to the current "
-"directory."
+"directory.\n"
 msgstr ""
 "Cách ứng xử của lệnh “git add %s (hay %s)” khi không có tham số đường dẫn "
 "từ\n"
@@ -1718,32 +1770,192 @@
 "  git add %s .\n"
 "  (hay git add %s .)\n"
 "\n"
-"Với phiên bản hiện tại của Git, lệnh bị hạn chế cho thư-mục hiện tại."
+"Với phiên bản hiện tại của Git, lệnh bị hạn chế cho thư-mục hiện tại.\n"
 
-#: builtin/add.c:381
+#: builtin/add.c:100
+#, c-format
+msgid ""
+"You ran 'git add' with neither '-A (--all)' or '--ignore-removal',\n"
+"whose behaviour will change in Git 2.0 with respect to paths you removed.\n"
+"Paths like '%s' that are\n"
+"removed from your working tree are ignored with this version of Git.\n"
+"\n"
+"* 'git add --ignore-removal <pathspec>', which is the current default,\n"
+"  ignores paths you removed from your working tree.\n"
+"\n"
+"* 'git add --all <pathspec>' will let you also record the removals.\n"
+"\n"
+"Run 'git status' to check the paths you removed from your working tree.\n"
+msgstr ""
+"Bạn chạy “git add” mà không có “-A (--all)” cũng không “--ignore-removal”,\n"
+"cách ứng xử của nó sẽ thay đổi kể từ Git 2.0: nó quan tâm đến các đường dẫn "
+"mà\n"
+"bạn đã gỡ bỏ. Các đường dẫn như là “%s” cái mà\n"
+"bị gỡ bỏ từ cây làm việc của bạn thì bị bỏ qua với phiên bản này của Git.\n"
+"\n"
+"* “git add --ignore-removal <pathspec>”, cái hiện tại là mặc định,\n"
+"  bỏ qua các đường dẫn bạn đã gỡ bỏ từ cây làm việc của bạn.\n"
+"\n"
+"* “git add --all <pathspec>” sẽ đồng thời giúp bạn ghi lại việc dời đi.\n"
+"\n"
+"Chạy “git status” để kiểm tra các đường dẫn bạn đã gỡ bỏ từ cây làm việc của "
+"bạn.\n"
+
+#: builtin/add.c:144
+#, c-format
+msgid "unexpected diff status %c"
+msgstr "trạng thái lệnh diff không như mong đợi %c"
+
+#: builtin/add.c:149 builtin/commit.c:252
+msgid "updating files failed"
+msgstr "Cập nhật tập tin gặp lỗi"
+
+#: builtin/add.c:163
+#, c-format
+msgid "remove '%s'\n"
+msgstr "gỡ bỏ “%s”\n"
+
+#: builtin/add.c:253
+msgid "Unstaged changes after refreshing the index:"
+msgstr ""
+"Các thay đổi không được lưu trạng thái sau khi làm tươi mới lại bảng mục lục:"
+
+#: builtin/add.c:256 builtin/add.c:573 builtin/rm.c:337
+#, c-format
+msgid "pathspec '%s' did not match any files"
+msgstr "pathspec “%s” không khớp với bất kỳ tập tin nào"
+
+#: builtin/add.c:339
+msgid "Could not read the index"
+msgstr "Không thể đọc bảng mục lục"
+
+#: builtin/add.c:350
+#, c-format
+msgid "Could not open '%s' for writing."
+msgstr "Không thể mở “%s” để ghi."
+
+#: builtin/add.c:354
+msgid "Could not write patch"
+msgstr "Không thể ghi ra miếng vá"
+
+#: builtin/add.c:359
+#, c-format
+msgid "Could not stat '%s'"
+msgstr "không thể lấy trạng thái về “%s”"
+
+#: builtin/add.c:361
+msgid "Empty patch. Aborted."
+msgstr "Miếng vá trống rỗng. Đã bỏ qua."
+
+#: builtin/add.c:367
+#, c-format
+msgid "Could not apply '%s'"
+msgstr "Không thể apply (áp dụng miếng vá) “%s”"
+
+#: builtin/add.c:377
+msgid "The following paths are ignored by one of your .gitignore files:\n"
+msgstr ""
+"Các đường dẫn theo sau đây sẽ bị lờ đi bởi một trong các tập tin .gitignore "
+"của bạn:\n"
+
+#: builtin/add.c:394 builtin/clean.c:875 builtin/fetch.c:78 builtin/mv.c:63
+#: builtin/prune-packed.c:73 builtin/push.c:451 builtin/remote.c:1253
+#: builtin/rm.c:268
+msgid "dry run"
+msgstr "chạy thử"
+
+#: builtin/add.c:395 builtin/apply.c:4410 builtin/check-ignore.c:19
+#: builtin/commit.c:1220 builtin/count-objects.c:95 builtin/fsck.c:613
+#: builtin/log.c:1573 builtin/mv.c:62 builtin/read-tree.c:113
+msgid "be verbose"
+msgstr "chi tiết"
+
+#: builtin/add.c:397
+msgid "interactive picking"
+msgstr "sửa bằng cách tương tác"
+
+#: builtin/add.c:398 builtin/checkout.c:1073 builtin/reset.c:261
+msgid "select hunks interactively"
+msgstr "chọn “hunks” một cách tương tác"
+
+#: builtin/add.c:399
+msgid "edit current diff and apply"
+msgstr "sửa diff hiện nay và áp dụng nó"
+
+#: builtin/add.c:400
+msgid "allow adding otherwise ignored files"
+msgstr "cho phép thêm các tập tin bị bỏ qua khác"
+
+#: builtin/add.c:401
+msgid "update tracked files"
+msgstr "cập nhật các tập tin được theo vết"
+
+#: builtin/add.c:402
+msgid "record only the fact that the path will be added later"
+msgstr "chỉ ghi lại sự việc mà đường dẫn sẽ được thêm vào sau"
+
+#: builtin/add.c:403
+msgid "add changes from all tracked and untracked files"
+msgstr ""
+"thêm các thay đổi từ tất cả các tập tin có cũng như không được theo dõi dấu "
+"vết"
+
+#. takes no arguments
+#: builtin/add.c:406
+msgid "ignore paths removed in the working tree (same as --no-all)"
+msgstr ""
+"lờ đi các đường dẫn bị gỡ bỏ trong cây thư mục làm việc (giống với --no-all)"
+
+#: builtin/add.c:408
+msgid "don't add, only refresh the index"
+msgstr "không thêm, chỉ làm tươi mới bảng mục lục"
+
+#: builtin/add.c:409
+msgid "just skip files which cannot be added because of errors"
+msgstr "chie bỏ qua những tập tin mà nó không thể được thêm vào bởi vì gặp lỗi"
+
+#: builtin/add.c:410
+msgid "check if - even missing - files are ignored in dry run"
+msgstr ""
+"kiểm tra xem - thậm chí thiếu - tập tin bị bỏ qua trong quá trình chạy thử"
+
+#: builtin/add.c:432
+#, c-format
+msgid "Use -f if you really want to add them.\n"
+msgstr "Sử dụng tùy chọn -f nếu bạn thực sự muốn thêm chúng vào.\n"
+
+#: builtin/add.c:433
+msgid "no files added"
+msgstr "chưa có tập tin nào được thêm vào"
+
+#: builtin/add.c:439
+msgid "adding files failed"
+msgstr "thêm tập tin gặp lỗi"
+
+#: builtin/add.c:478
 msgid "-A and -u are mutually incompatible"
 msgstr "-A và -u xung khắc nhau"
 
-#: builtin/add.c:383
+#: builtin/add.c:496
 msgid "Option --ignore-missing can only be used together with --dry-run"
 msgstr "Tùy chọn --ignore-missing chỉ có thể được dùng cùng với --dry-run"
 
-#: builtin/add.c:414
+#: builtin/add.c:526
 #, c-format
 msgid "Nothing specified, nothing added.\n"
 msgstr "Không có gì được chỉ ra, không có gì được thêm vào.\n"
 
-#: builtin/add.c:415
+#: builtin/add.c:527
 #, c-format
 msgid "Maybe you wanted to say 'git add .'?\n"
 msgstr "Có lẽ bạn muốn là “git add .” phải không?\n"
 
-#: builtin/add.c:421 builtin/check-ignore.c:67 builtin/clean.c:204
-#: builtin/commit.c:293 builtin/mv.c:82 builtin/rm.c:235
+#: builtin/add.c:533 builtin/check-ignore.c:161 builtin/clean.c:919
+#: builtin/commit.c:312 builtin/mv.c:82 builtin/rm.c:297
 msgid "index file corrupt"
 msgstr "tập tin ghi bảng mục lục bị hỏng"
 
-#: builtin/add.c:481 builtin/apply.c:4505 builtin/mv.c:229 builtin/rm.c:370
+#: builtin/add.c:605 builtin/apply.c:4506 builtin/mv.c:229 builtin/rm.c:432
 msgid "Unable to write new index file"
 msgstr "Không thể ghi tập tin lưu bảng mục lục mới"
 
@@ -1930,298 +2142,298 @@
 msgid "cannot checkout %s"
 msgstr "không thể \"checkout\" %s"
 
-#: builtin/apply.c:3140 builtin/apply.c:3149 builtin/apply.c:3193
+#: builtin/apply.c:3140 builtin/apply.c:3149 builtin/apply.c:3194
 #, c-format
 msgid "read of %s failed"
 msgstr "đọc %s gặp lỗi"
 
-#: builtin/apply.c:3173 builtin/apply.c:3395
+#: builtin/apply.c:3174 builtin/apply.c:3396
 #, c-format
 msgid "path %s has been renamed/deleted"
 msgstr "đường dẫn %s đã bị xóa/đổi tên"
 
-#: builtin/apply.c:3254 builtin/apply.c:3409
+#: builtin/apply.c:3255 builtin/apply.c:3410
 #, c-format
 msgid "%s: does not exist in index"
 msgstr "%s: không tồn tại trong bảng mục lục"
 
-#: builtin/apply.c:3258 builtin/apply.c:3401 builtin/apply.c:3423
+#: builtin/apply.c:3259 builtin/apply.c:3402 builtin/apply.c:3424
 #, c-format
 msgid "%s: %s"
 msgstr "%s: %s"
 
-#: builtin/apply.c:3263 builtin/apply.c:3417
+#: builtin/apply.c:3264 builtin/apply.c:3418
 #, c-format
 msgid "%s: does not match index"
 msgstr "%s: không khớp trong mục lục"
 
-#: builtin/apply.c:3365
+#: builtin/apply.c:3366
 msgid "removal patch leaves file contents"
 msgstr "loại bỏ miếng vá để lại nội dung tập tin"
 
-#: builtin/apply.c:3434
+#: builtin/apply.c:3435
 #, c-format
 msgid "%s: wrong type"
 msgstr "%s: sai kiểu"
 
-#: builtin/apply.c:3436
+#: builtin/apply.c:3437
 #, c-format
 msgid "%s has type %o, expected %o"
 msgstr "%s có kiểu %o, mong chờ %o"
 
-#: builtin/apply.c:3537
+#: builtin/apply.c:3538
 #, c-format
 msgid "%s: already exists in index"
 msgstr "%s: đã có từ trước trong bảng mục lục"
 
-#: builtin/apply.c:3540
+#: builtin/apply.c:3541
 #, c-format
 msgid "%s: already exists in working directory"
 msgstr "%s: đã sẵn có trong thư mục đang làm việc"
 
-#: builtin/apply.c:3560
+#: builtin/apply.c:3561
 #, c-format
 msgid "new mode (%o) of %s does not match old mode (%o)"
 msgstr "chế độ mới (%o) của %s không khớp với chế độ cũ (%o)"
 
-#: builtin/apply.c:3565
+#: builtin/apply.c:3566
 #, c-format
 msgid "new mode (%o) of %s does not match old mode (%o) of %s"
 msgstr "chế độ mới (%o) của %s không khớp với chế độ cũ (%o) của %s"
 
-#: builtin/apply.c:3573
+#: builtin/apply.c:3574
 #, c-format
 msgid "%s: patch does not apply"
 msgstr "%s: miếng vá không được áp dụng"
 
-#: builtin/apply.c:3586
+#: builtin/apply.c:3587
 #, c-format
 msgid "Checking patch %s..."
 msgstr "Đang kiểm tra miếng vá %s..."
 
-#: builtin/apply.c:3679 builtin/checkout.c:215 builtin/reset.c:124
+#: builtin/apply.c:3680 builtin/checkout.c:216 builtin/reset.c:127
 #, c-format
 msgid "make_cache_entry failed for path '%s'"
 msgstr "make_cache_entry gặp lỗi đối với đường dẫn “%s”"
 
-#: builtin/apply.c:3822
+#: builtin/apply.c:3823
 #, c-format
 msgid "unable to remove %s from index"
 msgstr "không thể gỡ bỏ %s từ mục lục"
 
-#: builtin/apply.c:3850
+#: builtin/apply.c:3851
 #, c-format
-msgid "corrupt patch for subproject %s"
-msgstr "miếng vá sai hỏng cho dự án con (subproject) %s"
+msgid "corrupt patch for submodule %s"
+msgstr "miếng vá sai hỏng cho mô-đun-con (subproject) %s"
 
-#: builtin/apply.c:3854
+#: builtin/apply.c:3855
 #, c-format
 msgid "unable to stat newly created file '%s'"
 msgstr "không thể lấy trạng thái về tập tin %s mới hơn đã được tạo"
 
-#: builtin/apply.c:3859
+#: builtin/apply.c:3860
 #, c-format
 msgid "unable to create backing store for newly created file %s"
 msgstr "không thể tạo “backing store” cho tập tin được tạo mới hơn %s"
 
-#: builtin/apply.c:3862 builtin/apply.c:3970
+#: builtin/apply.c:3863 builtin/apply.c:3971
 #, c-format
 msgid "unable to add cache entry for %s"
 msgstr "không thể thêm mục nhớ tạm cho %s"
 
-#: builtin/apply.c:3895
+#: builtin/apply.c:3896
 #, c-format
 msgid "closing file '%s'"
 msgstr "đang đóng tập tin “%s”"
 
-#: builtin/apply.c:3944
+#: builtin/apply.c:3945
 #, c-format
 msgid "unable to write file '%s' mode %o"
 msgstr "không thể ghi vào tập tin “%s” chế độ (mode) %o"
 
-#: builtin/apply.c:4031
+#: builtin/apply.c:4032
 #, c-format
 msgid "Applied patch %s cleanly."
 msgstr "Đã áp dụng miếng và %s một cách sạch sẽ."
 
-#: builtin/apply.c:4039
+#: builtin/apply.c:4040
 msgid "internal error"
 msgstr "lỗi nội bộ"
 
 #. Say this even without --verbose
-#: builtin/apply.c:4042
+#: builtin/apply.c:4043
 #, c-format
 msgid "Applying patch %%s with %d reject..."
 msgid_plural "Applying patch %%s with %d rejects..."
 msgstr[0] "Đang áp dụng miếng vá %%s với %d lần từ chối..."
 msgstr[1] "Đang áp dụng miếng vá %%s với %d lần từ chối..."
 
-#: builtin/apply.c:4052
+#: builtin/apply.c:4053
 #, c-format
 msgid "truncating .rej filename to %.*s.rej"
 msgstr "đang cắt cụt tên tập tin .rej thành %.*s.rej"
 
-#: builtin/apply.c:4073
+#: builtin/apply.c:4074
 #, c-format
 msgid "Hunk #%d applied cleanly."
 msgstr "Khối nhớ #%d được áp dụng gọn gàng."
 
-#: builtin/apply.c:4076
+#: builtin/apply.c:4077
 #, c-format
 msgid "Rejected hunk #%d."
 msgstr "hunk #%d bị từ chối."
 
-#: builtin/apply.c:4226
+#: builtin/apply.c:4227
 msgid "unrecognized input"
 msgstr "không thừa nhận đầu vào"
 
-#: builtin/apply.c:4237
+#: builtin/apply.c:4238
 msgid "unable to read index file"
 msgstr "không thể đọc tập tin lưu bảng mục lục"
 
-#: builtin/apply.c:4356 builtin/apply.c:4359 builtin/clone.c:92
+#: builtin/apply.c:4357 builtin/apply.c:4360 builtin/clone.c:91
 #: builtin/fetch.c:63
 msgid "path"
 msgstr "đường-dẫn"
 
-#: builtin/apply.c:4357
+#: builtin/apply.c:4358
 msgid "don't apply changes matching the given path"
 msgstr "không áp dụng các thay đổi khớp với đường dẫn đã cho"
 
-#: builtin/apply.c:4360
+#: builtin/apply.c:4361
 msgid "apply changes matching the given path"
 msgstr "áp dụng các thay đổi khớp với đường dẫn đã cho"
 
-#: builtin/apply.c:4362
+#: builtin/apply.c:4363
 msgid "num"
 msgstr "số"
 
-#: builtin/apply.c:4363
+#: builtin/apply.c:4364
 msgid "remove <num> leading slashes from traditional diff paths"
 msgstr "gỡ bỏ <số> phần dẫn đầu (slashe) từ đường dẫn diff cổ điển"
 
-#: builtin/apply.c:4366
+#: builtin/apply.c:4367
 msgid "ignore additions made by the patch"
 msgstr "lờ đi phần phụ thêm tạo ra bởi miếng vá"
 
-#: builtin/apply.c:4368
+#: builtin/apply.c:4369
 msgid "instead of applying the patch, output diffstat for the input"
 msgstr ""
 "thay vì áp dụng một miếng vá, kết xuất kết quả từ lệnh diffstat cho đầu ra"
 
-#: builtin/apply.c:4372
+#: builtin/apply.c:4373
 msgid "show number of added and deleted lines in decimal notation"
 msgstr ""
 "hiển thị số lượng các dòng được thêm vào và xóa đi theo ký hiệu thập phân"
 
-#: builtin/apply.c:4374
+#: builtin/apply.c:4375
 msgid "instead of applying the patch, output a summary for the input"
 msgstr "thay vì áp dụng một miếng vá, kết xuất kết quả cho đầu vào"
 
-#: builtin/apply.c:4376
+#: builtin/apply.c:4377
 msgid "instead of applying the patch, see if the patch is applicable"
 msgstr "thay vì áp dụng miếng vá, hãy xem xem miếng vá có thích hợp không"
 
-#: builtin/apply.c:4378
+#: builtin/apply.c:4379
 msgid "make sure the patch is applicable to the current index"
 msgstr "hãy chắc chắn là miếng vá thích hợp với bảng mục lục hiện hành"
 
-#: builtin/apply.c:4380
+#: builtin/apply.c:4381
 msgid "apply a patch without touching the working tree"
 msgstr "áp dụng một miếng vá mà không động chạm đến cây làm việc"
 
-#: builtin/apply.c:4382
+#: builtin/apply.c:4383
 msgid "also apply the patch (use with --stat/--summary/--check)"
 msgstr ""
 "đồng thời áp dụng miếng vá (dùng với tùy chọn --stat/--summary/--check)"
 
-#: builtin/apply.c:4384
+#: builtin/apply.c:4385
 msgid "attempt three-way merge if a patch does not apply"
 msgstr "thử hòa trộn kiểu three-way nếu việc vá không thể thực hiện được"
 
-#: builtin/apply.c:4386
+#: builtin/apply.c:4387
 msgid "build a temporary index based on embedded index information"
 msgstr ""
 "xây dựng bảng mục lục tạm thời trên cơ sở thông tin bảng mục lục được nhúng"
 
-#: builtin/apply.c:4388 builtin/checkout-index.c:197 builtin/ls-files.c:463
+#: builtin/apply.c:4389 builtin/checkout-index.c:197 builtin/ls-files.c:462
 msgid "paths are separated with NUL character"
 msgstr "các đường dẫn bị ngăn cách bởi ký tự NULL"
 
-#: builtin/apply.c:4391
+#: builtin/apply.c:4392
 msgid "ensure at least <n> lines of context match"
 msgstr "đảm bảo rằng có ít nhất <n> dòng nội dung khớp"
 
-#: builtin/apply.c:4392
+#: builtin/apply.c:4393
 msgid "action"
 msgstr "hành động"
 
-#: builtin/apply.c:4393
+#: builtin/apply.c:4394
 msgid "detect new or modified lines that have whitespace errors"
 msgstr "tìm thấy một dòng mới hoặc bị sửa đổi mà nó có lỗi do khoảng trắng"
 
-#: builtin/apply.c:4396 builtin/apply.c:4399
+#: builtin/apply.c:4397 builtin/apply.c:4400
 msgid "ignore changes in whitespace when finding context"
 msgstr "lờ đi sự thay đổi do khoảng trắng khi quét nội dung"
 
-#: builtin/apply.c:4402
+#: builtin/apply.c:4403
 msgid "apply the patch in reverse"
 msgstr "áp dụng miếng vá theo chiều ngược"
 
-#: builtin/apply.c:4404
+#: builtin/apply.c:4405
 msgid "don't expect at least one line of context"
 msgstr "đừng hy vọng có ít nhất một dòng nội dung"
 
-#: builtin/apply.c:4406
+#: builtin/apply.c:4407
 msgid "leave the rejected hunks in corresponding *.rej files"
 msgstr "để lại khối dữ liệu bị từ chối trong các tập tin *.rej tương ứng"
 
-#: builtin/apply.c:4408
+#: builtin/apply.c:4409
 msgid "allow overlapping hunks"
 msgstr "cho phép chồng khối nhớ"
 
-#: builtin/apply.c:4411
+#: builtin/apply.c:4412
 msgid "tolerate incorrectly detected missing new-line at the end of file"
 msgstr ""
 "đã dò tìm thấy dung sai không chính xác thiếu dòng mới tại cuối tập tin"
 
-#: builtin/apply.c:4414
+#: builtin/apply.c:4415
 msgid "do not trust the line counts in the hunk headers"
 msgstr "không tin số lượng dòng trong phần đầu khối dữ liệu"
 
-#: builtin/apply.c:4416
+#: builtin/apply.c:4417
 msgid "root"
 msgstr "root"
 
-#: builtin/apply.c:4417
+#: builtin/apply.c:4418
 msgid "prepend <root> to all filenames"
 msgstr "treo thêm <root> vào tất cả các tên tập tin"
 
-#: builtin/apply.c:4439
+#: builtin/apply.c:4440
 msgid "--3way outside a repository"
 msgstr "--3way ở ngoài một kho chứa"
 
-#: builtin/apply.c:4447
+#: builtin/apply.c:4448
 msgid "--index outside a repository"
 msgstr "--index ở ngoài một kho chứa"
 
-#: builtin/apply.c:4450
+#: builtin/apply.c:4451
 msgid "--cached outside a repository"
 msgstr "--cached ở ngoài một kho chứa"
 
-#: builtin/apply.c:4466
+#: builtin/apply.c:4467
 #, c-format
 msgid "can't open patch '%s'"
 msgstr "không thể mở miếng vá “%s”"
 
-#: builtin/apply.c:4480
+#: builtin/apply.c:4481
 #, c-format
 msgid "squelched %d whitespace error"
 msgid_plural "squelched %d whitespace errors"
 msgstr[0] "đã chấm dứt %d lỗi khoảng trắng"
 msgstr[1] "đã chấm dứt %d lỗi khoảng trắng"
 
-#: builtin/apply.c:4486 builtin/apply.c:4496
+#: builtin/apply.c:4487 builtin/apply.c:4497
 #, c-format
 msgid "%d line adds whitespace errors."
 msgid_plural "%d lines add whitespace errors."
@@ -2277,105 +2489,105 @@
 "cập nhật BISECT_HEAD thay vì lấy ra (checking out) lần chuyển giao (commit) "
 "hiện hành"
 
-#: builtin/blame.c:25
+#: builtin/blame.c:26
 msgid "git blame [options] [rev-opts] [rev] [--] file"
 msgstr "git blame [các-tùy-chọn] [rev-opts] [rev] [--] tập-tin"
 
-#: builtin/blame.c:30 builtin/shortlog.c:15
+#: builtin/blame.c:31
 msgid "[rev-opts] are documented in git-rev-list(1)"
 msgstr "[rev-opts] được mô tả trong git-rev-list(1)"
 
-#: builtin/blame.c:2350
+#: builtin/blame.c:2276
 msgid "Show blame entries as we find them, incrementally"
 msgstr "Hiển thị các mục “blame” như là chúng ta thấy chúng, tăng dần"
 
-#: builtin/blame.c:2351
+#: builtin/blame.c:2277
 msgid "Show blank SHA-1 for boundary commits (Default: off)"
 msgstr ""
 "Hiển thị SHA-1 trắng cho những lần chuyển giao biên giới (Mặc định: off)"
 
-#: builtin/blame.c:2352
+#: builtin/blame.c:2278
 msgid "Do not treat root commits as boundaries (Default: off)"
 msgstr "Không coi các lần chuyển giao gốc là giới hạn (Mặc định: off)"
 
-#: builtin/blame.c:2353
+#: builtin/blame.c:2279
 msgid "Show work cost statistics"
 msgstr "Hiển thị thống kê công sức làm việc"
 
-#: builtin/blame.c:2354
+#: builtin/blame.c:2280
 msgid "Show output score for blame entries"
 msgstr "Hiển thị kết xuất điểm số có các mục tin “blame”"
 
-#: builtin/blame.c:2355
+#: builtin/blame.c:2281
 msgid "Show original filename (Default: auto)"
 msgstr "Hiển thị tên tập tin gốc (Mặc định: auto)"
 
-#: builtin/blame.c:2356
+#: builtin/blame.c:2282
 msgid "Show original linenumber (Default: off)"
 msgstr "Hiển thị số dòng gốc (Mặc định: off)"
 
-#: builtin/blame.c:2357
+#: builtin/blame.c:2283
 msgid "Show in a format designed for machine consumption"
 msgstr "Hiển thị ở định dạng đã thiết kế cho sự tiêu dùng bằng máy"
 
-#: builtin/blame.c:2358
+#: builtin/blame.c:2284
 msgid "Show porcelain format with per-line commit information"
 msgstr "Hiển thị định dạng “porcelain” với thông tin chuyển giao mỗi dòng"
 
-#: builtin/blame.c:2359
+#: builtin/blame.c:2285
 msgid "Use the same output mode as git-annotate (Default: off)"
 msgstr "Dùng cùng chế độ xuất ra vóigit-annotate (Mặc định: off)"
 
-#: builtin/blame.c:2360
+#: builtin/blame.c:2286
 msgid "Show raw timestamp (Default: off)"
 msgstr "Hiển thị dấu vết thời gian dạng thô (Mặc định: off)"
 
-#: builtin/blame.c:2361
+#: builtin/blame.c:2287
 msgid "Show long commit SHA1 (Default: off)"
 msgstr "Hiển thị SHA1 của lần chuyển giao (commit) dạng dài (Mặc định: off)"
 
-#: builtin/blame.c:2362
+#: builtin/blame.c:2288
 msgid "Suppress author name and timestamp (Default: off)"
 msgstr "Không hiển thị tên tác giả và dấu vết thời gian (Mặc định: off)"
 
-#: builtin/blame.c:2363
+#: builtin/blame.c:2289
 msgid "Show author email instead of name (Default: off)"
 msgstr "Hiển thị thư điện tử của tác giả thay vì tên (Mặc định: off)"
 
-#: builtin/blame.c:2364
+#: builtin/blame.c:2290
 msgid "Ignore whitespace differences"
 msgstr "Bỏ qua các khác biệt do khoảng trắng gây ra"
 
-#: builtin/blame.c:2365
+#: builtin/blame.c:2291
 msgid "Spend extra cycles to find better match"
 msgstr "Tiêu thụ thêm năng tài nguyên máy móc để tìm kiếm tốt hơn nữa"
 
-#: builtin/blame.c:2366
+#: builtin/blame.c:2292
 msgid "Use revisions from <file> instead of calling git-rev-list"
 msgstr ""
 "Sử dụng điểm xét duyệt (revision) từ <tập tin> thay vì gọi “git-rev-list”"
 
-#: builtin/blame.c:2367
+#: builtin/blame.c:2293
 msgid "Use <file>'s contents as the final image"
 msgstr "Sử dụng nội dung của <tập tin> như là ảnh cuối cùng"
 
-#: builtin/blame.c:2368 builtin/blame.c:2369
+#: builtin/blame.c:2294 builtin/blame.c:2295
 msgid "score"
 msgstr "điểm số"
 
-#: builtin/blame.c:2368
+#: builtin/blame.c:2294
 msgid "Find line copies within and across files"
 msgstr "Tìm các bản sao chép dòng trong và ngang qua tập tin"
 
-#: builtin/blame.c:2369
+#: builtin/blame.c:2295
 msgid "Find line movements within and across files"
 msgstr "Tìm các di chuyển dòng trong và ngang qua tập tin"
 
-#: builtin/blame.c:2370
+#: builtin/blame.c:2296
 msgid "n,m"
 msgstr "n,m"
 
-#: builtin/blame.c:2370
+#: builtin/blame.c:2296
 msgid "Process only line range n,m, counting from 1"
 msgstr "Xử lý chỉ dòng vùng n,m, tính từ 1"
 
@@ -2395,7 +2607,7 @@
 msgid "git branch [options] (-m | -M) [<oldbranch>] <newbranch>"
 msgstr "git branch [các-tùy-chọn] (-m | -M) [<nhánh-cũ>] <nhánh-mới>"
 
-#: builtin/branch.c:146
+#: builtin/branch.c:150
 #, c-format
 msgid ""
 "deleting branch '%s' that has been merged to\n"
@@ -2404,7 +2616,7 @@
 "đang xóa nhánh “%s” mà nó lại đã được hòa trộn vào\n"
 "         “%s”, nhưng vẫn chưa được hòa trộn vào HEAD."
 
-#: builtin/branch.c:150
+#: builtin/branch.c:154
 #, c-format
 msgid ""
 "not deleting branch '%s' that is not yet merged to\n"
@@ -2413,12 +2625,12 @@
 "không xóa nhánh “%s” cái mà chưa được hòa trộn vào\n"
 "         “%s”, cho dù là nó đã được hòa trộn vào HEAD."
 
-#: builtin/branch.c:164
+#: builtin/branch.c:168
 #, c-format
 msgid "Couldn't look up commit object for '%s'"
 msgstr "Không thể tìm kiếm đối tượng chuyển giao (commit) cho “%s”"
 
-#: builtin/branch.c:168
+#: builtin/branch.c:172
 #, c-format
 msgid ""
 "The branch '%s' is not fully merged.\n"
@@ -2427,290 +2639,290 @@
 "Nhánh “%s” không được trộn một cách đầy đủ.\n"
 "Nếu bạn thực sự muốn xóa nó, thì chạy lệnh “git branch -D %s”."
 
-#: builtin/branch.c:181
+#: builtin/branch.c:185
 msgid "Update of config-file failed"
 msgstr "Cập nhật tập tin cấu hình gặp lỗi"
 
-#: builtin/branch.c:209
+#: builtin/branch.c:213
 msgid "cannot use -a with -d"
 msgstr "không thể dùng tùy chọn -a với -d"
 
-#: builtin/branch.c:215
+#: builtin/branch.c:219
 msgid "Couldn't look up commit object for HEAD"
 msgstr "Không thể tìm kiếm đối tượng chuyển giao (commit) cho HEAD"
 
-#: builtin/branch.c:223
+#: builtin/branch.c:227
 #, c-format
 msgid "Cannot delete the branch '%s' which you are currently on."
 msgstr "Không thể xóa nhánh “%s” cái mà bạn hiện nay đang ở."
 
-#: builtin/branch.c:236
+#: builtin/branch.c:240
 #, c-format
 msgid "remote branch '%s' not found."
 msgstr "không tìm thấy nhánh máy chủ “%s”."
 
-#: builtin/branch.c:237
+#: builtin/branch.c:241
 #, c-format
 msgid "branch '%s' not found."
 msgstr "không tìm thấy nhánh “%s”."
 
-#: builtin/branch.c:251
+#: builtin/branch.c:255
 #, c-format
 msgid "Error deleting remote branch '%s'"
 msgstr "Gặp lỗi khi đang xóa nhánh trên máy chủ “%s”"
 
-#: builtin/branch.c:252
+#: builtin/branch.c:256
 #, c-format
 msgid "Error deleting branch '%s'"
 msgstr "Lỗi khi xoá bỏ nhánh “%s”"
 
-#: builtin/branch.c:259
+#: builtin/branch.c:263
 #, c-format
 msgid "Deleted remote branch %s (was %s).\n"
 msgstr "Nhánh trên máy chủ \"%s\" đã bị xóa (từng là %s).\n"
 
-#: builtin/branch.c:260
+#: builtin/branch.c:264
 #, c-format
 msgid "Deleted branch %s (was %s).\n"
 msgstr "Nhánh “%s” đã bị xóa (từng là %s)\n"
 
-#: builtin/branch.c:362
+#: builtin/branch.c:366
 #, c-format
 msgid "branch '%s' does not point at a commit"
 msgstr "nhánh “%s” không chỉ đến một lần chuyển giao (commit) nào cả"
 
-#: builtin/branch.c:434
+#: builtin/branch.c:453
 #, c-format
 msgid "[%s: behind %d]"
 msgstr "[%s: đằng sau %d]"
 
-#: builtin/branch.c:436
+#: builtin/branch.c:455
 #, c-format
 msgid "[behind %d]"
 msgstr "[đằng sau %d]"
 
-#: builtin/branch.c:440
+#: builtin/branch.c:459
 #, c-format
 msgid "[%s: ahead %d]"
 msgstr "[%s: phía trước %d]"
 
-#: builtin/branch.c:442
+#: builtin/branch.c:461
 #, c-format
 msgid "[ahead %d]"
 msgstr "[phía trước %d]"
 
-#: builtin/branch.c:445
+#: builtin/branch.c:464
 #, c-format
 msgid "[%s: ahead %d, behind %d]"
 msgstr "[%s: trước %d, sau %d]"
 
-#: builtin/branch.c:448
+#: builtin/branch.c:467
 #, c-format
 msgid "[ahead %d, behind %d]"
 msgstr "[trước %d, sau %d]"
 
-#: builtin/branch.c:470
+#: builtin/branch.c:490
 msgid " **** invalid ref ****"
 msgstr " **** tham chiếu sai ****"
 
-#: builtin/branch.c:562
+#: builtin/branch.c:582
 #, c-format
 msgid "(no branch, rebasing %s)"
 msgstr "(không nhánh, đang rebase %s)"
 
-#: builtin/branch.c:565
+#: builtin/branch.c:585
 #, c-format
 msgid "(no branch, bisect started on %s)"
 msgstr "(không nhánh, bisect được bắt đầu tại %s)"
 
-#: builtin/branch.c:568
+#: builtin/branch.c:588
 #, c-format
 msgid "(detached from %s)"
 msgstr "(được tách rời từ %s)"
 
-#: builtin/branch.c:571
+#: builtin/branch.c:591
 msgid "(no branch)"
 msgstr "(không nhánh)"
 
-#: builtin/branch.c:617
+#: builtin/branch.c:637
 #, c-format
 msgid "object '%s' does not point to a commit"
 msgstr "đối tượng “%s” không chỉ đến một lần chuyển giao (commit) nào cả"
 
-#: builtin/branch.c:649
+#: builtin/branch.c:669
 msgid "some refs could not be read"
 msgstr "một số tham chiếu đã không thể đọc được"
 
-#: builtin/branch.c:662
+#: builtin/branch.c:682
 msgid "cannot rename the current branch while not on any."
 msgstr "không thể đổi tên nhánh hiện hành trong khi nó chẳng ở đâu cả."
 
-#: builtin/branch.c:672
+#: builtin/branch.c:692
 #, c-format
 msgid "Invalid branch name: '%s'"
 msgstr "Sai tên nhánh: “%s”"
 
-#: builtin/branch.c:687
+#: builtin/branch.c:707
 msgid "Branch rename failed"
 msgstr "Đổi tên nhánh gặp lỗi"
 
-#: builtin/branch.c:691
+#: builtin/branch.c:711
 #, c-format
 msgid "Renamed a misnamed branch '%s' away"
 msgstr "Đã đổi tên nhánh khuyết danh “%s” đi"
 
-#: builtin/branch.c:695
+#: builtin/branch.c:715
 #, c-format
 msgid "Branch renamed to %s, but HEAD is not updated!"
 msgstr "Nhánh bị đổi tên thành %s, nhưng HEAD lại không được cập nhật!"
 
-#: builtin/branch.c:702
+#: builtin/branch.c:722
 msgid "Branch is renamed, but update of config-file failed"
 msgstr "Nhánh bị đổi tên, nhưng cập nhật tập tin cấu hình gặp lỗi"
 
-#: builtin/branch.c:717
+#: builtin/branch.c:737
 #, c-format
 msgid "malformed object name %s"
 msgstr "tên đối tượng dị hình %s"
 
-#: builtin/branch.c:741
+#: builtin/branch.c:761
 #, c-format
 msgid "could not write branch description template: %s"
 msgstr "không thể ghi vào mẫu mô tả nhánh: %s"
 
-#: builtin/branch.c:771
+#: builtin/branch.c:791
 msgid "Generic options"
 msgstr "Tùy chọn chung"
 
-#: builtin/branch.c:773
+#: builtin/branch.c:793
 msgid "show hash and subject, give twice for upstream branch"
 msgstr "hiển thị mã băm và chủ đề, đưa ra hai lần cho nhánh thượng nguồn"
 
-#: builtin/branch.c:774
+#: builtin/branch.c:794
 msgid "suppress informational messages"
 msgstr "Thu hồi các thông điệp thông tin"
 
-#: builtin/branch.c:775
+#: builtin/branch.c:795
 msgid "set up tracking mode (see git-pull(1))"
 msgstr "cài đặt chế độ theo vết (xem git-pull(1))"
 
-#: builtin/branch.c:777
+#: builtin/branch.c:797
 msgid "change upstream info"
 msgstr "thay đổi thông tin thượng nguồn (upstream)"
 
-#: builtin/branch.c:781
+#: builtin/branch.c:801
 msgid "use colored output"
 msgstr "sử dụng kết xuất có tô màu"
 
-#: builtin/branch.c:782
+#: builtin/branch.c:802
 msgid "act on remote-tracking branches"
 msgstr "thao tác trên nhánh “remote-tracking”"
 
-#: builtin/branch.c:785 builtin/branch.c:791 builtin/branch.c:812
-#: builtin/branch.c:818 builtin/commit.c:1368 builtin/commit.c:1369
-#: builtin/commit.c:1370 builtin/commit.c:1371 builtin/tag.c:468
+#: builtin/branch.c:805 builtin/branch.c:811 builtin/branch.c:832
+#: builtin/branch.c:838 builtin/commit.c:1433 builtin/commit.c:1434
+#: builtin/commit.c:1435 builtin/commit.c:1436 builtin/tag.c:468
 msgid "commit"
 msgstr "commit"
 
-#: builtin/branch.c:786 builtin/branch.c:792
+#: builtin/branch.c:806 builtin/branch.c:812
 msgid "print only branches that contain the commit"
 msgstr "chỉ hiển thị những nhánh mà nó chứa lần chuyển giao"
 
-#: builtin/branch.c:798
+#: builtin/branch.c:818
 msgid "Specific git-branch actions:"
 msgstr "Hành động git-branch:"
 
-#: builtin/branch.c:799
+#: builtin/branch.c:819
 msgid "list both remote-tracking and local branches"
 msgstr "liệt kê cả nhánh “remote-tracking” và nội bộ"
 
-#: builtin/branch.c:801
+#: builtin/branch.c:821
 msgid "delete fully merged branch"
 msgstr "xóa một cách đầy đủ nhánh đã hòa trộn"
 
-#: builtin/branch.c:802
+#: builtin/branch.c:822
 msgid "delete branch (even if not merged)"
 msgstr "xoá nhánh (cho dù là chưa được hòa trộn)"
 
-#: builtin/branch.c:803
+#: builtin/branch.c:823
 msgid "move/rename a branch and its reflog"
 msgstr "di chuyển hay đổi tên một nhánh và reflog của nó"
 
-#: builtin/branch.c:804
+#: builtin/branch.c:824
 msgid "move/rename a branch, even if target exists"
 msgstr "di chuyển hoặc đổi tên một nhánh, thậm chí cả khi đích đã có sẵn"
 
-#: builtin/branch.c:805
+#: builtin/branch.c:825
 msgid "list branch names"
 msgstr "liệt kê các tên nhánh"
 
-#: builtin/branch.c:806
+#: builtin/branch.c:826
 msgid "create the branch's reflog"
 msgstr "tạo reflog của nhánh"
 
-#: builtin/branch.c:808
+#: builtin/branch.c:828
 msgid "edit the description for the branch"
 msgstr "sửa mô tả cho nhánh"
 
-#: builtin/branch.c:809
+#: builtin/branch.c:829
 msgid "force creation (when already exists)"
 msgstr "ép buộc tạo (khi đã sẵn tồn tại rồi)"
 
-#: builtin/branch.c:812
+#: builtin/branch.c:832
 msgid "print only not merged branches"
 msgstr "chỉ hiển thị các nhánh chưa được hòa trộn"
 
-#: builtin/branch.c:818
+#: builtin/branch.c:838
 msgid "print only merged branches"
 msgstr "chỉ hiển thị các nhánh được hòa trộn"
 
-#: builtin/branch.c:822
+#: builtin/branch.c:842
 msgid "list branches in columns"
 msgstr "liệt kê các nhánh trong các cột"
 
-#: builtin/branch.c:835
+#: builtin/branch.c:855
 msgid "Failed to resolve HEAD as a valid ref."
 msgstr "Gặp lỗi khi phân giải HEAD như là một tham chiếu (ref) hợp lệ."
 
-#: builtin/branch.c:840 builtin/clone.c:609
+#: builtin/branch.c:860 builtin/clone.c:630
 msgid "HEAD not found below refs/heads!"
 msgstr "không tìm thấy HEAD ở dưới refs/heads!"
 
-#: builtin/branch.c:863
+#: builtin/branch.c:883
 msgid "--column and --verbose are incompatible"
 msgstr "--column và --verbose xung khắc nhau"
 
-#: builtin/branch.c:869 builtin/branch.c:908
+#: builtin/branch.c:889 builtin/branch.c:928
 msgid "branch name required"
 msgstr "cần tên nhánh"
 
-#: builtin/branch.c:884
+#: builtin/branch.c:904
 msgid "Cannot give description to detached HEAD"
 msgstr "Không thể đưa ra mô tả HEAD đã tách rời"
 
-#: builtin/branch.c:889
+#: builtin/branch.c:909
 msgid "cannot edit description of more than one branch"
 msgstr "không thể sửa mô tả cho nhiều hơn một nhánh"
 
-#: builtin/branch.c:896
+#: builtin/branch.c:916
 #, c-format
 msgid "No commit on branch '%s' yet."
 msgstr "Vẫn chưa chuyển giao trên nhánh “%s”."
 
-#: builtin/branch.c:899
+#: builtin/branch.c:919
 #, c-format
 msgid "No branch named '%s'."
 msgstr "Không có nhánh nào có tên “%s”."
 
-#: builtin/branch.c:914
+#: builtin/branch.c:934
 msgid "too many branches for a rename operation"
 msgstr "quá nhiều nhánh dành cho thao tác đổi tên"
 
-#: builtin/branch.c:919
+#: builtin/branch.c:939
 msgid "too many branches to set new upstream"
 msgstr "quá nhiều nhánh được đặt cho dòng ngược (upstream) mới"
 
-#: builtin/branch.c:923
+#: builtin/branch.c:943
 #, c-format
 msgid ""
 "could not set upstream of HEAD to %s when it does not point to any branch."
@@ -2718,42 +2930,42 @@
 "không thể đặt dòng ngược (upstream) của HEAD thành %s khi mà nó chẳng chỉ "
 "đến nhánh nào cả."
 
-#: builtin/branch.c:926 builtin/branch.c:948 builtin/branch.c:970
+#: builtin/branch.c:946 builtin/branch.c:968 builtin/branch.c:990
 #, c-format
 msgid "no such branch '%s'"
 msgstr "không có nhánh nào như thế “%s”"
 
-#: builtin/branch.c:930
+#: builtin/branch.c:950
 #, c-format
 msgid "branch '%s' does not exist"
 msgstr "nhánh “%s” chưa sẵn có"
 
-#: builtin/branch.c:942
+#: builtin/branch.c:962
 msgid "too many branches to unset upstream"
 msgstr "quá nhiều nhánh để bỏ đặt ngược dòng (upstream)"
 
-#: builtin/branch.c:946
+#: builtin/branch.c:966
 msgid "could not unset upstream of HEAD when it does not point to any branch."
 msgstr ""
 "không thể bỏ đặt ngược dòng (upstream) của HEAD không chỉ đến một nhánh nào "
 "cả."
 
-#: builtin/branch.c:952
+#: builtin/branch.c:972
 #, c-format
 msgid "Branch '%s' has no upstream information"
 msgstr "Nhánh “%s” không có thông tin thượng nguồn (upstream)"
 
-#: builtin/branch.c:967
+#: builtin/branch.c:987
 msgid "it does not make sense to create 'HEAD' manually"
-msgstr "không hợp lý khi tạo 'HEAD' thủ công "
+msgstr "không hợp lý khi tạo “HEAD” thủ công "
 
-#: builtin/branch.c:973
+#: builtin/branch.c:993
 msgid "-a and -r options to 'git branch' do not make sense with a branch name"
 msgstr ""
 "hai tùy chọn -a và -r áp dụng cho lệnh “git branch” không hợp lý đối với tên "
 "nhánh"
 
-#: builtin/branch.c:976
+#: builtin/branch.c:996
 #, c-format
 msgid ""
 "The --set-upstream flag is deprecated and will be removed. Consider using --"
@@ -2762,7 +2974,7 @@
 "Cờ --set-upstream bị phản đối và sẽ bị xóa bỏ. Nên dùng --track hoặc --set-"
 "upstream-to\n"
 
-#: builtin/branch.c:993
+#: builtin/branch.c:1013
 #, c-format
 msgid ""
 "\n"
@@ -2773,12 +2985,12 @@
 "Nếu bạn muốn “%s” theo dõi “%s”, thực hiện lệnh sau:\n"
 "\n"
 
-#: builtin/branch.c:994
+#: builtin/branch.c:1014
 #, c-format
 msgid "    git branch -d %s\n"
 msgstr "    git branch -d %s\n"
 
-#: builtin/branch.c:995
+#: builtin/branch.c:1015
 #, c-format
 msgid "    git branch --set-upstream-to %s\n"
 msgstr "    git branch --set-upstream-to %s\n"
@@ -2796,44 +3008,44 @@
 msgid "Need a repository to unbundle."
 msgstr "Cần một kho chứa để mà bung một bundle."
 
-#: builtin/cat-file.c:247
+#: builtin/cat-file.c:285
 msgid "git cat-file (-t|-s|-e|-p|<type>|--textconv) <object>"
 msgstr "git cat-file (-t|-s|-e|-p|<kiểu>|--textconv) <đối tượng>"
 
-#: builtin/cat-file.c:248
+#: builtin/cat-file.c:286
 msgid "git cat-file (--batch|--batch-check) < <list_of_objects>"
 msgstr "git cat-file (--batch|--batch-check) < <danh-sách-đối-tượng>"
 
-#: builtin/cat-file.c:266
+#: builtin/cat-file.c:323
 msgid "<type> can be one of: blob, tree, commit, tag"
 msgstr "<kiểu> là một trong số: blob, tree, commit, tag"
 
-#: builtin/cat-file.c:267
+#: builtin/cat-file.c:324
 msgid "show object type"
 msgstr "hiển thị kiểu đối tượng"
 
-#: builtin/cat-file.c:268
+#: builtin/cat-file.c:325
 msgid "show object size"
 msgstr "hiển thị kích thước đối tượng"
 
-#: builtin/cat-file.c:270
+#: builtin/cat-file.c:327
 msgid "exit with zero when there's no error"
 msgstr "thoát với 0 khi không có lỗi"
 
-#: builtin/cat-file.c:271
+#: builtin/cat-file.c:328
 msgid "pretty-print object's content"
 msgstr "in nội dung đối tượng dạng dễ đọc"
 
-#: builtin/cat-file.c:273
+#: builtin/cat-file.c:330
 msgid "for blob objects, run textconv on object's content"
 msgstr "với đối tượng blob, chạy lệnh textconv trên nội dung của đối tượng"
 
-#: builtin/cat-file.c:275
+#: builtin/cat-file.c:332
 msgid "show info and content of objects fed from the standard input"
 msgstr ""
 "hiển thị thông tin và nội dung của các đối tượng lấy từ đầu vào tiêu chuẩn"
 
-#: builtin/cat-file.c:278
+#: builtin/cat-file.c:335
 msgid "show info about objects fed from the standard input"
 msgstr "hiển thị các thông tin về đối tượng fed  từ đầu vào tiêu chuẩn"
 
@@ -2862,30 +3074,55 @@
 msgid "input paths are terminated by a null character"
 msgstr "các đường dẫn được  ngăn cách bởi ký tự null"
 
-#: builtin/check-ignore.c:18 builtin/checkout.c:1041 builtin/gc.c:177
+#: builtin/check-ignore.c:18 builtin/checkout.c:1054 builtin/gc.c:177
 msgid "suppress progress reporting"
 msgstr "chặn các báo cáo tiến trình hoạt động"
 
-#: builtin/check-ignore.c:151
+#: builtin/check-ignore.c:26
+msgid "show non-matching input paths"
+msgstr "hiển thị những đường dẫn đầu vào không khớp với mẫu"
+
+#: builtin/check-ignore.c:143
 msgid "cannot specify pathnames with --stdin"
 msgstr "không thể chỉ định các tên đường dẫn với --stdin"
 
-#: builtin/check-ignore.c:154
+#: builtin/check-ignore.c:146
 msgid "-z only makes sense with --stdin"
 msgstr "-z chỉ hợp lý với --stdin"
 
-#: builtin/check-ignore.c:156
+#: builtin/check-ignore.c:148
 msgid "no path specified"
 msgstr "chưa ghi rõ đường dẫn"
 
-#: builtin/check-ignore.c:160
+#: builtin/check-ignore.c:152
 msgid "--quiet is only valid with a single pathname"
 msgstr "--quiet chỉ hợp lệ với tên đường dẫn đơn"
 
-#: builtin/check-ignore.c:162
+#: builtin/check-ignore.c:154
 msgid "cannot have both --quiet and --verbose"
 msgstr "không thể dùng cả hai tùy chọn --quiet và --verbose"
 
+#: builtin/check-ignore.c:157
+msgid "--non-matching is only valid with --verbose"
+msgstr "tùy-chọn --non-matching chỉ hợp lệ khi dùng với --verbose"
+
+#: builtin/check-mailmap.c:8
+msgid "git check-mailmap [options] <contact>..."
+msgstr "git check-mailmap [các-tùy-chọn] <danh-bạ>..."
+
+#: builtin/check-mailmap.c:13
+msgid "also read contacts from stdin"
+msgstr "đồng thời đọc các danh bạ từ đầu vào tiêu chuẩn"
+
+#: builtin/check-mailmap.c:24
+#, c-format
+msgid "unable to parse contact: %s"
+msgstr "không thể phân tích danh bạ: “%s”"
+
+#: builtin/check-mailmap.c:47
+msgid "no contacts specified"
+msgstr "chưa chỉ ra danh bạ"
+
 #: builtin/checkout-index.c:126
 msgid "git checkout-index [options] [--] [<file>...]"
 msgstr "git checkout-index [các-tùy-chọn] [--] [<tập-tin>...]"
@@ -2939,107 +3176,107 @@
 msgid "git checkout [options] [<branch>] -- <file>..."
 msgstr "git checkout [các-tùy-chọn] [<nhánh>] -- <tập-tin>..."
 
-#: builtin/checkout.c:116 builtin/checkout.c:149
+#: builtin/checkout.c:117 builtin/checkout.c:150
 #, c-format
 msgid "path '%s' does not have our version"
 msgstr "đường dẫn “%s” không có các phiên bản của chúng ta"
 
-#: builtin/checkout.c:118 builtin/checkout.c:151
+#: builtin/checkout.c:119 builtin/checkout.c:152
 #, c-format
 msgid "path '%s' does not have their version"
 msgstr "đường dẫn “%s” không có các phiên bản của chúng"
 
-#: builtin/checkout.c:134
+#: builtin/checkout.c:135
 #, c-format
 msgid "path '%s' does not have all necessary versions"
 msgstr "đường dẫn “%s” không có tất cả các phiên bản cần thiết"
 
-#: builtin/checkout.c:178
+#: builtin/checkout.c:179
 #, c-format
 msgid "path '%s' does not have necessary versions"
 msgstr "đường dẫn “%s” không có các phiên bản cần thiết"
 
-#: builtin/checkout.c:195
+#: builtin/checkout.c:196
 #, c-format
 msgid "path '%s': cannot merge"
 msgstr "đường dẫn “%s”: không thể hòa trộn"
 
-#: builtin/checkout.c:212
+#: builtin/checkout.c:213
 #, c-format
 msgid "Unable to add merge result for '%s'"
 msgstr "Không thể thêm kết quả hòa trộn cho “%s”"
 
-#: builtin/checkout.c:236 builtin/checkout.c:239 builtin/checkout.c:242
-#: builtin/checkout.c:245
+#: builtin/checkout.c:237 builtin/checkout.c:240 builtin/checkout.c:243
+#: builtin/checkout.c:246
 #, c-format
 msgid "'%s' cannot be used with updating paths"
 msgstr "“%s” không thể được sử dụng với các đường dẫn cập nhật"
 
-#: builtin/checkout.c:248 builtin/checkout.c:251
+#: builtin/checkout.c:249 builtin/checkout.c:252
 #, c-format
 msgid "'%s' cannot be used with %s"
 msgstr "“%s” không thể được sử dụng với %s"
 
-#: builtin/checkout.c:254
+#: builtin/checkout.c:255
 #, c-format
 msgid "Cannot update paths and switch to branch '%s' at the same time."
 msgstr ""
 "Không thể cập nhật các đường dẫn và chuyển đến nhánh “%s” cùng một lúc."
 
-#: builtin/checkout.c:265 builtin/checkout.c:455
+#: builtin/checkout.c:266 builtin/checkout.c:458
 msgid "corrupt index file"
 msgstr "tập tin ghi bảng mục lục bị hỏng"
 
-#: builtin/checkout.c:326 builtin/checkout.c:333
+#: builtin/checkout.c:329 builtin/checkout.c:336
 #, c-format
 msgid "path '%s' is unmerged"
 msgstr "đường dẫn “%s” không được hòa trộn"
 
-#: builtin/checkout.c:477
+#: builtin/checkout.c:480
 msgid "you need to resolve your current index first"
 msgstr "bạn cần phải phân giải bảng mục lục hiện tại của bạn trước đã"
 
-#: builtin/checkout.c:598
+#: builtin/checkout.c:601
 #, c-format
 msgid "Can not do reflog for '%s'\n"
 msgstr "Không thể thực hiện reflog cho “%s”\n"
 
-#: builtin/checkout.c:631
+#: builtin/checkout.c:639
 msgid "HEAD is now at"
 msgstr "HEAD hiện giờ tại"
 
-#: builtin/checkout.c:638
+#: builtin/checkout.c:646
 #, c-format
 msgid "Reset branch '%s'\n"
 msgstr "Đặt lại nhánh “%s”\n"
 
-#: builtin/checkout.c:641
+#: builtin/checkout.c:649
 #, c-format
 msgid "Already on '%s'\n"
 msgstr "Đã sẵn sàng trên “%s”\n"
 
-#: builtin/checkout.c:645
+#: builtin/checkout.c:653
 #, c-format
 msgid "Switched to and reset branch '%s'\n"
 msgstr "Đã chuyển tới và reset nhánh “%s”\n"
 
-#: builtin/checkout.c:647 builtin/checkout.c:984
+#: builtin/checkout.c:655 builtin/checkout.c:997
 #, c-format
 msgid "Switched to a new branch '%s'\n"
 msgstr "Đã chuyển đến nhánh mới “%s”\n"
 
-#: builtin/checkout.c:649
+#: builtin/checkout.c:657
 #, c-format
 msgid "Switched to branch '%s'\n"
 msgstr "Đã chuyển đến nhánh “%s”\n"
 
-#: builtin/checkout.c:705
+#: builtin/checkout.c:713
 #, c-format
 msgid " ... and %d more.\n"
 msgstr " ... và nhiều hơn %d.\n"
 
 #. The singular version
-#: builtin/checkout.c:711
+#: builtin/checkout.c:719
 #, c-format
 msgid ""
 "Warning: you are leaving %d commit behind, not connected to\n"
@@ -3064,7 +3301,7 @@
 "\n"
 "%s\n"
 
-#: builtin/checkout.c:729
+#: builtin/checkout.c:737
 #, c-format
 msgid ""
 "If you want to keep them by creating a new branch, this may be a good time\n"
@@ -3080,134 +3317,138 @@
 " git branch tên_nhánh_mới %s\n"
 "\n"
 
-#: builtin/checkout.c:759
+#: builtin/checkout.c:767
 msgid "internal error in revision walk"
-msgstr "lỗi nội bộ trong khi di chuyển qua các điểm xét lại"
+msgstr "lỗi nội bộ trong khi di chuyển qua các điểm xét duyệt"
 
-#: builtin/checkout.c:763
+#: builtin/checkout.c:771
 msgid "Previous HEAD position was"
 msgstr "Vị trí kế trước của HEAD là"
 
-#: builtin/checkout.c:790 builtin/checkout.c:979
+#: builtin/checkout.c:798 builtin/checkout.c:992
 msgid "You are on a branch yet to be born"
 msgstr "Bạn tại nhánh mà nó chưa hề được sinh ra"
 
 #. case (1)
-#: builtin/checkout.c:915
+#: builtin/checkout.c:928
 #, c-format
 msgid "invalid reference: %s"
 msgstr "tham chiếu sai: %s"
 
 #. case (1): want a tree
-#: builtin/checkout.c:954
+#: builtin/checkout.c:967
 #, c-format
 msgid "reference is not a tree: %s"
 msgstr "tham chiếu không phải là một cây (tree):%s"
 
-#: builtin/checkout.c:993
+#: builtin/checkout.c:1006
 msgid "paths cannot be used with switching branches"
 msgstr "các đường dẫn không thể dùng cùng với các nhánh chuyển"
 
-#: builtin/checkout.c:996 builtin/checkout.c:1000
+#: builtin/checkout.c:1009 builtin/checkout.c:1013
 #, c-format
 msgid "'%s' cannot be used with switching branches"
 msgstr "“%s” không thể được sử dụng với các nhánh chuyển"
 
-#: builtin/checkout.c:1004 builtin/checkout.c:1007 builtin/checkout.c:1012
-#: builtin/checkout.c:1015
+#: builtin/checkout.c:1017 builtin/checkout.c:1020 builtin/checkout.c:1025
+#: builtin/checkout.c:1028
 #, c-format
 msgid "'%s' cannot be used with '%s'"
 msgstr "“%s” không thể được sử dụng với “%s”"
 
-#: builtin/checkout.c:1020
+#: builtin/checkout.c:1033
 #, c-format
 msgid "Cannot switch branch to a non-commit '%s'"
 msgstr "Không thể chuyển nhánh đến một non-commit “%s”"
 
-#: builtin/checkout.c:1042 builtin/checkout.c:1044 builtin/clone.c:90
+#: builtin/checkout.c:1055 builtin/checkout.c:1057 builtin/clone.c:89
 #: builtin/remote.c:169 builtin/remote.c:171
 msgid "branch"
 msgstr "nhánh"
 
-#: builtin/checkout.c:1043
+#: builtin/checkout.c:1056
 msgid "create and checkout a new branch"
 msgstr "tạo và checkout một nhánh mới"
 
-#: builtin/checkout.c:1045
+#: builtin/checkout.c:1058
 msgid "create/reset and checkout a branch"
 msgstr "create/reset và checkout một nhánh"
 
-#: builtin/checkout.c:1046
+#: builtin/checkout.c:1059
 msgid "create reflog for new branch"
 msgstr "tạo reflog cho nhánh mới"
 
-#: builtin/checkout.c:1047
+#: builtin/checkout.c:1060
 msgid "detach the HEAD at named commit"
 msgstr "rời bỏ HEAD tại lần chuyển giao danh nghĩa"
 
-#: builtin/checkout.c:1048
+#: builtin/checkout.c:1061
 msgid "set upstream info for new branch"
 msgstr "đặt thông tin thượng nguồn (upstream) cho nhánh mới"
 
-#: builtin/checkout.c:1050
+#: builtin/checkout.c:1063
 msgid "new branch"
 msgstr "nhánh mới"
 
-#: builtin/checkout.c:1050
+#: builtin/checkout.c:1063
 msgid "new unparented branch"
 msgstr "nhánh mồ côi mới"
 
-#: builtin/checkout.c:1051
+#: builtin/checkout.c:1064
 msgid "checkout our version for unmerged files"
 msgstr ""
 "lấy ra (checkout) phiên bản của chúng ta cho các tập tin chưa được hòa trộn"
 
-#: builtin/checkout.c:1053
+#: builtin/checkout.c:1066
 msgid "checkout their version for unmerged files"
 msgstr ""
 "lấy ra (checkout) phiên bản của chúng họ cho các tập tin chưa được hòa trộn"
 
-#: builtin/checkout.c:1055
+#: builtin/checkout.c:1068
 msgid "force checkout (throw away local modifications)"
 msgstr "ép buộc lấy ra (checkout) (bỏ đi những thay đổi nội bộ)"
 
-#: builtin/checkout.c:1056
+#: builtin/checkout.c:1069
 msgid "perform a 3-way merge with the new branch"
 msgstr "thực hiện hòa trộn kiểu 3-way với nhánh mới"
 
-#: builtin/checkout.c:1057 builtin/merge.c:217
+#: builtin/checkout.c:1070 builtin/merge.c:232
 msgid "update ignored files (default)"
 msgstr "cập nhật các tập tin bị bỏ qua (mặc định)"
 
-#: builtin/checkout.c:1058 builtin/log.c:1149 parse-options.h:245
+#: builtin/checkout.c:1071 builtin/log.c:1208 parse-options.h:249
 msgid "style"
 msgstr "kiểu"
 
-#: builtin/checkout.c:1059
+#: builtin/checkout.c:1072
 msgid "conflict style (merge or diff3)"
 msgstr "xung đột kiểu (hòa trộn hay diff3)"
 
-#: builtin/checkout.c:1062
+#: builtin/checkout.c:1075
+msgid "do not limit pathspecs to sparse entries only"
+msgstr "không giới hạn pathspecs chỉ thành các mục thưa thớt"
+
+#: builtin/checkout.c:1077
 msgid "second guess 'git checkout no-such-branch'"
 msgstr "gợi ý thứ hai “git checkout không-nhánh-nào-như-vậy”"
 
-#: builtin/checkout.c:1086
+#: builtin/checkout.c:1101
 msgid "-b, -B and --orphan are mutually exclusive"
 msgstr "Tùy chọn -b|-B và --orphan loại từ lẫn nhau"
 
-#: builtin/checkout.c:1103
+#: builtin/checkout.c:1118
 msgid "--track needs a branch name"
 msgstr "--track cần tên một nhánh"
 
-#: builtin/checkout.c:1110
+#: builtin/checkout.c:1125
 msgid "Missing branch name; try -b"
 msgstr "Thiếu tên nhánh; hãy thử -b"
 
-#: builtin/checkout.c:1145
+#: builtin/checkout.c:1160
 msgid "invalid path specification"
 msgstr "đường dẫn đã cho không hợp lệ"
 
-#: builtin/checkout.c:1152
+#: builtin/checkout.c:1167
 #, c-format
 msgid ""
 "Cannot update paths and switch to branch '%s' at the same time.\n"
@@ -3217,12 +3458,12 @@
 "Bạn đã có ý định checkout “%s” cái mà không thể được phân giải như là lần "
 "chuyển giao (commit)?"
 
-#: builtin/checkout.c:1157
+#: builtin/checkout.c:1172
 #, c-format
 msgid "git checkout: --detach does not take a path argument '%s'"
 msgstr "git checkout: --detach không nhận một đối số đường dẫn “%s”"
 
-#: builtin/checkout.c:1161
+#: builtin/checkout.c:1176
 msgid ""
 "git checkout: --ours/--theirs, --force and --merge are incompatible when\n"
 "checking out of the index."
@@ -3230,310 +3471,427 @@
 "git checkout: --ours/--theirs, --force và --merge là xung khắc với nhau khi\n"
 "checkout bảng mục lục (index)."
 
-#: builtin/clean.c:20
-msgid "git clean [-d] [-f] [-n] [-q] [-e <pattern>] [-x | -X] [--] <paths>..."
-msgstr "git clean [-d] [-f] [-n] [-q] [-e <mẫu>] [-x | -X] [--] <đường-dẫn>..."
+#: builtin/clean.c:25
+msgid ""
+"git clean [-d] [-f] [-i] [-n] [-q] [-e <pattern>] [-x | -X] [--] <paths>..."
+msgstr ""
+"git clean [-d] [-f] [-i] [-n] [-q] [-e <mẫu>] [-x | -X] [--] <đường-dẫn>..."
 
-#: builtin/clean.c:24
+#: builtin/clean.c:29
 #, c-format
 msgid "Removing %s\n"
 msgstr "Đang gỡ bỏ %s\n"
 
-#: builtin/clean.c:25
+#: builtin/clean.c:30
 #, c-format
 msgid "Would remove %s\n"
 msgstr "Có thể gỡ bỏ %s\n"
 
-#: builtin/clean.c:26
+#: builtin/clean.c:31
 #, c-format
 msgid "Skipping repository %s\n"
 msgstr "Đang bỏ qua kho chứa %s\n"
 
-#: builtin/clean.c:27
+#: builtin/clean.c:32
 #, c-format
 msgid "Would skip repository %s\n"
 msgstr "Nên bỏ qua kho chứa %s\n"
 
-#: builtin/clean.c:28
+#: builtin/clean.c:33
 #, c-format
 msgid "failed to remove %s"
 msgstr "gặp lỗi khi gỡ bỏ %s"
 
-#: builtin/clean.c:160
+#: builtin/clean.c:293
+msgid ""
+"Prompt help:\n"
+"1          - select a numbered item\n"
+"foo        - select item based on unique prefix\n"
+"           - (empty) select nothing"
+msgstr ""
+"Trợ giúp về nhắc:\n"
+"1          - chọn một mục được đánh số\n"
+"foo        - chọn mục trên cơ sở tiền tố duy nhất\n"
+"           - (trống rỗng) không chọn gì cả"
+
+#: builtin/clean.c:297
+msgid ""
+"Prompt help:\n"
+"1          - select a single item\n"
+"3-5        - select a range of items\n"
+"2-3,6-9    - select multiple ranges\n"
+"foo        - select item based on unique prefix\n"
+"-...       - unselect specified items\n"
+"*          - choose all items\n"
+"           - (empty) finish selecting"
+msgstr ""
+"Trợ giúp về nhắc:\n"
+"1          - chọn một mục đơn\n"
+"3-5        - chọn một vùng\n"
+"2-3,6-9    - chọn nhiều vùng\n"
+"foo        - chọn mục dựa trên tiền tố duy nhất\n"
+"-...       - không chọn các mục đã chỉ ra\n"
+"*          - chọn tất\n"
+"           - (trống rỗng) kết thúc việc chọn"
+
+#: builtin/clean.c:515
+#, c-format
+msgid "Huh (%s)?"
+msgstr "Hả (%s)?"
+
+#: builtin/clean.c:658
+#, c-format
+msgid "Input ignore patterns>> "
+msgstr "Mẫu để lọc các tập tin cần lờ đi đầu vào>>"
+
+#: builtin/clean.c:695
+#, c-format
+msgid "WARNING: Cannot find items matched by: %s"
+msgstr "CẢNH BÁO: Không tìm thấy các mục được khớp bởi: %s"
+
+#: builtin/clean.c:716
+msgid "Select items to delete"
+msgstr "Chọn mục muốn xóa"
+
+#: builtin/clean.c:756
+#, c-format
+msgid "remove %s? "
+msgstr "gỡ bỏ “%s”?"
+
+#: builtin/clean.c:781
+msgid "Bye."
+msgstr "Tạm biệt."
+
+#: builtin/clean.c:789
+msgid ""
+"clean               - start cleaning\n"
+"filter by pattern   - exclude items from deletion\n"
+"select by numbers   - select items to be deleted by numbers\n"
+"ask each            - confirm each deletion (like \"rm -i\")\n"
+"quit                - stop cleaning\n"
+"help                - this screen\n"
+"?                   - help for prompt selection"
+msgstr ""
+"clean               - bắt đầu dọn dẹp\n"
+"filter by pattern   - loại trừ các mục khỏi việc xóa\n"
+"select by numbers   - chọn các mục cần xóa bằng số\n"
+"ask each            - xác nhận trước mỗi lần xóa (giống như \"rm -i\")\n"
+"quit                - dừng việc dọn dẹp lại\n"
+"help                - hiển thị chính trợ giúp này\n"
+"?                   - trợ giúp dành cho chọn bằng cách nhắc"
+
+#: builtin/clean.c:816
+msgid "*** Commands ***"
+msgstr "*** Lệnh ***"
+
+#: builtin/clean.c:817
+msgid "What now"
+msgstr "Giờ thì sao"
+
+#: builtin/clean.c:825
+msgid "Would remove the following item:"
+msgid_plural "Would remove the following items:"
+msgstr[0] "Có muốn gỡ bỏ mục sau đây không:"
+msgstr[1] "Có muốn gỡ bỏ các mục sau đây không:"
+
+#: builtin/clean.c:842
+msgid "No more files to clean, exiting."
+msgstr "Không còn tập-tin nào để dọn dẹp, đang thoát ra."
+
+#: builtin/clean.c:874
 msgid "do not print names of files removed"
 msgstr "không hiển thị tên của các tập tin đã gỡ bỏ"
 
-#: builtin/clean.c:162
+#: builtin/clean.c:876
 msgid "force"
 msgstr "ép buộc"
 
-#: builtin/clean.c:164
+#: builtin/clean.c:877
+msgid "interactive cleaning"
+msgstr "sửa bằng cách tương tác"
+
+#: builtin/clean.c:879
 msgid "remove whole directories"
 msgstr "gỡ bỏ toàn bộ thư mục"
 
-#: builtin/clean.c:165 builtin/describe.c:412 builtin/grep.c:717
-#: builtin/ls-files.c:494 builtin/name-rev.c:231 builtin/show-ref.c:182
+#: builtin/clean.c:880 builtin/describe.c:420 builtin/grep.c:716
+#: builtin/ls-files.c:493 builtin/name-rev.c:315 builtin/show-ref.c:186
 msgid "pattern"
 msgstr "mẫu"
 
-#: builtin/clean.c:166
+#: builtin/clean.c:881
 msgid "add <pattern> to ignore rules"
 msgstr "thêm <mẫu> vào trong qui tắc bỏ qua"
 
-#: builtin/clean.c:167
+#: builtin/clean.c:882
 msgid "remove ignored files, too"
 msgstr "đồng thời gỡ bỏ cả các tập tin bị bỏ qua"
 
-#: builtin/clean.c:169
+#: builtin/clean.c:884
 msgid "remove only ignored files"
 msgstr "chỉ gỡ bỏ những tập tin bị bỏ qua"
 
-#: builtin/clean.c:187
+#: builtin/clean.c:902
 msgid "-x and -X cannot be used together"
 msgstr "-x và -X không thể dùng cùng một lúc với nhau"
 
-#: builtin/clean.c:191
+#: builtin/clean.c:906
 msgid ""
-"clean.requireForce set to true and neither -n nor -f given; refusing to clean"
-msgstr ""
-"clean.requireForce được đặt thành true và không đưa ra tùy chọn  -n mà cũng "
-"không -f; từ chối lệnh dọn dẹp (clean)"
-
-#: builtin/clean.c:194
-msgid ""
-"clean.requireForce defaults to true and neither -n nor -f given; refusing to "
+"clean.requireForce set to true and neither -i, -n nor -f given; refusing to "
 "clean"
 msgstr ""
-"clean.requireForce mặc định được đặt thành true và không đưa ra tùy chọn  -n "
-"mà cũng không -f; từ chối lệnh dọn dẹp (clean)"
+"clean.requireForce được đặt thành true và không đưa ra tùy chọn -n mà cũng "
+"không -f; từ chối lệnh dọn dẹp (clean)"
 
-#: builtin/clone.c:37
+#: builtin/clean.c:909
+msgid ""
+"clean.requireForce defaults to true and neither -i, -n nor -f given; "
+"refusing to clean"
+msgstr ""
+"clean.requireForce mặc định được đặt là true và không đưa ra tùy chọn -n mà "
+"cũng không -f; từ chối lệnh dọn dẹp (clean)"
+
+#: builtin/clone.c:36
 msgid "git clone [options] [--] <repo> [<dir>]"
 msgstr "git clone [các-tùy-chọn] [--] <kho> [<t.mục>]"
 
-#: builtin/clone.c:65 builtin/fetch.c:82 builtin/merge.c:214
-#: builtin/push.c:436
+#: builtin/clone.c:64 builtin/fetch.c:82 builtin/merge.c:229
+#: builtin/push.c:462
 msgid "force progress reporting"
 msgstr "ép buộc báo cáo tiến trình"
 
-#: builtin/clone.c:67
+#: builtin/clone.c:66
 msgid "don't create a checkout"
 msgstr "không tạo một checkout"
 
-#: builtin/clone.c:68 builtin/clone.c:70 builtin/init-db.c:488
+#: builtin/clone.c:67 builtin/clone.c:69 builtin/init-db.c:488
 msgid "create a bare repository"
 msgstr "tạo kho chứa bare"
 
-#: builtin/clone.c:73
+#: builtin/clone.c:72
 msgid "create a mirror repository (implies bare)"
 msgstr "tạo kho bản sao (mirror) (ngụ ý là bare)"
 
-#: builtin/clone.c:75
+#: builtin/clone.c:74
 msgid "to clone from a local repository"
 msgstr "để nhân bản từ kho nội bộ"
 
-#: builtin/clone.c:77
+#: builtin/clone.c:76
 msgid "don't use local hardlinks, always copy"
 msgstr "không sử dụng liên kết cứng nội bộ, luôn sao chép"
 
-#: builtin/clone.c:79
+#: builtin/clone.c:78
 msgid "setup as shared repository"
 msgstr "cài đặt đây là kho chia sẻ"
 
-#: builtin/clone.c:81 builtin/clone.c:83
+#: builtin/clone.c:80 builtin/clone.c:82
 msgid "initialize submodules in the clone"
 msgstr "khởi tạo mô-đun-con trong bản sao"
 
-#: builtin/clone.c:84 builtin/init-db.c:485
+#: builtin/clone.c:83 builtin/init-db.c:485
 msgid "template-directory"
 msgstr "thư-mục-tạm"
 
-#: builtin/clone.c:85 builtin/init-db.c:486
+#: builtin/clone.c:84 builtin/init-db.c:486
 msgid "directory from which templates will be used"
 msgstr "thư mục mà tại đó các mẫu sẽ được dùng"
 
-#: builtin/clone.c:87
+#: builtin/clone.c:86
 msgid "reference repository"
 msgstr "kho tham chiếu"
 
-#: builtin/clone.c:88 builtin/column.c:26 builtin/merge-file.c:44
+#: builtin/clone.c:87 builtin/column.c:26 builtin/merge-file.c:44
 msgid "name"
 msgstr "tên"
 
-#: builtin/clone.c:89
+#: builtin/clone.c:88
 msgid "use <name> instead of 'origin' to track upstream"
 msgstr "dùng <tên> thay vì “origin” để theo dõi thượng nguồn (uptream)"
 
-#: builtin/clone.c:91
+#: builtin/clone.c:90
 msgid "checkout <branch> instead of the remote's HEAD"
 msgstr "lấy ra nhánh (checkout <nhánh>) thay vì HEAD của máy chủ"
 
-#: builtin/clone.c:93
+#: builtin/clone.c:92
 msgid "path to git-upload-pack on the remote"
 msgstr "đường dẫn đến git-upload-pack trên máy chủ"
 
-#: builtin/clone.c:94 builtin/fetch.c:83 builtin/grep.c:662
+#: builtin/clone.c:93 builtin/fetch.c:83 builtin/grep.c:661
 msgid "depth"
 msgstr "độ sâu"
 
-#: builtin/clone.c:95
+#: builtin/clone.c:94
 msgid "create a shallow clone of that depth"
 msgstr "tạo bản sao không đầy đủ cho mức sâu đã cho"
 
-#: builtin/clone.c:97
+#: builtin/clone.c:96
 msgid "clone only one branch, HEAD or --branch"
 msgstr "nhân bản (clone) chỉ một nhánh, HEAD hoặc --branch"
 
-#: builtin/clone.c:98 builtin/init-db.c:494
+#: builtin/clone.c:97 builtin/init-db.c:494
 msgid "gitdir"
 msgstr "gitdir"
 
-#: builtin/clone.c:99 builtin/init-db.c:495
+#: builtin/clone.c:98 builtin/init-db.c:495
 msgid "separate git dir from working tree"
 msgstr "không dùng chung thư mục dành riêng cho git và thư mục làm việc"
 
-#: builtin/clone.c:100
+#: builtin/clone.c:99
 msgid "key=value"
 msgstr "khóa=giá trị"
 
-#: builtin/clone.c:101
+#: builtin/clone.c:100
 msgid "set config inside the new repository"
 msgstr "đặt cấu hình bên trong một kho chứa mới"
 
-#: builtin/clone.c:244
+#: builtin/clone.c:253
 #, c-format
-msgid "reference repository '%s' is not a local directory."
-msgstr "kho tham chiếu “%s” không phải là một thư mục nội bộ."
+msgid "reference repository '%s' is not a local repository."
+msgstr "kho tham chiếu “%s” không phải là một kho nội bộ."
 
-#: builtin/clone.c:307
+#: builtin/clone.c:316
 #, c-format
 msgid "failed to create directory '%s'"
 msgstr "tạo thư mục \"%s\" gặp lỗi"
 
-#: builtin/clone.c:309 builtin/diff.c:77
+#: builtin/clone.c:318 builtin/diff.c:77
 #, c-format
 msgid "failed to stat '%s'"
 msgstr "gặp lỗi stat (lấy trạng thái về) “%s”"
 
-#: builtin/clone.c:311
+#: builtin/clone.c:320
 #, c-format
 msgid "%s exists and is not a directory"
 msgstr "%s tồn tại nhưng không phải là một thư mục"
 
-#: builtin/clone.c:325
+#: builtin/clone.c:334
 #, c-format
 msgid "failed to stat %s\n"
 msgstr "lỗi stat (lấy trạng thái về) %s\n"
 
-#: builtin/clone.c:347
+#: builtin/clone.c:356
 #, c-format
 msgid "failed to create link '%s'"
 msgstr "gặp lỗi khi tạo được liên kết mềm %s"
 
-#: builtin/clone.c:351
+#: builtin/clone.c:360
 #, c-format
 msgid "failed to copy file to '%s'"
 msgstr "gặp lỗi khi chép tập tin tới “%s”"
 
-#: builtin/clone.c:374
+#: builtin/clone.c:383
 #, c-format
 msgid "done.\n"
 msgstr "hoàn tất.\n"
 
-#: builtin/clone.c:387
+#: builtin/clone.c:396
 msgid ""
 "Clone succeeded, but checkout failed.\n"
 "You can inspect what was checked out with 'git status'\n"
 "and retry the checkout with 'git checkout -f HEAD'\n"
 msgstr ""
 "Việc nhân bản thành công, nhưng checkout gặp lỗi.\n"
-"Bạn kiểm tra kỹ xem cái gì được lấy ra bằng lệnh 'git status'\n"
-"và thử checkout với lệnh 'git checkout -f HEAD'\n"
+"Bạn kiểm tra kỹ xem cái gì được lấy ra bằng lệnh “git status”\n"
+"và thử checkout với lệnh “git checkout -f HEAD”\n"
 
-#: builtin/clone.c:466
+#: builtin/clone.c:475
 #, c-format
 msgid "Could not find remote branch %s to clone."
 msgstr "Không tìm thấy nhánh máy chủ %s để nhân bản (clone)."
 
-#: builtin/clone.c:540
+#: builtin/clone.c:555
+#, c-format
+msgid "Checking connectivity... "
+msgstr "Đang kiểm tra kết nối..."
+
+#: builtin/clone.c:558
 msgid "remote did not send all necessary objects"
 msgstr "máy chủ đã không gửi tất cả các đối tượng cần thiết"
 
-#: builtin/clone.c:600
+#: builtin/clone.c:560
+#, c-format
+msgid "done\n"
+msgstr "xong.\n"
+
+#: builtin/clone.c:621
 msgid "remote HEAD refers to nonexistent ref, unable to checkout.\n"
 msgstr "refers HEAD máy chủ  chỉ đến ref không tồn tại, không thể checkout.\n"
 
-#: builtin/clone.c:631
+#: builtin/clone.c:652
 msgid "unable to checkout working tree"
 msgstr "không thể lấy ra (checkout) cây làm việc"
 
-#: builtin/clone.c:739
+#: builtin/clone.c:760
 msgid "Too many arguments."
 msgstr "Có quá nhiều đối số."
 
-#: builtin/clone.c:743
+#: builtin/clone.c:764
 msgid "You must specify a repository to clone."
 msgstr "Bạn phải chỉ định một kho để mà nhân bản (clone)."
 
-#: builtin/clone.c:754
+#: builtin/clone.c:775
 #, c-format
 msgid "--bare and --origin %s options are incompatible."
 msgstr "tùy chọn --bare và --origin %s xung khắc nhau."
 
-#: builtin/clone.c:757
+#: builtin/clone.c:778
 msgid "--bare and --separate-git-dir are incompatible."
 msgstr "tùy chọn --bare và --separate-git-dir xung khắc nhau."
 
-#: builtin/clone.c:770
+#: builtin/clone.c:791
 #, c-format
 msgid "repository '%s' does not exist"
 msgstr "kho chứa “%s” chưa tồn tại"
 
-#: builtin/clone.c:775
+#: builtin/clone.c:796
 msgid "--depth is ignored in local clones; use file:// instead."
 msgstr "--depth bị lờ đi khi nhân bản nội bộ; hãy sử dụng file:// để thay thế."
 
-#: builtin/clone.c:785
+#: builtin/clone.c:798
+msgid "--local is ignored"
+msgstr "--local bị lờ đi"
+
+#: builtin/clone.c:808
 #, c-format
 msgid "destination path '%s' already exists and is not an empty directory."
 msgstr "đường dẫn đích “%s” đã có từ trước và không phải là một thư mục rỗng."
 
-#: builtin/clone.c:795
+#: builtin/clone.c:818
 #, c-format
 msgid "working tree '%s' already exists."
 msgstr "cây làm việc “%s” đã sẵn tồn tại rồi."
 
-#: builtin/clone.c:808 builtin/clone.c:820
+#: builtin/clone.c:831 builtin/clone.c:843
 #, c-format
 msgid "could not create leading directories of '%s'"
 msgstr "không thể tạo các thư mục dẫn đầu của “%s”"
 
-#: builtin/clone.c:811
+#: builtin/clone.c:834
 #, c-format
 msgid "could not create work tree dir '%s'."
 msgstr "không thể tạo cây thư mục làm việc dir “%s”."
 
-#: builtin/clone.c:830
+#: builtin/clone.c:853
 #, c-format
 msgid "Cloning into bare repository '%s'...\n"
 msgstr "Đang nhân bản thành kho chứa bare “%s”...\n"
 
-#: builtin/clone.c:832
+#: builtin/clone.c:855
 #, c-format
 msgid "Cloning into '%s'...\n"
 msgstr "Đang nhân bản thành “%s”...\n"
 
-#: builtin/clone.c:867
+#: builtin/clone.c:890
 #, c-format
 msgid "Don't know how to clone %s"
 msgstr "Không biết làm cách nào để nhân bản (clone) %s"
 
-#: builtin/clone.c:916
+#: builtin/clone.c:942
 #, c-format
 msgid "Remote branch %s not found in upstream %s"
 msgstr "Nhánh máy chủ %s không tìm thấy trong thượng nguồn (upstream) %s"
 
-#: builtin/clone.c:923
+#: builtin/clone.c:949
 msgid "You appear to have cloned an empty repository."
 msgstr "Bạn hình như là đã nhân bản một kho trống rỗng."
 
@@ -3569,15 +3927,15 @@
 msgid "--command must be the first argument"
 msgstr "--command phải là đối số đầu tiên"
 
-#: builtin/commit.c:34
+#: builtin/commit.c:35
 msgid "git commit [options] [--] <pathspec>..."
 msgstr "git commit [các-tùy-chọn] [--] <pathspec>..."
 
-#: builtin/commit.c:39
+#: builtin/commit.c:40
 msgid "git status [options] [--] <pathspec>..."
 msgstr "git status [các-tùy-chọn] [--] <pathspec>..."
 
-#: builtin/commit.c:44
+#: builtin/commit.c:45
 msgid ""
 "Your name and email address were configured automatically based\n"
 "on your username and hostname. Please check that they are accurate.\n"
@@ -3605,7 +3963,7 @@
 "\n"
 "    git commit --amend --reset-author\n"
 
-#: builtin/commit.c:56
+#: builtin/commit.c:57
 msgid ""
 "You asked to amend the most recent commit, but doing so would make\n"
 "it empty. You can repeat your command with --allow-empty, or you can\n"
@@ -3618,114 +3976,132 @@
 "hoặc là bạn gỡ bỏ các lần chuyển giao một cách hoàn toàn bằng lệnh:\n"
 "\"git reset HEAD^\".\n"
 
-#: builtin/commit.c:61
+#: builtin/commit.c:62
 msgid ""
 "The previous cherry-pick is now empty, possibly due to conflict resolution.\n"
 "If you wish to commit it anyway, use:\n"
 "\n"
 "    git commit --allow-empty\n"
 "\n"
-"Otherwise, please use 'git reset'\n"
 msgstr ""
 "Lần cherry-pick trước hiện nay trống rỗng, có lẽ là bởi vì sự phân giải xung "
 "đột.\n"
-"Nếu bạn muốn chuyển giao nó cho dù thế nào đi nữa, sử dụng:\n"
+"Nếu bạn vẫn muốn chuyển giao nó cho dù thế nào đi nữa, sử dụng:\n"
 "\n"
 "    git commit --allow-empty\n"
 "\n"
-"Nếu không, hãy thử dùng “git reset”\n"
 
-#: builtin/commit.c:260
+#: builtin/commit.c:69
+msgid "Otherwise, please use 'git reset'\n"
+msgstr "Nếu không được thì dùng lệnh \"git reset\"\n"
+
+#: builtin/commit.c:72
+msgid ""
+"If you wish to skip this commit, use:\n"
+"\n"
+"    git reset\n"
+"\n"
+"Then \"git cherry-pick --continue\" will resume cherry-picking\n"
+"the remaining commits.\n"
+msgstr ""
+"Nếu bạn muốn bỏ qua lần chuyển giao này thì dùng:\n"
+"\n"
+"    git reset\n"
+"\n"
+"Thế thì \"git cherry-pick --continue\" sẽ phục hồi lại việc cherry-pick\n"
+"những lần chuyển giao còn lại.\n"
+
+#: builtin/commit.c:279
 msgid "failed to unpack HEAD tree object"
 msgstr "gặp lỗi khi tháo dỡ HEAD đối tượng cây"
 
-#: builtin/commit.c:302
+#: builtin/commit.c:321
 msgid "unable to create temporary index"
 msgstr "không thể tạo bảng mục lục tạm thời"
 
-#: builtin/commit.c:308
+#: builtin/commit.c:327
 msgid "interactive add failed"
 msgstr "việc thêm tương tác gặp lỗi"
 
-#: builtin/commit.c:341 builtin/commit.c:362 builtin/commit.c:412
+#: builtin/commit.c:360 builtin/commit.c:381 builtin/commit.c:431
 msgid "unable to write new_index file"
 msgstr "không thể ghi tập tin lưu bảng mục lục mới (new_index)"
 
-#: builtin/commit.c:393
+#: builtin/commit.c:412
 msgid "cannot do a partial commit during a merge."
 msgstr ""
 "không thể thực hiện việc chuyển giao (commit) cục bộ trong khi đang được hòa "
 "trộn."
 
-#: builtin/commit.c:395
+#: builtin/commit.c:414
 msgid "cannot do a partial commit during a cherry-pick."
 msgstr ""
 "không thể thực hiện việc chuyển giao (commit) bộ phận trong khi đang cherry-"
 "pick."
 
-#: builtin/commit.c:405
+#: builtin/commit.c:424
 msgid "cannot read the index"
 msgstr "không đọc được bảng mục lục"
 
-#: builtin/commit.c:425
+#: builtin/commit.c:444
 msgid "unable to write temporary index file"
 msgstr "không thể ghi tập tin lưu bảng mục lục tạm thời"
 
-#: builtin/commit.c:513 builtin/commit.c:519
+#: builtin/commit.c:535 builtin/commit.c:541
 #, c-format
 msgid "invalid commit: %s"
 msgstr "lần chuyển giao (commit) không hợp lệ: %s"
 
-#: builtin/commit.c:542
+#: builtin/commit.c:563
 msgid "malformed --author parameter"
 msgstr "đối số --author bị dị hình"
 
-#: builtin/commit.c:562
+#: builtin/commit.c:583
 #, c-format
 msgid "Malformed ident string: '%s'"
 msgstr "Chuỗi thụt lề đầu dòng dị hình: “%s”"
 
-#: builtin/commit.c:600 builtin/commit.c:633 builtin/commit.c:956
+#: builtin/commit.c:621 builtin/commit.c:654 builtin/commit.c:982
 #, c-format
 msgid "could not lookup commit %s"
 msgstr "không thể tìm kiếm commit (lần chuyển giao) %s"
 
-#: builtin/commit.c:612 builtin/shortlog.c:272
+#: builtin/commit.c:633 builtin/shortlog.c:271
 #, c-format
 msgid "(reading log message from standard input)\n"
 msgstr "(đang đọc thông điệp nhật ký từ đầu vào tiêu chuẩn)\n"
 
-#: builtin/commit.c:614
+#: builtin/commit.c:635
 msgid "could not read log from standard input"
 msgstr "không thể đọc nhật ký từ đầu vào tiêu chuẩn"
 
-#: builtin/commit.c:618
+#: builtin/commit.c:639
 #, c-format
 msgid "could not read log file '%s'"
 msgstr "không đọc được tệp nhật ký “%s”"
 
-#: builtin/commit.c:624
+#: builtin/commit.c:645
 msgid "commit has empty message"
 msgstr "lần chuyển giao (commit) có ghi chú trống rỗng"
 
-#: builtin/commit.c:640
+#: builtin/commit.c:661
 msgid "could not read MERGE_MSG"
 msgstr "không thể đọc MERGE_MSG"
 
-#: builtin/commit.c:644
+#: builtin/commit.c:665
 msgid "could not read SQUASH_MSG"
 msgstr "không thể đọc SQUASH_MSG"
 
-#: builtin/commit.c:648
+#: builtin/commit.c:669
 #, c-format
 msgid "could not read '%s'"
 msgstr "Không thể đọc “%s”."
 
-#: builtin/commit.c:709
+#: builtin/commit.c:730
 msgid "could not write commit template"
 msgstr "không thể ghi mẫu commit"
 
-#: builtin/commit.c:720
+#: builtin/commit.c:741
 #, c-format
 msgid ""
 "\n"
@@ -3740,7 +4116,7 @@
 "\t%s\n"
 "và thử lại.\n"
 
-#: builtin/commit.c:725
+#: builtin/commit.c:746
 #, c-format
 msgid ""
 "\n"
@@ -3755,7 +4131,7 @@
 "\t%s\n"
 "và thử lại.\n"
 
-#: builtin/commit.c:737
+#: builtin/commit.c:758
 #, c-format
 msgid ""
 "Please enter the commit message for your changes. Lines starting\n"
@@ -3766,7 +4142,7 @@
 "bắt đầu bằng “%c” sẽ được bỏ qua, nếu phần chú thích rỗng sẽ hủy bỏ lần "
 "chuyển giao (commit).\n"
 
-#: builtin/commit.c:742
+#: builtin/commit.c:763
 #, c-format
 msgid ""
 "Please enter the commit message for your changes. Lines starting\n"
@@ -3778,372 +4154,372 @@
 "bắt đầu bằng “%c” sẽ được bỏ qua; bạn có thể xóa chúng đi nếu muốn thế.\n"
 "Phần chú thích này nếu trống rỗng sẽ hủy bỏ lần chuyển giao (commit).\n"
 
-#: builtin/commit.c:755
+#: builtin/commit.c:776
 #, c-format
 msgid "%sAuthor:    %s"
 msgstr "%sTác giả:    %s"
 
-#: builtin/commit.c:762
+#: builtin/commit.c:783
 #, c-format
 msgid "%sCommitter: %s"
 msgstr "%sNgười chuyển giao (commit): %s"
 
-#: builtin/commit.c:782
+#: builtin/commit.c:803
 msgid "Cannot read index"
 msgstr "không đọc được bảng mục lục"
 
-#: builtin/commit.c:819
+#: builtin/commit.c:845
 msgid "Error building trees"
 msgstr "Gặp lỗi khi xây dựng cây"
 
-#: builtin/commit.c:834 builtin/tag.c:359
+#: builtin/commit.c:860 builtin/tag.c:359
 #, c-format
 msgid "Please supply the message using either -m or -F option.\n"
 msgstr "Xin hãy áp dụng thông điệp sử dụng hoặc là tùy chọn -m hoặc là -F.\n"
 
-#: builtin/commit.c:931
+#: builtin/commit.c:957
 #, c-format
 msgid "No existing author found with '%s'"
 msgstr "Không tìm thấy tác giả có sẵn với “%s”"
 
-#: builtin/commit.c:946 builtin/commit.c:1140
+#: builtin/commit.c:972 builtin/commit.c:1208
 #, c-format
 msgid "Invalid untracked files mode '%s'"
 msgstr "Chế độ cho các tập tin không bị theo vết không hợp lệ “%s”"
 
-#: builtin/commit.c:976
+#: builtin/commit.c:1009
+msgid "--long and -z are incompatible"
+msgstr "hai tùy chọn -long và -z không tương thích với nhau"
+
+#: builtin/commit.c:1039
 msgid "Using both --reset-author and --author does not make sense"
 msgstr "Sử dụng cả hai tùy chọn --reset-author và --author không hợp lý"
 
-#: builtin/commit.c:987
+#: builtin/commit.c:1050
 msgid "You have nothing to amend."
 msgstr "Không có gì để amend (tu bổ) cả."
 
-#: builtin/commit.c:990
+#: builtin/commit.c:1053
 msgid "You are in the middle of a merge -- cannot amend."
 msgstr ""
 "Bạn đang ở giữa của quá trình hòa trộn -- không thể thực hiện amend (tu bổ)."
 
-#: builtin/commit.c:992
+#: builtin/commit.c:1055
 msgid "You are in the middle of a cherry-pick -- cannot amend."
 msgstr ""
 "Bạn đang ở giữa của quá trình cherry-pick -- không thể thực hiện amend (tu "
 "bổ)."
 
-#: builtin/commit.c:995
+#: builtin/commit.c:1058
 msgid "Options --squash and --fixup cannot be used together"
 msgstr "Các tùy chọn --squash và --fixup không thể sử dụng cùng với nhau"
 
-#: builtin/commit.c:1005
+#: builtin/commit.c:1068
 msgid "Only one of -c/-C/-F/--fixup can be used."
 msgstr "Chỉ một tùy chọn trong số -c/-C/-F/--fixup được sử dụng"
 
-#: builtin/commit.c:1007
+#: builtin/commit.c:1070
 msgid "Option -m cannot be combined with -c/-C/-F/--fixup."
 msgstr "Tùy chọn -m không thể được tổ hợp cùng với -c/-C/-F/--fixup."
 
-#: builtin/commit.c:1015
+#: builtin/commit.c:1078
 msgid "--reset-author can be used only with -C, -c or --amend."
 msgstr ""
 "--reset-author chỉ có thể được sử dụng với tùy chọn -C, -c hay --amend."
 
-#: builtin/commit.c:1032
+#: builtin/commit.c:1095
 msgid "Only one of --include/--only/--all/--interactive/--patch can be used."
 msgstr ""
 "Chỉ một trong các tùy chọn --include/--only/--all/--interactive/--patch được "
 "sử dụng."
 
-#: builtin/commit.c:1034
+#: builtin/commit.c:1097
 msgid "No paths with --include/--only does not make sense."
 msgstr "Không đường dẫn với các tùy chọn --include/--only không hợp lý."
 
-#: builtin/commit.c:1036
+#: builtin/commit.c:1099
 msgid "Clever... amending the last one with dirty index."
 msgstr "Giỏi...  tu bổ cái cuối với bảng mục lục phi nghĩa."
 
-#: builtin/commit.c:1038
+#: builtin/commit.c:1101
 msgid "Explicit paths specified without -i nor -o; assuming --only paths..."
 msgstr ""
 "Những đường dẫn rõ ràng được chỉ ra không có tùy chọn -i cũng không -o; đang "
 "giả định --only những-đường-dẫn..."
 
-#: builtin/commit.c:1048 builtin/tag.c:575
+#: builtin/commit.c:1111 builtin/tag.c:575
 #, c-format
 msgid "Invalid cleanup mode %s"
 msgstr "Chế độ dọn dẹp không hợp lệ %s"
 
-#: builtin/commit.c:1053
+#: builtin/commit.c:1116
 msgid "Paths with -a does not make sense."
 msgstr "Các đường dẫn với tùy chọn -a không hợp lý."
 
-#: builtin/commit.c:1059 builtin/commit.c:1194
-msgid "--long and -z are incompatible"
-msgstr "hai tùy chọn -long và -z không tương thích với nhau"
-
-#: builtin/commit.c:1154 builtin/commit.c:1390
+#: builtin/commit.c:1222 builtin/commit.c:1455
 msgid "show status concisely"
 msgstr "hiển thị trạng thái ở dạng súc tích"
 
-#: builtin/commit.c:1156 builtin/commit.c:1392
+#: builtin/commit.c:1224 builtin/commit.c:1457
 msgid "show branch information"
 msgstr "hiển thị thông tin nhánh"
 
-#: builtin/commit.c:1158 builtin/commit.c:1394 builtin/push.c:426
+#: builtin/commit.c:1226 builtin/commit.c:1459 builtin/push.c:452
 msgid "machine-readable output"
 msgstr "kết xuất dạng máy-có-thể-đọc"
 
-#: builtin/commit.c:1161 builtin/commit.c:1396
+#: builtin/commit.c:1229 builtin/commit.c:1461
 msgid "show status in long format (default)"
 msgstr "hiển thị trạng thái ở định dạng dài (mặc định)"
 
-#: builtin/commit.c:1164 builtin/commit.c:1399
+#: builtin/commit.c:1232 builtin/commit.c:1464
 msgid "terminate entries with NUL"
 msgstr "chấm dứt các mục bằng NUL"
 
-#: builtin/commit.c:1166 builtin/commit.c:1402 builtin/fast-export.c:653
-#: builtin/fast-export.c:656 builtin/tag.c:459
+#: builtin/commit.c:1234 builtin/commit.c:1467 builtin/fast-export.c:667
+#: builtin/fast-export.c:670 builtin/tag.c:459
 msgid "mode"
 msgstr "chế độ"
 
-#: builtin/commit.c:1167 builtin/commit.c:1402
+#: builtin/commit.c:1235 builtin/commit.c:1467
 msgid "show untracked files, optional modes: all, normal, no. (Default: all)"
 msgstr ""
 "hiển thị các tập tin chưa được theo dõi  dấu vết, các chế độ tùy chọn:  all, "
 "normal, no. (Mặc định: all)"
 
-#: builtin/commit.c:1170
+#: builtin/commit.c:1238
 msgid "show ignored files"
 msgstr "hiển thị các tập tin ẩn"
 
-#: builtin/commit.c:1171 parse-options.h:151
+#: builtin/commit.c:1239 parse-options.h:154
 msgid "when"
 msgstr "khi"
 
-#: builtin/commit.c:1172
+#: builtin/commit.c:1240
 msgid ""
 "ignore changes to submodules, optional when: all, dirty, untracked. "
 "(Default: all)"
 msgstr ""
-"bỏ qua các thay đổi trong mô-đun con, tùy chọn khi: all, dirty, untracked. "
+"bỏ qua các thay đổi trong mô-đun-con, tùy chọn khi: all, dirty, untracked. "
 "(Mặc định: all)"
 
-#: builtin/commit.c:1174
+#: builtin/commit.c:1242
 msgid "list untracked files in columns"
 msgstr "hiển thị danh sách các tập-tin chưa được theo dõi trong các cột"
 
-#: builtin/commit.c:1248
+#: builtin/commit.c:1313
 msgid "couldn't look up newly created commit"
 msgstr "không thể tìm thấy lần chuyển giao (commit) mới hơn đã được tạo"
 
-#: builtin/commit.c:1250
+#: builtin/commit.c:1315
 msgid "could not parse newly created commit"
 msgstr ""
 "không thể phân tích cú pháp của đối tượng chuyển giao mới hơn đã được tạo"
 
-#: builtin/commit.c:1291
+#: builtin/commit.c:1356
 msgid "detached HEAD"
 msgstr "đã rời khỏi HEAD"
 
-#: builtin/commit.c:1293
+#: builtin/commit.c:1358
 msgid " (root-commit)"
 msgstr " (root-commit)"
 
-#: builtin/commit.c:1360
+#: builtin/commit.c:1425
 msgid "suppress summary after successful commit"
 msgstr "không hiển thị tổng kết sau khi chuyển giao thành công"
 
-#: builtin/commit.c:1361
+#: builtin/commit.c:1426
 msgid "show diff in commit message template"
 msgstr "hiển thị sự khác biệt trong mẫu tin nhắn chuyển giao"
 
-#: builtin/commit.c:1363
+#: builtin/commit.c:1428
 msgid "Commit message options"
 msgstr "Các tùy chọn ghi chú commit"
 
-#: builtin/commit.c:1364 builtin/tag.c:457
+#: builtin/commit.c:1429 builtin/tag.c:457
 msgid "read message from file"
 msgstr "đọc chú thích từ tập tin"
 
-#: builtin/commit.c:1365
+#: builtin/commit.c:1430
 msgid "author"
 msgstr "tác giả"
 
-#: builtin/commit.c:1365
+#: builtin/commit.c:1430
 msgid "override author for commit"
 msgstr "ghi đè tác giả cho commit"
 
-#: builtin/commit.c:1366 builtin/gc.c:178
+#: builtin/commit.c:1431 builtin/gc.c:178
 msgid "date"
 msgstr "ngày tháng"
 
-#: builtin/commit.c:1366
+#: builtin/commit.c:1431
 msgid "override date for commit"
 msgstr "ghi đè ngày tháng cho commit"
 
-#: builtin/commit.c:1367 builtin/merge.c:208 builtin/notes.c:533
-#: builtin/notes.c:690 builtin/tag.c:455
+#: builtin/commit.c:1432 builtin/merge.c:223 builtin/notes.c:405
+#: builtin/notes.c:562 builtin/tag.c:455
 msgid "message"
 msgstr "thông điệp"
 
-#: builtin/commit.c:1367
+#: builtin/commit.c:1432
 msgid "commit message"
 msgstr "chú thích của lần commit"
 
-#: builtin/commit.c:1368
+#: builtin/commit.c:1433
 msgid "reuse and edit message from specified commit"
 msgstr ""
 "dùng lại các ghi chú từ lần chuyển giao (commit) đã cho nhưng có cho sửa chữa"
 
-#: builtin/commit.c:1369
+#: builtin/commit.c:1434
 msgid "reuse message from specified commit"
 msgstr "dùng lại các ghi chú từ lần chuyển giao (commit) đã cho"
 
-#: builtin/commit.c:1370
+#: builtin/commit.c:1435
 msgid "use autosquash formatted message to fixup specified commit"
 msgstr ""
 "dùng ghi chú có định dạng autosquash để sửa chữa lần chuyển giao đã chỉ ra"
 
-#: builtin/commit.c:1371
+#: builtin/commit.c:1436
 msgid "use autosquash formatted message to squash specified commit"
 msgstr ""
 "dùng lời nhắn có định dạng tự động nén để nén lại các lần chuyển giao đã chỉ "
 "ra"
 
-#: builtin/commit.c:1372
+#: builtin/commit.c:1437
 msgid "the commit is authored by me now (used with -C/-c/--amend)"
 msgstr ""
 "lần chuyển giao nhận tôi là tác giả (được dùng với tùy chọn -C/-c/--amend)"
 
-#: builtin/commit.c:1373 builtin/log.c:1104 builtin/revert.c:109
+#: builtin/commit.c:1438 builtin/log.c:1160 builtin/revert.c:111
 msgid "add Signed-off-by:"
 msgstr "thêm dòng Signed-off-by:"
 
-#: builtin/commit.c:1374
+#: builtin/commit.c:1439
 msgid "use specified template file"
 msgstr "sử dụng tập tin mẫu đã cho"
 
-#: builtin/commit.c:1375
+#: builtin/commit.c:1440
 msgid "force edit of commit"
 msgstr "ép buộc sửa lần commit"
 
-#: builtin/commit.c:1376
+#: builtin/commit.c:1441
 msgid "default"
 msgstr "mặc định"
 
-#: builtin/commit.c:1376 builtin/tag.c:460
+#: builtin/commit.c:1441 builtin/tag.c:460
 msgid "how to strip spaces and #comments from message"
 msgstr "làm thế nào để cắt bỏ khoảng trắng và #ghichú từ mẩu tin nhắn"
 
-#: builtin/commit.c:1377
+#: builtin/commit.c:1442
 msgid "include status in commit message template"
 msgstr "bao gồm các trạng thái ghi mẫu ghi chú chuyển giao (commit)"
 
-#: builtin/commit.c:1378 builtin/merge.c:215 builtin/tag.c:461
+#: builtin/commit.c:1443 builtin/merge.c:230 builtin/tag.c:461
 msgid "key id"
 msgstr "id khóa"
 
-#: builtin/commit.c:1379 builtin/merge.c:216
+#: builtin/commit.c:1444 builtin/merge.c:231
 msgid "GPG sign commit"
 msgstr "ký lần commit dùng GPG"
 
 #. end commit message options
-#: builtin/commit.c:1382
+#: builtin/commit.c:1447
 msgid "Commit contents options"
 msgstr "Các tùy nội dung ghi chú commit"
 
-#: builtin/commit.c:1383
+#: builtin/commit.c:1448
 msgid "commit all changed files"
 msgstr "chuyển giao tất cả các tập tin có thay đổi"
 
-#: builtin/commit.c:1384
+#: builtin/commit.c:1449
 msgid "add specified files to index for commit"
 msgstr "thêm các tập tin đã chỉ ra vào bảng mục lục để chuyển giao (commit)"
 
-#: builtin/commit.c:1385
+#: builtin/commit.c:1450
 msgid "interactively add files"
 msgstr "thêm các tập-tin bằng tương tác"
 
-#: builtin/commit.c:1386
+#: builtin/commit.c:1451
 msgid "interactively add changes"
 msgstr "thêm các thay đổi bằng tương tác"
 
-#: builtin/commit.c:1387
+#: builtin/commit.c:1452
 msgid "commit only specified files"
 msgstr "chỉ chuyển giao các tập tin đã chỉ ra"
 
-#: builtin/commit.c:1388
+#: builtin/commit.c:1453
 msgid "bypass pre-commit hook"
 msgstr "vòng qua móc (hook) pre-commit"
 
-#: builtin/commit.c:1389
+#: builtin/commit.c:1454
 msgid "show what would be committed"
 msgstr "hiển thị xem cái gì có thể được chuyển giao"
 
-#: builtin/commit.c:1400
+#: builtin/commit.c:1465
 msgid "amend previous commit"
 msgstr "tu bổ (amend) lần commit trước"
 
-#: builtin/commit.c:1401
+#: builtin/commit.c:1466
 msgid "bypass post-rewrite hook"
 msgstr "vòng qua móc (hook) post-rewrite"
 
-#: builtin/commit.c:1406
+#: builtin/commit.c:1471
 msgid "ok to record an empty change"
 msgstr "ok để ghi lại một thay đổi trống rỗng"
 
-#: builtin/commit.c:1409
+#: builtin/commit.c:1474
 msgid "ok to record a change with an empty message"
 msgstr "ok để ghi các thay đổi với lời nhắn trống rỗng"
 
-#: builtin/commit.c:1441
+#: builtin/commit.c:1507
 msgid "could not parse HEAD commit"
 msgstr "không thể phân tích commit (lần chuyển giao) HEAD"
 
-#: builtin/commit.c:1479 builtin/merge.c:510
+#: builtin/commit.c:1545 builtin/merge.c:525
 #, c-format
 msgid "could not open '%s' for reading"
 msgstr "không thể mở “%s” để đọc"
 
-#: builtin/commit.c:1486
+#: builtin/commit.c:1552
 #, c-format
 msgid "Corrupt MERGE_HEAD file (%s)"
 msgstr "Tập tin MERGE_HEAD sai hỏng (%s)"
 
-#: builtin/commit.c:1493
+#: builtin/commit.c:1559
 msgid "could not read MERGE_MODE"
 msgstr "không thể đọc MERGE_MODE"
 
-#: builtin/commit.c:1512
+#: builtin/commit.c:1578
 #, c-format
 msgid "could not read commit message: %s"
 msgstr "không thể đọc thông điệp (message) commit (lần chuyển giao): %s"
 
-#: builtin/commit.c:1526
+#: builtin/commit.c:1592
 #, c-format
 msgid "Aborting commit; you did not edit the message.\n"
 msgstr ""
 "Đang bỏ qua việc chuyển giao (commit); bạn đã không biên soạn thông điệp "
 "(message).\n"
 
-#: builtin/commit.c:1531
+#: builtin/commit.c:1597
 #, c-format
 msgid "Aborting commit due to empty commit message.\n"
 msgstr ""
 "Đang bỏ qua lần chuyển giao (commit) bởi vì thông điệp của nó trống rỗng.\n"
 
-#: builtin/commit.c:1546 builtin/merge.c:847 builtin/merge.c:872
+#: builtin/commit.c:1612 builtin/merge.c:861 builtin/merge.c:886
 msgid "failed to write commit object"
 msgstr "gặp lỗi khi ghi đối tượng chuyển giao (commit)"
 
-#: builtin/commit.c:1567
+#: builtin/commit.c:1633
 msgid "cannot lock HEAD ref"
 msgstr "không thể khóa HEAD ref (tham chiếu)"
 
-#: builtin/commit.c:1571
+#: builtin/commit.c:1637
 msgid "cannot update HEAD ref"
 msgstr "không thể cập nhật ref (tham chiếu) HEAD"
 
-#: builtin/commit.c:1582
+#: builtin/commit.c:1648
 msgid ""
 "Repository has been updated, but unable to write\n"
 "new_index file. Check that disk is not full or quota is\n"
@@ -4158,171 +4534,183 @@
 msgid "git config [options]"
 msgstr "git config [các-tùy-chọn]"
 
-#: builtin/config.c:51
+#: builtin/config.c:52
 msgid "Config file location"
 msgstr "Vị trí tập tin cấu hình"
 
-#: builtin/config.c:52
+#: builtin/config.c:53
 msgid "use global config file"
 msgstr "đặt tập tin cấu hình cần toàn cục"
 
-#: builtin/config.c:53
+#: builtin/config.c:54
 msgid "use system config file"
 msgstr "sử dụng tập tin cấu hình hệ thống"
 
-#: builtin/config.c:54
+#: builtin/config.c:55
 msgid "use repository config file"
 msgstr "dùng tập tin cấu hình của kho"
 
-#: builtin/config.c:55
+#: builtin/config.c:56
 msgid "use given config file"
 msgstr "sử dụng tập tin cấu hình đã cho"
 
-#: builtin/config.c:56
+#: builtin/config.c:57
+msgid "blob-id"
+msgstr "blob-id"
+
+#: builtin/config.c:57
+msgid "read config from given blob object"
+msgstr "đọc cấu hình từ đối tượng blob đã cho"
+
+#: builtin/config.c:58
 msgid "Action"
 msgstr "Hành động"
 
-#: builtin/config.c:57
+#: builtin/config.c:59
 msgid "get value: name [value-regex]"
 msgstr "lấy giá-trị: tên [value-regex]"
 
-#: builtin/config.c:58
+#: builtin/config.c:60
 msgid "get all values: key [value-regex]"
 msgstr "lấy tất cả giá-trị: khóa [value-regex]"
 
-#: builtin/config.c:59
+#: builtin/config.c:61
 msgid "get values for regexp: name-regex [value-regex]"
 msgstr "lấy giá trị cho regexp: name-regex [value-regex]"
 
-#: builtin/config.c:60
+#: builtin/config.c:62
 msgid "replace all matching variables: name value [value_regex]"
 msgstr "thay thế tất cả các biến khớp mẫu: tên giá-trị [value_regex]"
 
-#: builtin/config.c:61
+#: builtin/config.c:63
 msgid "add a new variable: name value"
 msgstr "thêm biến mới: tên giá-trị"
 
-#: builtin/config.c:62
+#: builtin/config.c:64
 msgid "remove a variable: name [value-regex]"
 msgstr "gỡ bỏ biến: tên [value-regex]"
 
-#: builtin/config.c:63
+#: builtin/config.c:65
 msgid "remove all matches: name [value-regex]"
 msgstr "gỡ bỏ mọi cái khớp: tên [value-regex]"
 
-#: builtin/config.c:64
+#: builtin/config.c:66
 msgid "rename section: old-name new-name"
 msgstr "đổi tên chương: tên-cũ tên-mới"
 
-#: builtin/config.c:65
+#: builtin/config.c:67
 msgid "remove a section: name"
 msgstr "gỡ bỏ chương: tên"
 
-#: builtin/config.c:66
+#: builtin/config.c:68
 msgid "list all"
 msgstr "liệt kê tất"
 
-#: builtin/config.c:67
+#: builtin/config.c:69
 msgid "open an editor"
 msgstr "mở một trình biên soạn"
 
-#: builtin/config.c:68 builtin/config.c:69
+#: builtin/config.c:70 builtin/config.c:71
 msgid "slot"
 msgstr "khe"
 
-#: builtin/config.c:68
+#: builtin/config.c:70
 msgid "find the color configured: [default]"
 msgstr "tìm cấu hình màu sắc: [mặc định]"
 
-#: builtin/config.c:69
+#: builtin/config.c:71
 msgid "find the color setting: [stdout-is-tty]"
 msgstr "tìm các cài đặt về màu sắc: [stdout-là-tty]"
 
-#: builtin/config.c:70
+#: builtin/config.c:72
 msgid "Type"
 msgstr "Kiểu"
 
-#: builtin/config.c:71
+#: builtin/config.c:73
 msgid "value is \"true\" or \"false\""
 msgstr "giá trị là \"true\" hoặc \"false\""
 
-#: builtin/config.c:72
+#: builtin/config.c:74
 msgid "value is decimal number"
 msgstr "giá trị ở dạng số thập phân"
 
-#: builtin/config.c:73
+#: builtin/config.c:75
 msgid "value is --bool or --int"
 msgstr "giá trị là --bool hoặc --int"
 
-#: builtin/config.c:74
+#: builtin/config.c:76
 msgid "value is a path (file or directory name)"
 msgstr "giá trị là đường dẫn (tên tập tin hay thư mục)"
 
-#: builtin/config.c:75
+#: builtin/config.c:77
 msgid "Other"
 msgstr "Khác"
 
-#: builtin/config.c:76
+#: builtin/config.c:78
 msgid "terminate values with NUL byte"
 msgstr "chấm dứt giá trị với byte NUL"
 
-#: builtin/config.c:77
+#: builtin/config.c:79
 msgid "respect include directives on lookup"
 msgstr "tôn trọng kể cà các hướng trong tìm kiếm"
 
 #: builtin/count-objects.c:82
-msgid "git count-objects [-v]"
-msgstr "git count-objects [-v]"
+msgid "git count-objects [-v] [-H | --human-readable]"
+msgstr "git count-objects [-v] [-H | --human-readable]"
 
-#: builtin/describe.c:15
+#: builtin/count-objects.c:97
+msgid "print sizes in human readable format"
+msgstr "hiển thị kích cỡ theo định dạng dành cho người đọc"
+
+#: builtin/describe.c:16
 msgid "git describe [options] <committish>*"
 msgstr "git describe [các-tùy-chọn] <committish>*"
 
-#: builtin/describe.c:16
+#: builtin/describe.c:17
 msgid "git describe [options] --dirty"
 msgstr "git describe [các-tùy-chọn] --dirty"
 
-#: builtin/describe.c:233
+#: builtin/describe.c:237
 #, c-format
 msgid "annotated tag %s not available"
 msgstr "thẻ đã được ghi chú %s không sẵn để dùng"
 
-#: builtin/describe.c:237
+#: builtin/describe.c:241
 #, c-format
 msgid "annotated tag %s has no embedded name"
 msgstr "thẻ được chú giải %s không có tên nhúng"
 
-#: builtin/describe.c:239
+#: builtin/describe.c:243
 #, c-format
 msgid "tag '%s' is really '%s' here"
 msgstr "thẻ “%s” đã thực sự ở đây “%s” rồi"
 
-#: builtin/describe.c:266
+#: builtin/describe.c:270
 #, c-format
 msgid "Not a valid object name %s"
 msgstr "Không phải tên đối tượng %s hợp lệ"
 
-#: builtin/describe.c:269
+#: builtin/describe.c:273
 #, c-format
 msgid "%s is not a valid '%s' object"
 msgstr "%s không phải là một đối tượng “%s” hợp lệ"
 
-#: builtin/describe.c:286
+#: builtin/describe.c:290
 #, c-format
 msgid "no tag exactly matches '%s'"
 msgstr "không có thẻ nào khớp chính xác với “%s”"
 
-#: builtin/describe.c:288
+#: builtin/describe.c:292
 #, c-format
 msgid "searching to describe %s\n"
 msgstr "Đang tìm kiếm để mô tả %s\n"
 
-#: builtin/describe.c:328
+#: builtin/describe.c:332
 #, c-format
 msgid "finished search at %s\n"
 msgstr "việc tìm kiếm đã kết thúc tại %s\n"
 
-#: builtin/describe.c:352
+#: builtin/describe.c:359
 #, c-format
 msgid ""
 "No annotated tags can describe '%s'.\n"
@@ -4331,7 +4719,7 @@
 "Không có thẻ được chú giải nào được mô tả là “%s”.\n"
 "Tuy nhiên, ở đây có những thẻ không được chú giải: hãy thử --tags."
 
-#: builtin/describe.c:356
+#: builtin/describe.c:363
 #, c-format
 msgid ""
 "No tags can describe '%s'.\n"
@@ -4340,12 +4728,12 @@
 "Không có thẻ (tag) có thể mô tả “%s”.\n"
 "Hãy thử --always, hoặt tạo một số thẻ."
 
-#: builtin/describe.c:377
+#: builtin/describe.c:384
 #, c-format
 msgid "traversed %lu commits\n"
 msgstr "đã xuyên %lu qua lần chuyển giao (commit)\n"
 
-#: builtin/describe.c:380
+#: builtin/describe.c:387
 #, c-format
 msgid ""
 "more than %i tags found; listed %i most recent\n"
@@ -4354,59 +4742,63 @@
 "tìm thấy nhiều hơn %i thẻ (tag); đã liệt kê %i gần đây nhất\n"
 "bỏ đi tìm kiếm tại %s\n"
 
-#: builtin/describe.c:402
+#: builtin/describe.c:409
 msgid "find the tag that comes after the commit"
 msgstr "tìm các thẻ mà nó đến trước lần chuyển giao"
 
-#: builtin/describe.c:403
+#: builtin/describe.c:410
 msgid "debug search strategy on stderr"
 msgstr "chiến lược tìm kiếm trên đầu ra lỗi chuẩn stderr"
 
-#: builtin/describe.c:404
+#: builtin/describe.c:411
 msgid "use any ref"
 msgstr "dùng ref bất kỳ"
 
-#: builtin/describe.c:405
+#: builtin/describe.c:412
 msgid "use any tag, even unannotated"
-msgstr "dùng thẻ bất kỳ, cả khi `unannotated'"
+msgstr "dùng thẻ bất kỳ, cả khi “unannotated”"
 
-#: builtin/describe.c:406
+#: builtin/describe.c:413
 msgid "always use long format"
 msgstr "luôn dùng định dạng dài"
 
-#: builtin/describe.c:409
+#: builtin/describe.c:414
+msgid "only follow first parent"
+msgstr "chỉ theo cha mẹ đầu tiên"
+
+#: builtin/describe.c:417
 msgid "only output exact matches"
 msgstr "chỉ xuất những gì khớp chính xác"
 
-#: builtin/describe.c:411
+#: builtin/describe.c:419
 msgid "consider <n> most recent tags (default: 10)"
 msgstr "coi như  <n> thẻ gần đây nhất (mặc định: 10)"
 
-#: builtin/describe.c:413
+#: builtin/describe.c:421
 msgid "only consider tags matching <pattern>"
 msgstr "chỉ cân nhắc đến những thẻ khớp với  <mẫu>"
 
-#: builtin/describe.c:415 builtin/name-rev.c:238
+#: builtin/describe.c:423 builtin/name-rev.c:322
 msgid "show abbreviated commit object as fallback"
 msgstr "hiển thị đối tượng chuyển giao vắn tắt như là fallback"
 
-#: builtin/describe.c:416
+#: builtin/describe.c:424
 msgid "mark"
 msgstr "dấu"
 
-#: builtin/describe.c:417
+#: builtin/describe.c:425
 msgid "append <mark> on dirty working tree (default: \"-dirty\")"
 msgstr "thêm <dấu> trên cây thư mục làm việc bẩn (mặc định \"-dirty\")"
 
-#: builtin/describe.c:435
+#: builtin/describe.c:443
 msgid "--long is incompatible with --abbrev=0"
 msgstr "--long là xung khắc với tùy chọn --abbrev=0"
 
-#: builtin/describe.c:461
+#: builtin/describe.c:469
 msgid "No names found, cannot describe anything."
 msgstr "Không tìm thấy các tên, không thể mô tả gì cả."
 
-#: builtin/describe.c:481
+#: builtin/describe.c:489
 msgid "--dirty is incompatible with committishes"
 msgstr "--dirty là xung khắc với các tùy chọn dành cho chuyển giao (commit)"
 
@@ -4415,31 +4807,26 @@
 msgid "'%s': not a regular file or symlink"
 msgstr "“%s”: không phải tập tin bình thường hay liên kết tượng trưng"
 
-#: builtin/diff.c:228
+#: builtin/diff.c:230
 #, c-format
 msgid "invalid option: %s"
 msgstr "tùy chọn sai: %s"
 
-#: builtin/diff.c:305
+#: builtin/diff.c:307
 msgid "Not a git repository"
 msgstr "Không phải là kho git"
 
-#: builtin/diff.c:348
+#: builtin/diff.c:350
 #, c-format
 msgid "invalid object '%s' given."
 msgstr "đối tượng đã cho “%s” không hợp lệ."
 
-#: builtin/diff.c:353
-#, c-format
-msgid "more than %d trees given: '%s'"
-msgstr "đã chỉ ra nhiều hơn %d cây (tree): “%s”"
-
-#: builtin/diff.c:363
+#: builtin/diff.c:359
 #, c-format
 msgid "more than two blobs given: '%s'"
 msgstr "đã cho nhiều hơn hai đối tượng blob: “%s”"
 
-#: builtin/diff.c:371
+#: builtin/diff.c:366
 #, c-format
 msgid "unhandled object '%s' given."
 msgstr "đã cho đối tượng không thể nắm giữ “%s”."
@@ -4448,39 +4835,39 @@
 msgid "git fast-export [rev-list-opts]"
 msgstr "git fast-export [rev-list-opts]"
 
-#: builtin/fast-export.c:652
+#: builtin/fast-export.c:666
 msgid "show progress after <n> objects"
 msgstr "hiển thị tiến triển sau <n> đối tượng"
 
-#: builtin/fast-export.c:654
+#: builtin/fast-export.c:668
 msgid "select handling of signed tags"
 msgstr "chọn điều khiển của thẻ đã ký"
 
-#: builtin/fast-export.c:657
+#: builtin/fast-export.c:671
 msgid "select handling of tags that tag filtered objects"
 msgstr "chọn sự xử lý của các thẻ, cái mà đánh thẻ các đối tượng được lọc ra"
 
-#: builtin/fast-export.c:660
+#: builtin/fast-export.c:674
 msgid "Dump marks to this file"
 msgstr "Đổ các đánh dấu này vào tập-tin"
 
-#: builtin/fast-export.c:662
+#: builtin/fast-export.c:676
 msgid "Import marks from this file"
 msgstr "nhập vào đánh dấu từ tập tin này"
 
-#: builtin/fast-export.c:664
+#: builtin/fast-export.c:678
 msgid "Fake a tagger when tags lack one"
 msgstr "Làm giả một cái thẻ khi thẻ bị thiếu một cái"
 
-#: builtin/fast-export.c:666
+#: builtin/fast-export.c:680
 msgid "Output full tree for each commit"
 msgstr "Xuất ra toàn bộ cây cho mỗi lần chuyển giao"
 
-#: builtin/fast-export.c:668
+#: builtin/fast-export.c:682
 msgid "Use the done feature to terminate the stream"
 msgstr "Sử dụng tính năng done để chấm dứt luồng dữ liệu"
 
-#: builtin/fast-export.c:669
+#: builtin/fast-export.c:683
 msgid "Skip output of blob data"
 msgstr "Bỏ qua kết xuất của dữ liệu blob"
 
@@ -4502,7 +4889,7 @@
 
 #: builtin/fetch.c:60
 msgid "fetch from all remotes"
-msgstr "fetch từ tất cả các máy chủ"
+msgstr "lấy về từ tất cả các máy chủ"
 
 #: builtin/fetch.c:62
 msgid "append to .git/FETCH_HEAD instead of overwriting"
@@ -4518,15 +4905,15 @@
 
 #: builtin/fetch.c:67
 msgid "fetch from multiple remotes"
-msgstr "fetch từ nhiều máy chủ cùng lúc"
+msgstr "lấy từ nhiều máy chủ cùng lúc"
 
 #: builtin/fetch.c:69
 msgid "fetch all tags and associated objects"
-msgstr "lấy (fetch) tất cả các thẻ cùng với các đối tượng liên quan đến nó"
+msgstr "lấy tất cả các thẻ cùng với các đối tượng liên quan đến nó"
 
 #: builtin/fetch.c:71
 msgid "do not fetch all tags (--no-tags)"
-msgstr "không lấy (fetch) tất cả các thẻ (--no-tags)"
+msgstr "không lấy tất cả các thẻ (--no-tags)"
 
 #: builtin/fetch.c:73
 msgid "prune remote-tracking branches no longer on remote"
@@ -4540,7 +4927,7 @@
 
 #: builtin/fetch.c:75
 msgid "control recursive fetching of submodules"
-msgstr "điều khiển việc lấy về (fetch) đệ quy trong các mô-đun-con"
+msgstr "điều khiển việc lấy về đệ quy trong các mô-đun-con"
 
 #: builtin/fetch.c:79
 msgid "keep downloaded pack"
@@ -4548,7 +4935,7 @@
 
 #: builtin/fetch.c:81
 msgid "allow updating of HEAD ref"
-msgstr "cho phép cập nhật ref (tham chiếu) HEAD"
+msgstr "cho phép cập nhật th.chiếu HEAD"
 
 #: builtin/fetch.c:84
 msgid "deepen history of shallow clone"
@@ -4558,7 +4945,7 @@
 msgid "convert to a complete repository"
 msgstr "chuyển đổi hoàn toàn sang kho git"
 
-#: builtin/fetch.c:88 builtin/log.c:1121
+#: builtin/fetch.c:88 builtin/log.c:1177
 msgid "dir"
 msgstr "tmục"
 
@@ -4570,76 +4957,76 @@
 msgid "default mode for recursion"
 msgstr "chế độ mặc định cho đệ qui"
 
-#: builtin/fetch.c:204
+#: builtin/fetch.c:220
 msgid "Couldn't find remote ref HEAD"
 msgstr "Không thể tìm thấy máy chủ cho tham chiếu HEAD"
 
-#: builtin/fetch.c:257
+#: builtin/fetch.c:273
 #, c-format
 msgid "object %s not found"
 msgstr "Không tìm thấy đối tượng %s"
 
-#: builtin/fetch.c:262
+#: builtin/fetch.c:278
 msgid "[up to date]"
 msgstr "[đã cập nhật]"
 
-#: builtin/fetch.c:276
+#: builtin/fetch.c:292
 #, c-format
 msgid "! %-*s %-*s -> %s  (can't fetch in current branch)"
 msgstr "! %-*s %-*s -> %s  (không thể fetch (lấy) về nhánh hiện hành)"
 
-#: builtin/fetch.c:277 builtin/fetch.c:363
+#: builtin/fetch.c:293 builtin/fetch.c:379
 msgid "[rejected]"
 msgstr "[Bị từ chối]"
 
-#: builtin/fetch.c:288
+#: builtin/fetch.c:304
 msgid "[tag update]"
 msgstr "[cập nhật thẻ]"
 
-#: builtin/fetch.c:290 builtin/fetch.c:325 builtin/fetch.c:343
+#: builtin/fetch.c:306 builtin/fetch.c:341 builtin/fetch.c:359
 msgid "  (unable to update local ref)"
 msgstr "  (không thể cập nhật tham chiếu (ref) nội bộ)"
 
-#: builtin/fetch.c:308
+#: builtin/fetch.c:324
 msgid "[new tag]"
 msgstr "[thẻ mới]"
 
-#: builtin/fetch.c:311
+#: builtin/fetch.c:327
 msgid "[new branch]"
 msgstr "[nhánh mới]"
 
-#: builtin/fetch.c:314
+#: builtin/fetch.c:330
 msgid "[new ref]"
 msgstr "[ref (tham chiếu) mới]"
 
-#: builtin/fetch.c:359
+#: builtin/fetch.c:375
 msgid "unable to update local ref"
 msgstr "không thể cập nhật tham chiếu (ref) nội bộ"
 
-#: builtin/fetch.c:359
+#: builtin/fetch.c:375
 msgid "forced update"
 msgstr "cưỡng bức cập nhật"
 
-#: builtin/fetch.c:365
+#: builtin/fetch.c:381
 msgid "(non-fast-forward)"
 msgstr "(non-fast-forward)"
 
-#: builtin/fetch.c:396 builtin/fetch.c:688
+#: builtin/fetch.c:412 builtin/fetch.c:718
 #, c-format
 msgid "cannot open %s: %s\n"
 msgstr "không thể mở %s: %s\n"
 
-#: builtin/fetch.c:405
+#: builtin/fetch.c:421
 #, c-format
 msgid "%s did not send all necessary objects\n"
 msgstr "%s đã không gửi tất cả các đối tượng cần thiết\n"
 
-#: builtin/fetch.c:491
+#: builtin/fetch.c:520
 #, c-format
 msgid "From %.*s\n"
 msgstr "Từ %.*s\n"
 
-#: builtin/fetch.c:502
+#: builtin/fetch.c:531
 #, c-format
 msgid ""
 "some local refs could not be updated; try running\n"
@@ -4648,57 +5035,57 @@
 "một số tham chiếu (refs) nội bộ không thể được cập nhật; hãy thử chạy\n"
 " “git remote prune %s” để bỏ đi những nhánh cũ, hay bị xung đột"
 
-#: builtin/fetch.c:552
+#: builtin/fetch.c:581
 #, c-format
 msgid "   (%s will become dangling)"
 msgstr "   (%s sẽ trở thành không đầu (không được quản lý))"
 
-#: builtin/fetch.c:553
+#: builtin/fetch.c:582
 #, c-format
 msgid "   (%s has become dangling)"
 msgstr "   (%s đã trở thành không đầu (không được quản lý))"
 
-#: builtin/fetch.c:560
+#: builtin/fetch.c:589
 msgid "[deleted]"
 msgstr "[đã xóa]"
 
-#: builtin/fetch.c:561 builtin/remote.c:1055
+#: builtin/fetch.c:590 builtin/remote.c:1055
 msgid "(none)"
 msgstr "(không)"
 
-#: builtin/fetch.c:678
+#: builtin/fetch.c:708
 #, c-format
 msgid "Refusing to fetch into current branch %s of non-bare repository"
 msgstr ""
 "Từ chối việc lấy (fetch) vào trong nhánh hiện tại %s của một kho chứa không "
 "phải kho trần (bare)"
 
-#: builtin/fetch.c:712
+#: builtin/fetch.c:742
 #, c-format
 msgid "Don't know how to fetch from %s"
-msgstr "Không biết làm cách nào để lấy về (fetch) từ %s"
+msgstr "Không biết làm cách nào để lấy về từ %s"
 
-#: builtin/fetch.c:789
+#: builtin/fetch.c:823
 #, c-format
 msgid "Option \"%s\" value \"%s\" is not valid for %s"
 msgstr "Tùy chọn \"%s\" có giá trị \"%s\" là không hợp lệ cho %s"
 
-#: builtin/fetch.c:792
+#: builtin/fetch.c:826
 #, c-format
 msgid "Option \"%s\" is ignored for %s\n"
 msgstr "Tùy chọn \"%s\" bị bỏ qua với %s\n"
 
-#: builtin/fetch.c:894
+#: builtin/fetch.c:928
 #, c-format
 msgid "Fetching %s\n"
-msgstr "Đang lấy (fetch) %s\n"
+msgstr "Đang lấy về %s\n"
 
-#: builtin/fetch.c:896 builtin/remote.c:100
+#: builtin/fetch.c:930 builtin/remote.c:100
 #, c-format
 msgid "Could not fetch %s"
-msgstr "không thể fetch (lấy) %s"
+msgstr "không thể lấy về %s"
 
-#: builtin/fetch.c:915
+#: builtin/fetch.c:949
 msgid ""
 "No remote repository specified.  Please, specify either a URL or a\n"
 "remote name from which new revisions should be fetched."
@@ -4706,32 +5093,32 @@
 "Chưa chỉ ra kho chứa máy chủ.  Xin hãy chỉ định hoặc là URL hoặc\n"
 "tên máy chủ từ cái mà những điểm xét duyệt mới có thể được fetch (lấy về)."
 
-#: builtin/fetch.c:935
+#: builtin/fetch.c:969
 msgid "You need to specify a tag name."
 msgstr "Bạn phải định rõ tên thẻ."
 
-#: builtin/fetch.c:981
+#: builtin/fetch.c:1015
 msgid "--depth and --unshallow cannot be used together"
 msgstr "tùy chọn --depth và --unshallow không thể sử dụng cùng với nhau"
 
-#: builtin/fetch.c:983
+#: builtin/fetch.c:1017
 msgid "--unshallow on a complete repository does not make sense"
 msgstr "--unshallow trên kho hoàn chỉnh là không hợp lý"
 
-#: builtin/fetch.c:1002
+#: builtin/fetch.c:1036
 msgid "fetch --all does not take a repository argument"
 msgstr "lệnh lấy về \"fetch --all\" không lấy đối số kho chứa"
 
-#: builtin/fetch.c:1004
+#: builtin/fetch.c:1038
 msgid "fetch --all does not make sense with refspecs"
 msgstr "lệnh lấy về \"fetch --all\" không hợp lý với refspecs"
 
-#: builtin/fetch.c:1015
+#: builtin/fetch.c:1049
 #, c-format
 msgid "No such remote or remote group: %s"
 msgstr "không có nhóm máy chủ hay máy chủ như thế: %s"
 
-#: builtin/fetch.c:1023
+#: builtin/fetch.c:1057
 msgid "Fetching a group and specifying refspecs does not make sense"
 msgstr "Việc lấy về cả một nhóm và chỉ định refspecs không hợp lý"
 
@@ -4740,29 +5127,29 @@
 msgstr ""
 "git fmt-merge-msg [-m <thông điệp>] [--log[=<n>]|--no-log] [--file <tập-tin>]"
 
-#: builtin/fmt-merge-msg.c:659 builtin/fmt-merge-msg.c:662 builtin/grep.c:701
-#: builtin/merge.c:188 builtin/show-branch.c:656 builtin/show-ref.c:175
-#: builtin/tag.c:446 parse-options.h:133 parse-options.h:239
+#: builtin/fmt-merge-msg.c:663 builtin/fmt-merge-msg.c:666 builtin/grep.c:700
+#: builtin/merge.c:203 builtin/show-branch.c:655 builtin/show-ref.c:179
+#: builtin/tag.c:446 parse-options.h:133 parse-options.h:243
 msgid "n"
 msgstr "n"
 
-#: builtin/fmt-merge-msg.c:660
+#: builtin/fmt-merge-msg.c:664
 msgid "populate log with at most <n> entries from shortlog"
 msgstr "gắn nhật ký với ít nhất <n> mục từ lệnh “shortlog”"
 
-#: builtin/fmt-merge-msg.c:663
+#: builtin/fmt-merge-msg.c:667
 msgid "alias for --log (deprecated)"
 msgstr "bí danh cho --log (không được dùng)"
 
-#: builtin/fmt-merge-msg.c:666
+#: builtin/fmt-merge-msg.c:670
 msgid "text"
 msgstr "văn bản"
 
-#: builtin/fmt-merge-msg.c:667
+#: builtin/fmt-merge-msg.c:671
 msgid "use <text> as start of message"
 msgstr "dùng <văn bản thường> để bắt đầu ghi chú"
 
-#: builtin/fmt-merge-msg.c:668
+#: builtin/fmt-merge-msg.c:672
 msgid "file to read from"
 msgstr "tập tin để đọc dữ liệu từ đó"
 
@@ -4902,223 +5289,223 @@
 msgid "grep: failed to create thread: %s"
 msgstr "grep: gặp lỗi tạo tuyến (thread): %s"
 
-#: builtin/grep.c:365
+#: builtin/grep.c:364
 #, c-format
 msgid "Failed to chdir: %s"
 msgstr "Gặp lỗi với lệnh chdir: %s"
 
-#: builtin/grep.c:443 builtin/grep.c:478
+#: builtin/grep.c:442 builtin/grep.c:477
 #, c-format
 msgid "unable to read tree (%s)"
 msgstr "không thể đọc cây (%s)"
 
-#: builtin/grep.c:493
+#: builtin/grep.c:492
 #, c-format
 msgid "unable to grep from object of type %s"
 msgstr "không thể thực hiện lệnh grep (lọc tìm) từ đối tượng thuộc kiểu %s"
 
-#: builtin/grep.c:551
+#: builtin/grep.c:550
 #, c-format
 msgid "switch `%c' expects a numerical value"
 msgstr "chuyển đến “%c” cần một giá trị bằng số"
 
-#: builtin/grep.c:568
+#: builtin/grep.c:567
 #, c-format
 msgid "cannot open '%s'"
 msgstr "không mở được “%s”"
 
-#: builtin/grep.c:643
+#: builtin/grep.c:642
 msgid "search in index instead of in the work tree"
 msgstr "tìm trong bảng mục lục thay vì trong cây làm việc"
 
-#: builtin/grep.c:645
+#: builtin/grep.c:644
 msgid "find in contents not managed by git"
 msgstr "tìm trong nội dung không được quản lý bởi git"
 
-#: builtin/grep.c:647
+#: builtin/grep.c:646
 msgid "search in both tracked and untracked files"
 msgstr "tìm kiếm các tập tin được và chưa được theo dõi dấu vết"
 
-#: builtin/grep.c:649
+#: builtin/grep.c:648
 msgid "search also in ignored files"
 msgstr "tìm cả trong các tập tin đã bị lờ đi"
 
-#: builtin/grep.c:652
+#: builtin/grep.c:651
 msgid "show non-matching lines"
 msgstr "hiển thị  những dòng không khớp với mẫu"
 
-#: builtin/grep.c:654
+#: builtin/grep.c:653
 msgid "case insensitive matching"
 msgstr "phân biệt chữ hoa/thường"
 
-#: builtin/grep.c:656
+#: builtin/grep.c:655
 msgid "match patterns only at word boundaries"
 msgstr "chỉ khớp mẫu tại đường ranh giới từ"
 
-#: builtin/grep.c:658
+#: builtin/grep.c:657
 msgid "process binary files as text"
 msgstr "xử lý tập tin nhị phân như là dạng văn bản thường"
 
-#: builtin/grep.c:660
+#: builtin/grep.c:659
 msgid "don't match patterns in binary files"
 msgstr "không khớp mẫu trong các tập tin nhị phân"
 
-#: builtin/grep.c:663
+#: builtin/grep.c:662
 msgid "descend at most <depth> levels"
 msgstr "giảm xuống ít nhất mức <sâu>"
 
-#: builtin/grep.c:667
+#: builtin/grep.c:666
 msgid "use extended POSIX regular expressions"
 msgstr "dùng biểu thức chính qui POSIX có mở rộng"
 
-#: builtin/grep.c:670
+#: builtin/grep.c:669
 msgid "use basic POSIX regular expressions (default)"
 msgstr "sử dụng biểu thức chính quy kiểu POSIX (mặc định)"
 
-#: builtin/grep.c:673
+#: builtin/grep.c:672
 msgid "interpret patterns as fixed strings"
 msgstr "diễn dịch các mẫu như là chuỗi cố định"
 
-#: builtin/grep.c:676
+#: builtin/grep.c:675
 msgid "use Perl-compatible regular expressions"
 msgstr "sử dụng biểu thức chính quy tương thích Perl"
 
-#: builtin/grep.c:679
+#: builtin/grep.c:678
 msgid "show line numbers"
 msgstr "hiển thị số của dòng"
 
-#: builtin/grep.c:680
+#: builtin/grep.c:679
 msgid "don't show filenames"
 msgstr "không hiển thị tên tập tin"
 
-#: builtin/grep.c:681
+#: builtin/grep.c:680
 msgid "show filenames"
 msgstr "hiển thị các tên tập tin"
 
-#: builtin/grep.c:683
+#: builtin/grep.c:682
 msgid "show filenames relative to top directory"
 msgstr "hiển thị tên tập tin tương đối với thư mục đỉnh (top)"
 
-#: builtin/grep.c:685
+#: builtin/grep.c:684
 msgid "show only filenames instead of matching lines"
 msgstr "chỉ hiển thị tên tập tin thay vì những dòng khớp với mẫu"
 
-#: builtin/grep.c:687
+#: builtin/grep.c:686
 msgid "synonym for --files-with-matches"
 msgstr "đồng nghĩa với --files-with-matches"
 
-#: builtin/grep.c:690
+#: builtin/grep.c:689
 msgid "show only the names of files without match"
 msgstr "chỉ hiển thị tên cho những tập tin không khớp với mẫu"
 
-#: builtin/grep.c:692
+#: builtin/grep.c:691
 msgid "print NUL after filenames"
 msgstr "thêm NUL vào sau tên tập tin"
 
-#: builtin/grep.c:694
+#: builtin/grep.c:693
 msgid "show the number of matches instead of matching lines"
 msgstr "hiển thị số lượng khớp thay vì những dòng khớp với mẫu"
 
-#: builtin/grep.c:695
+#: builtin/grep.c:694
 msgid "highlight matches"
 msgstr "tô sáng cái khớp"
 
-#: builtin/grep.c:697
+#: builtin/grep.c:696
 msgid "print empty line between matches from different files"
 msgstr "hiển thị dòng trống giữa các lần khớp từ các tập tin khác biệt"
 
-#: builtin/grep.c:699
+#: builtin/grep.c:698
 msgid "show filename only once above matches from same file"
 msgstr ""
 "hiển thị tên tập tin một lần phía trên các lần khớp từ cùng một tập tin"
 
-#: builtin/grep.c:702
+#: builtin/grep.c:701
 msgid "show <n> context lines before and after matches"
 msgstr "hiển thị <n> dòng nội dung phía trước và sau các lần khớp"
 
-#: builtin/grep.c:705
+#: builtin/grep.c:704
 msgid "show <n> context lines before matches"
 msgstr "hiển thị <n> dòng nội dung trước khớp"
 
-#: builtin/grep.c:707
+#: builtin/grep.c:706
 msgid "show <n> context lines after matches"
 msgstr "hiển thị <n> dòng nội dung sau khớp"
 
-#: builtin/grep.c:708
+#: builtin/grep.c:707
 msgid "shortcut for -C NUM"
 msgstr "Dạng tắt cho -C SỐ"
 
-#: builtin/grep.c:711
+#: builtin/grep.c:710
 msgid "show a line with the function name before matches"
 msgstr "hiển thị dòng vói tên hàm trước các lần khớp"
 
-#: builtin/grep.c:713
+#: builtin/grep.c:712
 msgid "show the surrounding function"
 msgstr "hiển thị hàm bao quanh"
 
-#: builtin/grep.c:716
+#: builtin/grep.c:715
 msgid "read patterns from file"
 msgstr "đọc mẫu từ tập-tin"
 
-#: builtin/grep.c:718
+#: builtin/grep.c:717
 msgid "match <pattern>"
 msgstr "match <mẫu>"
 
-#: builtin/grep.c:720
+#: builtin/grep.c:719
 msgid "combine patterns specified with -e"
 msgstr "tổ hợp mẫu được chỉ ra với tùy chọn -e"
 
-#: builtin/grep.c:732
+#: builtin/grep.c:731
 msgid "indicate hit with exit status without output"
 msgstr "đưa ra gợi ý với trạng thái thoát mà không có kết xuất"
 
-#: builtin/grep.c:734
+#: builtin/grep.c:733
 msgid "show only matches from files that match all patterns"
 msgstr "chỉ hiển thị những cái khớp từ tập tin mà nó khớp toàn bộ các mẫu"
 
-#: builtin/grep.c:736
+#: builtin/grep.c:735
 msgid "show parse tree for grep expression"
 msgstr "hiển thị cây phân tích cú pháp cho biểu thức “grep” (tìm kiếm)"
 
-#: builtin/grep.c:740
+#: builtin/grep.c:739
 msgid "pager"
 msgstr "trang giấy"
 
-#: builtin/grep.c:740
+#: builtin/grep.c:739
 msgid "show matching files in the pager"
 msgstr "hiển thị các tập tin khớp trong trang giấy"
 
-#: builtin/grep.c:743
+#: builtin/grep.c:742
 msgid "allow calling of grep(1) (ignored by this build)"
 msgstr "cho phép gọi grep(1) (bị bỏ qua bởi lần dịch này)"
 
-#: builtin/grep.c:744 builtin/show-ref.c:184
+#: builtin/grep.c:743 builtin/show-ref.c:188
 msgid "show usage"
 msgstr "hiển thị cách dùng"
 
-#: builtin/grep.c:811
+#: builtin/grep.c:810
 msgid "no pattern given."
 msgstr "chưa chỉ ra mẫu."
 
-#: builtin/grep.c:866
+#: builtin/grep.c:865
 msgid "--open-files-in-pager only works on the worktree"
 msgstr "--open-files-in-pager chỉ làm việc trên cây-làm-việc"
 
-#: builtin/grep.c:889
+#: builtin/grep.c:888
 msgid "--cached or --untracked cannot be used with --no-index."
 msgstr "--cached hay --untracked không được sử dụng với --no-index."
 
-#: builtin/grep.c:894
+#: builtin/grep.c:893
 msgid "--no-index or --untracked cannot be used with revs."
 msgstr ""
 "--no-index hay --untracked không được sử dụng cùng với các tùy chọn liên "
 "quan đến revs."
 
-#: builtin/grep.c:897
+#: builtin/grep.c:896
 msgid "--[no-]exclude-standard cannot be used for tracked contents."
 msgstr "--[no-]exclude-standard không thể sử dụng cho nội dung lưu dấu vết."
 
-#: builtin/grep.c:905
+#: builtin/grep.c:904
 msgid "both --cached and trees are given."
 msgstr "cả hai --cached và các cây phải được chỉ ra."
 
@@ -5158,10 +5545,14 @@
 msgid "process file as it were from this path"
 msgstr "xử lý tập tin như là nó đang ở thư mục này"
 
-#: builtin/help.c:42
+#: builtin/help.c:41
 msgid "print all available commands"
 msgstr "hiển thị danh sách các câu lệnh người dùng có thể sử dụng"
 
+#: builtin/help.c:42
+msgid "print list of useful guides"
+msgstr "hiển thị danh sách các hướng dẫn hữu dụng"
+
 #: builtin/help.c:43
 msgid "show man page"
 msgstr "hiển thị trang man"
@@ -5175,8 +5566,8 @@
 msgstr "hiện trang info"
 
 #: builtin/help.c:52
-msgid "git help [--all] [--man|--web|--info] [command]"
-msgstr "git help [--all] [--man|--web|--info] [lệnh]"
+msgid "git help [--all] [--guides] [--man|--web|--info] [command]"
+msgstr "git help [--all] [--guides] [--man|--web|--info] [lệnh]"
 
 #: builtin/help.c:64
 #, c-format
@@ -5232,290 +5623,322 @@
 msgid "no info viewer handled the request"
 msgstr "không có trình xem trợ giúp dạng info tiếp hợp với yêu cầu"
 
-#: builtin/help.c:429 builtin/help.c:436
+#: builtin/help.c:420
+msgid "Defining attributes per path"
+msgstr "Định nghĩa các thuộc tính cho mỗi đường dẫn"
+
+#: builtin/help.c:421
+msgid "A Git glossary"
+msgstr "Thuật ngữ chuyên môn Git"
+
+#: builtin/help.c:422
+msgid "Specifies intentionally untracked files to ignore"
+msgstr "Chỉ định các tập tin không cần theo dõi"
+
+#: builtin/help.c:423
+msgid "Defining submodule properties"
+msgstr "Định nghĩa thuộc tính mô-đun-con"
+
+#: builtin/help.c:424
+msgid "Specifying revisions and ranges for Git"
+msgstr "Chỉ định điểm xét duyệt và vùng cho Git"
+
+#: builtin/help.c:425
+msgid "A tutorial introduction to Git (for version 1.5.1 or newer)"
+msgstr "Hướng dẫn cách dùng Git ở mức cơ bản (bản 1.5.1 hay mới hơn)"
+
+#: builtin/help.c:426
+msgid "An overview of recommended workflows with Git"
+msgstr "Tổng quan về luồng công việc khuyến nghị nên dùng với Git."
+
+#: builtin/help.c:438
+msgid "The common Git guides are:\n"
+msgstr "Các chỉ dẫn chung về cách dùng Git là:\n"
+
+#: builtin/help.c:460 builtin/help.c:476
 #, c-format
 msgid "usage: %s%s"
 msgstr "cách sử dụng: %s%s"
 
-#: builtin/help.c:452
+#: builtin/help.c:492
 #, c-format
 msgid "`git %s' is aliased to `%s'"
 msgstr "“git %s” được đặt bí danh thành “%s”"
 
-#: builtin/index-pack.c:182
+#: builtin/index-pack.c:184
 #, c-format
 msgid "object type mismatch at %s"
 msgstr "kiểu đối tượng không khớp tại %s"
 
-#: builtin/index-pack.c:202
+#: builtin/index-pack.c:204
 msgid "object of unexpected type"
 msgstr "đối tượng của kiểu không mong đợi"
 
-#: builtin/index-pack.c:239
+#: builtin/index-pack.c:244
 #, c-format
 msgid "cannot fill %d byte"
 msgid_plural "cannot fill %d bytes"
 msgstr[0] "không thể điền vào %d byte"
 msgstr[1] "không thể điền vào %d byte"
 
-#: builtin/index-pack.c:249
+#: builtin/index-pack.c:254
 msgid "early EOF"
 msgstr "vừa đúng lúc EOF"
 
-#: builtin/index-pack.c:250
+#: builtin/index-pack.c:255
 msgid "read error on input"
 msgstr "lỗi đọc ở đầu vào"
 
-#: builtin/index-pack.c:262
+#: builtin/index-pack.c:267
 msgid "used more bytes than were available"
 msgstr "sử dụng nhiều hơn số lượng byte mà nó sẵn có"
 
-#: builtin/index-pack.c:269
+#: builtin/index-pack.c:274
 msgid "pack too large for current definition of off_t"
 msgstr "pack quá lớn so với định nghĩa hiện tại của kiểu off_t"
 
-#: builtin/index-pack.c:285
+#: builtin/index-pack.c:290
 #, c-format
 msgid "unable to create '%s'"
 msgstr "không thể tạo “%s”"
 
-#: builtin/index-pack.c:290
+#: builtin/index-pack.c:295
 #, c-format
 msgid "cannot open packfile '%s'"
 msgstr "không thể mở packfile “%s”"
 
-#: builtin/index-pack.c:304
+#: builtin/index-pack.c:309
 msgid "pack signature mismatch"
 msgstr "chữ ký cho pack không khớp"
 
-#: builtin/index-pack.c:306
+#: builtin/index-pack.c:311
 #, c-format
 msgid "pack version %<PRIu32> unsupported"
 msgstr "không hỗ trợ phiên bản pack %<PRIu32>"
 
-#: builtin/index-pack.c:324
+#: builtin/index-pack.c:329
 #, c-format
 msgid "pack has bad object at offset %lu: %s"
 msgstr "pack có đối tượng sai khoảng bù (offset) %lu: %s"
 
-#: builtin/index-pack.c:446
+#: builtin/index-pack.c:451
 #, c-format
 msgid "inflate returned %d"
 msgstr "xả nén trả về %d"
 
-#: builtin/index-pack.c:495
+#: builtin/index-pack.c:500
 msgid "offset value overflow for delta base object"
 msgstr "tràn giá trị khoảng bù cho đối tượng delta cơ sở"
 
-#: builtin/index-pack.c:503
+#: builtin/index-pack.c:508
 msgid "delta base offset is out of bound"
 msgstr "khoảng bù cơ sở cho delta nằm ngoài phạm vi"
 
-#: builtin/index-pack.c:511
+#: builtin/index-pack.c:516
 #, c-format
 msgid "unknown object type %d"
 msgstr "không hiểu kiểu đối tượng %d"
 
-#: builtin/index-pack.c:542
+#: builtin/index-pack.c:547
 msgid "cannot pread pack file"
 msgstr "không thể chạy hàm pread cho tập tin pack"
 
-#: builtin/index-pack.c:544
+#: builtin/index-pack.c:549
 #, c-format
 msgid "premature end of pack file, %lu byte missing"
 msgid_plural "premature end of pack file, %lu bytes missing"
 msgstr[0] "tập tin pack bị kết thúc sớm, %lu byte bị thiếu"
 msgstr[1] "tập tin pack bị kết thúc sớm, %lu byte bị thiếu"
 
-#: builtin/index-pack.c:570
+#: builtin/index-pack.c:575
 msgid "serious inflate inconsistency"
 msgstr "sự mâu thuẫn xả nén nghiêm trọng"
 
-#: builtin/index-pack.c:661 builtin/index-pack.c:667 builtin/index-pack.c:690
-#: builtin/index-pack.c:724 builtin/index-pack.c:733
+#: builtin/index-pack.c:666 builtin/index-pack.c:672 builtin/index-pack.c:695
+#: builtin/index-pack.c:729 builtin/index-pack.c:738
 #, c-format
 msgid "SHA1 COLLISION FOUND WITH %s !"
 msgstr "SỰ VA CHẠM SHA1 ĐÃ XẢY RA VỚI %s!"
 
-#: builtin/index-pack.c:664 builtin/pack-objects.c:170
+#: builtin/index-pack.c:669 builtin/pack-objects.c:170
 #: builtin/pack-objects.c:262
 #, c-format
 msgid "unable to read %s"
 msgstr "không thể đọc %s"
 
-#: builtin/index-pack.c:730
+#: builtin/index-pack.c:735
 #, c-format
 msgid "cannot read existing object %s"
 msgstr "không thể đọc đối tượng đã tồn tại %s"
 
-#: builtin/index-pack.c:744
+#: builtin/index-pack.c:749
 #, c-format
 msgid "invalid blob object %s"
 msgstr "đối tượng blob không hợp lệ %s"
 
-#: builtin/index-pack.c:759
+#: builtin/index-pack.c:763
 #, c-format
 msgid "invalid %s"
 msgstr "%s không hợp lệ"
 
-#: builtin/index-pack.c:761
+#: builtin/index-pack.c:766
 msgid "Error in object"
 msgstr "Lỗi trong đối tượng"
 
-#: builtin/index-pack.c:763
+#: builtin/index-pack.c:768
 #, c-format
 msgid "Not all child objects of %s are reachable"
 msgstr "Không phải tất cả các đối tượng con của %s là có thể với tới được"
 
-#: builtin/index-pack.c:833 builtin/index-pack.c:863
+#: builtin/index-pack.c:838 builtin/index-pack.c:868
 msgid "failed to apply delta"
 msgstr "gặp lỗi khi áp dụng delta"
 
-#: builtin/index-pack.c:1004
+#: builtin/index-pack.c:1009
 msgid "Receiving objects"
 msgstr "Đang nhận về các đối tượng"
 
-#: builtin/index-pack.c:1004
+#: builtin/index-pack.c:1009
 msgid "Indexing objects"
 msgstr "Các đối tượng bảng mục lục"
 
-#: builtin/index-pack.c:1030
+#: builtin/index-pack.c:1035
 msgid "pack is corrupted (SHA1 mismatch)"
 msgstr "pack bị sai hỏng (SHA1 không khớp)"
 
-#: builtin/index-pack.c:1035
+#: builtin/index-pack.c:1040
 msgid "cannot fstat packfile"
 msgstr "không thể fstat packfile"
 
-#: builtin/index-pack.c:1038
+#: builtin/index-pack.c:1043
 msgid "pack has junk at the end"
 msgstr "pack có phần thừa ở cuối"
 
-#: builtin/index-pack.c:1049
+#: builtin/index-pack.c:1054
 msgid "confusion beyond insanity in parse_pack_objects()"
 msgstr "lộn xộn hơn cả điên rồ khi chạy hàm parse_pack_objects()"
 
-#: builtin/index-pack.c:1072
+#: builtin/index-pack.c:1077
 msgid "Resolving deltas"
 msgstr "Đang phân giải các delta"
 
-#: builtin/index-pack.c:1082
+#: builtin/index-pack.c:1087
 #, c-format
 msgid "unable to create thread: %s"
 msgstr "không thể tạo tuyến: %s"
 
-#: builtin/index-pack.c:1124
+#: builtin/index-pack.c:1129
 msgid "confusion beyond insanity"
 msgstr "lộn xộn hơn cả điên rồ"
 
-#: builtin/index-pack.c:1132
+#: builtin/index-pack.c:1137
 #, c-format
 msgid "completed with %d local objects"
 msgstr "đầy đủ với %d đối tượng nội bộ"
 
-#: builtin/index-pack.c:1142
+#: builtin/index-pack.c:1147
 #, c-format
 msgid "Unexpected tail checksum for %s (disk corruption?)"
 msgstr "Tổng kiểm tra tail không như mong đợi cho %s (đĩa hỏng?)"
 
-#: builtin/index-pack.c:1146
+#: builtin/index-pack.c:1151
 #, c-format
 msgid "pack has %d unresolved delta"
 msgid_plural "pack has %d unresolved deltas"
 msgstr[0] "pack có %d delta chưa được giải quyết"
 msgstr[1] "pack có %d delta chưa được giải quyết"
 
-#: builtin/index-pack.c:1171
+#: builtin/index-pack.c:1176
 #, c-format
 msgid "unable to deflate appended object (%d)"
 msgstr "không thể xả đối tượng nối thêm (%d)"
 
-#: builtin/index-pack.c:1250
+#: builtin/index-pack.c:1255
 #, c-format
 msgid "local object %s is corrupt"
 msgstr "đối tượng nội bộ %s bị hỏng"
 
-#: builtin/index-pack.c:1274
+#: builtin/index-pack.c:1279
 msgid "error while closing pack file"
 msgstr "gặp lỗi trong khi đóng tập tin pack"
 
-#: builtin/index-pack.c:1287
+#: builtin/index-pack.c:1292
 #, c-format
 msgid "cannot write keep file '%s'"
 msgstr "không thể ghi tập tin giữ lại “%s”"
 
-#: builtin/index-pack.c:1295
+#: builtin/index-pack.c:1300
 #, c-format
 msgid "cannot close written keep file '%s'"
 msgstr "không thể đóng tập tin giữ lại đã được ghi “%s”"
 
-#: builtin/index-pack.c:1308
+#: builtin/index-pack.c:1313
 msgid "cannot store pack file"
 msgstr "không thể lưu tập tin pack"
 
-#: builtin/index-pack.c:1319
+#: builtin/index-pack.c:1324
 msgid "cannot store index file"
 msgstr "không thể lưu trữ tập tin ghi mục lục"
 
-#: builtin/index-pack.c:1352
+#: builtin/index-pack.c:1357
 #, c-format
 msgid "bad pack.indexversion=%<PRIu32>"
 msgstr "sai pack.indexversion=%<PRIu32>"
 
-#: builtin/index-pack.c:1358
+#: builtin/index-pack.c:1363
 #, c-format
 msgid "invalid number of threads specified (%d)"
 msgstr "số tuyến chỉ ra không hợp lệ (%d)"
 
-#: builtin/index-pack.c:1362 builtin/index-pack.c:1535
+#: builtin/index-pack.c:1367 builtin/index-pack.c:1545
 #, c-format
 msgid "no threads support, ignoring %s"
 msgstr "không hỗ trợ đa tuyến, bỏ qua %s"
 
-#: builtin/index-pack.c:1420
+#: builtin/index-pack.c:1425
 #, c-format
 msgid "Cannot open existing pack file '%s'"
 msgstr "Không thể mở tập tin pack đã sẵn có “%s”"
 
-#: builtin/index-pack.c:1422
+#: builtin/index-pack.c:1427
 #, c-format
 msgid "Cannot open existing pack idx file for '%s'"
 msgstr "Không thể mở tập tin “pack idx” cho “%s”"
 
-#: builtin/index-pack.c:1469
+#: builtin/index-pack.c:1474
 #, c-format
 msgid "non delta: %d object"
 msgid_plural "non delta: %d objects"
 msgstr[0] "không delta: %d đối tượng"
 msgstr[1] "không delta: %d đối tượng"
 
-#: builtin/index-pack.c:1476
+#: builtin/index-pack.c:1481
 #, c-format
 msgid "chain length = %d: %lu object"
 msgid_plural "chain length = %d: %lu objects"
 msgstr[0] "chiều dài xích = %d: %lu đối tượng"
 msgstr[1] "chiều dài xích = %d: %lu đối tượng"
 
-#: builtin/index-pack.c:1503
+#: builtin/index-pack.c:1509
 msgid "Cannot come back to cwd"
 msgstr "Không thể quay lại cwd"
 
-#: builtin/index-pack.c:1547 builtin/index-pack.c:1550
-#: builtin/index-pack.c:1562 builtin/index-pack.c:1566
+#: builtin/index-pack.c:1557 builtin/index-pack.c:1560
+#: builtin/index-pack.c:1572 builtin/index-pack.c:1576
 #, c-format
 msgid "bad %s"
 msgstr "%s sai"
 
-#: builtin/index-pack.c:1580
+#: builtin/index-pack.c:1590
 msgid "--fix-thin cannot be used without --stdin"
 msgstr "--fix-thin không thể được dùng mà không có --stdin"
 
-#: builtin/index-pack.c:1584 builtin/index-pack.c:1594
+#: builtin/index-pack.c:1594 builtin/index-pack.c:1604
 #, c-format
 msgid "packfile name '%s' does not end with '.pack'"
 msgstr "tên tập tin packfile “%s” không được kết thúc bằng đuôi “.pack”"
 
-#: builtin/index-pack.c:1603
+#: builtin/index-pack.c:1613
 msgid "--verify with no packfile name given"
 msgstr "dùng tùy chọn --verify mà không đưa ra tên packfile"
 
@@ -5651,7 +6074,7 @@
 msgid "specify that the git repository is to be shared amongst several users"
 msgstr "chỉ ra cái mà kho git được chia sẻ giữa nhiều người dùng"
 
-#: builtin/init-db.c:493 builtin/prune-packed.c:77
+#: builtin/init-db.c:493 builtin/prune-packed.c:75
 msgid "be quiet"
 msgstr "im lặng"
 
@@ -5683,241 +6106,255 @@
 msgid "Cannot access work tree '%s'"
 msgstr "không thể truy cập cây (tree) làm việc “%s”"
 
-#: builtin/log.c:40
-msgid "git log [<options>] [<since>..<until>] [[--] <path>...]\n"
-msgstr "git log [<các-tùy-chọn>] [<kể-từ>..<cho-đến>] [[--] <đường-dẫn>...]\n"
-
 #: builtin/log.c:41
+msgid "git log [<options>] [<revision range>] [[--] <path>...]\n"
+msgstr "git log [<các-tùy-chọn>] [<vùng xem xét>] [[--] <đường-dẫn>...]\n"
+
+#: builtin/log.c:42
 msgid "   or: git show [options] <object>..."
 msgstr "  hay: git show [các-tùy-chọn] <đối-tượng>..."
 
-#: builtin/log.c:103
+#: builtin/log.c:124
 msgid "suppress diff output"
 msgstr "chặn mọi kết xuất từ diff"
 
-#: builtin/log.c:104
+#: builtin/log.c:125
 msgid "show source"
 msgstr "hiển thị mã nguồn"
 
-#: builtin/log.c:105
+#: builtin/log.c:126
 msgid "Use mail map file"
 msgstr "Sử dụng tập tin ánh xạ thư"
 
-#: builtin/log.c:106
+#: builtin/log.c:127
 msgid "decorate options"
 msgstr "các tùy chọn trang trí"
 
-#: builtin/log.c:199
+#: builtin/log.c:230
 #, c-format
 msgid "Final output: %d %s\n"
 msgstr "Kết xuất cuối cùng: %d %s\n"
 
-#: builtin/log.c:422 builtin/log.c:514
+#: builtin/log.c:453 builtin/log.c:545
 #, c-format
 msgid "Could not read object %s"
 msgstr "Không thể đọc đối tượng %s"
 
-#: builtin/log.c:538
+#: builtin/log.c:569
 #, c-format
 msgid "Unknown type: %d"
 msgstr "Không nhận ra kiểu: %d"
 
-#: builtin/log.c:630
+#: builtin/log.c:669
 msgid "format.headers without value"
 msgstr "format.headers không có giá trị cụ thể"
 
-#: builtin/log.c:704
+#: builtin/log.c:751
 msgid "name of output directory is too long"
 msgstr "tên của thư mục kết xuất quá dài"
 
-#: builtin/log.c:720
+#: builtin/log.c:767
 #, c-format
 msgid "Cannot open patch file %s"
 msgstr "Không thể mở tập tin miếng vá: %s"
 
-#: builtin/log.c:734
+#: builtin/log.c:781
 msgid "Need exactly one range."
 msgstr "Cần chính xác một vùng."
 
-#: builtin/log.c:742
+#: builtin/log.c:789
 msgid "Not a range."
 msgstr "Không phải là một vùng."
 
-#: builtin/log.c:815
+#: builtin/log.c:891
 msgid "Cover letter needs email format"
 msgstr "”Cover letter” cần cho định dạng thư"
 
-#: builtin/log.c:888
+#: builtin/log.c:967
 #, c-format
 msgid "insane in-reply-to: %s"
 msgstr "in-reply-to điên rồ: %s"
 
-#: builtin/log.c:916
+#: builtin/log.c:995
 msgid "git format-patch [options] [<since> | <revision range>]"
 msgstr "git format-patch [các-tùy-chọn] [<kể-từ> | <vùng-xem-xét>]"
 
-#: builtin/log.c:961
+#: builtin/log.c:1040
 msgid "Two output directories?"
 msgstr "Hai thư mục kết xuất?"
 
-#: builtin/log.c:1099
+#: builtin/log.c:1155
 msgid "use [PATCH n/m] even with a single patch"
 msgstr "dùng [PATCH n/m] ngay cả với miếng vá đơn"
 
-#: builtin/log.c:1102
+#: builtin/log.c:1158
 msgid "use [PATCH] even with multiple patches"
 msgstr "dùng [VÁ] ngay cả với các miếng vá phức tạp"
 
-#: builtin/log.c:1106
+#: builtin/log.c:1162
 msgid "print patches to standard out"
 msgstr "hiển thị miếng vá ra đầu ra chuẩn"
 
-#: builtin/log.c:1108
+#: builtin/log.c:1164
 msgid "generate a cover letter"
 msgstr "tạo bì thư"
 
-#: builtin/log.c:1110
+#: builtin/log.c:1166
 msgid "use simple number sequence for output file names"
 msgstr "sử dụng chỗi dãy số dạng đơn giản cho tên tập-tin xuất ra"
 
-#: builtin/log.c:1111
+#: builtin/log.c:1167
 msgid "sfx"
 msgstr "sfx"
 
-#: builtin/log.c:1112
+#: builtin/log.c:1168
 msgid "use <sfx> instead of '.patch'"
 msgstr "sử dụng <sfx> thay cho “.patch”"
 
-#: builtin/log.c:1114
+#: builtin/log.c:1170
 msgid "start numbering patches at <n> instead of 1"
 msgstr "bắt đầu đánh số miếng vá từ <n> thay vì 1"
 
-#: builtin/log.c:1116
+#: builtin/log.c:1172
 msgid "mark the series as Nth re-roll"
 msgstr "đánh dấu chuỗi nối tiếp dạng thứ-N re-roll"
 
-#: builtin/log.c:1118
+#: builtin/log.c:1174
 msgid "Use [<prefix>] instead of [PATCH]"
 msgstr "Dùng [<tiền-tố>] thay cho [VÁ]"
 
-#: builtin/log.c:1121
+#: builtin/log.c:1177
 msgid "store resulting files in <dir>"
 msgstr "lưu các tập tin kết quả trong <t.mục>"
 
-#: builtin/log.c:1124
+#: builtin/log.c:1180
 msgid "don't strip/add [PATCH]"
 msgstr "không strip/add [VÁ]"
 
-#: builtin/log.c:1127
+#: builtin/log.c:1183
 msgid "don't output binary diffs"
 msgstr "không kết xuất diff (những khác biệt) nhị phân"
 
-#: builtin/log.c:1129
+#: builtin/log.c:1185
 msgid "don't include a patch matching a commit upstream"
 msgstr "không bao gồm miếng vá khớp với một lần chuyển giao thượng nguồn"
 
-#: builtin/log.c:1131
+#: builtin/log.c:1187
 msgid "show patch format instead of default (patch + stat)"
 msgstr "hiển thị định dạng miếng vá thay vì mặc định (miếng vá + thống kê)"
 
-#: builtin/log.c:1133
+#: builtin/log.c:1189
 msgid "Messaging"
 msgstr "Lời nhắn"
 
-#: builtin/log.c:1134
+#: builtin/log.c:1190
 msgid "header"
 msgstr "đầu đề thư"
 
-#: builtin/log.c:1135
+#: builtin/log.c:1191
 msgid "add email header"
 msgstr "thêm đầu đề thư"
 
-#: builtin/log.c:1136 builtin/log.c:1138
+#: builtin/log.c:1192 builtin/log.c:1194
 msgid "email"
 msgstr "thư điện tử"
 
-#: builtin/log.c:1136
+#: builtin/log.c:1192
 msgid "add To: header"
 msgstr "thêm To: đầu đề thư"
 
-#: builtin/log.c:1138
+#: builtin/log.c:1194
 msgid "add Cc: header"
 msgstr "thêm Cc: đầu đề thư"
 
-#: builtin/log.c:1140
+#: builtin/log.c:1196
+msgid "ident"
+msgstr "thụt lề"
+
+#: builtin/log.c:1197
+msgid "set From address to <ident> (or committer ident if absent)"
+msgstr ""
+"đặt `Địa chỉ gửi' thành <thụ lề> (hoặc thụt lề người commit nếu bỏ quên)"
+
+#: builtin/log.c:1199
 msgid "message-id"
 msgstr "message-id"
 
-#: builtin/log.c:1141
+#: builtin/log.c:1200
 msgid "make first mail a reply to <message-id>"
 msgstr "dùng thư đầu tiên để trả lời <message-id>"
 
-#: builtin/log.c:1142 builtin/log.c:1145
+#: builtin/log.c:1201 builtin/log.c:1204
 msgid "boundary"
 msgstr "ranh giới"
 
-#: builtin/log.c:1143
+#: builtin/log.c:1202
 msgid "attach the patch"
 msgstr "đính kèm miếng vá"
 
-#: builtin/log.c:1146
+#: builtin/log.c:1205
 msgid "inline the patch"
 msgstr "dùng miếng vá làm nội dung"
 
-#: builtin/log.c:1150
+#: builtin/log.c:1209
 msgid "enable message threading, styles: shallow, deep"
 msgstr "cho phép luồng lời nhắn, kiểu: “shallow”, “deep”"
 
-#: builtin/log.c:1152
+#: builtin/log.c:1211
 msgid "signature"
 msgstr "chữ ký"
 
-#: builtin/log.c:1153
+#: builtin/log.c:1212
 msgid "add a signature"
 msgstr "thêm chữ ký"
 
-#: builtin/log.c:1155
+#: builtin/log.c:1214
 msgid "don't print the patch filenames"
 msgstr "không hiển thị các tên tập tin của miếng vá"
 
-#: builtin/log.c:1239
+#: builtin/log.c:1288
+#, c-format
+msgid "invalid ident line: %s"
+msgstr "dòng thụt lề không hợp lệ: %s"
+
+#: builtin/log.c:1303
 msgid "-n and -k are mutually exclusive."
 msgstr "-n và  -k loại từ lẫn nhau."
 
-#: builtin/log.c:1241
+#: builtin/log.c:1305
 msgid "--subject-prefix and -k are mutually exclusive."
 msgstr "--subject-prefix và -k xung khắc nhau."
 
-#: builtin/log.c:1249
+#: builtin/log.c:1313
 msgid "--name-only does not make sense"
 msgstr "--name-only không hợp lý"
 
-#: builtin/log.c:1251
+#: builtin/log.c:1315
 msgid "--name-status does not make sense"
 msgstr "--name-status không hợp lý"
 
-#: builtin/log.c:1253
+#: builtin/log.c:1317
 msgid "--check does not make sense"
 msgstr "--check không hợp lý"
 
-#: builtin/log.c:1276
+#: builtin/log.c:1340
 msgid "standard output, or directory, which one?"
 msgstr "đầu ra chuẩn, hay thư mục, chọn cái nào?"
 
-#: builtin/log.c:1278
+#: builtin/log.c:1342
 #, c-format
 msgid "Could not create directory '%s'"
 msgstr "Không thể tạo thư mục “%s”"
 
-#: builtin/log.c:1431
+#: builtin/log.c:1490
 msgid "Failed to create output files"
 msgstr "Gặp lỗi khi tạo các tập tin kết xuất"
 
-#: builtin/log.c:1480
+#: builtin/log.c:1539
 msgid "git cherry [-v] [<upstream> [<head> [<limit>]]]"
 msgstr "git cherry [-v] [<thượng-nguồn> [<head> [<giới-hạn>]]]"
 
-#: builtin/log.c:1535
+#: builtin/log.c:1594
 #, c-format
 msgid ""
 "Could not find a tracked remote branch, please specify <upstream> manually.\n"
@@ -5925,103 +6362,103 @@
 "Không tìm thấy nhánh mạng bị theo vết, hãy chỉ định <thượng-nguồn> một cách "
 "thủ công.\n"
 
-#: builtin/log.c:1548 builtin/log.c:1550 builtin/log.c:1562
+#: builtin/log.c:1607 builtin/log.c:1609 builtin/log.c:1621
 #, c-format
 msgid "Unknown commit %s"
 msgstr "Không hiểu lần chuyển giao (commit) %s"
 
-#: builtin/ls-files.c:409
+#: builtin/ls-files.c:408
 msgid "git ls-files [options] [<file>...]"
 msgstr "git ls-files [các-tùy-chọn] [<tập-tin>...]"
 
-#: builtin/ls-files.c:466
+#: builtin/ls-files.c:465
 msgid "identify the file status with tags"
 msgstr "nhận dạng các trạng thái tập tin với thẻ"
 
-#: builtin/ls-files.c:468
+#: builtin/ls-files.c:467
 msgid "use lowercase letters for 'assume unchanged' files"
 msgstr ""
 "dùng chữ cái viết thường cho các tập tin “assume unchanged” (giả định không "
 "thay đổi)"
 
-#: builtin/ls-files.c:470
+#: builtin/ls-files.c:469
 msgid "show cached files in the output (default)"
 msgstr "hiển thị các tập tin được nhớ tạm vào đầu ra (mặc định)"
 
-#: builtin/ls-files.c:472
+#: builtin/ls-files.c:471
 msgid "show deleted files in the output"
 msgstr "hiển thị các tập tin đã xóa trong kết xuất"
 
-#: builtin/ls-files.c:474
+#: builtin/ls-files.c:473
 msgid "show modified files in the output"
 msgstr "hiển thị các tập tin đã bị sửa đổi ra kết xuất"
 
-#: builtin/ls-files.c:476
+#: builtin/ls-files.c:475
 msgid "show other files in the output"
 msgstr "hiển thị các tập tin khác trong kết xuất"
 
-#: builtin/ls-files.c:478
+#: builtin/ls-files.c:477
 msgid "show ignored files in the output"
 msgstr "hiển thị các tập tin bị bỏ qua trong kết xuất"
 
-#: builtin/ls-files.c:481
+#: builtin/ls-files.c:480
 msgid "show staged contents' object name in the output"
 msgstr "hiển thị tên đối tượng của nội dung được lưu trạng thái ở kết xuất"
 
-#: builtin/ls-files.c:483
+#: builtin/ls-files.c:482
 msgid "show files on the filesystem that need to be removed"
 msgstr "hiển thị các tập tin trên hệ thống tập tin mà nó cần được gỡ bỏ"
 
-#: builtin/ls-files.c:485
+#: builtin/ls-files.c:484
 msgid "show 'other' directories' name only"
 msgstr "chỉ hiển thị tên của các thư mục “khác”"
 
-#: builtin/ls-files.c:488
+#: builtin/ls-files.c:487
 msgid "don't show empty directories"
 msgstr "không hiển thị thư mục rỗng"
 
-#: builtin/ls-files.c:491
+#: builtin/ls-files.c:490
 msgid "show unmerged files in the output"
 msgstr "hiển thị các tập tin chưa hòa trộn trong kết xuất"
 
-#: builtin/ls-files.c:493
+#: builtin/ls-files.c:492
 msgid "show resolve-undo information"
 msgstr "hiển thị thông tin resolve-undo"
 
-#: builtin/ls-files.c:495
+#: builtin/ls-files.c:494
 msgid "skip files matching pattern"
 msgstr "bỏ qua những tập tin khớp với một mẫu"
 
-#: builtin/ls-files.c:498
+#: builtin/ls-files.c:497
 msgid "exclude patterns are read from <file>"
 msgstr "mẫu loại trừ được đọc từ <tập tin>"
 
-#: builtin/ls-files.c:501
+#: builtin/ls-files.c:500
 msgid "read additional per-directory exclude patterns in <file>"
 msgstr "đọc thêm các mẫu ngoại trừ mỗi thư mục trong <tập tin>"
 
-#: builtin/ls-files.c:503
+#: builtin/ls-files.c:502
 msgid "add the standard git exclusions"
 msgstr "thêm loại trừ tiêu chuẩn kiểu git"
 
-#: builtin/ls-files.c:506
+#: builtin/ls-files.c:505
 msgid "make the output relative to the project top directory"
 msgstr "làm cho kết xuất liên quan đến thư mục ở mức cao nhất (gốc) của dự án"
 
-#: builtin/ls-files.c:509
+#: builtin/ls-files.c:508
 msgid "if any <file> is not in the index, treat this as an error"
 msgstr "nếu <tập tin> bất kỳ không ở trong bảng mục lục, xử lý nó như một lỗi"
 
-#: builtin/ls-files.c:510
+#: builtin/ls-files.c:509
 msgid "tree-ish"
 msgstr "tree-ish"
 
-#: builtin/ls-files.c:511
+#: builtin/ls-files.c:510
 msgid "pretend that paths removed since <tree-ish> are still present"
 msgstr ""
 "giả định rằng các đường dẫn đã bị gỡ bỏ kể từ <tree-ish> nay vẫn hiện diện"
 
-#: builtin/ls-files.c:513
+#: builtin/ls-files.c:512
 msgid "show debugging data"
 msgstr "hiển thị dữ liệu gỡ lỗi"
 
@@ -6073,170 +6510,170 @@
 msgid "git merge --abort"
 msgstr "git merge --abort"
 
-#: builtin/merge.c:90
+#: builtin/merge.c:98
 msgid "switch `m' requires a value"
 msgstr "switch “m” yêu cầu một giá trị"
 
-#: builtin/merge.c:127
+#: builtin/merge.c:135
 #, c-format
 msgid "Could not find merge strategy '%s'.\n"
 msgstr "Không tìm thấy chiến lược hòa trộn “%s”.\n"
 
-#: builtin/merge.c:128
+#: builtin/merge.c:136
 #, c-format
 msgid "Available strategies are:"
 msgstr "Các chiến lược sẵn sàng là:"
 
-#: builtin/merge.c:133
+#: builtin/merge.c:141
 #, c-format
 msgid "Available custom strategies are:"
 msgstr "Các chiến lược tùy chỉnh sẵn sàng là:"
 
-#: builtin/merge.c:183
+#: builtin/merge.c:198
 msgid "do not show a diffstat at the end of the merge"
 msgstr "không hiển thị thống kê khác biệt tại cuối của lần hòa trộn"
 
-#: builtin/merge.c:186
+#: builtin/merge.c:201
 msgid "show a diffstat at the end of the merge"
 msgstr "hiển thị thống kê khác biệt tại cuối của hòa trộn"
 
-#: builtin/merge.c:187
+#: builtin/merge.c:202
 msgid "(synonym to --stat)"
 msgstr "(đồng nghĩa với --stat)"
 
-#: builtin/merge.c:189
+#: builtin/merge.c:204
 msgid "add (at most <n>) entries from shortlog to merge commit message"
 msgstr "thêm (ít nhất <n>) mục từ shortlog cho ghi chú chuyển giao hòa trộn"
 
-#: builtin/merge.c:192
+#: builtin/merge.c:207
 msgid "create a single commit instead of doing a merge"
 msgstr "tạo một lần chuyển giao (commit) đưon thay vì thực hiện việc hòa trộn"
 
-#: builtin/merge.c:194
+#: builtin/merge.c:209
 msgid "perform a commit if the merge succeeds (default)"
 msgstr "thực hiện chuyển giao nếu hòa trộn thành công (mặc định)"
 
-#: builtin/merge.c:196
+#: builtin/merge.c:211
 msgid "edit message before committing"
 msgstr "sửa chú thích trước khi chuyển giao (commit)"
 
-#: builtin/merge.c:198
+#: builtin/merge.c:212
 msgid "allow fast-forward (default)"
 msgstr "cho phép fast-forward (mặc định)"
 
-#: builtin/merge.c:200
+#: builtin/merge.c:214
 msgid "abort if fast-forward is not possible"
 msgstr "bỏ qua nếu fast-forward không thể được"
 
-#: builtin/merge.c:203
+#: builtin/merge.c:218
 msgid "Verify that the named commit has a valid GPG signature"
 msgstr "Thẩm tra xem lần chuyển giao có tên đó có chữ ký GPG hợp lệ hay không"
 
-#: builtin/merge.c:204 builtin/notes.c:866 builtin/revert.c:112
+#: builtin/merge.c:219 builtin/notes.c:738 builtin/revert.c:114
 msgid "strategy"
 msgstr "chiến lược"
 
-#: builtin/merge.c:205
+#: builtin/merge.c:220
 msgid "merge strategy to use"
 msgstr "chiến lược hòa trộn sẽ dùng"
 
-#: builtin/merge.c:206
+#: builtin/merge.c:221
 msgid "option=value"
 msgstr "tùy_chọn=giá_trị"
 
-#: builtin/merge.c:207
+#: builtin/merge.c:222
 msgid "option for selected merge strategy"
 msgstr "tùy chọn cho chiến lược hòa trộn đã chọn"
 
-#: builtin/merge.c:209
+#: builtin/merge.c:224
 msgid "merge commit message (for a non-fast-forward merge)"
 msgstr ""
 "hòa trộn ghi chú của lần chuyển giao (dành cho hòa trộn non-fast-forward)"
 
-#: builtin/merge.c:213
+#: builtin/merge.c:228
 msgid "abort the current in-progress merge"
 msgstr "bãi bỏ quá trình hòa trộn hiện tại đang thực hiện"
 
-#: builtin/merge.c:242
+#: builtin/merge.c:257
 msgid "could not run stash."
 msgstr "không thể chạy stash."
 
-#: builtin/merge.c:247
+#: builtin/merge.c:262
 msgid "stash failed"
 msgstr "stash gặp lỗi"
 
-#: builtin/merge.c:252
+#: builtin/merge.c:267
 #, c-format
 msgid "not a valid object: %s"
 msgstr "không phải là một đối tượng hợp lệ: %s"
 
-#: builtin/merge.c:271 builtin/merge.c:288
+#: builtin/merge.c:286 builtin/merge.c:303
 msgid "read-tree failed"
 msgstr "read-tree gặp lỗi"
 
-#: builtin/merge.c:318
+#: builtin/merge.c:333
 msgid " (nothing to squash)"
 msgstr " (không có gì để squash)"
 
-#: builtin/merge.c:331
+#: builtin/merge.c:346
 #, c-format
 msgid "Squash commit -- not updating HEAD\n"
 msgstr "Squash commit -- không cập nhật HEAD\n"
 
-#: builtin/merge.c:363
+#: builtin/merge.c:378
 msgid "Writing SQUASH_MSG"
 msgstr "Đang ghi SQUASH_MSG"
 
-#: builtin/merge.c:365
+#: builtin/merge.c:380
 msgid "Finishing SQUASH_MSG"
 msgstr "Hoàn thành SQUASH_MSG"
 
-#: builtin/merge.c:388
+#: builtin/merge.c:403
 #, c-format
 msgid "No merge message -- not updating HEAD\n"
 msgstr "Không thông điệp hòa trộn -- không cập nhật HEAD\n"
 
-#: builtin/merge.c:438
+#: builtin/merge.c:453
 #, c-format
 msgid "'%s' does not point to a commit"
 msgstr "“%s” không chỉ đến một lần chuyển giao (commit) nào cả"
 
-#: builtin/merge.c:550
+#: builtin/merge.c:565
 #, c-format
 msgid "Bad branch.%s.mergeoptions string: %s"
 msgstr "Chuỗi branch.%s.mergeoptions sai: %s"
 
-#: builtin/merge.c:643
+#: builtin/merge.c:657
 msgid "git write-tree failed to write a tree"
 msgstr "lệnh git write-tree gặp lỗi khi ghi một cây"
 
-#: builtin/merge.c:671
+#: builtin/merge.c:685
 msgid "Not handling anything other than two heads merge."
 msgstr "Không cầm nắm gì ngoài hai head hòa trộn"
 
-#: builtin/merge.c:685
+#: builtin/merge.c:699
 #, c-format
 msgid "Unknown option for merge-recursive: -X%s"
 msgstr "Không hiểu tùy chọn cho merge-recursive: -X%s"
 
-#: builtin/merge.c:699
+#: builtin/merge.c:713
 #, c-format
 msgid "unable to write %s"
 msgstr "không thể ghi %s"
 
-#: builtin/merge.c:788
+#: builtin/merge.c:802
 #, c-format
 msgid "Could not read from '%s'"
 msgstr "Không thể đọc từ “%s”"
 
-#: builtin/merge.c:797
+#: builtin/merge.c:811
 #, c-format
 msgid "Not committing merge; use 'git commit' to complete the merge.\n"
 msgstr ""
 "Vẫn chưa hòa trộn các lần chuyển giao (commit); sử dụng lệnh “git commit” để "
 "hoàn tất việc hòa trộn.\n"
 
-#: builtin/merge.c:803
+#: builtin/merge.c:817
 #, c-format
 msgid ""
 "Please enter a commit message to explain why this merge is necessary,\n"
@@ -6254,55 +6691,50 @@
 "rỗng\n"
 "sẽ hủy bỏ lần chuyển giao (commit).\n"
 
-#: builtin/merge.c:827
+#: builtin/merge.c:841
 msgid "Empty commit message."
 msgstr "Chú thích của lần commit (chuyển giao) bị trống rỗng."
 
-#: builtin/merge.c:839
+#: builtin/merge.c:853
 #, c-format
 msgid "Wonderful.\n"
 msgstr "Thần kỳ.\n"
 
-#: builtin/merge.c:904
+#: builtin/merge.c:918
 #, c-format
 msgid "Automatic merge failed; fix conflicts and then commit the result.\n"
 msgstr ""
 "Việc tự động hòa trộn gặp lỗi; hãy sửa các xung đột sau đó chuyển giao "
 "(commit) kết quả.\n"
 
-#: builtin/merge.c:920
+#: builtin/merge.c:934
 #, c-format
 msgid "'%s' is not a commit"
 msgstr "%s không phải là một lần commit (chuyển giao)"
 
-#: builtin/merge.c:961
+#: builtin/merge.c:975
 msgid "No current branch."
 msgstr "không phải nhánh hiện hành"
 
-#: builtin/merge.c:963
+#: builtin/merge.c:977
 msgid "No remote for the current branch."
 msgstr "Không có máy chủ cho nhánh hiện hành."
 
-#: builtin/merge.c:965
+#: builtin/merge.c:979
 msgid "No default upstream defined for the current branch."
 msgstr "Không có thượng nguồn mặc định được định nghĩa cho nhánh hiện hành."
 
-#: builtin/merge.c:970
+#: builtin/merge.c:984
 #, c-format
-msgid "No remote tracking branch for %s from %s"
+msgid "No remote-tracking branch for %s from %s"
 msgstr "Không nhánh mạng theo vết cho %s từ %s"
 
-#: builtin/merge.c:1057 builtin/merge.c:1214
-#, c-format
-msgid "%s - not something we can merge"
-msgstr "%s - không phải là một số thứ chúng tôi có thể hòa trộn"
-
-#: builtin/merge.c:1125
+#: builtin/merge.c:1140
 msgid "There is no merge to abort (MERGE_HEAD missing)."
 msgstr ""
 "Ở đây không có lần hòa trộn nào được hủy bỏ giữa chừng cả (thiếu MERGE_HEAD)."
 
-#: builtin/merge.c:1141 git-pull.sh:31
+#: builtin/merge.c:1156 git-pull.sh:31
 msgid ""
 "You have not concluded your merge (MERGE_HEAD exists).\n"
 "Please, commit your changes before you can merge."
@@ -6310,11 +6742,11 @@
 "Bạn chưa kết thúc việc hòa trộng (MERGE_HEAD vẫn tồn tại).\n"
 "Hãy chuyển giao (commit) các thay đổi trước khi bạn có thể hòa trộn."
 
-#: builtin/merge.c:1144 git-pull.sh:34
+#: builtin/merge.c:1159 git-pull.sh:34
 msgid "You have not concluded your merge (MERGE_HEAD exists)."
 msgstr "Bạn chưa kết thúc việc hòa trộng (MERGE_HEAD vẫn tồn tại)."
 
-#: builtin/merge.c:1148
+#: builtin/merge.c:1163
 msgid ""
 "You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists).\n"
 "Please, commit your changes before you can merge."
@@ -6322,107 +6754,108 @@
 "Bạn chưa kết thúc việc cherry-pick (CHERRY_PICK_HEAD vẫn tồn tại).\n"
 "Hãy chuyển giao (commit) các thay đổi trước khi bạn có thể hòa trộn."
 
-#: builtin/merge.c:1151
+#: builtin/merge.c:1166
 msgid "You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists)."
 msgstr "Bạn chưa kết thúc việc cherry-pick (CHERRY_PICK_HEAD vẫn tồn tại)."
 
-#: builtin/merge.c:1160
+#: builtin/merge.c:1175
 msgid "You cannot combine --squash with --no-ff."
 msgstr "Bạn không thể kết hợp --squash với --no-ff."
 
-#: builtin/merge.c:1165
-msgid "You cannot combine --no-ff with --ff-only."
-msgstr "Bạn không thể kết hợp --no-ff với --ff-only."
-
-#: builtin/merge.c:1172
+#: builtin/merge.c:1184
 msgid "No commit specified and merge.defaultToUpstream not set."
 msgstr ""
 "Không chỉ ra lần chuyển giao (commit) và merge.defaultToUpstream chưa được "
 "đặt."
 
-#: builtin/merge.c:1204
+#: builtin/merge.c:1216
 msgid "Can merge only exactly one commit into empty head"
 msgstr ""
 "Không thể hòa trộn một cách đúng đắn một lần chuyển giao (commit) vào một "
 "head rỗng"
 
-#: builtin/merge.c:1207
+#: builtin/merge.c:1219
 msgid "Squash commit into empty head not supported yet"
 msgstr "Squash commit vào một head trống rỗng vẫn chưa được hỗ trợ"
 
-#: builtin/merge.c:1209
+#: builtin/merge.c:1221
 msgid "Non-fast-forward commit does not make sense into an empty head"
 msgstr ""
 "Chuyển giao (commit) không-fast-forward không hợp lý ở trong một head trống "
 "rỗng"
 
-#: builtin/merge.c:1265
+#: builtin/merge.c:1226
+#, c-format
+msgid "%s - not something we can merge"
+msgstr "%s - không phải là một số thứ chúng tôi có thể hòa trộn"
+
+#: builtin/merge.c:1277
 #, c-format
 msgid "Commit %s has an untrusted GPG signature, allegedly by %s."
 msgstr ""
 "Lần chuyển giao %s có một chữ ký GPG không đáng tin, được cho là bởi %s."
 
-#: builtin/merge.c:1268
+#: builtin/merge.c:1280
 #, c-format
 msgid "Commit %s has a bad GPG signature allegedly by %s."
 msgstr "Lần chuyển giao %s có một chữ ký GPG sai, được cho là bởi %s."
 
 #. 'N'
-#: builtin/merge.c:1271
+#: builtin/merge.c:1283
 #, c-format
 msgid "Commit %s does not have a GPG signature."
 msgstr "Lần chuyển giao (commit) %s không có chữ ký GPG."
 
-#: builtin/merge.c:1274
+#: builtin/merge.c:1286
 #, c-format
 msgid "Commit %s has a good GPG signature by %s\n"
 msgstr "Lần chuyển giao %s có một chữ ký GPG tốt bởi %s\n"
 
-#: builtin/merge.c:1358
+#: builtin/merge.c:1370
 #, c-format
 msgid "Updating %s..%s\n"
 msgstr "Đang cập nhật %s..%s\n"
 
-#: builtin/merge.c:1397
+#: builtin/merge.c:1409
 #, c-format
 msgid "Trying really trivial in-index merge...\n"
 msgstr "Đang thử hòa trộn kiểu “trivial in-index”...\n"
 
-#: builtin/merge.c:1404
+#: builtin/merge.c:1416
 #, c-format
 msgid "Nope.\n"
 msgstr "Không.\n"
 
-#: builtin/merge.c:1436
+#: builtin/merge.c:1448
 msgid "Not possible to fast-forward, aborting."
 msgstr "Thực hiện lệnh fast-forward là không thể được, đang bỏ qua."
 
-#: builtin/merge.c:1459 builtin/merge.c:1538
+#: builtin/merge.c:1471 builtin/merge.c:1550
 #, c-format
 msgid "Rewinding the tree to pristine...\n"
 msgstr "Đang tua lại cây thành thời xa xưa...\n"
 
-#: builtin/merge.c:1463
+#: builtin/merge.c:1475
 #, c-format
 msgid "Trying merge strategy %s...\n"
 msgstr "Đang thử chiến lược hòa trộn %s...\n"
 
-#: builtin/merge.c:1529
+#: builtin/merge.c:1541
 #, c-format
 msgid "No merge strategy handled the merge.\n"
 msgstr "Không có chiến lược hòa trộn nào được nắm giữ (handle) sự hòa trộn.\n"
 
-#: builtin/merge.c:1531
+#: builtin/merge.c:1543
 #, c-format
 msgid "Merge with strategy %s failed.\n"
 msgstr "Hòa trộn với chiến lược %s gặp lỗi.\n"
 
-#: builtin/merge.c:1540
+#: builtin/merge.c:1552
 #, c-format
 msgid "Using the %s to prepare resolving by hand.\n"
 msgstr "Sử dụng %s để chuẩn bị giải quyết bằng tay.\n"
 
-#: builtin/merge.c:1552
+#: builtin/merge.c:1564
 #, c-format
 msgid "Automatic merge went well; stopped before committing as requested\n"
 msgstr ""
@@ -6591,48 +7024,52 @@
 msgid "renaming '%s' failed"
 msgstr "đổi tên %s gặp lỗi"
 
-#: builtin/name-rev.c:175
+#: builtin/name-rev.c:259
 msgid "git name-rev [options] <commit>..."
 msgstr "git name-rev [các-tùy-chọn] <commit>..."
 
-#: builtin/name-rev.c:176
+#: builtin/name-rev.c:260
 msgid "git name-rev [options] --all"
 msgstr "git name-rev [các-tùy-chọn] --all"
 
-#: builtin/name-rev.c:177
+#: builtin/name-rev.c:261
 msgid "git name-rev [options] --stdin"
 msgstr "git name-rev [các-tùy-chọn] --stdin"
 
-#: builtin/name-rev.c:229
+#: builtin/name-rev.c:313
 msgid "print only names (no SHA-1)"
 msgstr "chỉ hiển thị tên (không SHA-1)"
 
-#: builtin/name-rev.c:230
+#: builtin/name-rev.c:314
 msgid "only use tags to name the commits"
 msgstr "chỉ dùng các thẻ để đặt tên cho các lần chuyển giao"
 
-#: builtin/name-rev.c:232
+#: builtin/name-rev.c:316
 msgid "only use refs matching <pattern>"
 msgstr "chỉ sử dụng các tham chiếu (refs) khớp với <mẫu>"
 
-#: builtin/name-rev.c:234
+#: builtin/name-rev.c:318
 msgid "list all commits reachable from all refs"
 msgstr ""
 "liệt kê tất cả các lần chuyển giao có thể đọc được từ tất cả các tham chiếu"
 
-#: builtin/name-rev.c:235
+#: builtin/name-rev.c:319
 msgid "read from stdin"
 msgstr "đọc từ đầu vào tiêu chuẩn"
 
-#: builtin/name-rev.c:236
+#: builtin/name-rev.c:320
 msgid "allow to print `undefined` names"
 msgstr "cho phép hiển thị các tên “chưa định nghĩa“"
 
-#: builtin/notes.c:26
+#: builtin/name-rev.c:326
+msgid "dereference tags in the input (internal use)"
+msgstr "bãi bỏ tham chiếu các thẻ trong đầu vào (dùng nội bộ)"
+
+#: builtin/notes.c:24
 msgid "git notes [--ref <notes_ref>] [list [<object>]]"
 msgstr "git notes [--ref <notes_ref>] [list [<đối-tượng>]]"
 
-#: builtin/notes.c:27
+#: builtin/notes.c:25
 msgid ""
 "git notes [--ref <notes_ref>] add [-f] [-m <msg> | -F <file> | (-c | -C) "
 "<object>] [<object>]"
@@ -6640,11 +7077,11 @@
 "git notes [--ref <notes_ref>] add [-f] [-m <lời-nhắn> | -F <tập-tin> | (-c | "
 "-C) <đối-tượng>] [<đối-tượng>]"
 
-#: builtin/notes.c:28
+#: builtin/notes.c:26
 msgid "git notes [--ref <notes_ref>] copy [-f] <from-object> <to-object>"
 msgstr "git notes [--ref <notes_ref>] copy [-f] <từ-đối-tượng> <đến-đối-tượng>"
 
-#: builtin/notes.c:29
+#: builtin/notes.c:27
 msgid ""
 "git notes [--ref <notes_ref>] append [-m <msg> | -F <file> | (-c | -C) "
 "<object>] [<object>]"
@@ -6652,223 +7089,200 @@
 "git notes [--ref <notes_ref>] append [-m <lời-nhắn> | -F <tập-tin> | (-c | -"
 "C) <đối-tượng>] [<đối-tượng>]"
 
-#: builtin/notes.c:30
+#: builtin/notes.c:28
 msgid "git notes [--ref <notes_ref>] edit [<object>]"
 msgstr "git notes [--ref <notes_ref>] edit [<đối-tượng>]"
 
-#: builtin/notes.c:31
+#: builtin/notes.c:29
 msgid "git notes [--ref <notes_ref>] show [<object>]"
 msgstr "git notes [--ref <notes_ref>] show [<đối-tượng>]"
 
-#: builtin/notes.c:32
+#: builtin/notes.c:30
 msgid ""
 "git notes [--ref <notes_ref>] merge [-v | -q] [-s <strategy> ] <notes_ref>"
 msgstr ""
 "git notes [--ref <notes_ref>] merge [-v | -q] [-s <chiến-lược> ] <notes_ref>"
 
-#: builtin/notes.c:33
+#: builtin/notes.c:31
 msgid "git notes merge --commit [-v | -q]"
 msgstr "git notes merge --commit [-v | -q]"
 
-#: builtin/notes.c:34
+#: builtin/notes.c:32
 msgid "git notes merge --abort [-v | -q]"
 msgstr "git notes merge --abort [-v | -q]"
 
-#: builtin/notes.c:35
+#: builtin/notes.c:33
 msgid "git notes [--ref <notes_ref>] remove [<object>...]"
 msgstr "git notes [--ref <notes_ref>] remove [<đối-tượng>...]"
 
-#: builtin/notes.c:36
+#: builtin/notes.c:34
 msgid "git notes [--ref <notes_ref>] prune [-n | -v]"
 msgstr "git notes [--ref <notes_ref>] prune [-n | -v]"
 
-#: builtin/notes.c:37
+#: builtin/notes.c:35
 msgid "git notes [--ref <notes_ref>] get-ref"
 msgstr "git notes [--ref <notes_ref>] get-ref"
 
-#: builtin/notes.c:42
+#: builtin/notes.c:40
 msgid "git notes [list [<object>]]"
 msgstr "git notes [list [<đối tượng>]]"
 
-#: builtin/notes.c:47
+#: builtin/notes.c:45
 msgid "git notes add [<options>] [<object>]"
 msgstr "git notes add [<các-tùy-chọn>] [<đối-tượng>]"
 
-#: builtin/notes.c:52
+#: builtin/notes.c:50
 msgid "git notes copy [<options>] <from-object> <to-object>"
 msgstr "git notes copy [<các-tùy-chọn>] <từ-đối-tượng> <đến-đối-tượng>"
 
-#: builtin/notes.c:53
+#: builtin/notes.c:51
 msgid "git notes copy --stdin [<from-object> <to-object>]..."
 msgstr "git notes copy --stdin [<từ-đối-tượng> <đến-đối-tượng>]..."
 
-#: builtin/notes.c:58
+#: builtin/notes.c:56
 msgid "git notes append [<options>] [<object>]"
 msgstr "git notes append [<các-tùy-chọn>] [<đối-tượng>]"
 
-#: builtin/notes.c:63
+#: builtin/notes.c:61
 msgid "git notes edit [<object>]"
 msgstr "git notes edit [<đối tượng>]"
 
-#: builtin/notes.c:68
+#: builtin/notes.c:66
 msgid "git notes show [<object>]"
 msgstr "git notes show [<đối tượng>]"
 
-#: builtin/notes.c:73
+#: builtin/notes.c:71
 msgid "git notes merge [<options>] <notes_ref>"
 msgstr "git notes merge [<các-tùy-chọn>] <notes_ref>"
 
-#: builtin/notes.c:74
+#: builtin/notes.c:72
 msgid "git notes merge --commit [<options>]"
 msgstr "git notes merge --commit [<các-tùy-chọn>]"
 
-#: builtin/notes.c:75
+#: builtin/notes.c:73
 msgid "git notes merge --abort [<options>]"
 msgstr "git notes merge --abort [<các-tùy-chọn>]"
 
-#: builtin/notes.c:80
+#: builtin/notes.c:78
 msgid "git notes remove [<object>]"
 msgstr "git notes remove [<đối tượng>]"
 
-#: builtin/notes.c:85
+#: builtin/notes.c:83
 msgid "git notes prune [<options>]"
 msgstr "git notes prune [<các-tùy-chọn>]"
 
-#: builtin/notes.c:90
+#: builtin/notes.c:88
 msgid "git notes get-ref"
 msgstr "git notes get-ref"
 
-#: builtin/notes.c:139
+#: builtin/notes.c:137
 #, c-format
 msgid "unable to start 'show' for object '%s'"
 msgstr "không thể khởi chạy “show” cho đối tượng “%s”"
 
-#: builtin/notes.c:143
+#: builtin/notes.c:141
 msgid "could not read 'show' output"
 msgstr "không thể đọc kết xuất “show”"
 
-#: builtin/notes.c:151
+#: builtin/notes.c:149
 #, c-format
 msgid "failed to finish 'show' for object '%s'"
 msgstr "gặp lỗi khi hoàn thành “show” cho đối tượng “%s”"
 
-#: builtin/notes.c:169 builtin/tag.c:341
+#: builtin/notes.c:167 builtin/tag.c:341
 #, c-format
 msgid "could not create file '%s'"
 msgstr "không thể tạo tập tin “%s”"
 
-#: builtin/notes.c:188
+#: builtin/notes.c:186
 msgid "Please supply the note contents using either -m or -F option"
 msgstr ""
 "Xin hãy áp dụng nội dung của ghi chú sử dụng hoặc là tùy chọn -m hoặc là -F"
 
-#: builtin/notes.c:209 builtin/notes.c:972
+#: builtin/notes.c:207 builtin/notes.c:844
 #, c-format
 msgid "Removing note for object %s\n"
 msgstr "Đang gỡ bỏ ghi chú (note) cho đối tượng %s\n"
 
-#: builtin/notes.c:214
+#: builtin/notes.c:212
 msgid "unable to write note object"
 msgstr "không thể ghi đối tượng ghi chú (note)"
 
-#: builtin/notes.c:216
+#: builtin/notes.c:214
 #, c-format
 msgid "The note contents has been left in %s"
 msgstr "Nội dung ghi chú còn lại %s"
 
-#: builtin/notes.c:250 builtin/tag.c:540
+#: builtin/notes.c:248 builtin/tag.c:540
 #, c-format
 msgid "cannot read '%s'"
 msgstr "không thể đọc “%s”"
 
-#: builtin/notes.c:252 builtin/tag.c:543
+#: builtin/notes.c:250 builtin/tag.c:543
 #, c-format
 msgid "could not open or read '%s'"
 msgstr "không thể mở hay đọc “%s”"
 
-#: builtin/notes.c:271 builtin/notes.c:444 builtin/notes.c:446
-#: builtin/notes.c:506 builtin/notes.c:560 builtin/notes.c:643
-#: builtin/notes.c:648 builtin/notes.c:723 builtin/notes.c:765
-#: builtin/notes.c:967 builtin/tag.c:556
+#: builtin/notes.c:269 builtin/notes.c:316 builtin/notes.c:318
+#: builtin/notes.c:378 builtin/notes.c:432 builtin/notes.c:515
+#: builtin/notes.c:520 builtin/notes.c:595 builtin/notes.c:637
+#: builtin/notes.c:839 builtin/tag.c:556
 #, c-format
 msgid "Failed to resolve '%s' as a valid ref."
 msgstr "Gặp lỗi khi phân giải “%s” như là một tham chiếu (ref) hợp lệ."
 
-#: builtin/notes.c:274
+#: builtin/notes.c:272
 #, c-format
 msgid "Failed to read object '%s'."
 msgstr "Gặp lỗi khi đọc đối tượng “%s”."
 
-#: builtin/notes.c:298
-msgid "Cannot commit uninitialized/unreferenced notes tree"
-msgstr ""
-"Không thể chuyển giao (commit) chưa được khởi tạo hoặc không được tham chiếu "
-"cây ghi chú"
-
-#: builtin/notes.c:339
-#, c-format
-msgid "Bad notes.rewriteMode value: '%s'"
-msgstr "Giá trị notes.rewriteMode sai: “%s”"
-
-#: builtin/notes.c:349
-#, c-format
-msgid "Refusing to rewrite notes in %s (outside of refs/notes/)"
-msgstr "Từ chối ghi đè ghi chú trong %s (nằm ngoài của refs/notes/)"
-
-#. TRANSLATORS: The first %s is the name of the
-#. environment variable, the second %s is its value
-#: builtin/notes.c:376
-#, c-format
-msgid "Bad %s value: '%s'"
-msgstr "Giá trị %s sai: “%s”"
-
-#: builtin/notes.c:440
+#: builtin/notes.c:312
 #, c-format
 msgid "Malformed input line: '%s'."
 msgstr "Dòng nhập vào dị hình: “%s”."
 
-#: builtin/notes.c:455
+#: builtin/notes.c:327
 #, c-format
 msgid "Failed to copy notes from '%s' to '%s'"
 msgstr "Gặp lỗi khi sao chép ghi chú (note) từ “%s” tới “%s”"
 
-#: builtin/notes.c:499 builtin/notes.c:553 builtin/notes.c:626
-#: builtin/notes.c:638 builtin/notes.c:711 builtin/notes.c:758
-#: builtin/notes.c:1032
+#: builtin/notes.c:371 builtin/notes.c:425 builtin/notes.c:498
+#: builtin/notes.c:510 builtin/notes.c:583 builtin/notes.c:630
+#: builtin/notes.c:904
 msgid "too many parameters"
 msgstr "quá nhiều đối số"
 
-#: builtin/notes.c:512 builtin/notes.c:771
+#: builtin/notes.c:384 builtin/notes.c:643
 #, c-format
 msgid "No note found for object %s."
 msgstr "không tìm thấy ghi chú cho đối tượng %s."
 
-#: builtin/notes.c:534 builtin/notes.c:691
+#: builtin/notes.c:406 builtin/notes.c:563
 msgid "note contents as a string"
 msgstr "nội dung ghi chú (note) nằm trong một chuỗi"
 
-#: builtin/notes.c:537 builtin/notes.c:694
+#: builtin/notes.c:409 builtin/notes.c:566
 msgid "note contents in a file"
 msgstr "nội dung ghi chú (note) nằm trong một tập tin"
 
-#: builtin/notes.c:539 builtin/notes.c:542 builtin/notes.c:696
-#: builtin/notes.c:699 builtin/tag.c:474
+#: builtin/notes.c:411 builtin/notes.c:414 builtin/notes.c:568
+#: builtin/notes.c:571 builtin/tag.c:474
 msgid "object"
 msgstr "đối tượng"
 
-#: builtin/notes.c:540 builtin/notes.c:697
+#: builtin/notes.c:412 builtin/notes.c:569
 msgid "reuse and edit specified note object"
 msgstr "dùng lại nhưng có sửa chữa đối tượng note đã chỉ ra"
 
-#: builtin/notes.c:543 builtin/notes.c:700
+#: builtin/notes.c:415 builtin/notes.c:572
 msgid "reuse specified note object"
 msgstr "dùng lại đối tượng ghi chú (note) đã chỉ ra"
 
-#: builtin/notes.c:545 builtin/notes.c:613
+#: builtin/notes.c:417 builtin/notes.c:485
 msgid "replace existing notes"
 msgstr "thay thế ghi chú trước"
 
-#: builtin/notes.c:579
+#: builtin/notes.c:451
 #, c-format
 msgid ""
 "Cannot add notes. Found existing notes for object %s. Use '-f' to overwrite "
@@ -6877,24 +7291,24 @@
 "Không thể thêm các ghi chú. Đã tìm thấy các ghi chú đã có sẵn cho đối tượng "
 "%s. Sử dụng tùy chọn “-f” để ghi đè lên các ghi chú cũ"
 
-#: builtin/notes.c:584 builtin/notes.c:661
+#: builtin/notes.c:456 builtin/notes.c:533
 #, c-format
 msgid "Overwriting existing notes for object %s\n"
 msgstr "Đang ghi đè lên ghi chú cũ cho đối tượng %s\n"
 
-#: builtin/notes.c:614
+#: builtin/notes.c:486
 msgid "read objects from stdin"
 msgstr "đọc các đối tượng từ đầu vào tiêu chuẩn"
 
-#: builtin/notes.c:616
+#: builtin/notes.c:488
 msgid "load rewriting config for <command> (implies --stdin)"
 msgstr "tải cấu hình chép lại cho <lệnh> (ngầm định là --stdin)"
 
-#: builtin/notes.c:634
+#: builtin/notes.c:506
 msgid "too few parameters"
 msgstr "quá ít đối số"
 
-#: builtin/notes.c:655
+#: builtin/notes.c:527
 #, c-format
 msgid ""
 "Cannot copy notes. Found existing notes for object %s. Use '-f' to overwrite "
@@ -6903,12 +7317,12 @@
 "Không thể sao chép các ghi chú. Đã tìm thấy các ghi chú đã có sẵn cho đối "
 "tượng %s. Sử dụng tùy chọn “-f” để ghi đè lên các ghi chú cũ"
 
-#: builtin/notes.c:667
+#: builtin/notes.c:539
 #, c-format
 msgid "Missing notes on source object %s. Cannot copy."
 msgstr "Thiếu ghi chú trên đối tượng nguốn %s. Không thể sao chép."
 
-#: builtin/notes.c:716
+#: builtin/notes.c:588
 #, c-format
 msgid ""
 "The -m/-F/-c/-C options have been deprecated for the 'edit' subcommand.\n"
@@ -6917,15 +7331,15 @@
 "Các tùy chọn -m/-F/-c/-C đã cổ không còn dùng nữa cho lệnh con “edit”.\n"
 "Xin hãy sử dụng lệnh sau để thay thế: “git notes add -f -m/-F/-c/-C”.\n"
 
-#: builtin/notes.c:863
+#: builtin/notes.c:735
 msgid "General options"
 msgstr "Tùy chọn chung"
 
-#: builtin/notes.c:865
+#: builtin/notes.c:737
 msgid "Merge options"
 msgstr "Tùy chọn về hòa trộn"
 
-#: builtin/notes.c:867
+#: builtin/notes.c:739
 msgid ""
 "resolve notes conflicts using the given strategy (manual/ours/theirs/union/"
 "cat_sort_uniq)"
@@ -6933,46 +7347,46 @@
 "phân giải các xung đột “notes” sử dụng chiến lược đã đưa ra (manual/ours/"
 "theirs/union/cat_sort_uniq)"
 
-#: builtin/notes.c:869
+#: builtin/notes.c:741
 msgid "Committing unmerged notes"
 msgstr "Chuyển giao các note chưa được hòa trộn"
 
-#: builtin/notes.c:871
+#: builtin/notes.c:743
 msgid "finalize notes merge by committing unmerged notes"
 msgstr ""
 "các note cuối cùng được hòa trộn bởi các note chưa hòa trộn của lần chuyển "
 "giao"
 
-#: builtin/notes.c:873
+#: builtin/notes.c:745
 msgid "Aborting notes merge resolution"
 msgstr "Hủy bỏ phân giải ghi chú (note) hòa trộn"
 
-#: builtin/notes.c:875
+#: builtin/notes.c:747
 msgid "abort notes merge"
 msgstr "bỏ qua hòa trộn các ghi chú (note)"
 
-#: builtin/notes.c:970
+#: builtin/notes.c:842
 #, c-format
 msgid "Object %s has no note\n"
 msgstr "Đối tượng %s không có ghi chú (note)\n"
 
-#: builtin/notes.c:982
+#: builtin/notes.c:854
 msgid "attempt to remove non-existent note is not an error"
 msgstr "cố gắng gỡ bỏ một note chưa từng tồn tại không phải là một lỗi"
 
-#: builtin/notes.c:985
+#: builtin/notes.c:857
 msgid "read object names from the standard input"
 msgstr "đọc tên đối tượng từ thiết bị nhập chuẩn"
 
-#: builtin/notes.c:1066
+#: builtin/notes.c:938
 msgid "notes_ref"
 msgstr "notes_ref"
 
-#: builtin/notes.c:1067
+#: builtin/notes.c:939
 msgid "use notes from <notes_ref>"
 msgstr "dùng “notes” từ <notes_ref>"
 
-#: builtin/notes.c:1102 builtin/remote.c:1598
+#: builtin/notes.c:974 builtin/remote.c:1598
 #, c-format
 msgid "Unknown subcommand: %s"
 msgstr "Không hiểu câu lệnh con: %s"
@@ -7213,7 +7627,7 @@
 "    git push %s %s\n"
 "%s"
 
-#: builtin/push.c:121
+#: builtin/push.c:117
 #, c-format
 msgid ""
 "You are not currently on a branch.\n"
@@ -7228,7 +7642,7 @@
 "\n"
 "    git push %s HEAD:<tên-của-nhánh-máy-chủ>\n"
 
-#: builtin/push.c:128
+#: builtin/push.c:131
 #, c-format
 msgid ""
 "The current branch %s has no upstream branch.\n"
@@ -7242,12 +7656,12 @@
 "\n"
 "    git push --set-upstream %s %s\n"
 
-#: builtin/push.c:136
+#: builtin/push.c:139
 #, c-format
 msgid "The current branch %s has multiple upstream branches, refusing to push."
 msgstr "Nhánh hiện tại %s có đa nhánh thượng nguồn (upstream), từ chối push."
 
-#: builtin/push.c:139
+#: builtin/push.c:142
 #, c-format
 msgid ""
 "You are pushing to remote '%s', which is not the upstream of\n"
@@ -7259,7 +7673,7 @@
 "nhánh hiện tại “%s” của bạn, mà không báo cho tôi biết là cái gì được push\n"
 "để cập nhật nhánh máy chủ nào."
 
-#: builtin/push.c:151
+#: builtin/push.c:165
 msgid ""
 "push.default is unset; its implicit value is changing in\n"
 "Git 2.0 from 'matching' to 'simple'. To squelch this message\n"
@@ -7292,28 +7706,28 @@
 "tự\n"
 "“current” thay vì “simple” nếu bạn thỉnh thoảng phải sử dụng bản Git cũ)"
 
-#: builtin/push.c:199
+#: builtin/push.c:225
 msgid ""
 "You didn't specify any refspecs to push, and push.default is \"nothing\"."
 msgstr ""
 "Bạn đã không chỉ ra một refspecs nào để push, và push.default là \"không là "
 "gì cả\"."
 
-#: builtin/push.c:206
+#: builtin/push.c:232
 msgid ""
 "Updates were rejected because the tip of your current branch is behind\n"
-"its remote counterpart. Merge the remote changes (e.g. 'git pull')\n"
-"before pushing again.\n"
+"its remote counterpart. Integrate the remote changes (e.g.\n"
+"'git pull ...') before pushing again.\n"
 "See the 'Note about fast-forwards' in 'git push --help' for details."
 msgstr ""
 "Việc cập nhật bị từ chối bởi vì đầu mút của nhánh được push nằm đằng sau bộ\n"
 "phận tương ứng của máy chủ. Hòa trộn với các thay đổi từ máy chủ (v.d. “git "
-"pull”)\n"
+"pull...”)\n"
 "trước khi lại push lần nữa.\n"
-"Xem trong phần “Note about fast-forwards” từ lệnh “git push --help” để có "
-"thông tin chi tiết."
+"Xem “Note about fast-forwards” từ lệnh “git push --help” để có thông tin chi "
+"tiết."
 
-#: builtin/push.c:212
+#: builtin/push.c:238
 msgid ""
 "Updates were rejected because a pushed branch tip is behind its remote\n"
 "counterpart. If you did not intend to push that branch, you may want to\n"
@@ -7328,41 +7742,40 @@
 "thành “simple”, “current” hoặc “upstream” để chỉ push nhánh hiện hành mà "
 "thôi."
 
-#: builtin/push.c:218
+#: builtin/push.c:244
 msgid ""
 "Updates were rejected because a pushed branch tip is behind its remote\n"
-"counterpart. Check out this branch and merge the remote changes\n"
-"(e.g. 'git pull') before pushing again.\n"
+"counterpart. Check out this branch and integrate the remote changes\n"
+"(e.g. 'git pull ...') before pushing again.\n"
 "See the 'Note about fast-forwards' in 'git push --help' for details."
 msgstr ""
 "Việc cập nhật bị từ chối bởi vì đầu mút của nhánh được push nằm đằng sau bộ\n"
 "phận tương ứng của máy chủ. Checkou nhánh này và hòa trộn với các thay đổi "
 "từ máy chủ\n"
-"(v.d. “git pull”) trước khi lại push lần nữa.\n"
-"Xem trong phần “Note about fast-forwards” từ lệnh “git push --help” để có "
-"thông tin chi tiết."
+"(v.d. “git pull ...”) trước khi lại push lần nữa.\n"
+"Xem “Note about fast-forwards” từ lệnh “git push --help” để có thông tin chi "
+"tiết."
 
-#: builtin/push.c:224
+#: builtin/push.c:250
 msgid ""
 "Updates were rejected because the remote contains work that you do\n"
 "not have locally. This is usually caused by another repository pushing\n"
-"to the same ref. You may want to first merge the remote changes (e.g.,\n"
-"'git pull') before pushing again.\n"
+"to the same ref. You may want to first integrate the remote changes\n"
+"(e.g., 'git pull ...') before pushing again.\n"
 "See the 'Note about fast-forwards' in 'git push --help' for details."
 msgstr ""
 "Việc cập nhật bị từ chối bởi vì máy chủ có chứa công việc mà bạn không\n"
-"có ở máy nội bộ của mình. Lỗi này thường có nguyên nhân bởi kho khác đẩy dữ "
-"liệu lên\n"
-"cùng một tham chiếu. Bạn có lẽ muốn hòa trộn với các thay đổi từ máy chủ\n"
-"(v.d. “git pull”) trước khi lại push lần nữa.\n"
-"Xem trong phần “Note about fast-forwards” từ lệnh “git push --help” để có "
-"thông tin chi tiết."
+"có ở máy nội bộ của mình. Lỗi này thường có nguyên nhân bởi kho khác đẩy\n"
+"dữ liệu lên cùng một tham chiếu. Bạn có lẽ muốn hòa trộn với các thay đổi\n"
+"từ máy chủ(v.d. “git pull...”) trước khi lại push lần nữa.\n"
+"Xem “Note about fast-forwards” từ lệnh “git push --help” để có thông tin chi "
+"tiết."
 
-#: builtin/push.c:231
+#: builtin/push.c:257
 msgid "Updates were rejected because the tag already exists in the remote."
 msgstr "Việc cập nhật bị từ chối bởi vì thẻ đã sẵn có từ trước trên máy chủ."
 
-#: builtin/push.c:234
+#: builtin/push.c:260
 msgid ""
 "You cannot update a remote ref that points at a non-commit object,\n"
 "or update a remote ref to make it point at a non-commit object,\n"
@@ -7374,22 +7787,22 @@
 "tượng\n"
 "không phải chuyển giao, mà không sử dụng tùy chọn “--force”.\n"
 
-#: builtin/push.c:294
+#: builtin/push.c:320
 #, c-format
 msgid "Pushing to %s\n"
 msgstr "Đang push (đẩy) lên %s\n"
 
-#: builtin/push.c:298
+#: builtin/push.c:324
 #, c-format
 msgid "failed to push some refs to '%s'"
 msgstr "gặp lỗi khi push (đẩy lên) một số tham chiếu (ref) đến “%s”"
 
-#: builtin/push.c:331
+#: builtin/push.c:357
 #, c-format
 msgid "bad repository '%s'"
 msgstr "repository (kho) sai “%s”"
 
-#: builtin/push.c:332
+#: builtin/push.c:358
 msgid ""
 "No configured push destination.\n"
 "Either specify the URL from the command-line or configure a remote "
@@ -7410,88 +7823,88 @@
 "\n"
 "    git push <tên>\n"
 
-#: builtin/push.c:347
+#: builtin/push.c:373
 msgid "--all and --tags are incompatible"
 msgstr "--all và --tags xung khắc nhau"
 
-#: builtin/push.c:348
+#: builtin/push.c:374
 msgid "--all can't be combined with refspecs"
 msgstr "--all không thể được tổ hợp cùng với refspecs"
 
-#: builtin/push.c:353
+#: builtin/push.c:379
 msgid "--mirror and --tags are incompatible"
 msgstr "--mirror và --tags xung khắc nhau"
 
-#: builtin/push.c:354
+#: builtin/push.c:380
 msgid "--mirror can't be combined with refspecs"
 msgstr "--mirror không thể được tổ hợp cùng với refspecs"
 
-#: builtin/push.c:359
+#: builtin/push.c:385
 msgid "--all and --mirror are incompatible"
 msgstr "--all và --mirror xung khắc nhau"
 
-#: builtin/push.c:419
+#: builtin/push.c:445
 msgid "repository"
 msgstr "kho"
 
-#: builtin/push.c:420
+#: builtin/push.c:446
 msgid "push all refs"
 msgstr "push tất cả refs"
 
-#: builtin/push.c:421
+#: builtin/push.c:447
 msgid "mirror all refs"
 msgstr "mirror tất cả refs"
 
-#: builtin/push.c:423
+#: builtin/push.c:449
 msgid "delete refs"
 msgstr "xóa refs"
 
-#: builtin/push.c:424
+#: builtin/push.c:450
 msgid "push tags (can't be used with --all or --mirror)"
 msgstr ""
 "các thẻ push (không thể sử dụng cùng với các tùy chọn --all hay --mirror)"
 
-#: builtin/push.c:427
+#: builtin/push.c:453
 msgid "force updates"
 msgstr "ép buộc cập nhật"
 
-#: builtin/push.c:428
+#: builtin/push.c:454
 msgid "check"
 msgstr "kiểm tra"
 
-#: builtin/push.c:429
+#: builtin/push.c:455
 msgid "control recursive pushing of submodules"
 msgstr "điều khiển việc đẩy lên (push) đệ qui của mô-đun-con"
 
-#: builtin/push.c:431
+#: builtin/push.c:457
 msgid "use thin pack"
 msgstr "tạo gói nhẹ"
 
-#: builtin/push.c:432 builtin/push.c:433
+#: builtin/push.c:458 builtin/push.c:459
 msgid "receive pack program"
 msgstr "nhận về chương trình pack"
 
-#: builtin/push.c:434
+#: builtin/push.c:460
 msgid "set upstream for git pull/status"
 msgstr "đặt thượng nguồn (upstream) cho git pull/status"
 
-#: builtin/push.c:437
+#: builtin/push.c:463
 msgid "prune locally removed refs"
 msgstr "prune (cắt cụt) những tham chiếu (refs) bị gỡ bỏ"
 
-#: builtin/push.c:439
+#: builtin/push.c:465
 msgid "bypass pre-push hook"
 msgstr "vòng qua “pre-push hook”"
 
-#: builtin/push.c:440
+#: builtin/push.c:466
 msgid "push missing but relevant tags"
 msgstr "push bị trượt nhưng các thẻ thích hợp"
 
-#: builtin/push.c:450
+#: builtin/push.c:476
 msgid "--delete is incompatible with --all, --mirror and --tags"
 msgstr "--delete là xung khắc với các tùy chọn --all, --mirror và --tags"
 
-#: builtin/push.c:452
+#: builtin/push.c:478
 msgid "--delete doesn't make sense without any refs"
 msgstr "--delete không hợp lý nếu không có bất kỳ tham chiếu (refs) nào"
 
@@ -7506,71 +7919,81 @@
 "[--index-output=<tập-tin>] (--empty | <tree-ish1> [<tree-ish2> [<tree-"
 "ish3>]])"
 
-#: builtin/read-tree.c:108
+#: builtin/read-tree.c:109
 msgid "write resulting index to <file>"
 msgstr "ghi mục lục kết quả vào <tập-tin>"
 
-#: builtin/read-tree.c:111
+#: builtin/read-tree.c:112
 msgid "only empty the index"
 msgstr "chỉ với bảng mục lục trống rỗng"
 
-#: builtin/read-tree.c:113
+#: builtin/read-tree.c:114
 msgid "Merging"
 msgstr "Hòa trộn"
 
-#: builtin/read-tree.c:115
+#: builtin/read-tree.c:116
 msgid "perform a merge in addition to a read"
 msgstr "thực hiện một hòa trộn thêm vào việc đọc"
 
-#: builtin/read-tree.c:117
+#: builtin/read-tree.c:118
 msgid "3-way merge if no file level merging required"
 msgstr ""
 "hòa trộn kiểu “3-way” nếu không có tập tin mức hòa trộn nào được yêu cầu "
 
-#: builtin/read-tree.c:119
+#: builtin/read-tree.c:120
 msgid "3-way merge in presence of adds and removes"
 msgstr "hòa trộn 3-way trong sự hiện diện của “adds” và “removes”"
 
-#: builtin/read-tree.c:121
+#: builtin/read-tree.c:122
 msgid "same as -m, but discard unmerged entries"
 msgstr "giống với -m, nhưng bỏ qua các mục chưa được hòa trộn"
 
-#: builtin/read-tree.c:122
+#: builtin/read-tree.c:123
 msgid "<subdirectory>/"
 msgstr "<thư-mục-con>/"
 
-#: builtin/read-tree.c:123
+#: builtin/read-tree.c:124
 msgid "read the tree into the index under <subdirectory>/"
 msgstr "đọc cây vào trong bảng mục lục dưới <thư_mục_con>/"
 
-#: builtin/read-tree.c:126
+#: builtin/read-tree.c:127
 msgid "update working tree with merge result"
 msgstr "cập nhật cây làm việc với kết quả hòa trộn"
 
-#: builtin/read-tree.c:128
+#: builtin/read-tree.c:129
 msgid "gitignore"
 msgstr "gitignore"
 
-#: builtin/read-tree.c:129
+#: builtin/read-tree.c:130
 msgid "allow explicitly ignored files to be overwritten"
 msgstr "cho phép các tập tin rõ ràng bị lờ đi được ghi đè"
 
-#: builtin/read-tree.c:132
+#: builtin/read-tree.c:133
 msgid "don't check the working tree after merging"
 msgstr "không kiểm tra cây làm việc sau hòa trộn"
 
-#: builtin/read-tree.c:133
+#: builtin/read-tree.c:134
 msgid "don't update the index or the work tree"
 msgstr "không cập nhật bảng mục lục hay cây làm việc"
 
-#: builtin/read-tree.c:135
+#: builtin/read-tree.c:136
 msgid "skip applying sparse checkout filter"
 msgstr "bỏ qua áp dụng bộ lọc lấy ra (checkout) thưa thớt"
 
-#: builtin/read-tree.c:137
+#: builtin/read-tree.c:138
 msgid "debug unpack-trees"
 msgstr "gỡ lỗi unpack-trees"
 
+#: builtin/reflog.c:500
+#, c-format
+msgid "%s' for '%s' is not a valid timestamp"
+msgstr "%s' cho '%s' không phải là dấu thời gian hợp lệ"
+
+#: builtin/reflog.c:616 builtin/reflog.c:621
+#, c-format
+msgid "'%s' is not a valid timestamp"
+msgstr "“%s” không phải là dấu thời gian hợp lệ"
+
 #: builtin/remote.c:11
 msgid "git remote [-v | --verbose]"
 msgstr "git remote [-v | --verbose]"
@@ -8146,97 +8569,97 @@
 msgid "Failed to find tree of %s."
 msgstr "Gặp lỗi khi tìm cây của %s."
 
-#: builtin/reset.c:98
+#: builtin/reset.c:99
 #, c-format
 msgid "HEAD is now at %s"
 msgstr "HEAD hiện giờ tại %s"
 
-#: builtin/reset.c:169
+#: builtin/reset.c:172
 #, c-format
 msgid "Cannot do a %s reset in the middle of a merge."
 msgstr "Không thể thực hiện một %s reset ở giữa của quá trình hòa trộn."
 
-#: builtin/reset.c:248
+#: builtin/reset.c:251
 msgid "be quiet, only report errors"
 msgstr "làm việc ở chế độ im lặng, chỉ hiển thị khi có lỗi"
 
-#: builtin/reset.c:250
+#: builtin/reset.c:253
 msgid "reset HEAD and index"
 msgstr "đặt lại (reset) HEAD và bảng mục lục"
 
-#: builtin/reset.c:251
+#: builtin/reset.c:254
 msgid "reset only HEAD"
 msgstr "chỉ đặt lại (reset) HEAD"
 
-#: builtin/reset.c:253 builtin/reset.c:255
+#: builtin/reset.c:256 builtin/reset.c:258
 msgid "reset HEAD, index and working tree"
 msgstr "đặt lại HEAD, bảng mục lục và cây làm việc"
 
-#: builtin/reset.c:257
+#: builtin/reset.c:260
 msgid "reset HEAD but keep local changes"
 msgstr "đặt lại HEAD nhưng giữ lại các thay đổi nội bộ"
 
-#: builtin/reset.c:275
+#: builtin/reset.c:278
 #, c-format
 msgid "Failed to resolve '%s' as a valid revision."
 msgstr "Gặp lỗi khi phân giải “%s” như là điểm xét duyệt hợp lệ."
 
-#: builtin/reset.c:278 builtin/reset.c:286
+#: builtin/reset.c:281 builtin/reset.c:289
 #, c-format
 msgid "Could not parse object '%s'."
 msgstr "không thể phân tích đối tượng “%s”."
 
-#: builtin/reset.c:283
+#: builtin/reset.c:286
 #, c-format
 msgid "Failed to resolve '%s' as a valid tree."
 msgstr "Gặp lỗi khi phân giải “%s” như là một cây (tree) hợp lệ."
 
-#: builtin/reset.c:292
+#: builtin/reset.c:295
 msgid "--patch is incompatible with --{hard,mixed,soft}"
 msgstr "--patch xung khắc với --{hard,mixed,soft}"
 
-#: builtin/reset.c:301
+#: builtin/reset.c:304
 msgid "--mixed with paths is deprecated; use 'git reset -- <paths>' instead."
 msgstr ""
 "--mixed với các đường dẫn không còn dùng nữa; hãy thay thế bằng lệnh “git "
 "reset -- <đường_dẫn>”."
 
-#: builtin/reset.c:303
+#: builtin/reset.c:306
 #, c-format
 msgid "Cannot do %s reset with paths."
 msgstr "Không thể thực hiện lệnh %s reset với các đường dẫn."
 
-#: builtin/reset.c:313
+#: builtin/reset.c:316
 #, c-format
 msgid "%s reset is not allowed in a bare repository"
 msgstr "%s reset không được phép trên kho bare (trên máy chủ)"
 
-#: builtin/reset.c:333
+#: builtin/reset.c:336
 #, c-format
 msgid "Could not reset index file to revision '%s'."
-msgstr "Không thể đặt lại (reset) bảng mục lục thành điểm xét lại “%s”."
+msgstr "Không thể đặt lại (reset) bảng mục lục thành điểm xét duyệt “%s”."
 
-#: builtin/reset.c:339
+#: builtin/reset.c:342
 msgid "Unstaged changes after reset:"
 msgstr "Những thay đổi bị bỏ trạng thái (stage) sau khi reset:"
 
-#: builtin/reset.c:344
+#: builtin/reset.c:347
 msgid "Could not write new index file."
 msgstr "Không thể ghi tập tin lưu bảng mục lục mới."
 
-#: builtin/rev-parse.c:339
+#: builtin/rev-parse.c:345
 msgid "git rev-parse --parseopt [options] -- [<args>...]"
 msgstr "git rev-parse --parseopt [các-tùy-chọn] -- [<th.số>...]"
 
-#: builtin/rev-parse.c:344
+#: builtin/rev-parse.c:350
 msgid "keep the `--` passed as an arg"
 msgstr "giữ “--“ chuyển qua làm tham số"
 
-#: builtin/rev-parse.c:346
+#: builtin/rev-parse.c:352
 msgid "stop parsing after the first non-option argument"
 msgstr "dừng phân tích sau đối số đầu tiên không có tùy chọn"
 
-#: builtin/rev-parse.c:464
+#: builtin/rev-parse.c:470
 msgid ""
 "git rev-parse --parseopt [options] -- [<args>...]\n"
 "   or: git rev-parse --sq-quote [<arg>...]\n"
@@ -8251,191 +8674,219 @@
 "Chạy lệnh \"git rev-parse --parseopt -h\" để có thêm thông tin về cách dùng."
 
 #: builtin/revert.c:22
-msgid "git revert [options] <commit-ish>"
-msgstr "git revert [các-tùy-chọn] <commit-ish>"
+msgid "git revert [options] <commit-ish>..."
+msgstr "git revert [các-tùy-chọn] <commit-ish>..."
 
 #: builtin/revert.c:23
 msgid "git revert <subcommand>"
 msgstr "git revert <lệnh-con>"
 
 #: builtin/revert.c:28
-msgid "git cherry-pick [options] <commit-ish>"
-msgstr "git cherry-pick [các-tùy-chọn] <commit-ish>"
+msgid "git cherry-pick [options] <commit-ish>..."
+msgstr "git cherry-pick [các-tùy-chọn] <commit-ish>..."
 
 #: builtin/revert.c:29
 msgid "git cherry-pick <subcommand>"
 msgstr "git cherry-pick <lệnh-con>"
 
-#: builtin/revert.c:70 builtin/revert.c:92
+#: builtin/revert.c:71 builtin/revert.c:94
 #, c-format
 msgid "%s: %s cannot be used with %s"
 msgstr "%s: %s không thể được sử dụng với %s"
 
-#: builtin/revert.c:103
+#: builtin/revert.c:105
 msgid "end revert or cherry-pick sequence"
 msgstr "kết thúc cherry-pick hay revert liên tiếp nhau"
 
-#: builtin/revert.c:104
+#: builtin/revert.c:106
 msgid "resume revert or cherry-pick sequence"
 msgstr "phục hồi lại cherry-pick hay revert liên tiếp nhau"
 
-#: builtin/revert.c:105
+#: builtin/revert.c:107
 msgid "cancel revert or cherry-pick sequence"
 msgstr "không cherry-pick hay revert liên tiếp nhau"
 
-#: builtin/revert.c:106
+#: builtin/revert.c:108
 msgid "don't automatically commit"
 msgstr "không commit một cách tự động."
 
-#: builtin/revert.c:107
+#: builtin/revert.c:109
 msgid "edit the commit message"
 msgstr "sửa lại chú thích cho commit"
 
-#: builtin/revert.c:110
+#: builtin/revert.c:112
 msgid "parent number"
 msgstr "số của cha mẹ"
 
-#: builtin/revert.c:112
+#: builtin/revert.c:114
 msgid "merge strategy"
 msgstr "chiến lược hòa trộn"
 
-#: builtin/revert.c:113
+#: builtin/revert.c:115
 msgid "option"
 msgstr "tùy chọn"
 
-#: builtin/revert.c:114
+#: builtin/revert.c:116
 msgid "option for merge strategy"
 msgstr "tùy chọn cho chiến lược hòa trộn"
 
-#: builtin/revert.c:125
+#: builtin/revert.c:127
 msgid "append commit name"
 msgstr "nối thêm tên lần chuyển giao (commit)"
 
-#: builtin/revert.c:126
+#: builtin/revert.c:128
 msgid "allow fast-forward"
 msgstr "cho phép fast-forward"
 
-#: builtin/revert.c:127
+#: builtin/revert.c:129
 msgid "preserve initially empty commits"
 msgstr "cấm khởi tạo lần chuyển giao trống rỗng"
 
-#: builtin/revert.c:128
+#: builtin/revert.c:130
 msgid "allow commits with empty messages"
 msgstr "chấp nhận chuyển giao (commit) mà không ghi chú gì"
 
-#: builtin/revert.c:129
+#: builtin/revert.c:131
 msgid "keep redundant, empty commits"
 msgstr "giữ lại các lần chuyển giao dư thừa, rỗng"
 
-#: builtin/revert.c:133
+#: builtin/revert.c:135
 msgid "program error"
 msgstr "lỗi chương trình"
 
-#: builtin/revert.c:223
+#: builtin/revert.c:225
 msgid "revert failed"
 msgstr "revert gặp lỗi"
 
-#: builtin/revert.c:238
+#: builtin/revert.c:240
 msgid "cherry-pick failed"
 msgstr "cherry-pick gặp lỗi"
 
-#: builtin/rm.c:15
+#: builtin/rm.c:16
 msgid "git rm [options] [--] <file>..."
 msgstr "git rm [các-tùy-chọn] [--] <tập-tin>..."
 
-#: builtin/rm.c:64 builtin/rm.c:186
-#, c-format
+#: builtin/rm.c:64
 msgid ""
-"submodule '%s' (or one of its nested submodules) uses a .git directory\n"
+"the following submodule (or one of its nested submodules)\n"
+"uses a .git directory:"
+msgid_plural ""
+"the following submodules (or one of its nested submodules)\n"
+"use a .git directory:"
+msgstr[0] ""
+"mô-đun-con sau đây (hay một trong số mô-đun-con bên trong của nó)\n"
+"dùng một thư mục .git:"
+msgstr[1] ""
+"các mô-đun-con sau đây (hay một trong số mô-đun-con bên trong của nó)\n"
+"dùng một thư mục .git:"
+
+#: builtin/rm.c:70
+msgid ""
+"\n"
 "(use 'rm -rf' if you really want to remove it including all of its history)"
 msgstr ""
-"mô-đun-con “%s” (hoặc cái nằm trong các mô-đun-con) dùng thư mục .git\n"
-"(dùng “rm -rf” nếu bạn thực sự muốn gỡ bỏ nó cùng với tất cả lịch sử của "
+"\n"
+"(dùng /\"rm -rf/\" nếu bạn thực sự muốn gỡ bỏ nó cùng với tất cả lịch sử của "
 "chúng)"
 
-#: builtin/rm.c:174
-#, c-format
+#: builtin/rm.c:230
 msgid ""
-"'%s' has staged content different from both the file and the HEAD\n"
+"the following file has staged content different from both the\n"
+"file and the HEAD:"
+msgid_plural ""
+"the following files have staged content different from both the\n"
+"file and the HEAD:"
+msgstr[0] ""
+"tập tin sau đây có trạng thái khác biệt nội dung từ cả tập tin\n"
+"và cả HEAD:"
+msgstr[1] ""
+"các tập tin sau đây có trạng thái khác biệt nội dung từ cả tập tin\n"
+"và cả HEAD:"
+
+#: builtin/rm.c:235
+msgid ""
+"\n"
 "(use -f to force removal)"
 msgstr ""
-"“%s” có nội dung được lưu trạng thái khác biệt từ cả tập tin và cả HEAD\n"
-"(dùng tùy chọn -f để ép buộc gỡ bỏ)"
+"\n"
+"(dùng -f để buộc gỡ bỏ)"
 
-#: builtin/rm.c:180
-#, c-format
+#: builtin/rm.c:239
+msgid "the following file has changes staged in the index:"
+msgid_plural "the following files have changes staged in the index:"
+msgstr[0] "tập tin sau đây có thay đổi trạng thái trong bảng mục lục:"
+msgstr[1] "các tập tin sau đây có thay đổi trạng thái trong bảng mục lục:"
+
+#: builtin/rm.c:243 builtin/rm.c:254
 msgid ""
-"'%s' has changes staged in the index\n"
+"\n"
 "(use --cached to keep the file, or -f to force removal)"
 msgstr ""
-"“%s” có các thay đổi được lưu trạng thái trong bảng mục lục\n"
+"\n"
 "(dùng tùy chọn --cached để giữ tập tin, hoặc -f để ép buộc gỡ bỏ)"
 
-#: builtin/rm.c:191
-#, c-format
-msgid ""
-"'%s' has local modifications\n"
-"(use --cached to keep the file, or -f to force removal)"
-msgstr ""
-"“%s” có các thay đổi nội bộ\n"
-"(dùng tùy chọn --cached để giữ tập tin, hoặc -f để ép buộc gỡ bỏ)"
+#: builtin/rm.c:251
+msgid "the following file has local modifications:"
+msgid_plural "the following files have local modifications:"
+msgstr[0] "tập tin sau đây có những thay đổi nội bộ:"
+msgstr[1] "những tập tin sau đây có những thay đổi nội bộ:"
 
-#: builtin/rm.c:207
+#: builtin/rm.c:269
 msgid "do not list removed files"
 msgstr "không liệt kê các tập tin đã gỡ bỏ"
 
-#: builtin/rm.c:208
+#: builtin/rm.c:270
 msgid "only remove from the index"
 msgstr "chỉ gỡ bỏ từ mục lục"
 
-#: builtin/rm.c:209
+#: builtin/rm.c:271
 msgid "override the up-to-date check"
 msgstr "ghi đè lên kiểm tra cập nhật"
 
-#: builtin/rm.c:210
+#: builtin/rm.c:272
 msgid "allow recursive removal"
 msgstr "cho phép gỡ bỏ đệ qui"
 
-#: builtin/rm.c:212
+#: builtin/rm.c:274
 msgid "exit with a zero status even if nothing matched"
 msgstr "thoát ra với trạng thái khác không thậm chí nếu không có gì khớp"
 
-#: builtin/rm.c:283
+#: builtin/rm.c:345
 #, c-format
 msgid "not removing '%s' recursively without -r"
 msgstr "không thể gỡ bỏ “%s” một cách đệ qui mà không có tùy chọn -r"
 
-#: builtin/rm.c:322
+#: builtin/rm.c:384
 #, c-format
 msgid "git rm: unable to remove %s"
 msgstr "git rm: không thể gỡ bỏ %s"
 
 #: builtin/shortlog.c:13
-msgid "git shortlog [-n] [-s] [-e] [-w] [rev-opts] [--] [<commit-id>... ]"
-msgstr "git shortlog [-n] [-s] [-e] [-w] [rev-opts] [--] [<commit-id>... ]"
+msgid "git shortlog [<options>] [<revision range>] [[--] [<path>...]]"
+msgstr "git shortlog [các-tùy-chọn] [<vùng-xét-duyệt>] [[--] [<đường-dẫn>...]]"
 
-#: builtin/shortlog.c:133
+#: builtin/shortlog.c:131
 #, c-format
 msgid "Missing author: %s"
 msgstr "Thiếu tên tác giả: %s"
 
-#: builtin/shortlog.c:229
+#: builtin/shortlog.c:228
 msgid "sort output according to the number of commits per author"
 msgstr "sắp xếp kết xuất tuân theo số lượng chuyển giao trên mỗi tác giả"
 
-#: builtin/shortlog.c:231
+#: builtin/shortlog.c:230
 msgid "Suppress commit descriptions, only provides commit count"
 msgstr "Chặn mọi mô tả lần chuyển giao, chỉ đưa ra số lượng lần chuyển giao"
 
-#: builtin/shortlog.c:233
+#: builtin/shortlog.c:232
 msgid "Show the email address of each author"
 msgstr "Hiển thị thư điện tử cho từng tác giả"
 
-#: builtin/shortlog.c:234
+#: builtin/shortlog.c:233
 msgid "w[,i1[,i2]]"
 msgstr "w[,i1[,i2]]"
 
-#: builtin/shortlog.c:235
+#: builtin/shortlog.c:234
 msgid "Linewrap output"
 msgstr "Ngắt dòng khi quá dài"
 
@@ -8455,47 +8906,47 @@
 msgid "git show-branch (-g|--reflog)[=<n>[,<base>]] [--list] [<ref>]"
 msgstr "git show-branch (-g|--reflog)[=<n>[,<nền>]] [--list] [<ref>]"
 
-#: builtin/show-branch.c:651
+#: builtin/show-branch.c:650
 msgid "show remote-tracking and local branches"
 msgstr "hiển thị các nhánh remote-tracking và nội bộ"
 
-#: builtin/show-branch.c:653
+#: builtin/show-branch.c:652
 msgid "show remote-tracking branches"
 msgstr "hiển thị các nhánh remote-tracking"
 
-#: builtin/show-branch.c:655
+#: builtin/show-branch.c:654
 msgid "color '*!+-' corresponding to the branch"
 msgstr "màu “*!+-” tương ứng với nhánh"
 
-#: builtin/show-branch.c:657
+#: builtin/show-branch.c:656
 msgid "show <n> more commits after the common ancestor"
 msgstr "hiển thị thêm <n> lần chuyển giao sau cha mẹ chung"
 
-#: builtin/show-branch.c:659
+#: builtin/show-branch.c:658
 msgid "synonym to more=-1"
 msgstr "đồng nghĩa với more=-1"
 
-#: builtin/show-branch.c:660
+#: builtin/show-branch.c:659
 msgid "suppress naming strings"
 msgstr "chặn các chuỗi đặt tên"
 
-#: builtin/show-branch.c:662
+#: builtin/show-branch.c:661
 msgid "include the current branch"
 msgstr "bao gồm nhánh hiện hành"
 
-#: builtin/show-branch.c:664
+#: builtin/show-branch.c:663
 msgid "name commits with their object names"
 msgstr "đặt tên các lần chuyển giao bằng các tên của đối tượng của chúng"
 
-#: builtin/show-branch.c:666
+#: builtin/show-branch.c:665
 msgid "show possible merge bases"
 msgstr "hiển thị mọi cơ sở có thể dùng để hòa trộn"
 
-#: builtin/show-branch.c:668
+#: builtin/show-branch.c:667
 msgid "show refs unreachable from any other ref"
 msgstr "hiển thị các tham chiếu không thể được đọc bởi bất kỳ tham chiếu khác"
 
-#: builtin/show-branch.c:670
+#: builtin/show-branch.c:669
 msgid "show commits in topological order"
 msgstr "hiển thị các lần chuyển giao theo thứ tự tôpô"
 
@@ -8508,14 +8959,14 @@
 msgstr "hiển thị các lần hòa trộn có thể đọc được chỉ từ một đầu mút"
 
 #: builtin/show-branch.c:676
-msgid "show commits where no parent comes before its children"
-msgstr "hiển thị các lần chuyển giao nơi mà cha mẹ đến trước con của nó"
+msgid "topologically sort, maintaining date order where possible"
+msgstr "sắp xếp hình thái học, bảo trì thứ tự ngày nếu có thể"
 
-#: builtin/show-branch.c:678
+#: builtin/show-branch.c:679
 msgid "<n>[,<base>]"
 msgstr "<n>[,<cơ sở>]"
 
-#: builtin/show-branch.c:679
+#: builtin/show-branch.c:680
 msgid "show <n> most recent ref-log entries starting at base"
 msgstr "hiển thị <n> các mục “ref-log” gần nhất kể từ nền (base)"
 
@@ -8531,38 +8982,38 @@
 msgid "git show-ref --exclude-existing[=pattern] < ref-list"
 msgstr "git show-ref --exclude-existing[=mẫu] < ref-list"
 
-#: builtin/show-ref.c:165
+#: builtin/show-ref.c:168
 msgid "only show tags (can be combined with heads)"
 msgstr "chỉ hiển thị thẻ (có thể tổ hợp cùng với đầu)"
 
-#: builtin/show-ref.c:166
+#: builtin/show-ref.c:169
 msgid "only show heads (can be combined with tags)"
 msgstr "chỉ hiển thị đầu (có thể tổ hợp cùng với thẻ)"
 
-#: builtin/show-ref.c:167
+#: builtin/show-ref.c:170
 msgid "stricter reference checking, requires exact ref path"
 msgstr ""
 "việc kiểm tra tham chiếu chính xác, đòi hỏi chính xác đường dẫn tham chiếu "
 "(ref)"
 
-#: builtin/show-ref.c:170 builtin/show-ref.c:172
-msgid "show the HEAD reference"
-msgstr "hiển thị tham chiếu của HEAD"
+#: builtin/show-ref.c:173 builtin/show-ref.c:176
+msgid "show the HEAD reference, even if it would be filtered out"
+msgstr "hiển thị tham chiếu HEAD, ngay cả khi nó đã được lọc ra"
 
-#: builtin/show-ref.c:174
+#: builtin/show-ref.c:178
 msgid "dereference tags into object IDs"
 msgstr "bãi bỏ tham chiếu các thẻ thành ra các ID đối tượng"
 
-#: builtin/show-ref.c:176
+#: builtin/show-ref.c:180
 msgid "only show SHA1 hash using <n> digits"
 msgstr "chỉ hiển thị mã băm SHA1 sử dụng <n> chữ số"
 
-#: builtin/show-ref.c:180
+#: builtin/show-ref.c:184
 msgid "do not print results to stdout (useful with --verify)"
 msgstr ""
 "không hiển thị kết quả ra đầu ra chuẩn (stdout) (chỉ hữu dụng với --verify)"
 
-#: builtin/show-ref.c:182
+#: builtin/show-ref.c:186
 msgid "show refs from stdin that aren't in local repository"
 msgstr ""
 "hiển thị các tham chiếu (refs) từ đầu vào tiêu chuẩn (stdin) cái mà không ở "
@@ -8983,24 +9434,33 @@
 msgid "only useful for debugging"
 msgstr "chỉ hữu ích khi cần gỡ lỗi"
 
-#: git.c:16
-msgid "See 'git help <command>' for more information on a specific command."
+#: git.c:17
+msgid ""
+"'git help -a' and 'git help -g' lists available subcommands and some\n"
+"concept guides. See 'git help <command>' or 'git help <concept>'\n"
+"to read about a specific subcommand or concept."
 msgstr ""
-"Chạy lệnh “git help <tên-lệnh>” để có thêm thông tin về lệnh được chỉ ra."
+"“git help -a” và “git help -g” liệt kê các câu lệnh con sẵn có và một số\n"
+"hướng dẫn về khái niệm. Xem “git help <lệnh>” hay “git help <khái-niệm>”\n"
+"để xem các đặc tả cho lệnh hay khái niệm cụ thể."
 
-#: parse-options.h:156
+#: parse-options.h:144
+msgid "expiry date"
+msgstr "ngày hết hạn"
+
+#: parse-options.h:159
 msgid "no-op (backward compatibility)"
 msgstr "no-op (tương thích ngược)"
 
-#: parse-options.h:232
+#: parse-options.h:236
 msgid "be more verbose"
 msgstr "chi tiết hơn nữa"
 
-#: parse-options.h:234
+#: parse-options.h:238
 msgid "be more quiet"
 msgstr "im lặng hơn nữa"
 
-#: parse-options.h:240
+#: parse-options.h:244
 msgid "use <n> digits to display SHA-1s"
 msgstr "sử dụng <n> chữ số để hiển thị SHA-1s"
 
@@ -9018,7 +9478,7 @@
 
 #: common-cmds.h:11
 msgid "Checkout a branch or paths to the working tree"
-msgstr "Lấy ra (checkout) một nhánh hay các đường dẫn tới cây làm việc"
+msgstr "Lấy ra một nhánh hay các đường dẫn tới cây làm việc"
 
 #: common-cmds.h:12
 msgid "Clone a repository into a new directory"
@@ -9031,12 +9491,12 @@
 #: common-cmds.h:14
 msgid "Show changes between commits, commit and working tree, etc"
 msgstr ""
-"Hiển thị các thay đổi giữa những lần chuyển giao (commit), commit và cây làm "
-"việc, v.v.."
+"Xem các thay đổi giữa những lần chuyển giao,\n"
+"               giữa một lần chuyển giao và cây làm việc, v.v.."
 
 #: common-cmds.h:15
 msgid "Download objects and refs from another repository"
-msgstr "Các đối tượng và tham chiếu được tải về từ kho chứa khác"
+msgstr "Tải về các đối tượng và tham chiếu từ kho chứa khác"
 
 #: common-cmds.h:16
 msgid "Print lines matching a pattern"
@@ -9044,40 +9504,37 @@
 
 #: common-cmds.h:17
 msgid "Create an empty Git repository or reinitialize an existing one"
-msgstr ""
-"Tạo một kho git trống rỗng hay khởi tạo lại một kho đã tồn tại từ trước"
+msgstr "Tạo một kho git mới hay khởi tạo lại một kho đã tồn tại từ trước"
 
 #: common-cmds.h:18
 msgid "Show commit logs"
-msgstr "Hiển thị nhật ký các lần chuyển giao (commit)"
+msgstr "Hiển thị nhật ký các lần chuyển giao"
 
 #: common-cmds.h:19
 msgid "Join two or more development histories together"
-msgstr ""
-"Hợp nhất hai hay nhiều hơn lịch sử của các nhà phát triển phần mềm lại với "
-"nhau"
+msgstr "Hợp nhất hai hay nhiều hơn lịch sử của các nhà phát triển"
 
 #: common-cmds.h:20
 msgid "Move or rename a file, a directory, or a symlink"
-msgstr "Di chuyển, đổi tên một tập tin, thư mục hay liên kết tượng trưng"
+msgstr "Di chuyển hay đổi tên một tập tin, thư mục hoặc liên kết mềm"
 
 #: common-cmds.h:21
-msgid "Fetch from and merge with another repository or a local branch"
-msgstr "Lấy về (fetch) và hòa trộn với kho khác hay nhánh nội bộ"
+msgid "Fetch from and integrate with another repository or a local branch"
+msgstr "Lấy về và hợp nhất với kho khác hay một nhánh nội bộ"
 
 #: common-cmds.h:22
 msgid "Update remote refs along with associated objects"
-msgstr ""
-"Cập nhật tham chiếu (refs) máy chủ cùng với các đối tượng liên quan đến nó"
+msgstr "Cập nhật th.chiếu máy chủ cùng với các đối tượng liên quan đến nó"
 
 #: common-cmds.h:23
 msgid "Forward-port local commits to the updated upstream head"
 msgstr ""
-"Forward-port những lần chuyển giao nội bộ tới head thượng nguồn đã cập nhật"
+"Chuyển tiếp những lần chuyển giao nội bộ\n"
+"               tới head thượng nguồn đã cập nhật"
 
 #: common-cmds.h:24
 msgid "Reset current HEAD to the specified state"
-msgstr "Đặt lại HEAD hiện hành thành một trạng thái được chỉ ra"
+msgstr "Đặt lại HEAD hiện hành thành trạng thái đã cho"
 
 #: common-cmds.h:25
 msgid "Remove files from the working tree and from the index"
@@ -9093,9 +9550,7 @@
 
 #: common-cmds.h:28
 msgid "Create, list, delete or verify a tag object signed with GPG"
-msgstr ""
-"Tạo, liệt kê, xóa hay xác thực một đối tượng thẻ (tag) mà nó được ký sử dụng "
-"GPG"
+msgstr "Tạo, liệt kê, xóa hay xác thực một đối tượng thẻ được ký bằng GPG"
 
 #: git-am.sh:50
 msgid "You need to set your committer info first"
@@ -9112,11 +9567,11 @@
 #: git-am.sh:105
 #, sh-format
 msgid ""
-"When you have resolved this problem, run \"$cmdline --resolved\".\n"
+"When you have resolved this problem, run \"$cmdline --continue\".\n"
 "If you prefer to skip this patch, run \"$cmdline --skip\" instead.\n"
 "To restore the original branch and stop patching, run \"$cmdline --abort\"."
 msgstr ""
-"Khi bạn cần giải quyết vấn đề này hãy chạy lệnh \"$cmdline --resolved\".\n"
+"Khi bạn cần giải quyết vấn đề này hãy chạy lệnh \"$cmdline --continue\".\n"
 "Nếu bạn có ý định bỏ qua miếng vá, thay vào đó bạn chạy \"$cmdline --skip"
 "\".\n"
 "Để phục hồi lại thành nhánh nguyên thủy và dừng việc vá lại thì chạy "
@@ -9172,25 +9627,34 @@
 "Tùy chọn -b/--binary đã không dùng từ lâu rồi, và\n"
 "nó sẽ được bỏ đi. Xin đừng sử dụng nó thêm nữa."
 
-#: git-am.sh:477
+#: git-am.sh:479
 #, sh-format
 msgid "previous rebase directory $dotest still exists but mbox given."
 msgstr "thư mục rebase trước $dotest vẫn chưa sẵn sàng nhưng mbox được đưa ra."
 
-#: git-am.sh:482
+#: git-am.sh:484
 msgid "Please make up your mind. --skip or --abort?"
 msgstr "Xin hãy rõ ràng. --skip hay --abort?"
 
-#: git-am.sh:509
+#: git-am.sh:520
+#, sh-format
+msgid ""
+"Stray $dotest directory found.\n"
+"Use \"git am --abort\" to remove it."
+msgstr ""
+"Tìm thấy thư mục lạc $dotest.\n"
+"Dùng \"git am --abort\" để loại bỏ nó đi."
+
+#: git-am.sh:528
 msgid "Resolve operation not in progress, we are not resuming."
 msgstr "Thao tác phân giải không được tiến hành, chúng ta không phục hồi lại."
 
-#: git-am.sh:575
+#: git-am.sh:594
 #, sh-format
 msgid "Dirty index: cannot apply patches (dirty: $files)"
 msgstr "Bảng mục lục sai: không thể áp dụng các miếng vá (sai: $files)"
 
-#: git-am.sh:679
+#: git-am.sh:698
 #, sh-format
 msgid ""
 "Patch is empty.  Was it split wrong?\n"
@@ -9203,34 +9667,34 @@
 "Để phục hồi lại nhánh nguyên thủy và dừng vá lại hãy chạy lệnh \"$cmdline --"
 "abort\"."
 
-#: git-am.sh:706
+#: git-am.sh:725
 msgid "Patch does not have a valid e-mail address."
 msgstr "Miếng vá không có địa chỉ e-mail hợp lệ."
 
-#: git-am.sh:753
+#: git-am.sh:772
 msgid "cannot be interactive without stdin connected to a terminal."
 msgstr ""
 "không thể được tương tác mà không có stdin kết nối với một thiết bị cuối"
 
-#: git-am.sh:757
+#: git-am.sh:776
 msgid "Commit Body is:"
 msgstr "Thân của lần chuyển giao (commit) là:"
 
 #. TRANSLATORS: Make sure to include [y], [n], [e], [v] and [a]
 #. in your translation. The program will only accept English
 #. input at this point.
-#: git-am.sh:764
+#: git-am.sh:783
 msgid "Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all "
 msgstr ""
 "Áp dụng? đồng ý [y]/không [n]/chỉnh sửa [e]/hiển thị miếng [v]á/đồng ý tất "
 "cả [a] "
 
-#: git-am.sh:800
+#: git-am.sh:819
 #, sh-format
 msgid "Applying: $FIRSTLINE"
 msgstr "Đang áp dụng (miếng vá): $FIRSTLINE"
 
-#: git-am.sh:821
+#: git-am.sh:840
 msgid ""
 "No changes - did you forget to use 'git add'?\n"
 "If there is nothing left to stage, chances are that something else\n"
@@ -9241,7 +9705,7 @@
 "đã sẵn được đưa vào với cùng nội dung thay đổi; bạn có lẽ muốn bỏ qua miếng "
 "vá này."
 
-#: git-am.sh:829
+#: git-am.sh:848
 msgid ""
 "You still have unmerged paths in your index\n"
 "did you forget to use 'git add'?"
@@ -9249,16 +9713,16 @@
 "Bạn vẫn có những đường dẫn chưa được hòa trộn trong bảng mục lục của mình\n"
 "bạn đã quên sử dụng lệnh “git add” à?"
 
-#: git-am.sh:845
+#: git-am.sh:864
 msgid "No changes -- Patch already applied."
 msgstr "Không thay đổi gì cả -- Miếng vá đã được áp dụng rồi."
 
-#: git-am.sh:855
+#: git-am.sh:874
 #, sh-format
 msgid "Patch failed at $msgnum $FIRSTLINE"
 msgstr "Vá gặp lỗi tại $msgnum $FIRSTLINE"
 
-#: git-am.sh:858
+#: git-am.sh:877
 #, sh-format
 msgid ""
 "The copy of the patch that failed is found in:\n"
@@ -9267,7 +9731,7 @@
 "Bản sao chép của miếng vá mà nó gặp lỗi thì được tìm thấy trong:\n"
 "   $dotest/patch"
 
-#: git-am.sh:876
+#: git-am.sh:895
 msgid "applying to an empty history"
 msgstr "áp dụng vào một lịch sử trống rỗng"
 
@@ -9290,7 +9754,7 @@
 #: git-bisect.sh:99
 #, sh-format
 msgid "'$arg' does not appear to be a valid revision"
-msgstr "”$arg” không có vẻ như là một sự xét lại hợp lệ"
+msgstr "”$arg” không có vẻ như là một điểm xét duyệt hợp lệ"
 
 #: git-bisect.sh:117
 msgid "Bad HEAD - I need a HEAD"
@@ -9368,16 +9832,16 @@
 "sai.\n"
 "(Bạn có thể sử dụng \"git bisect bad\" và \"git bisect good\" cho chúng.)"
 
-#: git-bisect.sh:347 git-bisect.sh:474
+#: git-bisect.sh:363 git-bisect.sh:490
 msgid "We are not bisecting."
 msgstr "Chúng tôi không bisect."
 
-#: git-bisect.sh:354
+#: git-bisect.sh:370
 #, sh-format
 msgid "'$invalid' is not a valid commit"
 msgstr "”$invalid” không phải là lần chuyển giao (commit) hợp lệ"
 
-#: git-bisect.sh:363
+#: git-bisect.sh:379
 #, sh-format
 msgid ""
 "Could not check out original HEAD '$branch'.\n"
@@ -9386,25 +9850,25 @@
 "Không thể check-out HEAD nguyên thủy của “$branch”.\n"
 "Hãy thử “git bisect reset <lần-chuyển-giao>”."
 
-#: git-bisect.sh:390
+#: git-bisect.sh:406
 msgid "No logfile given"
 msgstr "Chưa chỉ ra tập tin ghi nhật ký"
 
-#: git-bisect.sh:391
+#: git-bisect.sh:407
 #, sh-format
 msgid "cannot read $file for replaying"
 msgstr "không thể đọc $file để thao diễn lại"
 
-#: git-bisect.sh:408
+#: git-bisect.sh:424
 msgid "?? what are you talking about?"
 msgstr "?? bạn đang nói gì thế?"
 
-#: git-bisect.sh:420
+#: git-bisect.sh:436
 #, sh-format
 msgid "running $command"
 msgstr "đang chạy lệnh $command"
 
-#: git-bisect.sh:427
+#: git-bisect.sh:443
 #, sh-format
 msgid ""
 "bisect run failed:\n"
@@ -9413,11 +9877,11 @@
 "chạy bisect gặp lỗi:\n"
 "mã trả về $res từ lệnh “$command” là < 0 hoặc >= 128"
 
-#: git-bisect.sh:453
+#: git-bisect.sh:469
 msgid "bisect run cannot continue any more"
 msgstr "bisect không thể tiếp tục thêm được nữa"
 
-#: git-bisect.sh:459
+#: git-bisect.sh:475
 #, sh-format
 msgid ""
 "bisect run failed:\n"
@@ -9426,7 +9890,7 @@
 "chạy bisect gặp lỗi:\n"
 "”bisect_state $state” đã thoát ra với mã lỗi $res"
 
-#: git-bisect.sh:466
+#: git-bisect.sh:482
 msgid "bisect run success"
 msgstr "bisect chạy thành công"
 
@@ -9475,7 +9939,7 @@
 msgid "Cannot rebase onto multiple branches"
 msgstr "Không thể thực hiện lệnh rebase (cơ cấu lại) trên nhiều nhánh"
 
-#: git-rebase.sh:53
+#: git-rebase.sh:54
 msgid ""
 "When you have resolved this problem, run \"git rebase --continue\".\n"
 "If you prefer to skip this patch, run \"git rebase --skip\" instead.\n"
@@ -9488,35 +9952,55 @@
 "Để phục hồi lại thành nhánh nguyên thủy và dừng việc vá lại thì chạy \"git "
 "rebase --abort\"."
 
+#: git-rebase.sh:156
+msgid "Applied autostash."
+msgstr "Đã áp dụng autostash."
+
+#: git-rebase.sh:159
+#, sh-format
+msgid "Cannot store $stash_sha1"
+msgstr "Không thể lưu $stash_sha1"
+
 #: git-rebase.sh:160
+msgid ""
+"Applying autostash resulted in conflicts.\n"
+"Your changes are safe in the stash.\n"
+"You can run \"git stash pop\" or \"git stash drop\" at any time.\n"
+msgstr ""
+"Áp dụng autostash có hiệu quả trong các xung đột.\n"
+"Các thay đổi của bạn an toàn trong stash (tạm cất đi).\n"
+"Bạn có thể chạy lệnh \"git stash pop\" hay \"git stash drop\" bất kỳ lúc "
+"nào.\n"
+
+#: git-rebase.sh:190
 msgid "The pre-rebase hook refused to rebase."
 msgstr "Móc (hook) pre-rebase từ chối rebase."
 
-#: git-rebase.sh:165
+#: git-rebase.sh:195
 msgid "It looks like git-am is in progress. Cannot rebase."
 msgstr ""
 "Hình như đang trong quá trình thực hiện lệnh git-am. Không thể chạy lệnh "
 "rebase."
 
-#: git-rebase.sh:296
+#: git-rebase.sh:329
 msgid "The --exec option must be used with the --interactive option"
 msgstr "Tùy chọn --exec phải được sử dụng cùng với tùy chọn --interactive"
 
-#: git-rebase.sh:301
+#: git-rebase.sh:334
 msgid "No rebase in progress?"
 msgstr "Không có tiến trình rebase nào phải không?"
 
-#: git-rebase.sh:312
+#: git-rebase.sh:345
 msgid "The --edit-todo action can only be used during interactive rebase."
 msgstr ""
 "Hành động “--edit-todo” chỉ có thể dùng trong quá trình “rebase” (sửa lịch "
 "sử) tương tác."
 
-#: git-rebase.sh:319
+#: git-rebase.sh:352
 msgid "Cannot read HEAD"
 msgstr "Không thể đọc HEAD"
 
-#: git-rebase.sh:322
+#: git-rebase.sh:355
 msgid ""
 "You must edit all merge conflicts and then\n"
 "mark them as resolved using git add"
@@ -9524,12 +10008,12 @@
 "Bạn phải sửa tất cả các lần hòa trộn xung đột và sau\n"
 "đó đánh dấu chúng là cần xử lý sử dụng lệnh git add"
 
-#: git-rebase.sh:340
+#: git-rebase.sh:373
 #, sh-format
 msgid "Could not move back to $head_name"
 msgstr "Không thể quay trở lại $head_name"
 
-#: git-rebase.sh:359
+#: git-rebase.sh:392
 #, sh-format
 msgid ""
 "It seems that there is already a $state_dir_base directory, and\n"
@@ -9552,57 +10036,66 @@
 "\n"
 "TÔI: là lệnh bạn vừa gọi!"
 
-#: git-rebase.sh:404
+#: git-rebase.sh:437
 #, sh-format
 msgid "invalid upstream $upstream_name"
 msgstr "thượng nguồn không hợp lệ $upstream_name"
 
-#: git-rebase.sh:428
+#: git-rebase.sh:461
 #, sh-format
 msgid "$onto_name: there are more than one merge bases"
 msgstr "$onto_name: ở đây có nhiều hơn một nền móng hòa trộn"
 
-#: git-rebase.sh:431 git-rebase.sh:435
+#: git-rebase.sh:464 git-rebase.sh:468
 #, sh-format
 msgid "$onto_name: there is no merge base"
 msgstr "$onto_name: ở đây không có nền móng hòa trộn nào"
 
-#: git-rebase.sh:440
+#: git-rebase.sh:473
 #, sh-format
 msgid "Does not point to a valid commit: $onto_name"
 msgstr "Không chỉ đến một lần chuyển giao (commit) không hợp lệ: $onto_name"
 
-#: git-rebase.sh:463
+#: git-rebase.sh:496
 #, sh-format
 msgid "fatal: no such branch: $branch_name"
 msgstr "nghiêm trọng: không có nhánh như thế: $branch_name"
 
-#: git-rebase.sh:483
+#: git-rebase.sh:519
+msgid "Cannot autostash"
+msgstr "Không thể autostash"
+
+#: git-rebase.sh:524
+#, sh-format
+msgid "Created autostash: $stash_abbrev"
+msgstr "Đã tạo autostash: $stash_abbrev"
+
+#: git-rebase.sh:528
 msgid "Please commit or stash them."
 msgstr "Xin hãy commit hoặc tạm cất (stash) chúng."
 
-#: git-rebase.sh:501
+#: git-rebase.sh:548
 #, sh-format
 msgid "Current branch $branch_name is up to date."
 msgstr "Nhánh hiện tại $branch_name đã được cập nhật rồi."
 
-#: git-rebase.sh:504
+#: git-rebase.sh:552
 #, sh-format
 msgid "Current branch $branch_name is up to date, rebase forced."
 msgstr "Nhánh hiện tại $branch_name đã được cập nhật rồi, lệnh rebase ép buộc."
 
-#: git-rebase.sh:515
+#: git-rebase.sh:563
 #, sh-format
 msgid "Changes from $mb to $onto:"
 msgstr "Thay đổi từ $mb thành $onto:"
 
 #. Detach HEAD and reset the tree
-#: git-rebase.sh:524
+#: git-rebase.sh:572
 msgid "First, rewinding head to replay your work on top of it..."
 msgstr ""
 "Trước tiên, di chuyển head để xem lại các công việc trên đỉnh của nó..."
 
-#: git-rebase.sh:532
+#: git-rebase.sh:582
 #, sh-format
 msgid "Fast-forwarded $branch_name to $onto_name."
 msgstr "Fast-forward $branch_name thành $onto_name."
@@ -9636,6 +10129,11 @@
 msgid "Cannot record working tree state"
 msgstr "Không thể ghi lại trạng thái cây làm việc hiện hành"
 
+#: git-stash.sh:190
+#, sh-format
+msgid "Cannot update $ref_stash with $w_commit"
+msgstr "Không thể cập nhật $ref_stash với $w_commit"
+
 #. TRANSLATORS: $option is an invalid option, like
 #. `--blah-blah'. The 7 spaces at the beginning of the
 #. second line correspond to "error: ". So you should line
@@ -9646,132 +10144,153 @@
 #. $ git stash save --blah-blah 2>&1 | head -n 2
 #. error: unknown option for 'stash save': --blah-blah
 #. To provide a message, use git stash save -- '--blah-blah'
-#: git-stash.sh:202
+#: git-stash.sh:241
 #, sh-format
 msgid ""
 "error: unknown option for 'stash save': $option\n"
 "       To provide a message, use git stash save -- '$option'"
 msgstr ""
 "lỗi: không hiểu tùy chọn cho “stash save”: $option\n"
-"       Để cung cấp một thông điệp, sử dụng git stash save -- “$option”"
+"     Để dùng thông điệp có chứa -- ở đầu, sử dụng git stash save -- \"$option"
+"\""
 
-#: git-stash.sh:223
+#: git-stash.sh:262
 msgid "No local changes to save"
 msgstr "Không có thay đổi nội bộ nào được ghi lại"
 
-#: git-stash.sh:227
+#: git-stash.sh:268
+msgid ""
+"The following untracked files would NOT be saved but need to be removed by "
+"stash save:"
+msgstr ""
+"Các tập tin chưa được theo dõi sau đây KHÔNG được ghi lại nhưng cần được gỡ "
+"bỏ bởi việc ghi lại stash:"
+
+#: git-stash.sh:270
+msgid ""
+"Aborting. Consider using either the --force or --include-untracked option."
+msgstr ""
+"Bãi bỏ. Cân nhắc dùng một trong hai tùy chọn --force và --include-untracked."
+
+#: git-stash.sh:274
 msgid "Cannot initialize stash"
 msgstr "Không thể khởi tạo stash"
 
-#: git-stash.sh:235
+#: git-stash.sh:278
 msgid "Cannot save the current status"
 msgstr "Không thể ghi lại trạng thái hiện hành"
 
-#: git-stash.sh:253
+#: git-stash.sh:296
 msgid "Cannot remove worktree changes"
 msgstr "Không thể gỡ bỏ các thay đổi cây-làm-việc"
 
-#: git-stash.sh:352
+#: git-stash.sh:395
 msgid "No stash found."
 msgstr "Không tìm thấy stash nào."
 
-#: git-stash.sh:359
+#: git-stash.sh:402
 #, sh-format
 msgid "Too many revisions specified: $REV"
-msgstr "Chỉ ra quá nhiều điểm xét lại: $REV"
+msgstr "Chỉ ra quá nhiều điểm xét duyệt: $REV"
 
-#: git-stash.sh:365
+#: git-stash.sh:408
 #, sh-format
 msgid "$reference is not valid reference"
 msgstr "$reference không phải là tham chiếu hợp lệ"
 
-#: git-stash.sh:393
+#: git-stash.sh:436
 #, sh-format
 msgid "'$args' is not a stash-like commit"
 msgstr "”$args” không phải là lần chuyển giao (commit) giống-stash"
 
-#: git-stash.sh:404
+#: git-stash.sh:447
 #, sh-format
 msgid "'$args' is not a stash reference"
 msgstr "”$args” không phải tham chiếu đến stash"
 
-#: git-stash.sh:412
+#: git-stash.sh:455
 msgid "unable to refresh index"
 msgstr "không thể làm tươi mới bảng mục lục"
 
-#: git-stash.sh:416
+#: git-stash.sh:459
 msgid "Cannot apply a stash in the middle of a merge"
 msgstr "Không thể áp dụng một stash ở giữa của quá trình hòa trộn"
 
-#: git-stash.sh:424
+#: git-stash.sh:467
 msgid "Conflicts in index. Try without --index."
 msgstr "Xung đột trong bảng mục lục. Hãy thử mà không dùng tùy chọn --index."
 
-#: git-stash.sh:426
+#: git-stash.sh:469
 msgid "Could not save index tree"
 msgstr "Không thể ghi lại cây chỉ mục"
 
-#: git-stash.sh:460
+#: git-stash.sh:503
 msgid "Cannot unstage modified files"
 msgstr "Không thể bỏ trạng thía của các tập tin đã được sửa chữa"
 
-#: git-stash.sh:475
+#: git-stash.sh:518
 msgid "Index was not unstashed."
 msgstr "Bảng mục lục đã không được bỏ stash."
 
-#: git-stash.sh:492
+#: git-stash.sh:535
 #, sh-format
 msgid "Dropped ${REV} ($s)"
-msgstr "Đã hạ xuống ${REV} ($s)"
+msgstr "Đã xóa ${REV} ($s)"
 
-#: git-stash.sh:493
+#: git-stash.sh:536
 #, sh-format
 msgid "${REV}: Could not drop stash entry"
 msgstr "${REV}: Không thể xóa bỏ mục stash"
 
-#: git-stash.sh:500
+#: git-stash.sh:543
 msgid "No branch name specified"
 msgstr "Chưa chỉ ra tên của nhánh"
 
-#: git-stash.sh:571
+#: git-stash.sh:615
 msgid "(To restore them type \"git stash apply\")"
 msgstr "(Để phục hồi lại chúng hãy gõ \"git stash apply\")"
 
-#: git-submodule.sh:91
+#: git-submodule.sh:95
 #, sh-format
 msgid "cannot strip one component off url '$remoteurl'"
 msgstr "không thể tháo bỏ một thành phần ra khỏi “$remoteurl” url"
 
-#: git-submodule.sh:196
+#: git-submodule.sh:237
 #, sh-format
 msgid "No submodule mapping found in .gitmodules for path '$sm_path'"
 msgstr ""
 "Không tìm thấy ánh xạ (mapping) mô-đun-con trong .gitmodules cho đường dẫn "
 "“$sm_path”"
 
-#: git-submodule.sh:239
+#: git-submodule.sh:281
 #, sh-format
 msgid "Clone of '$url' into submodule path '$sm_path' failed"
 msgstr "Nhân bản “$url” vào đường dẫn mô-đun-con “$sm_path” gặp lỗi"
 
-#: git-submodule.sh:251
+#: git-submodule.sh:293
 #, sh-format
 msgid "Gitdir '$a' is part of the submodule path '$b' or vice versa"
 msgstr ""
 "Gitdir “$a” là bộ phận của đường dẫn mô-đun-con “$b” hoặc \"vice versa\""
 
-#: git-submodule.sh:349
+#: git-submodule.sh:403
+msgid "Relative path can only be used from the toplevel of the working tree"
+msgstr ""
+"Đường dẫn tương đối chỉ có thể dùng từ thư mục ở mức cao nhất của cây làm "
+"việc"
+
+#: git-submodule.sh:413
 #, sh-format
 msgid "repo URL: '$repo' must be absolute or begin with ./|../"
 msgstr ""
 "repo URL: “$repo” phải là đường dẫn tuyệt đối hoặc là bắt đầu bằng ./|../"
 
-#: git-submodule.sh:366
+#: git-submodule.sh:430
 #, sh-format
 msgid "'$sm_path' already exists in the index"
 msgstr "”$sm_path” thực sự đã tồn tại ở bảng mục lục rồi"
 
-#: git-submodule.sh:370
+#: git-submodule.sh:434
 #, sh-format
 msgid ""
 "The following path is ignored by one of your .gitignore files:\n"
@@ -9783,36 +10302,36 @@
 "$sm_path\n"
 "Sử dụng -f nếu bạn thực sự muốn thêm nó vào."
 
-#: git-submodule.sh:388
+#: git-submodule.sh:452
 #, sh-format
 msgid "Adding existing repo at '$sm_path' to the index"
 msgstr "Đang thêm repo có sẵn tại “$sm_path” vào bảng mục lục"
 
-#: git-submodule.sh:390
+#: git-submodule.sh:454
 #, sh-format
 msgid "'$sm_path' already exists and is not a valid git repo"
 msgstr "”$sm_path” đã tồn tại từ trước và không phải là một kho git hợp lệ"
 
-#: git-submodule.sh:398
+#: git-submodule.sh:462
 #, sh-format
 msgid "A git directory for '$sm_name' is found locally with remote(s):"
 msgstr ""
 "Thư mục git cho “$sm_name” được tìm thấy một cách cục bộ với các máy chủ:"
 
-#: git-submodule.sh:400
+#: git-submodule.sh:464
 #, sh-format
 msgid ""
 "If you want to reuse this local git directory instead of cloning again from"
 msgstr "Nếu bạn muốn dùng lại thư mục git nội bộ này thay vì nhân bản từ nó"
 
-#: git-submodule.sh:402
+#: git-submodule.sh:466
 #, sh-format
 msgid ""
 "use the '--force' option. If the local git directory is not the correct repo"
 msgstr ""
 "dùng tùy chọn “--force”. Nếu thư mục git nội bộ không phải là repo (kho) đúng"
 
-#: git-submodule.sh:403
+#: git-submodule.sh:467
 #, sh-format
 msgid ""
 "or you are unsure what this means choose another name with the '--name' "
@@ -9821,70 +10340,71 @@
 "hay bạn không chắc chắn điều đó có nghĩa gì chọn tên khác với tùy chọn “--"
 "name”."
 
-#: git-submodule.sh:405
+#: git-submodule.sh:469
 #, sh-format
 msgid "Reactivating local git directory for submodule '$sm_name'."
 msgstr ""
 "Phục hồi sự hoạt động của thư mục git nội bộ cho mô-đun-con “$sm_name”."
 
-#: git-submodule.sh:417
+#: git-submodule.sh:481
 #, sh-format
 msgid "Unable to checkout submodule '$sm_path'"
-msgstr "Không thể checkout mô-đun con “$sm_path”"
+msgstr "Không thể checkout mô-đun-con “$sm_path”"
 
-#: git-submodule.sh:422
+#: git-submodule.sh:486
 #, sh-format
 msgid "Failed to add submodule '$sm_path'"
-msgstr "Gặp lỗi khi thêm mô-đun con “$sm_path”"
+msgstr "Gặp lỗi khi thêm mô-đun-con “$sm_path”"
 
-#: git-submodule.sh:431
+#: git-submodule.sh:495
 #, sh-format
 msgid "Failed to register submodule '$sm_path'"
-msgstr "Gặp lỗi khi đăng ký với hệ thống mô-đun con “$sm_path”"
+msgstr "Gặp lỗi khi đăng ký với hệ thống mô-đun-con “$sm_path”"
 
-#: git-submodule.sh:474
+#: git-submodule.sh:539
 #, sh-format
-msgid "Entering '$prefix$sm_path'"
-msgstr "Đang nhập “$prefix$sm_path”"
+msgid "Entering '$prefix$displaypath'"
+msgstr "Đang vào “$prefix$displaypath”"
 
-#: git-submodule.sh:488
+#: git-submodule.sh:554
 #, sh-format
-msgid "Stopping at '$sm_path'; script returned non-zero status."
-msgstr "Dừng lại tại “$sm_path”; script trả về trạng thái khác không."
-
-#: git-submodule.sh:532
-#, sh-format
-msgid "No url found for submodule path '$sm_path' in .gitmodules"
+msgid "Stopping at '$prefix$displaypath'; script returned non-zero status."
 msgstr ""
-"Không tìm thấy url cho đường dẫn mô-đun-con “$sm_path” trong .gitmodules"
+"Dừng lại tại “$prefix$displaypath”; script trả về trạng thái khác không."
 
-#: git-submodule.sh:541
+#: git-submodule.sh:600
 #, sh-format
-msgid "Failed to register url for submodule path '$sm_path'"
-msgstr "Gặp lỗi khi đăng ký url cho đường dẫn mô-đun-con “$sm_path”"
-
-#: git-submodule.sh:543
-#, sh-format
-msgid "Submodule '$name' ($url) registered for path '$sm_path'"
-msgstr "Mô-đun-con “$name” ($url) được đăng ký cho đường dẫn “$sm_path”"
-
-#: git-submodule.sh:551
-#, sh-format
-msgid "Failed to register update mode for submodule path '$sm_path'"
+msgid "No url found for submodule path '$displaypath' in .gitmodules"
 msgstr ""
-"Gặp lỗi khi đăng ký chế độ cập nhật cho đường dẫn mô-đun-con “$sm_path”"
+"Không tìm thấy url cho đường dẫn mô-đun-con “$displaypath” trong .gitmodules"
 
-#: git-submodule.sh:588
+#: git-submodule.sh:609
+#, sh-format
+msgid "Failed to register url for submodule path '$displaypath'"
+msgstr "Gặp lỗi khi đăng ký url cho đường dẫn mô-đun-con “$displaypath”"
+
+#: git-submodule.sh:611
+#, sh-format
+msgid "Submodule '$name' ($url) registered for path '$displaypath'"
+msgstr "Mô-đun-con “$name” ($url) được đăng ký cho đường dẫn “$displaypath”"
+
+#: git-submodule.sh:619
+#, sh-format
+msgid "Failed to register update mode for submodule path '$displaypath'"
+msgstr ""
+"Gặp lỗi khi đăng ký chế độ cập nhật cho đường dẫn mô-đun-con “$displaypath”"
+
+#: git-submodule.sh:656
 #, sh-format
 msgid "Use '.' if you really want to deinitialize all submodules"
-msgstr "Dùng '.' nếu bạn thực sự muốn gỡ bỏ mọi mô-đun-con"
+msgstr "Dùng “.” nếu bạn thực sự muốn gỡ bỏ mọi mô-đun-con"
 
-#: git-submodule.sh:603
+#: git-submodule.sh:673
 #, sh-format
-msgid "Submodule work tree '$sm_path' contains a .git directory"
-msgstr "Cây làm việc mô-đun-con '$sm_path' có chứa thư mục .git"
+msgid "Submodule work tree '$displaypath' contains a .git directory"
+msgstr "Cây làm việc mô-đun-con “$displaypath” có chứa thư mục .git"
 
-#: git-submodule.sh:604
+#: git-submodule.sh:674
 #, sh-format
 msgid ""
 "(use 'rm -rf' if you really want to remove it including all of its history)"
@@ -9892,147 +10412,218 @@
 "(dùng “rm -rf” nếu bạn thực sự muốn gỡ bỏ nó cùng với tất cả lịch sử của "
 "chúng)"
 
-#: git-submodule.sh:610
+#: git-submodule.sh:680
 #, sh-format
 msgid ""
-"Submodule work tree '$sm_path' contains local modifications; use '-f' to "
+"Submodule work tree '$displaypath' contains local modifications; use '-f' to "
 "discard them"
 msgstr ""
-"Cây làm việc mô-đun-con '$sm_path' chứa các thay đổi nội bộ; hãy dùng '-f' "
-"để loại bỏ chúng đi"
+"Cây làm việc mô-đun-con “$displaypath” chứa các thay đổi nội bộ; hãy dùng “-"
+"f” để loại bỏ chúng đi"
 
-#: git-submodule.sh:613
+#: git-submodule.sh:683
 #, sh-format
-msgid "Cleared directory '$sm_path'"
-msgstr "Thư mục được dọn “$sm_path”"
+msgid "Cleared directory '$displaypath'"
+msgstr "Đã tạo thư mục '$displaypath'"
 
-#: git-submodule.sh:614
+#: git-submodule.sh:684
 #, sh-format
-msgid "Could not remove submodule work tree '$sm_path'"
-msgstr "Không thể gỡ bỏ cây làm việc mô-đun con “$sm_path”"
+msgid "Could not remove submodule work tree '$displaypath'"
+msgstr "Không thể gỡ bỏ cây làm việc mô-đun-con “$displaypath”"
 
-#: git-submodule.sh:617
+#: git-submodule.sh:687
 #, sh-format
-msgid "Could not create empty submodule directory '$sm_path'"
-msgstr "Không thể tạo thư mục mô-đun-con rỗng “$sm_path”"
+msgid "Could not create empty submodule directory '$displaypath'"
+msgstr "Không thể tạo thư mục mô-đun-con rỗng “$displaypath”"
 
-#: git-submodule.sh:626
+#: git-submodule.sh:696
 #, sh-format
-msgid "Submodule '$name' ($url) unregistered for path '$sm_path'"
-msgstr "Mô-đun-con “$name” ($url) được bỏ đăng ký cho đường dẫn “$sm_path”"
+msgid "Submodule '$name' ($url) unregistered for path '$displaypath'"
+msgstr "Mô-đun-con “$name” ($url) được bỏ đăng ký cho đường dẫn “$displaypath”"
 
-#: git-submodule.sh:731
+#: git-submodule.sh:811
 #, sh-format
 msgid ""
-"Submodule path '$prefix$sm_path' not initialized\n"
+"Submodule path '$displaypath' not initialized\n"
 "Maybe you want to use 'update --init'?"
 msgstr ""
-"Đường dẫn mô-đun-con “$prefix$sm_path” chưa được khởi tạo\n"
+"Đường dẫn mô-đun-con “$displaypath” chưa được khởi tạo.\n"
 "Có lẽ bạn muốn sử dụng lệnh “update --init”?"
 
-#: git-submodule.sh:744
+#: git-submodule.sh:824
 #, sh-format
-msgid "Unable to find current revision in submodule path '$prefix$sm_path'"
+msgid "Unable to find current revision in submodule path '$displaypath'"
 msgstr ""
-"Không tìm thấy điểm xét lại hiện hành trong đường dẫn mô-đun-con “$prefix"
-"$sm_path”"
+"Không tìm thấy điểm xét duyệt hiện hành trong đường dẫn mô-đun-con "
+"“$displaypath”"
 
-#: git-submodule.sh:753
+#: git-submodule.sh:833
 #, sh-format
 msgid "Unable to fetch in submodule path '$sm_path'"
 msgstr "Không thể lấy về (fetch) trong đường dẫn mô-đun-con “$sm_path”"
 
-#: git-submodule.sh:777
+#: git-submodule.sh:857
 #, sh-format
-msgid "Unable to fetch in submodule path '$prefix$sm_path'"
-msgstr "Không thể lấy về (fetch) trong đường dẫn mô-đun-con “$prefix$sm_path”"
+msgid "Unable to fetch in submodule path '$displaypath'"
+msgstr "Không thể lấy về (fetch) trong đường dẫn mô-đun-con “$displaypath”"
 
-#: git-submodule.sh:791
+#: git-submodule.sh:871
 #, sh-format
-msgid "Unable to rebase '$sha1' in submodule path '$prefix$sm_path'"
-msgstr "Không thể rebase “$sha1” trong đường dẫn mô-đun-con “$prefix$sm_path”"
+msgid "Unable to rebase '$sha1' in submodule path '$displaypath'"
+msgstr "Không thể rebase “$sha1” trong đường dẫn mô-đun-con “$displaypath”"
 
-#: git-submodule.sh:792
+#: git-submodule.sh:872
 #, sh-format
-msgid "Submodule path '$prefix$sm_path': rebased into '$sha1'"
-msgstr "Đường dẫn mô-đun-con “$prefix$sm_path”: được rebase vào trong “$sha1”"
+msgid "Submodule path '$displaypath': rebased into '$sha1'"
+msgstr "Đường dẫn mô-đun-con “$displaypath”: được rebase vào trong “$sha1”"
 
-#: git-submodule.sh:797
+#: git-submodule.sh:877
 #, sh-format
-msgid "Unable to merge '$sha1' in submodule path '$prefix$sm_path'"
+msgid "Unable to merge '$sha1' in submodule path '$displaypath'"
 msgstr ""
-"Không thể hòa trộn (merge) “$sha1” trong đường dẫn mô-đun-con “$prefix"
-"$sm_path”"
+"Không thể hòa trộn (merge) “$sha1” trong đường dẫn mô-đun-con “$displaypath”"
 
-#: git-submodule.sh:798
+#: git-submodule.sh:878
 #, sh-format
-msgid "Submodule path '$prefix$sm_path': merged in '$sha1'"
-msgstr "Đường dẫn mô-đun-con “$prefix$sm_path”: được hòa trộn vào “$sha1”"
+msgid "Submodule path '$displaypath': merged in '$sha1'"
+msgstr "Đường dẫn mô-đun-con “$displaypath”: được hòa trộn vào “$sha1”"
 
-#: git-submodule.sh:803
+#: git-submodule.sh:883
 #, sh-format
-msgid "Unable to checkout '$sha1' in submodule path '$prefix$sm_path'"
+msgid ""
+"Execution of '$command $sha1' failed in submodule  path '$prefix$sm_path'"
 msgstr ""
-"Không thể checkout “$sha1” trong đường dẫn mô-đun-con “$prefix$sm_path”"
+"Thực hiện không thành công lệnh “$command $sha1” trong đường dẫn mô-đun-con "
+"“$prefix$sm_path”"
 
-#: git-submodule.sh:804
+#: git-submodule.sh:884
 #, sh-format
-msgid "Submodule path '$prefix$sm_path': checked out '$sha1'"
-msgstr "Đường dẫn mô-đun-con “$prefix$sm_path”: được checkout “$sha1”"
+msgid "Submodule path '$prefix$sm_path': '$command $sha1'"
+msgstr "Đường dẫn mô-đun-con “$prefix$sm_path”: “$command $sha1”"
 
-#: git-submodule.sh:831
+#: git-submodule.sh:889
 #, sh-format
-msgid "Failed to recurse into submodule path '$prefix$sm_path'"
-msgstr "Gặp lỗi khi đệ quy vào trong đường dẫn mô-đun-con “$prefix$sm_path”"
+msgid "Unable to checkout '$sha1' in submodule path '$displaypath'"
+msgstr "Không thể checkout “$sha1” trong đường dẫn mô-đun-con “$displaypath”"
 
-#: git-submodule.sh:939
+#: git-submodule.sh:890
+#, sh-format
+msgid "Submodule path '$displaypath': checked out '$sha1'"
+msgstr "Đường dẫn mô-đun-con “$displaypath”: đã checkout “$sha1”"
+
+#: git-submodule.sh:917
+#, sh-format
+msgid "Failed to recurse into submodule path '$displaypath'"
+msgstr "Gặp lỗi khi đệ quy vào trong đường dẫn mô-đun-con “$displaypath”"
+
+#: git-submodule.sh:1025
 msgid "The --cached option cannot be used with the --files option"
 msgstr "Tùy chọn --cached không thể dùng cùng với tùy chọn --files"
 
 #. unexpected type
-#: git-submodule.sh:979
+#: git-submodule.sh:1066
 #, sh-format
 msgid "unexpected mode $mod_dst"
 msgstr "chế độ không như mong chờ $mod_dst"
 
-#: git-submodule.sh:997
+#: git-submodule.sh:1086
 #, sh-format
-msgid "  Warn: $name doesn't contain commit $sha1_src"
-msgstr "  Cảnh báo: $name không chứa lần chuyển giao (commit) $sha1_src"
-
-#: git-submodule.sh:1000
-#, sh-format
-msgid "  Warn: $name doesn't contain commit $sha1_dst"
-msgstr "  Cảnh báo: $name không chứa lần chuyển giao (commit) $sha1_dst"
-
-#: git-submodule.sh:1003
-#, sh-format
-msgid "  Warn: $name doesn't contain commits $sha1_src and $sha1_dst"
+msgid "  Warn: $display_name doesn't contain commit $sha1_src"
 msgstr ""
-"  Cảnh báo: $name không chứa những lần chuyển giao (commit) $sha1_src và "
-"$sha1_dst"
+"  Cảnh báo: $display_name không chứa lần chuyển giao (commit) $sha1_src"
 
-#: git-submodule.sh:1028
+#: git-submodule.sh:1089
+#, sh-format
+msgid "  Warn: $display_name doesn't contain commit $sha1_dst"
+msgstr ""
+"  Cảnh báo: $display_name không chứa lần chuyển giao (commit) $sha1_dst"
+
+#: git-submodule.sh:1092
+#, sh-format
+msgid "  Warn: $display_name doesn't contain commits $sha1_src and $sha1_dst"
+msgstr ""
+"  Cảnh báo: $display_name không chứa những lần chuyển giao (commit) "
+"$sha1_src và $sha1_dst"
+
+#: git-submodule.sh:1117
 msgid "blob"
 msgstr "blob"
 
-#: git-submodule.sh:1066
+#: git-submodule.sh:1155
 msgid "Submodules changed but not updated:"
 msgstr "Những mô-đun-con đã bị thay đổi nhưng chưa được cập nhật:"
 
-#: git-submodule.sh:1068
+#: git-submodule.sh:1157
 msgid "Submodule changes to be committed:"
 msgstr "Những mô-đun-con thay đổi đã được chuyển giao (commit):"
 
-#: git-submodule.sh:1153
+#: git-submodule.sh:1242
 #, sh-format
 msgid "Failed to recurse into submodule path '$sm_path'"
 msgstr "Gặp lỗi khi đệ quy vào trong đường dẫn mô-đun-con “$sm_path”"
 
-#: git-submodule.sh:1216
+#: git-submodule.sh:1306
 #, sh-format
-msgid "Synchronizing submodule url for '$prefix$sm_path'"
-msgstr "Url Mô-đun-con đồng bộ hóa cho “$prefix$sm_path”"
+msgid "Synchronizing submodule url for '$displaypath'"
+msgstr "Url Mô-đun-con đồng bộ hóa cho “$displaypath”"
+
+#~ msgid "  (fix conflicts and then run \"git am --resolved\")"
+#~ msgstr "  (sửa các xung đột và sau đó chạy lệnh \"git am --resolved\")"
+
+#~ msgid "  (all conflicts fixed: run \"git commit\")"
+#~ msgstr "  (khi tất cả các xung đột đã sửa xong: chạy lệnh \"git commit\")"
+
+#~ msgid "more than %d trees given: '%s'"
+#~ msgstr "đã chỉ ra nhiều hơn %d cây (tree): “%s”"
+
+#~ msgid "You cannot combine --no-ff with --ff-only."
+#~ msgstr "Bạn không thể kết hợp --no-ff với --ff-only."
+
+#~ msgid ""
+#~ "submodule '%s' (or one of its nested submodules) uses a .git directory\n"
+#~ "(use 'rm -rf' if you really want to remove it including all of its "
+#~ "history)"
+#~ msgstr ""
+#~ "mô-đun-con “%s” (hoặc cái nằm trong các mô-đun-con) dùng thư mục .git\n"
+#~ "(dùng “rm -rf” nếu bạn thực sự muốn gỡ bỏ nó cùng với tất cả lịch sử của "
+#~ "chúng)"
+
+#~ msgid ""
+#~ "'%s' has changes staged in the index\n"
+#~ "(use --cached to keep the file, or -f to force removal)"
+#~ msgstr ""
+#~ "“%s” có các thay đổi được lưu trạng thái trong bảng mục lục\n"
+#~ "(dùng tùy chọn --cached để giữ tập tin, hoặc -f để ép buộc gỡ bỏ)"
+
+#~ msgid "show commits where no parent comes before its children"
+#~ msgstr "hiển thị các lần chuyển giao nơi mà cha mẹ đến trước con của nó"
+
+#~ msgid "show the HEAD reference"
+#~ msgstr "hiển thị tham chiếu của HEAD"
+
+#~ msgid "Unable to fetch in submodule path '$prefix$sm_path'"
+#~ msgstr ""
+#~ "Không thể lấy về (fetch) trong đường dẫn mô-đun-con “$prefix$sm_path”"
+
+#~ msgid "Failed to recurse into submodule path '$prefix$sm_path'"
+#~ msgstr "Gặp lỗi khi đệ quy vào trong đường dẫn mô-đun-con “$prefix$sm_path”"
+
+#~ msgid "It took %.2f seconds to enumerate untracked files.  'status -uno'"
+#~ msgstr "Cần %.2f giây để đếm các tập tin chưa được theo vết.  “status -uno”"
+
+#~ msgid "may speed it up, but you have to be careful not to forget to add"
+#~ msgstr ""
+#~ "có thể làm nó nhanh lên, nhưng bạn phải cẩn trọng đừng quên thêm nó vào"
+
+#~ msgid "new files yourself (see 'git help status')."
+#~ msgstr "tập tin mới của chính bạn (xem “git help status”.."
+
+#~ msgid "git shortlog [-n] [-s] [-e] [-w] [rev-opts] [--] [<commit-id>... ]"
+#~ msgstr "git shortlog [-n] [-s] [-e] [-w] [rev-opts] [--] [<commit-id>... ]"
+
+#~ msgid "See 'git help <command>' for more information on a specific command."
+#~ msgstr ""
+#~ "Chạy lệnh “git help <tên-lệnh>” để có thêm thông tin về lệnh được chỉ ra."
 
 #~ msgid "use any ref in .git/refs"
 #~ msgstr "sử dụng bất kỳ ref nào trong .git/refs"
diff --git a/po/zh_CN.po b/po/zh_CN.po
index 9a13def..b7b46f1 100644
--- a/po/zh_CN.po
+++ b/po/zh_CN.po
@@ -12,8 +12,8 @@
 msgstr ""
 "Project-Id-Version: Git\n"
 "Report-Msgid-Bugs-To: Git Mailing List <git@vger.kernel.org>\n"
-"POT-Creation-Date: 2013-04-10 15:16+0800\n"
-"PO-Revision-Date: 2013-04-12 09:23+0800\n"
+"POT-Creation-Date: 2013-08-06 14:10+0800\n"
+"PO-Revision-Date: 2013-08-06 14:45+0800\n"
 "Last-Translator: Jiang Xin <worldhello.net@gmail.com>\n"
 "Language-Team: GitHub <https://github.com/gotgit/git/>\n"
 "Language: zh_CN\n"
@@ -22,7 +22,7 @@
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n != 1);\n"
 
-#: advice.c:53
+#: advice.c:57
 #, c-format
 msgid "hint: %.*s\n"
 msgstr "提示:%.*s\n"
@@ -31,7 +31,7 @@
 #. * Message used both when 'git commit' fails and when
 #. * other commands doing a merge do.
 #.
-#: advice.c:83
+#: advice.c:87
 msgid ""
 "Fix them up in the work tree,\n"
 "and then use 'git add/rm <file>' as\n"
@@ -68,7 +68,7 @@
 msgid "archive format"
 msgstr "归档格式"
 
-#: archive.c:324 builtin/log.c:1117
+#: archive.c:324 builtin/log.c:1173
 msgid "prefix"
 msgstr "前缀"
 
@@ -76,11 +76,11 @@
 msgid "prepend prefix to each pathname in the archive"
 msgstr "为归档中每个路径名加上前缀"
 
-#: archive.c:326 builtin/archive.c:88 builtin/blame.c:2366
-#: builtin/blame.c:2367 builtin/config.c:55 builtin/fast-export.c:659
-#: builtin/fast-export.c:661 builtin/grep.c:715 builtin/hash-object.c:77
-#: builtin/ls-files.c:497 builtin/ls-files.c:500 builtin/notes.c:536
-#: builtin/notes.c:693 builtin/read-tree.c:107 parse-options.h:149
+#: archive.c:326 builtin/archive.c:88 builtin/blame.c:2292
+#: builtin/blame.c:2293 builtin/config.c:56 builtin/fast-export.c:673
+#: builtin/fast-export.c:675 builtin/grep.c:714 builtin/hash-object.c:77
+#: builtin/ls-files.c:496 builtin/ls-files.c:499 builtin/notes.c:408
+#: builtin/notes.c:565 builtin/read-tree.c:108 parse-options.h:152
 msgid "file"
 msgstr "文件"
 
@@ -112,7 +112,7 @@
 msgid "list supported archive formats"
 msgstr "列出支持的归档格式"
 
-#: archive.c:345 builtin/archive.c:90 builtin/clone.c:86
+#: archive.c:345 builtin/archive.c:90 builtin/clone.c:85
 msgid "repo"
 msgstr "版本库"
 
@@ -120,7 +120,7 @@
 msgid "retrieve the archive from remote repository <repo>"
 msgstr "从远程版本库(<版本库>)提取归档文件"
 
-#: archive.c:347 builtin/archive.c:92 builtin/notes.c:615
+#: archive.c:347 builtin/archive.c:92 builtin/notes.c:487
 msgid "command"
 msgstr "命令"
 
@@ -136,17 +136,86 @@
 "负值模版在 git attributes 中被忽略\n"
 "当字符串确实要以感叹号开始时,使用 '\\!'。"
 
-#: branch.c:201
+#: branch.c:60
+#, c-format
+msgid "Not setting branch %s as its own upstream."
+msgstr "未设置分支 %s 作为它自己的上游。"
+
+#: branch.c:82
+#, c-format
+msgid "Branch %s set up to track remote branch %s from %s by rebasing."
+msgstr "分支 %1$s 设置为使用变基来跟踪来自 %3$s 的远程分支 %2$s。"
+
+#: branch.c:83
+#, c-format
+msgid "Branch %s set up to track remote branch %s from %s."
+msgstr "分支 %1$s 设置为跟踪来自 %3$s 的远程分支 %2$s。"
+
+#: branch.c:87
+#, c-format
+msgid "Branch %s set up to track local branch %s by rebasing."
+msgstr "分支 %s 设置为使用变基来跟踪本地分支 %s。"
+
+#: branch.c:88
+#, c-format
+msgid "Branch %s set up to track local branch %s."
+msgstr "分支 %s 设置为跟踪本地分支 %s。"
+
+#: branch.c:92
+#, c-format
+msgid "Branch %s set up to track remote ref %s by rebasing."
+msgstr "分支 %s 设置为使用变基来跟踪远程引用 %s。"
+
+#: branch.c:93
+#, c-format
+msgid "Branch %s set up to track remote ref %s."
+msgstr "分支 %s 设置为跟踪远程引用 %s。"
+
+#: branch.c:97
+#, c-format
+msgid "Branch %s set up to track local ref %s by rebasing."
+msgstr "分支 %s 设置为使用变基来跟踪本地引用 %s。"
+
+#: branch.c:98
+#, c-format
+msgid "Branch %s set up to track local ref %s."
+msgstr "分支 %s 设置为跟踪本地引用 %s。"
+
+#: branch.c:118
+#, c-format
+msgid "Tracking not set up: name too long: %s"
+msgstr "跟踪未设置:名字太长:%s"
+
+#: branch.c:137
+#, c-format
+msgid "Not tracking: ambiguous information for ref %s"
+msgstr "未跟踪:引用 %s 有歧义"
+
+#: branch.c:182
+#, c-format
+msgid "'%s' is not a valid branch name."
+msgstr "'%s' 不是一个有效的分支名称。"
+
+#: branch.c:187
+#, c-format
+msgid "A branch named '%s' already exists."
+msgstr "一个分支名 '%s' 已经存在。"
+
+#: branch.c:195
+msgid "Cannot force update the current branch."
+msgstr "无法强制更新当前分支。"
+
+#: branch.c:216
 #, c-format
 msgid "Cannot setup tracking information; starting point '%s' is not a branch."
 msgstr "无法设置跟踪信息;起始点 '%s' 不是一个分支。"
 
-#: branch.c:203
+#: branch.c:218
 #, c-format
 msgid "the requested upstream branch '%s' does not exist"
 msgstr "请求的上游分支 '%s' 不存在"
 
-#: branch.c:205
+#: branch.c:220
 msgid ""
 "\n"
 "If you are planning on basing your work on an upstream\n"
@@ -164,6 +233,29 @@
 "如果您正计划推送一个能与对应远程分支建立跟踪的新的本地分支,\n"
 "您可能需要使用 \"git push -u\" 推送分支并配置和上游的关联。"
 
+#: branch.c:265
+#, c-format
+msgid "Not a valid object name: '%s'."
+msgstr "不是一个有效的对象名:'%s'。"
+
+#: branch.c:285
+#, c-format
+msgid "Ambiguous object name: '%s'."
+msgstr "歧义的对象名:'%s'。"
+
+#: branch.c:290
+#, c-format
+msgid "Not a valid branch point: '%s'."
+msgstr "无效的分支点:'%s'。"
+
+#: branch.c:296
+msgid "Failed to lock ref for update"
+msgstr "无法为更新锁定引用"
+
+#: branch.c:314
+msgid "Failed to write ref"
+msgstr "不能写引用"
+
 #: bundle.c:36
 #, c-format
 msgid "'%s' does not look like a v2 bundle file"
@@ -174,7 +266,7 @@
 msgid "unrecognized header: %s%s (%d)"
 msgstr "未能识别的包头:%s%s (%d)"
 
-#: bundle.c:89 builtin/commit.c:676
+#: bundle.c:89 builtin/commit.c:697
 #, c-format
 msgid "could not open '%s'"
 msgstr "不能打开 '%s'"
@@ -183,9 +275,9 @@
 msgid "Repository lacks these prerequisite commits:"
 msgstr "版本库缺少这些必备的提交:"
 
-#: bundle.c:164 sequencer.c:651 sequencer.c:1083 builtin/log.c:300
-#: builtin/log.c:754 builtin/log.c:1350 builtin/log.c:1566 builtin/merge.c:349
-#: builtin/shortlog.c:157
+#: bundle.c:164 sequencer.c:661 sequencer.c:1111 builtin/log.c:331
+#: builtin/log.c:801 builtin/log.c:1399 builtin/log.c:1625 builtin/merge.c:364
+#: builtin/shortlog.c:156
 msgid "revision walk setup failed"
 msgstr "版本遍历设置失败"
 
@@ -211,7 +303,7 @@
 msgid "rev-list died"
 msgstr "rev-list 终止"
 
-#: bundle.c:300 builtin/log.c:1246 builtin/shortlog.c:260
+#: bundle.c:300 builtin/log.c:1310 builtin/shortlog.c:259
 #, c-format
 msgid "unrecognized argument: %s"
 msgstr "未能识别的参数:%s"
@@ -242,12 +334,12 @@
 msgid "index-pack died"
 msgstr "index-pack 终止"
 
-#: commit.c:50
+#: commit.c:53
 #, c-format
 msgid "could not parse %s"
 msgstr "不能解析 %s"
 
-#: commit.c:52
+#: commit.c:55
 #, c-format
 msgid "%s %s is not a commit!"
 msgstr "%s %s 不是一个提交!"
@@ -256,16 +348,16 @@
 msgid "memory exhausted"
 msgstr "内存耗尽"
 
-#: connected.c:39
+#: connected.c:60
 msgid "Could not run 'git rev-list'"
 msgstr "不能执行 'git rev-list'"
 
-#: connected.c:48
+#: connected.c:80
 #, c-format
 msgid "failed write to rev-list: %s"
 msgstr "无法写入 rev-list:%s"
 
-#: connected.c:56
+#: connected.c:88
 #, c-format
 msgid "failed to close rev-list's stdin: %s"
 msgstr "无法关闭 rev-list 的标准输入:%s"
@@ -363,7 +455,7 @@
 "发现配置变量 'diff.dirstat' 中的错误:\n"
 "%s"
 
-#: diff.c:3480
+#: diff.c:3487
 #, c-format
 msgid ""
 "Failed to parse --dirstat/-X option parameter:\n"
@@ -372,7 +464,7 @@
 "无法解析 --dirstat/-X 选项的参数:\n"
 "%s"
 
-#: diff.c:3494
+#: diff.c:3501
 #, c-format
 msgid "Failed to parse --submodule option parameter: '%s'"
 msgstr "无法解析 --submodule 选项的参数:'%s'"
@@ -414,20 +506,20 @@
 msgid "'%s': short read %s"
 msgstr "'%s':读取不完整 %s"
 
-#: help.c:212
+#: help.c:210
 #, c-format
 msgid "available git commands in '%s'"
 msgstr "在 '%s' 下可用的 git 命令"
 
-#: help.c:219
+#: help.c:217
 msgid "git commands available from elsewhere on your $PATH"
 msgstr "在 $PATH 路径中的其他地方可用的 git 命令"
 
-#: help.c:235
+#: help.c:233
 msgid "The most commonly used git commands are:"
 msgstr "最常用的 git 命令有:"
 
-#: help.c:292
+#: help.c:290
 #, c-format
 msgid ""
 "'%s' appears to be a git command, but we were not\n"
@@ -436,11 +528,11 @@
 "'%s' 像是一个 git 命令,但却无法运行。\n"
 "可能是 git-%s 受损?"
 
-#: help.c:349
+#: help.c:347
 msgid "Uh oh. Your system reports no Git commands at all."
 msgstr "唉呀,您的系统中未发现 Git 命令。"
 
-#: help.c:371
+#: help.c:369
 #, c-format
 msgid ""
 "WARNING: You called a Git command named '%s', which does not exist.\n"
@@ -449,17 +541,17 @@
 "警告:您运行一个不存在的 Git 命令 '%s'。继续执行假定您要要运行的\n"
 "是 '%s'"
 
-#: help.c:376
+#: help.c:374
 #, c-format
 msgid "in %0.1f seconds automatically..."
 msgstr "在 %0.1f 秒钟后自动运行..."
 
-#: help.c:383
+#: help.c:381
 #, c-format
 msgid "git: '%s' is not a git command. See 'git --help'."
 msgstr "git:'%s' 不是一个 git 命令。参见 'git --help'。"
 
-#: help.c:387
+#: help.c:385 help.c:444
 msgid ""
 "\n"
 "Did you mean this?"
@@ -473,12 +565,17 @@
 "\n"
 "您指的是这其中的某一个么?"
 
+#: help.c:440
+#, c-format
+msgid "%s: %s - %s"
+msgstr "%s:%s - %s"
+
 #: merge.c:56
 msgid "failed to read the cache"
 msgstr "无法读取缓存"
 
-#: merge.c:110 builtin/checkout.c:362 builtin/checkout.c:563
-#: builtin/clone.c:635
+#: merge.c:110 builtin/checkout.c:365 builtin/checkout.c:566
+#: builtin/clone.c:656
 msgid "unable to write new index file"
 msgstr "无法写新的索引文件"
 
@@ -492,70 +589,70 @@
 msgid "addinfo_cache failed for path '%s'"
 msgstr "为路径 '%s' addinfo_cache 失败"
 
-#: merge-recursive.c:268
+#: merge-recursive.c:269
 msgid "error building trees"
 msgstr "无法创建树"
 
-#: merge-recursive.c:672
+#: merge-recursive.c:673
 #, c-format
 msgid "failed to create path '%s'%s"
 msgstr "无法创建路径 '%s'%s"
 
-#: merge-recursive.c:683
+#: merge-recursive.c:684
 #, c-format
 msgid "Removing %s to make room for subdirectory\n"
 msgstr "删除 %s 以便为子目录留出空间\n"
 
 #. something else exists
 #. .. but not some other error (who really cares what?)
-#: merge-recursive.c:697 merge-recursive.c:718
+#: merge-recursive.c:698 merge-recursive.c:719
 msgid ": perhaps a D/F conflict?"
 msgstr ":可能是一个目录/文件冲突?"
 
-#: merge-recursive.c:708
+#: merge-recursive.c:709
 #, c-format
 msgid "refusing to lose untracked file at '%s'"
 msgstr "拒绝丢弃 '%s' 中的未跟踪文件"
 
-#: merge-recursive.c:748
+#: merge-recursive.c:749
 #, c-format
 msgid "cannot read object %s '%s'"
 msgstr "不能读取对象 %s '%s'"
 
-#: merge-recursive.c:750
+#: merge-recursive.c:751
 #, c-format
 msgid "blob expected for %s '%s'"
 msgstr "%s '%s' 应为数据(blob)对象"
 
-#: merge-recursive.c:773 builtin/clone.c:303
+#: merge-recursive.c:774 builtin/clone.c:312
 #, c-format
 msgid "failed to open '%s'"
 msgstr "无法打开 '%s'"
 
-#: merge-recursive.c:781
+#: merge-recursive.c:782
 #, c-format
 msgid "failed to symlink '%s'"
 msgstr "无法创建符号链接 '%s'"
 
-#: merge-recursive.c:784
+#: merge-recursive.c:785
 #, c-format
 msgid "do not know what to do with %06o %s '%s'"
 msgstr "不知道如何处理 %06o %s '%s'"
 
-#: merge-recursive.c:922
+#: merge-recursive.c:923
 msgid "Failed to execute internal merge"
 msgstr "无法执行内部合并"
 
-#: merge-recursive.c:926
+#: merge-recursive.c:927
 #, c-format
 msgid "Unable to add %s to database"
 msgstr "不能添加 %s 至对象库"
 
-#: merge-recursive.c:942
+#: merge-recursive.c:943
 msgid "unsupported object type in the tree"
 msgstr "在树中有不支持的对象类型"
 
-#: merge-recursive.c:1021 merge-recursive.c:1035
+#: merge-recursive.c:1022 merge-recursive.c:1036
 #, c-format
 msgid ""
 "CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s left "
@@ -564,7 +661,7 @@
 "冲突(%1$s/删除):%2$s 在 %3$s 中被删除,在 %5$s 中被 %4$s。%7$s 在 %6$s 中"
 "的版本被保留。"
 
-#: merge-recursive.c:1027 merge-recursive.c:1040
+#: merge-recursive.c:1028 merge-recursive.c:1041
 #, c-format
 msgid ""
 "CONFLICT (%s/delete): %s deleted in %s and %s in %s. Version %s of %s left "
@@ -573,20 +670,20 @@
 "冲突(%1$s/删除):%2$s 在 %3$s 中被删除,在 %5$s 中被 %4$s。%7$s 在 %6$s 中"
 "的版本保留于 %8$s 中。"
 
-#: merge-recursive.c:1081
+#: merge-recursive.c:1082
 msgid "rename"
 msgstr "重命名"
 
-#: merge-recursive.c:1081
+#: merge-recursive.c:1082
 msgid "renamed"
 msgstr "重命名"
 
-#: merge-recursive.c:1137
+#: merge-recursive.c:1138
 #, c-format
 msgid "%s is a directory in %s adding as %s instead"
 msgstr "%s 是 %s 中的一个目录而以 %s 为名被添加"
 
-#: merge-recursive.c:1159
+#: merge-recursive.c:1160
 #, c-format
 msgid ""
 "CONFLICT (rename/rename): Rename \"%s\"->\"%s\" in branch \"%s\" rename \"%s"
@@ -595,148 +692,169 @@
 "冲突(重命名/重命名):在分支 \"%3$s\" 中重命名 \"%1$s\"->\"%2$s\",在分支 "
 "\"%6$s\" 中重命名 \"%4$s\"->\"%5$s\"%7$s"
 
-#: merge-recursive.c:1164
+#: merge-recursive.c:1165
 msgid " (left unresolved)"
 msgstr "(留下未解决)"
 
-#: merge-recursive.c:1218
+#: merge-recursive.c:1219
 #, c-format
 msgid "CONFLICT (rename/rename): Rename %s->%s in %s. Rename %s->%s in %s"
 msgstr ""
 "冲突(重命名/重命名):在 %3$s 中重命名 %1$s->%2$s,在 %6$s 中重命名 %4$s->"
 "%5$s"
 
-#: merge-recursive.c:1248
+#: merge-recursive.c:1249
 #, c-format
 msgid "Renaming %s to %s and %s to %s instead"
 msgstr "而是重命名 %s 至 %s,以及 %s 至 %s"
 
-#: merge-recursive.c:1447
+#: merge-recursive.c:1448
 #, c-format
 msgid "CONFLICT (rename/add): Rename %s->%s in %s. %s added in %s"
 msgstr "冲突(重命名/添加):在 %3$s 中重命名 %1$s->%2$s。在 %5$s 中添加 %4$s"
 
-#: merge-recursive.c:1457
+#: merge-recursive.c:1458
 #, c-format
 msgid "Adding merged %s"
 msgstr "添加合并后的 %s"
 
-#: merge-recursive.c:1462 merge-recursive.c:1660
+#: merge-recursive.c:1463 merge-recursive.c:1661
 #, c-format
 msgid "Adding as %s instead"
 msgstr "而是以 %s 为名添加"
 
-#: merge-recursive.c:1513
+#: merge-recursive.c:1514
 #, c-format
 msgid "cannot read object %s"
 msgstr "不能读取对象 %s"
 
-#: merge-recursive.c:1516
+#: merge-recursive.c:1517
 #, c-format
 msgid "object %s is not a blob"
 msgstr "对象 %s 不是一个数据(blob)对象"
 
-#: merge-recursive.c:1564
+#: merge-recursive.c:1565
 msgid "modify"
 msgstr "修改"
 
-#: merge-recursive.c:1564
+#: merge-recursive.c:1565
 msgid "modified"
 msgstr "修改"
 
-#: merge-recursive.c:1574
+#: merge-recursive.c:1575
 msgid "content"
 msgstr "内容"
 
-#: merge-recursive.c:1581
+#: merge-recursive.c:1582
 msgid "add/add"
 msgstr "添加/添加"
 
-#: merge-recursive.c:1615
+#: merge-recursive.c:1616
 #, c-format
 msgid "Skipped %s (merged same as existing)"
 msgstr "略过 %s(已经做过相同合并)"
 
-#: merge-recursive.c:1629
+#: merge-recursive.c:1630
 #, c-format
 msgid "Auto-merging %s"
 msgstr "自动合并 %s"
 
-#: merge-recursive.c:1633 git-submodule.sh:1029
+#: merge-recursive.c:1634 git-submodule.sh:1118
 msgid "submodule"
 msgstr "子模组"
 
-#: merge-recursive.c:1634
+#: merge-recursive.c:1635
 #, c-format
 msgid "CONFLICT (%s): Merge conflict in %s"
 msgstr "冲突(%s):合并冲突于 %s"
 
-#: merge-recursive.c:1724
+#: merge-recursive.c:1725
 #, c-format
 msgid "Removing %s"
 msgstr "删除 %s"
 
-#: merge-recursive.c:1749
+#: merge-recursive.c:1750
 msgid "file/directory"
 msgstr "文件/目录"
 
-#: merge-recursive.c:1755
+#: merge-recursive.c:1756
 msgid "directory/file"
 msgstr "目录/文件"
 
-#: merge-recursive.c:1760
+#: merge-recursive.c:1761
 #, c-format
 msgid "CONFLICT (%s): There is a directory with name %s in %s. Adding %s as %s"
 msgstr "冲突(%1$s):在 %3$s 中有一个名为 %2$s 的目录。以 %5$s 为名添加 %4$s"
 
-#: merge-recursive.c:1770
+#: merge-recursive.c:1771
 #, c-format
 msgid "Adding %s"
 msgstr "添加 %s"
 
-#: merge-recursive.c:1787
+#: merge-recursive.c:1788
 msgid "Fatal merge failure, shouldn't happen."
 msgstr "严重的合并错误,不应发生。"
 
-#: merge-recursive.c:1806
+#: merge-recursive.c:1807
 msgid "Already up-to-date!"
 msgstr "已经是最新的!"
 
-#: merge-recursive.c:1815
+#: merge-recursive.c:1816
 #, c-format
 msgid "merging of trees %s and %s failed"
 msgstr "无法合并树 %s 和 %s"
 
-#: merge-recursive.c:1845
+#: merge-recursive.c:1846
 #, c-format
 msgid "Unprocessed path??? %s"
 msgstr "未处理的路径??? %s"
 
-#: merge-recursive.c:1890
+#: merge-recursive.c:1891
 msgid "Merging:"
 msgstr "合并:"
 
-#: merge-recursive.c:1903
+#: merge-recursive.c:1904
 #, c-format
 msgid "found %u common ancestor:"
 msgid_plural "found %u common ancestors:"
 msgstr[0] "发现 %u 个共同祖先:"
 msgstr[1] "发现 %u 个共同祖先:"
 
-#: merge-recursive.c:1940
+#: merge-recursive.c:1941
 msgid "merge returned no commit"
 msgstr "合并未返回提交"
 
-#: merge-recursive.c:1997
+#: merge-recursive.c:1998
 #, c-format
 msgid "Could not parse object '%s'"
 msgstr "不能解析对象 '%s'"
 
-#: merge-recursive.c:2009 builtin/merge.c:658
+#: merge-recursive.c:2010 builtin/merge.c:672
 msgid "Unable to write index."
 msgstr "不能写入索引。"
 
-#: object.c:195
+#: notes-utils.c:40
+msgid "Cannot commit uninitialized/unreferenced notes tree"
+msgstr "不能提交未初始化/未引用的注解树"
+
+#: notes-utils.c:81
+#, c-format
+msgid "Bad notes.rewriteMode value: '%s'"
+msgstr "坏的 notes.rewriteMode 值:'%s'"
+
+#: notes-utils.c:91
+#, c-format
+msgid "Refusing to rewrite notes in %s (outside of refs/notes/)"
+msgstr "拒绝向 %s(在 refs/notes/ 之外)写入注解"
+
+#. TRANSLATORS: The first %s is the name of the
+#. environment variable, the second %s is its value
+#: notes-utils.c:118
+#, c-format
+msgid "Bad %s value: '%s'"
+msgstr "坏的 %s 值:'%s'"
+
+#: object.c:204
 #, c-format
 msgid "unable to parse object: %s"
 msgstr "不能解析对象:%s"
@@ -777,18 +895,18 @@
 msgid "'%s' is beyond a symbolic link"
 msgstr "'%s' 位于符号链接中"
 
-#: remote.c:1781
+#: remote.c:1788
 #, c-format
 msgid "Your branch is ahead of '%s' by %d commit.\n"
 msgid_plural "Your branch is ahead of '%s' by %d commits.\n"
 msgstr[0] "您的分支领先 '%s' 共 %d 个提交。\n"
 msgstr[1] "您的分支领先 '%s' 共 %d 个提交。\n"
 
-#: remote.c:1787
+#: remote.c:1794
 msgid "  (use \"git push\" to publish your local commits)\n"
 msgstr "  (使用 \"git push\" 来发布您的本地提交)\n"
 
-#: remote.c:1790
+#: remote.c:1797
 #, c-format
 msgid "Your branch is behind '%s' by %d commit, and can be fast-forwarded.\n"
 msgid_plural ""
@@ -797,11 +915,11 @@
 msgstr[1] "您的分支落后 '%s' 共 %d 个提交,并且可以快进。\n"
 
 #  译者:注意保持前导空格
-#: remote.c:1798
+#: remote.c:1805
 msgid "  (use \"git pull\" to update your local branch)\n"
 msgstr "  (使用 \"git pull\" 来更新您的本地分支)\n"
 
-#: remote.c:1801
+#: remote.c:1808
 #, c-format
 msgid ""
 "Your branch and '%s' have diverged,\n"
@@ -817,18 +935,27 @@
 "并且分别有 %d 和 %d 处不同的提交。\n"
 
 #  译者:注意保持前导空格
-#: remote.c:1811
+#: remote.c:1818
 msgid "  (use \"git pull\" to merge the remote branch into yours)\n"
 msgstr "  (使用 \"git pull\" 来合并远程分支)\n"
 
-#: sequencer.c:206 builtin/merge.c:776 builtin/merge.c:889 builtin/merge.c:999
-#: builtin/merge.c:1009
+#: run-command.c:80
+msgid "open /dev/null failed"
+msgstr "不能打开 /dev/null"
+
+#: run-command.c:82
+#, c-format
+msgid "dup2(%d,%d) failed"
+msgstr "不能调用 dup2(%d,%d)"
+
+#: sequencer.c:206 builtin/merge.c:790 builtin/merge.c:903
+#: builtin/merge.c:1013 builtin/merge.c:1023
 #, c-format
 msgid "Could not open '%s' for writing"
 msgstr "不能为写入打开 '%s'"
 
-#: sequencer.c:208 builtin/merge.c:335 builtin/merge.c:779
-#: builtin/merge.c:1001 builtin/merge.c:1014
+#: sequencer.c:208 builtin/merge.c:350 builtin/merge.c:793
+#: builtin/merge.c:1015 builtin/merge.c:1028
 #, c-format
 msgid "Could not write to '%s'"
 msgstr "不能写入 '%s'"
@@ -850,7 +977,7 @@
 "冲突解决完毕后,用 'git add <paths>' 或 'git rm <paths>'\n"
 "对修正后的文件做标记,然后用 'git commit' 提交"
 
-#: sequencer.c:245 sequencer.c:859 sequencer.c:942
+#: sequencer.c:245 sequencer.c:869 sequencer.c:952
 #, c-format
 msgid "Could not write to %s"
 msgstr "不能写入 %s"
@@ -873,205 +1000,236 @@
 msgstr "提交您的修改或保存进度后再继续。"
 
 #. TRANSLATORS: %s will be "revert" or "cherry-pick"
-#: sequencer.c:319
+#: sequencer.c:324
 #, c-format
 msgid "%s: Unable to write new index file"
 msgstr "%s:无法写入新索引文件"
 
-#: sequencer.c:350
+#: sequencer.c:355
 msgid "Could not resolve HEAD commit\n"
 msgstr "不能解析 HEAD 提交\n"
 
-#: sequencer.c:371
+#: sequencer.c:377
 msgid "Unable to update cache tree\n"
 msgstr "不能更新缓存\n"
 
-#: sequencer.c:416
+#: sequencer.c:422
 #, c-format
 msgid "Could not parse commit %s\n"
 msgstr "不能解析提交 %s\n"
 
-#: sequencer.c:421
+#: sequencer.c:427
 #, c-format
 msgid "Could not parse parent commit %s\n"
 msgstr "不能解析父提交 %s\n"
 
-#: sequencer.c:487
+#: sequencer.c:493
 msgid "Your index file is unmerged."
 msgstr "您的索引文件未完成合并。"
 
-#: sequencer.c:506
+#: sequencer.c:512
 #, c-format
 msgid "Commit %s is a merge but no -m option was given."
 msgstr "提交 %s 是一个合并提交但未提供 -m 选项。"
 
-#: sequencer.c:514
+#: sequencer.c:520
 #, c-format
 msgid "Commit %s does not have parent %d"
 msgstr "提交 %s 没有父提交 %d"
 
-#: sequencer.c:518
+#: sequencer.c:524
 #, c-format
 msgid "Mainline was specified but commit %s is not a merge."
 msgstr "指定了主线但提交 %s 不是一个合并。"
 
 #. TRANSLATORS: The first %s will be "revert" or
 #. "cherry-pick", the second %s a SHA1
-#: sequencer.c:531
+#: sequencer.c:537
 #, c-format
 msgid "%s: cannot parse parent commit %s"
 msgstr "%s:不能解析父提交 %s"
 
-#: sequencer.c:535
+#: sequencer.c:541
 #, c-format
 msgid "Cannot get commit message for %s"
 msgstr "不能得到 %s 的提交说明"
 
-#: sequencer.c:621
+#: sequencer.c:627
 #, c-format
 msgid "could not revert %s... %s"
 msgstr "不能还原 %s... %s"
 
-#: sequencer.c:622
+#: sequencer.c:628
 #, c-format
 msgid "could not apply %s... %s"
 msgstr "不能应用 %s... %s"
 
-#: sequencer.c:654
+#: sequencer.c:664
 msgid "empty commit set passed"
 msgstr "提供了空的提交集"
 
-#: sequencer.c:662
+#: sequencer.c:672
 #, c-format
 msgid "git %s: failed to read the index"
 msgstr "git %s:无法读取索引"
 
-#: sequencer.c:667
+#: sequencer.c:677
 #, c-format
 msgid "git %s: failed to refresh the index"
 msgstr "git %s:无法刷新索引"
 
-#: sequencer.c:725
+#: sequencer.c:735
 #, c-format
 msgid "Cannot %s during a %s"
 msgstr "无法 %s 在一个 %s 过程中"
 
-#: sequencer.c:747
+#: sequencer.c:757
 #, c-format
 msgid "Could not parse line %d."
 msgstr "不能解析第 %d 行。"
 
-#: sequencer.c:752
+#: sequencer.c:762
 msgid "No commits parsed."
 msgstr "没有提交被解析。"
 
-#: sequencer.c:765
+#: sequencer.c:775
 #, c-format
 msgid "Could not open %s"
 msgstr "不能打开 %s"
 
-#: sequencer.c:769
+#: sequencer.c:779
 #, c-format
 msgid "Could not read %s."
 msgstr "不能读取 %s。"
 
-#: sequencer.c:776
+#: sequencer.c:786
 #, c-format
 msgid "Unusable instruction sheet: %s"
 msgstr "无用的指令表单:%s"
 
-#: sequencer.c:804
+#: sequencer.c:814
 #, c-format
 msgid "Invalid key: %s"
 msgstr "无效键名:%s"
 
-#: sequencer.c:807
+#: sequencer.c:817
 #, c-format
 msgid "Invalid value for %s: %s"
 msgstr "%s 的值无效:%s"
 
-#: sequencer.c:819
+#: sequencer.c:829
 #, c-format
 msgid "Malformed options sheet: %s"
 msgstr "非法的选项表单:%s"
 
-#: sequencer.c:840
+#: sequencer.c:850
 msgid "a cherry-pick or revert is already in progress"
 msgstr "一个拣选或还原操作已在进行"
 
-#: sequencer.c:841
+#: sequencer.c:851
 msgid "try \"git cherry-pick (--continue | --quit | --abort)\""
 msgstr "尝试 \"git cherry-pick (--continue | --quit | --abort)\""
 
-#: sequencer.c:845
+#: sequencer.c:855
 #, c-format
 msgid "Could not create sequencer directory %s"
 msgstr "不能创建序列目录 %s"
 
-#: sequencer.c:861 sequencer.c:946
+#: sequencer.c:871 sequencer.c:956
 #, c-format
 msgid "Error wrapping up %s."
 msgstr "错误收尾 %s。"
 
-#: sequencer.c:880 sequencer.c:1014
+#: sequencer.c:890 sequencer.c:1024
 msgid "no cherry-pick or revert in progress"
 msgstr "拣选或还原操作并未进行"
 
-#: sequencer.c:882
+#: sequencer.c:892
 msgid "cannot resolve HEAD"
 msgstr "不能解析 HEAD"
 
-#: sequencer.c:884
+#: sequencer.c:894
 msgid "cannot abort from a branch yet to be born"
 msgstr "不能从尚未建立的分支终止"
 
-#: sequencer.c:906 builtin/apply.c:4060
+#: sequencer.c:916 builtin/apply.c:4061
 #, c-format
 msgid "cannot open %s: %s"
 msgstr "不能打开 %s:%s"
 
-#: sequencer.c:909
+#: sequencer.c:919
 #, c-format
 msgid "cannot read %s: %s"
 msgstr "不能读取 %s:%s"
 
-#: sequencer.c:910
+#: sequencer.c:920
 msgid "unexpected end of file"
 msgstr "意外的文件结束"
 
-#: sequencer.c:916
+#: sequencer.c:926
 #, c-format
 msgid "stored pre-cherry-pick HEAD file '%s' is corrupt"
 msgstr "保存拣选提交前的 HEAD 文件 '%s' 损坏"
 
-#: sequencer.c:939
+#: sequencer.c:949
 #, c-format
 msgid "Could not format %s."
 msgstr "不能格式化 %s。"
 
-#: sequencer.c:1101
+#: sequencer.c:1092
+#, c-format
+msgid "%s: can't cherry-pick a %s"
+msgstr "%s:不能拣选一个%s"
+
+#: sequencer.c:1095
+#, c-format
+msgid "%s: bad revision"
+msgstr "%s:错误的版本"
+
+#: sequencer.c:1129
 msgid "Can't revert as initial commit"
 msgstr "不能作为初始提交还原"
 
-#: sequencer.c:1102
+#: sequencer.c:1130
 msgid "Can't cherry-pick into empty head"
 msgstr "不能拣选到空分支"
 
-#: sha1_name.c:1036
+#: sha1_name.c:440
+msgid ""
+"Git normally never creates a ref that ends with 40 hex characters\n"
+"because it will be ignored when you just specify 40-hex. These refs\n"
+"may be created by mistake. For example,\n"
+"\n"
+"  git checkout -b $br $(git rev-parse ...)\n"
+"\n"
+"where \"$br\" is somehow empty and a 40-hex ref is created. Please\n"
+"examine these refs and maybe delete them. Turn this message off by\n"
+"running \"git config advice.objectNameWarning false\""
+msgstr ""
+"Git 通常不会创建一个以40位十六进制字符命名的引用,因为当你提供40位\n"
+"十六进制字符时将被忽略。不过这些引用也可能被错误地创建。例如:\n"
+"\n"
+"  git checkout -b $br $(git rev-parse ...)\n"
+"\n"
+"当 \"$br\" 空白时一个40位十六进制的引用将被创建。请检查这些引用,\n"
+"可能需要删除它们。用 \"git config advice.objectNameWarning false\"\n"
+"命令关闭本消息通知。"
+
+#: sha1_name.c:1097
 msgid "HEAD does not point to a branch"
 msgstr "HEAD 没有指向一个分支"
 
-#: sha1_name.c:1039
+#: sha1_name.c:1100
 #, c-format
 msgid "No such branch: '%s'"
 msgstr "没有此分支:'%s'"
 
-#: sha1_name.c:1041
+#: sha1_name.c:1102
 #, c-format
 msgid "No upstream configured for branch '%s'"
 msgstr "尚未给分支 '%s' 设置上游"
 
-#: sha1_name.c:1044
+#: sha1_name.c:1106
 #, c-format
 msgid "Upstream branch '%s' not stored as a remote-tracking branch"
 msgstr "上游分支 '%s' 没有存储为一个远程跟踪分支"
@@ -1081,298 +1239,308 @@
 msgid "unable to access '%s': %s"
 msgstr "不能访问 '%s':%s"
 
-#: wrapper.c:423
+#: wrapper.c:429
 #, c-format
 msgid "unable to access '%s'"
 msgstr "不能访问 '%s'"
 
-#: wrapper.c:434
+#: wrapper.c:440
 #, c-format
 msgid "unable to look up current user in the passwd file: %s"
 msgstr "无法在口令文件中查询到当前用户:%s"
 
-#: wrapper.c:435
+#: wrapper.c:441
 msgid "no such user"
 msgstr "无此用户"
 
-#: wt-status.c:140
+#: wt-status.c:141
 msgid "Unmerged paths:"
 msgstr "未合并的路径:"
 
 #  译者:注意保持前导空格
-#: wt-status.c:167 wt-status.c:194
+#: wt-status.c:168 wt-status.c:195
 #, c-format
 msgid "  (use \"git reset %s <file>...\" to unstage)"
 msgstr "  (使用 \"git reset %s <file>...\" 撤出暂存区)"
 
 #  译者:注意保持前导空格
-#: wt-status.c:169 wt-status.c:196
+#: wt-status.c:170 wt-status.c:197
 msgid "  (use \"git rm --cached <file>...\" to unstage)"
 msgstr "  (使用 \"git rm --cached <file>...\" 撤出暂存区)"
 
 #  译者:注意保持前导空格
-#: wt-status.c:173
+#: wt-status.c:174
 msgid "  (use \"git add <file>...\" to mark resolution)"
 msgstr "  (使用 \"git add <file>...\" 标记解决方案)"
 
 #  译者:注意保持前导空格
-#: wt-status.c:175 wt-status.c:179
+#: wt-status.c:176 wt-status.c:180
 msgid "  (use \"git add/rm <file>...\" as appropriate to mark resolution)"
 msgstr "  (酌情使用 \"git add/rm <file>...\" 标记解决方案)"
 
 #  译者:注意保持前导空格
-#: wt-status.c:177
+#: wt-status.c:178
 msgid "  (use \"git rm <file>...\" to mark resolution)"
 msgstr "  (使用 \"git rm <file>...\" 标记解决方案)"
 
-#: wt-status.c:188
+#: wt-status.c:189
 msgid "Changes to be committed:"
 msgstr "要提交的变更:"
 
-#: wt-status.c:206
+#: wt-status.c:207
 msgid "Changes not staged for commit:"
 msgstr "尚未暂存以备提交的变更:"
 
 #  译者:注意保持前导空格
-#: wt-status.c:210
+#: wt-status.c:211
 msgid "  (use \"git add <file>...\" to update what will be committed)"
 msgstr "  (使用 \"git add <file>...\" 更新要提交的内容)"
 
 #  译者:注意保持前导空格
-#: wt-status.c:212
+#: wt-status.c:213
 msgid "  (use \"git add/rm <file>...\" to update what will be committed)"
 msgstr "  (使用 \"git add/rm <file>...\" 更新要提交的内容)"
 
 #  译者:注意保持前导空格
-#: wt-status.c:213
+#: wt-status.c:214
 msgid ""
 "  (use \"git checkout -- <file>...\" to discard changes in working directory)"
 msgstr "  (使用 \"git checkout -- <file>...\" 丢弃工作区的改动)"
 
 #  译者:注意保持前导空格
-#: wt-status.c:215
+#: wt-status.c:216
 msgid "  (commit or discard the untracked or modified content in submodules)"
 msgstr "  (提交或丢弃子模组中未跟踪或修改的内容)"
 
 #  译者:注意保持前导空格
-#: wt-status.c:227
+#: wt-status.c:228
 #, c-format
 msgid "  (use \"git %s <file>...\" to include in what will be committed)"
 msgstr "  (使用 \"git %s <file>...\" 以包含要提交的内容)"
 
-#: wt-status.c:244
+#: wt-status.c:245
 msgid "bug"
 msgstr "bug"
 
-#: wt-status.c:249
+#: wt-status.c:250
 msgid "both deleted:"
 msgstr "双方删除:"
 
-#: wt-status.c:250
+#: wt-status.c:251
 msgid "added by us:"
 msgstr "由我们添加:"
 
-#: wt-status.c:251
+#: wt-status.c:252
 msgid "deleted by them:"
 msgstr "由他们删除:"
 
-#: wt-status.c:252
+#: wt-status.c:253
 msgid "added by them:"
 msgstr "由他们添加:"
 
-#: wt-status.c:253
+#: wt-status.c:254
 msgid "deleted by us:"
 msgstr "由我们删除:"
 
-#: wt-status.c:254
+#: wt-status.c:255
 msgid "both added:"
 msgstr "双方添加:"
 
-#: wt-status.c:255
+#: wt-status.c:256
 msgid "both modified:"
 msgstr "双方修改:"
 
 #  译者:末尾两个字节可能被删减,如果翻译为中文标点会出现半个汉字
-#: wt-status.c:285
+#: wt-status.c:286
 msgid "new commits, "
 msgstr "新提交, "
 
 #  译者:末尾两个字节可能被删减,如果翻译为中文标点会出现半个汉字
-#: wt-status.c:287
+#: wt-status.c:288
 msgid "modified content, "
 msgstr "修改的内容, "
 
 #  译者:末尾两个字节可能被删减,如果翻译为中文标点会出现半个汉字
-#: wt-status.c:289
+#: wt-status.c:290
 msgid "untracked content, "
 msgstr "未跟踪的内容, "
 
 #  译者:为保证在输出中对齐,注意调整句中空格!
-#: wt-status.c:306
+#: wt-status.c:307
 #, c-format
 msgid "new file:   %s"
 msgstr "新文件:    %s"
 
 #  译者:为保证在输出中对齐,注意调整句中空格!
-#: wt-status.c:309
+#: wt-status.c:310
 #, c-format
 msgid "copied:     %s -> %s"
 msgstr "拷贝:      %s -> %s"
 
 #  译者:为保证在输出中对齐,注意调整句中空格!
-#: wt-status.c:312
+#: wt-status.c:313
 #, c-format
 msgid "deleted:    %s"
 msgstr "删除:      %s"
 
 #  译者:为保证在输出中对齐,注意调整句中空格!
-#: wt-status.c:315
+#: wt-status.c:316
 #, c-format
 msgid "modified:   %s"
 msgstr "修改:      %s"
 
 #  译者:为保证在输出中对齐,注意调整句中空格!
-#: wt-status.c:318
+#: wt-status.c:319
 #, c-format
 msgid "renamed:    %s -> %s"
 msgstr "重命名:    %s -> %s"
 
 #  译者:为保证在输出中对齐,注意调整句中空格!
-#: wt-status.c:321
+#: wt-status.c:322
 #, c-format
 msgid "typechange: %s"
 msgstr "类型变更:  %s"
 
 #  译者:为保证在输出中对齐,注意调整句中空格!
-#: wt-status.c:324
+#: wt-status.c:325
 #, c-format
 msgid "unknown:    %s"
 msgstr "未知:      %s"
 
 #  译者:为保证在输出中对齐,注意调整句中空格!
-#: wt-status.c:327
+#: wt-status.c:328
 #, c-format
 msgid "unmerged:   %s"
 msgstr "未合并:    %s"
 
-#: wt-status.c:330
+#: wt-status.c:331
 #, c-format
 msgid "bug: unhandled diff status %c"
 msgstr "bug:未处理的差异状态 %c"
 
-#: wt-status.c:805
+#: wt-status.c:803
 msgid "You have unmerged paths."
 msgstr "您有尚未合并的路径。"
 
 #  译者:注意保持前导空格
-#: wt-status.c:808 wt-status.c:960
+#: wt-status.c:806
 msgid "  (fix conflicts and run \"git commit\")"
 msgstr "  (解决冲突并运行 \"git commit\")"
 
-#: wt-status.c:811
+#: wt-status.c:809
 msgid "All conflicts fixed but you are still merging."
 msgstr "所有冲突已解决但您仍处于合并中。"
 
 #  译者:注意保持前导空格
-#: wt-status.c:814
+#: wt-status.c:812
 msgid "  (use \"git commit\" to conclude merge)"
 msgstr "  (使用 \"git commit\" 结束合并)"
 
-#: wt-status.c:824
+#: wt-status.c:822
 msgid "You are in the middle of an am session."
 msgstr "您正处于一个 am 过程中。"
 
-#: wt-status.c:827
+#: wt-status.c:825
 msgid "The current patch is empty."
 msgstr "当前的补丁为空。"
 
 #  译者:注意保持前导空格
-#: wt-status.c:831
-msgid "  (fix conflicts and then run \"git am --resolved\")"
-msgstr "  (解决冲突,然后运行 \"git am --resolved\")"
+#: wt-status.c:829
+msgid "  (fix conflicts and then run \"git am --continue\")"
+msgstr "  (解决冲突,然后运行 \"git am --continue\")"
 
 #  译者:注意保持前导空格
-#: wt-status.c:833
+#: wt-status.c:831
 msgid "  (use \"git am --skip\" to skip this patch)"
 msgstr "  (使用 \"git am --skip\" 跳过此补丁)"
 
 #  译者:注意保持前导空格
-#: wt-status.c:835
+#: wt-status.c:833
 msgid "  (use \"git am --abort\" to restore the original branch)"
 msgstr "  (使用 \"git am --abort\" 恢复原有分支)"
 
-#: wt-status.c:895 wt-status.c:912
+#: wt-status.c:893 wt-status.c:910
 #, c-format
 msgid "You are currently rebasing branch '%s' on '%s'."
 msgstr "您正在将分支 '%s' 变基到 '%s'。"
 
-#: wt-status.c:900 wt-status.c:917
+#: wt-status.c:898 wt-status.c:915
 msgid "You are currently rebasing."
 msgstr "您正在变基。"
 
 #  译者:注意保持前导空格
-#: wt-status.c:903
+#: wt-status.c:901
 msgid "  (fix conflicts and then run \"git rebase --continue\")"
 msgstr "  (解决冲突,然后运行 \"git rebase --continue\")"
 
 #  译者:注意保持前导空格
-#: wt-status.c:905
+#: wt-status.c:903
 msgid "  (use \"git rebase --skip\" to skip this patch)"
 msgstr "  (使用 \"git rebase --skip\" 跳过此补丁)"
 
 #  译者:注意保持前导空格
-#: wt-status.c:907
+#: wt-status.c:905
 msgid "  (use \"git rebase --abort\" to check out the original branch)"
 msgstr "  (使用 \"git rebase --abort\" 以检出原有分支)"
 
 #  译者:注意保持前导空格
-#: wt-status.c:920
+#: wt-status.c:918
 msgid "  (all conflicts fixed: run \"git rebase --continue\")"
 msgstr "  (所有冲突已解决:运行 \"git rebase --continue\")"
 
-#: wt-status.c:924
+#: wt-status.c:922
 #, c-format
 msgid ""
 "You are currently splitting a commit while rebasing branch '%s' on '%s'."
 msgstr "您正在将分支 '%s' 变基到 '%s' 过程中拆分一个提交。"
 
-#: wt-status.c:929
+#: wt-status.c:927
 msgid "You are currently splitting a commit during a rebase."
 msgstr "您正在变基过程中拆分一个提交。"
 
 #  译者:注意保持前导空格
-#: wt-status.c:932
+#: wt-status.c:930
 msgid "  (Once your working directory is clean, run \"git rebase --continue\")"
 msgstr "  (一旦您工作目录提交干净后,运行 \"git rebase --continue\")"
 
-#: wt-status.c:936
+#: wt-status.c:934
 #, c-format
 msgid "You are currently editing a commit while rebasing branch '%s' on '%s'."
 msgstr "您正在将分支 '%s' 变基到 '%s' 过程中编辑一个提交。"
 
-#: wt-status.c:941
+#: wt-status.c:939
 msgid "You are currently editing a commit during a rebase."
 msgstr "您正在变基过程中编辑一个提交。"
 
 #  译者:注意保持前导空格
-#: wt-status.c:944
+#: wt-status.c:942
 msgid "  (use \"git commit --amend\" to amend the current commit)"
 msgstr "  (使用 \"git commit --amend\" 修补当前提交)"
 
 #  译者:注意保持前导空格
-#: wt-status.c:946
+#: wt-status.c:944
 msgid ""
 "  (use \"git rebase --continue\" once you are satisfied with your changes)"
 msgstr "  (当您对您的修改满意后执行 \"git rebase --continue\")"
 
-#: wt-status.c:956
+#: wt-status.c:954
 msgid "You are currently cherry-picking."
 msgstr "您正在做拣选操作。"
 
 #  译者:注意保持前导空格
+#: wt-status.c:958
+msgid "  (fix conflicts and run \"git cherry-pick --continue\")"
+msgstr "  (解决冲突并运行 \"git cherry-pick --continue\")"
+
+#  译者:注意保持前导空格
+#: wt-status.c:961
+msgid "  (all conflicts fixed: run \"git cherry-pick --continue\")"
+msgstr "  (所有冲突已解决:运行 \"git cherry-pick --continue\")"
+
+#  译者:注意保持前导空格
 #: wt-status.c:963
-msgid "  (all conflicts fixed: run \"git commit\")"
-msgstr "  (解决所有冲突后,执行 \"git commit\")"
+msgid "  (use \"git cherry-pick --abort\" to cancel the cherry-pick operation)"
+msgstr "  (使用 \"git cherry-pick --abort\" 以取消拣选操作)"
 
 #: wt-status.c:972
 #, c-format
@@ -1408,133 +1576,132 @@
 msgid "  (use \"git bisect reset\" to get back to the original branch)"
 msgstr "  (使用 \"git bisect reset\" 以回到原有分支)"
 
-#: wt-status.c:1175
+#: wt-status.c:1173
 msgid "On branch "
 msgstr "位于分支 "
 
-#: wt-status.c:1186
+#: wt-status.c:1180
+msgid "rebase in progress; onto "
+msgstr "变基正在进行中;至 "
+
+#: wt-status.c:1187
 msgid "HEAD detached at "
 msgstr "头指针分离于 "
 
-#: wt-status.c:1188
+#: wt-status.c:1189
 msgid "HEAD detached from "
 msgstr "头指针分离自 "
 
-#: wt-status.c:1191
+#: wt-status.c:1192
 msgid "Not currently on any branch."
 msgstr "当前不在任何分支上。"
 
-#: wt-status.c:1208
+#: wt-status.c:1209
 msgid "Initial commit"
 msgstr "初始提交"
 
-#: wt-status.c:1222
+#: wt-status.c:1223
 msgid "Untracked files"
 msgstr "未跟踪的文件"
 
-#: wt-status.c:1224
+#: wt-status.c:1225
 msgid "Ignored files"
 msgstr "忽略的文件"
 
-#  译者:以下三条实际为一个段落
-#: wt-status.c:1228
+#: wt-status.c:1229
 #, c-format
-msgid "It took %.2f seconds to enumerate untracked files.  'status -uno'"
-msgstr "耗费了 %.2f 秒以枚举未跟踪的文件。'status -uno'"
-
-#  译者:为对齐,下面两句内容有调整
-#: wt-status.c:1232
-msgid "may speed it up, but you have to be careful not to forget to add"
-msgstr "也许能提高速度,但您需要小心不要忘了添加新文件"
+msgid ""
+"It took %.2f seconds to enumerate untracked files. 'status -uno'\n"
+"may speed it up, but you have to be careful not to forget to add\n"
+"new files yourself (see 'git help status')."
+msgstr ""
+"耗费了 %.2f 秒以枚举未跟踪的文件。'status -uno' 也许能提高速度,\n"
+"但您需要小心不要忘了添加新文件(参见 'git help status')。"
 
 #: wt-status.c:1235
-msgid "new files yourself (see 'git help status')."
-msgstr "(参见 'git help status')。"
-
-#: wt-status.c:1238
 #, c-format
 msgid "Untracked files not listed%s"
 msgstr "未跟踪的文件没有列出%s"
 
 #  译者:中文字符串拼接,可删除前导空格
-#: wt-status.c:1240
+#: wt-status.c:1237
 msgid " (use -u option to show untracked files)"
 msgstr "(使用 -u 参数显示未跟踪的文件)"
 
-#: wt-status.c:1246
+#: wt-status.c:1243
 msgid "No changes"
 msgstr "没有修改"
 
-#: wt-status.c:1251
+#: wt-status.c:1248
 #, c-format
 msgid "no changes added to commit (use \"git add\" and/or \"git commit -a\")\n"
 msgstr "修改尚未加入提交(使用 \"git add\" 和/或 \"git commit -a\")\n"
 
-#: wt-status.c:1254
+#: wt-status.c:1251
 #, c-format
 msgid "no changes added to commit\n"
 msgstr "修改尚未加入提交\n"
 
-#: wt-status.c:1257
+#: wt-status.c:1254
 #, c-format
 msgid ""
 "nothing added to commit but untracked files present (use \"git add\" to "
 "track)\n"
 msgstr "提交为空,但是存在尚未跟踪的文件(使用 \"git add\" 建立跟踪)\n"
 
-#: wt-status.c:1260
+#: wt-status.c:1257
 #, c-format
 msgid "nothing added to commit but untracked files present\n"
 msgstr "提交为空,但是存在尚未跟踪的文件\n"
 
 #  译者:中文字符串拼接,可删除前导空格
-#: wt-status.c:1263
+#: wt-status.c:1260
 #, c-format
 msgid "nothing to commit (create/copy files and use \"git add\" to track)\n"
 msgstr "无文件要提交(创建/拷贝文件并使用 \"git add\" 建立跟踪)\n"
 
-#: wt-status.c:1266 wt-status.c:1271
+#: wt-status.c:1263 wt-status.c:1268
 #, c-format
 msgid "nothing to commit\n"
 msgstr "无文件要提交\n"
 
 #  译者:中文字符串拼接,可删除前导空格
-#: wt-status.c:1269
+#: wt-status.c:1266
 #, c-format
 msgid "nothing to commit (use -u to show untracked files)\n"
 msgstr "无文件要提交(使用 -u 显示未跟踪的文件)\n"
 
 #  译者:中文字符串拼接,可删除前导空格
-#: wt-status.c:1273
+#: wt-status.c:1270
 #, c-format
 msgid "nothing to commit, working directory clean\n"
 msgstr "无文件要提交,干净的工作区\n"
 
-#: wt-status.c:1381
+#: wt-status.c:1378
 msgid "HEAD (no branch)"
 msgstr "HEAD(非分支)"
 
 #  译者:注意保持句尾空格
-#: wt-status.c:1387
+#: wt-status.c:1384
 msgid "Initial commit on "
 msgstr "初始提交于 "
 
 #  译者:注意保持句尾空格
-#: wt-status.c:1402
+#: wt-status.c:1399
 msgid "behind "
 msgstr "落后 "
 
 #  译者:注意保持句尾空格
-#: wt-status.c:1405 wt-status.c:1408
+#: wt-status.c:1402 wt-status.c:1405
 msgid "ahead "
 msgstr "领先 "
 
 #  译者:注意保持句尾空格
-#: wt-status.c:1410
+#: wt-status.c:1407
 msgid ", behind "
 msgstr ",落后 "
 
-#: compat/precompose_utf8.c:58 builtin/clone.c:342
+#: compat/precompose_utf8.c:58 builtin/clone.c:351
 #, c-format
 msgid "failed to unlink '%s'"
 msgstr "无法删除 '%s'"
@@ -1543,125 +1710,6 @@
 msgid "git add [options] [--] <pathspec>..."
 msgstr "git add [选项] [--] <路径匹配>..."
 
-#: builtin/add.c:63
-#, c-format
-msgid "unexpected diff status %c"
-msgstr "意外的差异状态 %c"
-
-#: builtin/add.c:68 builtin/commit.c:233
-msgid "updating files failed"
-msgstr "更新文件失败"
-
-#: builtin/add.c:78
-#, c-format
-msgid "remove '%s'\n"
-msgstr "删除 '%s'\n"
-
-#: builtin/add.c:148
-msgid "Unstaged changes after refreshing the index:"
-msgstr "刷新索引之后尚未被暂存的变更:"
-
-#: builtin/add.c:151 builtin/add.c:460 builtin/rm.c:275
-#, c-format
-msgid "pathspec '%s' did not match any files"
-msgstr "路径 '%s' 未匹配任何文件"
-
-#: builtin/add.c:234
-msgid "Could not read the index"
-msgstr "不能读取索引"
-
-#: builtin/add.c:244
-#, c-format
-msgid "Could not open '%s' for writing."
-msgstr "不能打开 '%s' 以写入。"
-
-#: builtin/add.c:248
-msgid "Could not write patch"
-msgstr "不能生成补丁"
-
-#: builtin/add.c:253
-#, c-format
-msgid "Could not stat '%s'"
-msgstr "不能查看文件状态 '%s'"
-
-#: builtin/add.c:255
-msgid "Empty patch. Aborted."
-msgstr "空补丁。异常终止。"
-
-#: builtin/add.c:261
-#, c-format
-msgid "Could not apply '%s'"
-msgstr "不能应用 '%s'"
-
-#: builtin/add.c:271
-msgid "The following paths are ignored by one of your .gitignore files:\n"
-msgstr "下列路径根据您的一个 .gitignore 文件而被忽略:\n"
-
-#: builtin/add.c:277 builtin/clean.c:161 builtin/fetch.c:78 builtin/mv.c:63
-#: builtin/prune-packed.c:76 builtin/push.c:425 builtin/remote.c:1253
-#: builtin/rm.c:206
-msgid "dry run"
-msgstr "演习"
-
-#: builtin/add.c:278 builtin/apply.c:4409 builtin/check-ignore.c:19
-#: builtin/commit.c:1152 builtin/count-objects.c:95 builtin/fsck.c:613
-#: builtin/log.c:1514 builtin/mv.c:62 builtin/read-tree.c:112
-msgid "be verbose"
-msgstr "冗长输出"
-
-#: builtin/add.c:280
-msgid "interactive picking"
-msgstr "交互式拣选"
-
-#: builtin/add.c:281 builtin/checkout.c:1060 builtin/reset.c:258
-msgid "select hunks interactively"
-msgstr "交互式挑选数据块"
-
-#: builtin/add.c:282
-msgid "edit current diff and apply"
-msgstr "编辑当前差异并应用"
-
-#: builtin/add.c:283
-msgid "allow adding otherwise ignored files"
-msgstr "允许添加忽略的文件"
-
-#: builtin/add.c:284
-msgid "update tracked files"
-msgstr "更新已跟踪的文件"
-
-#: builtin/add.c:285
-msgid "record only the fact that the path will be added later"
-msgstr "只记录,该路径稍后再添加"
-
-#: builtin/add.c:286
-msgid "add changes from all tracked and untracked files"
-msgstr "添加所有改变的已跟踪文件和未跟踪文件"
-
-#: builtin/add.c:287
-msgid "don't add, only refresh the index"
-msgstr "不添加,只刷新索引"
-
-#: builtin/add.c:288
-msgid "just skip files which cannot be added because of errors"
-msgstr "跳过因出错不能添加的文件"
-
-#: builtin/add.c:289
-msgid "check if - even missing - files are ignored in dry run"
-msgstr "检查在演习模式下文件(即使不存在)是否被忽略"
-
-#: builtin/add.c:311
-#, c-format
-msgid "Use -f if you really want to add them.\n"
-msgstr "使用 -f 参数如果您确实要添加它们。\n"
-
-#: builtin/add.c:312
-msgid "no files added"
-msgstr "没有文件被添加"
-
-#: builtin/add.c:318
-msgid "adding files failed"
-msgstr "添加文件失败"
-
 #  译者:字符串首行行首要添加“warning: ”字串,故此首行要较其余行短
 #.
 #. * To be consistent with "git add -p" and most Git
@@ -1673,7 +1721,7 @@
 #. * to tree-wide, keeping the warning for a while, and
 #. * eventually we can drop the warning.
 #.
-#: builtin/add.c:335
+#: builtin/add.c:58
 #, c-format
 msgid ""
 "The behavior of 'git add %s (or %s)' with no path argument from a\n"
@@ -1690,10 +1738,10 @@
 "  (or git add %s .)\n"
 "\n"
 "With the current Git version, the command is restricted to the current "
-"directory."
+"directory.\n"
 msgstr ""
-"在 Git 2.0 版本,将不再允许在一个子目录下不带任何路径参数地执行\n"
-"命令 'git add %s (或 %s)'。所以不要再继续使用了。\n"
+"在 Git 2.0 版本,位于一个子目录下不带任何路径参数地执行命令\n"
+"'git add %s (或 %s)' 的行为将被改变,不要再继续使用了。\n"
 "如果要添加整个目录树的内容,执行:\n"
 "\n"
 "  git add %s :/\n"
@@ -1704,32 +1752,183 @@
 "  git add %s .\n"
 "  (或 git add %s .)\n"
 "\n"
-"对于当前版本的 Git,这条命令只作用于当前目录。"
+"对于当前版本的 Git,这条命令只作用于当前目录。\n"
 
-#: builtin/add.c:381
+#: builtin/add.c:100
+#, c-format
+msgid ""
+"You ran 'git add' with neither '-A (--all)' or '--ignore-removal',\n"
+"whose behaviour will change in Git 2.0 with respect to paths you removed.\n"
+"Paths like '%s' that are\n"
+"removed from your working tree are ignored with this version of Git.\n"
+"\n"
+"* 'git add --ignore-removal <pathspec>', which is the current default,\n"
+"  ignores paths you removed from your working tree.\n"
+"\n"
+"* 'git add --all <pathspec>' will let you also record the removals.\n"
+"\n"
+"Run 'git status' to check the paths you removed from your working tree.\n"
+msgstr ""
+"您在运行 'git add' 时没有指定 '-A (--all)' 或 '--ignore-removal',\n"
+"针对其中本地移除路径的行为将在 Git 2.0 版本库发生变化。\n"
+"像本地工作区移除的路径 '%s'\n"
+"在此版本的 Git 中被忽略。\n"
+"\n"
+"* 'git add --ignore-removal <pathspec>',是当前版本的默认操作,\n"
+"  忽略您本地工作区中移除的文件。\n"
+"\n"
+"* 'git add --all <pathspec>' 将让您同时对删除操作进行记录。\n"
+"\n"
+"运行 'git status' 来检查您本地工作区中移除的路径。\n"
+
+#: builtin/add.c:144
+#, c-format
+msgid "unexpected diff status %c"
+msgstr "意外的差异状态 %c"
+
+#: builtin/add.c:149 builtin/commit.c:252
+msgid "updating files failed"
+msgstr "更新文件失败"
+
+#: builtin/add.c:163
+#, c-format
+msgid "remove '%s'\n"
+msgstr "删除 '%s'\n"
+
+#: builtin/add.c:253
+msgid "Unstaged changes after refreshing the index:"
+msgstr "刷新索引之后尚未被暂存的变更:"
+
+#: builtin/add.c:256 builtin/add.c:573 builtin/rm.c:337
+#, c-format
+msgid "pathspec '%s' did not match any files"
+msgstr "路径 '%s' 未匹配任何文件"
+
+#: builtin/add.c:339
+msgid "Could not read the index"
+msgstr "不能读取索引"
+
+#: builtin/add.c:350
+#, c-format
+msgid "Could not open '%s' for writing."
+msgstr "不能打开 '%s' 以写入。"
+
+#: builtin/add.c:354
+msgid "Could not write patch"
+msgstr "不能生成补丁"
+
+#: builtin/add.c:359
+#, c-format
+msgid "Could not stat '%s'"
+msgstr "不能查看文件状态 '%s'"
+
+#: builtin/add.c:361
+msgid "Empty patch. Aborted."
+msgstr "空补丁。异常终止。"
+
+#: builtin/add.c:367
+#, c-format
+msgid "Could not apply '%s'"
+msgstr "不能应用 '%s'"
+
+#: builtin/add.c:377
+msgid "The following paths are ignored by one of your .gitignore files:\n"
+msgstr "下列路径根据您的一个 .gitignore 文件而被忽略:\n"
+
+#: builtin/add.c:394 builtin/clean.c:875 builtin/fetch.c:78 builtin/mv.c:63
+#: builtin/prune-packed.c:73 builtin/push.c:451 builtin/remote.c:1253
+#: builtin/rm.c:268
+msgid "dry run"
+msgstr "演习"
+
+#: builtin/add.c:395 builtin/apply.c:4410 builtin/check-ignore.c:19
+#: builtin/commit.c:1220 builtin/count-objects.c:95 builtin/fsck.c:613
+#: builtin/log.c:1573 builtin/mv.c:62 builtin/read-tree.c:113
+msgid "be verbose"
+msgstr "冗长输出"
+
+#: builtin/add.c:397
+msgid "interactive picking"
+msgstr "交互式拣选"
+
+#: builtin/add.c:398 builtin/checkout.c:1073 builtin/reset.c:261
+msgid "select hunks interactively"
+msgstr "交互式挑选数据块"
+
+#: builtin/add.c:399
+msgid "edit current diff and apply"
+msgstr "编辑当前差异并应用"
+
+#: builtin/add.c:400
+msgid "allow adding otherwise ignored files"
+msgstr "允许添加忽略的文件"
+
+#: builtin/add.c:401
+msgid "update tracked files"
+msgstr "更新已跟踪的文件"
+
+#: builtin/add.c:402
+msgid "record only the fact that the path will be added later"
+msgstr "只记录,该路径稍后再添加"
+
+#: builtin/add.c:403
+msgid "add changes from all tracked and untracked files"
+msgstr "添加所有改变的已跟踪文件和未跟踪文件"
+
+#. takes no arguments
+#: builtin/add.c:406
+msgid "ignore paths removed in the working tree (same as --no-all)"
+msgstr "忽略工作区中移除的路径(和 --no-all 相同)"
+
+#: builtin/add.c:408
+msgid "don't add, only refresh the index"
+msgstr "不添加,只刷新索引"
+
+#: builtin/add.c:409
+msgid "just skip files which cannot be added because of errors"
+msgstr "跳过因出错不能添加的文件"
+
+#: builtin/add.c:410
+msgid "check if - even missing - files are ignored in dry run"
+msgstr "检查在演习模式下文件(即使不存在)是否被忽略"
+
+#: builtin/add.c:432
+#, c-format
+msgid "Use -f if you really want to add them.\n"
+msgstr "使用 -f 参数如果您确实要添加它们。\n"
+
+#: builtin/add.c:433
+msgid "no files added"
+msgstr "没有文件被添加"
+
+#: builtin/add.c:439
+msgid "adding files failed"
+msgstr "添加文件失败"
+
+#: builtin/add.c:478
 msgid "-A and -u are mutually incompatible"
 msgstr "-A 和 -u 选项互斥"
 
-#: builtin/add.c:383
+#: builtin/add.c:496
 msgid "Option --ignore-missing can only be used together with --dry-run"
 msgstr "选项 --ignore-missing 只能和 --dry-run 同时使用"
 
-#: builtin/add.c:414
+#: builtin/add.c:526
 #, c-format
 msgid "Nothing specified, nothing added.\n"
 msgstr "没有指定文件,也没有文件被添加。\n"
 
-#: builtin/add.c:415
+#: builtin/add.c:527
 #, c-format
 msgid "Maybe you wanted to say 'git add .'?\n"
 msgstr "也许您想要执行 'git add .'?\n"
 
-#: builtin/add.c:421 builtin/check-ignore.c:67 builtin/clean.c:204
-#: builtin/commit.c:293 builtin/mv.c:82 builtin/rm.c:235
+#: builtin/add.c:533 builtin/check-ignore.c:161 builtin/clean.c:919
+#: builtin/commit.c:312 builtin/mv.c:82 builtin/rm.c:297
 msgid "index file corrupt"
 msgstr "索引文件损坏"
 
-#: builtin/add.c:481 builtin/apply.c:4505 builtin/mv.c:229 builtin/rm.c:370
+#: builtin/add.c:605 builtin/apply.c:4506 builtin/mv.c:229 builtin/rm.c:432
 msgid "Unable to write new index file"
 msgstr "无法写入新索引文件"
 
@@ -1908,293 +2107,293 @@
 msgid "cannot checkout %s"
 msgstr "不能检出 %s"
 
-#: builtin/apply.c:3140 builtin/apply.c:3149 builtin/apply.c:3193
+#: builtin/apply.c:3140 builtin/apply.c:3149 builtin/apply.c:3194
 #, c-format
 msgid "read of %s failed"
 msgstr "读取 %s 失败"
 
-#: builtin/apply.c:3173 builtin/apply.c:3395
+#: builtin/apply.c:3174 builtin/apply.c:3396
 #, c-format
 msgid "path %s has been renamed/deleted"
 msgstr "路径 %s 已经被重命名/删除"
 
-#: builtin/apply.c:3254 builtin/apply.c:3409
+#: builtin/apply.c:3255 builtin/apply.c:3410
 #, c-format
 msgid "%s: does not exist in index"
 msgstr "%s:不存在于索引中"
 
-#: builtin/apply.c:3258 builtin/apply.c:3401 builtin/apply.c:3423
+#: builtin/apply.c:3259 builtin/apply.c:3402 builtin/apply.c:3424
 #, c-format
 msgid "%s: %s"
 msgstr "%s:%s"
 
-#: builtin/apply.c:3263 builtin/apply.c:3417
+#: builtin/apply.c:3264 builtin/apply.c:3418
 #, c-format
 msgid "%s: does not match index"
 msgstr "%s:和索引不匹配"
 
-#: builtin/apply.c:3365
+#: builtin/apply.c:3366
 msgid "removal patch leaves file contents"
 msgstr "移除补丁仍留下了文件内容"
 
-#: builtin/apply.c:3434
+#: builtin/apply.c:3435
 #, c-format
 msgid "%s: wrong type"
 msgstr "%s:错误类型"
 
-#: builtin/apply.c:3436
+#: builtin/apply.c:3437
 #, c-format
 msgid "%s has type %o, expected %o"
 msgstr "%s 的类型是 %o,应为 %o"
 
-#: builtin/apply.c:3537
+#: builtin/apply.c:3538
 #, c-format
 msgid "%s: already exists in index"
 msgstr "%s:已经存在于索引中"
 
-#: builtin/apply.c:3540
+#: builtin/apply.c:3541
 #, c-format
 msgid "%s: already exists in working directory"
 msgstr "%s:已经存在于工作区中"
 
-#: builtin/apply.c:3560
+#: builtin/apply.c:3561
 #, c-format
 msgid "new mode (%o) of %s does not match old mode (%o)"
 msgstr "%2$s 的新模式(%1$o)和旧模式(%3$o)不匹配"
 
-#: builtin/apply.c:3565
+#: builtin/apply.c:3566
 #, c-format
 msgid "new mode (%o) of %s does not match old mode (%o) of %s"
 msgstr "%2$s 的新模式(%1$o)和 %4$s 的旧模式(%3$o)不匹配"
 
-#: builtin/apply.c:3573
+#: builtin/apply.c:3574
 #, c-format
 msgid "%s: patch does not apply"
 msgstr "%s:补丁未应用"
 
-#: builtin/apply.c:3586
+#: builtin/apply.c:3587
 #, c-format
 msgid "Checking patch %s..."
 msgstr "检查补丁 %s..."
 
-#: builtin/apply.c:3679 builtin/checkout.c:215 builtin/reset.c:124
+#: builtin/apply.c:3680 builtin/checkout.c:216 builtin/reset.c:127
 #, c-format
 msgid "make_cache_entry failed for path '%s'"
 msgstr "对路径 '%s' 的 make_cache_entry 操作失败"
 
-#: builtin/apply.c:3822
+#: builtin/apply.c:3823
 #, c-format
 msgid "unable to remove %s from index"
 msgstr "不能从索引中移除 %s"
 
-#: builtin/apply.c:3850
+#: builtin/apply.c:3851
 #, c-format
-msgid "corrupt patch for subproject %s"
-msgstr "子项目 %s 损坏的补丁"
+msgid "corrupt patch for submodule %s"
+msgstr "子模组 %s 损坏的补丁"
 
-#: builtin/apply.c:3854
+#: builtin/apply.c:3855
 #, c-format
 msgid "unable to stat newly created file '%s'"
 msgstr "不能枚举新建文件 '%s' 的状态"
 
-#: builtin/apply.c:3859
+#: builtin/apply.c:3860
 #, c-format
 msgid "unable to create backing store for newly created file %s"
 msgstr "不能为新建文件 %s 创建后端存储"
 
-#: builtin/apply.c:3862 builtin/apply.c:3970
+#: builtin/apply.c:3863 builtin/apply.c:3971
 #, c-format
 msgid "unable to add cache entry for %s"
 msgstr "无法为 %s 添加缓存条目"
 
-#: builtin/apply.c:3895
+#: builtin/apply.c:3896
 #, c-format
 msgid "closing file '%s'"
 msgstr "关闭文件 '%s'"
 
-#: builtin/apply.c:3944
+#: builtin/apply.c:3945
 #, c-format
 msgid "unable to write file '%s' mode %o"
 msgstr "不能写文件 '%s' 权限 %o"
 
-#: builtin/apply.c:4031
+#: builtin/apply.c:4032
 #, c-format
 msgid "Applied patch %s cleanly."
 msgstr "成功应用补丁 %s。"
 
-#: builtin/apply.c:4039
+#: builtin/apply.c:4040
 msgid "internal error"
 msgstr "内部错误"
 
 #. Say this even without --verbose
-#: builtin/apply.c:4042
+#: builtin/apply.c:4043
 #, c-format
 msgid "Applying patch %%s with %d reject..."
 msgid_plural "Applying patch %%s with %d rejects..."
 msgstr[0] "应用 %%s 个补丁,其中 %d 个被拒绝..."
 msgstr[1] "应用 %%s 个补丁,其中 %d 个被拒绝..."
 
-#: builtin/apply.c:4052
+#: builtin/apply.c:4053
 #, c-format
 msgid "truncating .rej filename to %.*s.rej"
 msgstr "截短 .rej 文件名为 %.*s.rej"
 
-#: builtin/apply.c:4073
+#: builtin/apply.c:4074
 #, c-format
 msgid "Hunk #%d applied cleanly."
 msgstr "第 #%d 个片段成功应用。"
 
-#: builtin/apply.c:4076
+#: builtin/apply.c:4077
 #, c-format
 msgid "Rejected hunk #%d."
 msgstr "拒绝第 #%d 个片段。"
 
-#: builtin/apply.c:4226
+#: builtin/apply.c:4227
 msgid "unrecognized input"
 msgstr "未能识别的输入"
 
-#: builtin/apply.c:4237
+#: builtin/apply.c:4238
 msgid "unable to read index file"
 msgstr "无法读取索引文件"
 
-#: builtin/apply.c:4356 builtin/apply.c:4359 builtin/clone.c:92
+#: builtin/apply.c:4357 builtin/apply.c:4360 builtin/clone.c:91
 #: builtin/fetch.c:63
 msgid "path"
 msgstr "路径"
 
-#: builtin/apply.c:4357
+#: builtin/apply.c:4358
 msgid "don't apply changes matching the given path"
 msgstr "不要应用与给出路径向匹配的变更"
 
-#: builtin/apply.c:4360
+#: builtin/apply.c:4361
 msgid "apply changes matching the given path"
 msgstr "应用与给出路径向匹配的变更"
 
-#: builtin/apply.c:4362
+#: builtin/apply.c:4363
 msgid "num"
 msgstr "数字"
 
-#: builtin/apply.c:4363
+#: builtin/apply.c:4364
 msgid "remove <num> leading slashes from traditional diff paths"
 msgstr "从传统的 diff 路径中移除指定数量的前导斜线"
 
-#: builtin/apply.c:4366
+#: builtin/apply.c:4367
 msgid "ignore additions made by the patch"
 msgstr "忽略补丁中的添加的文件"
 
-#: builtin/apply.c:4368
+#: builtin/apply.c:4369
 msgid "instead of applying the patch, output diffstat for the input"
 msgstr "不应用补丁,而是显示输入的差异统计(diffstat)"
 
-#: builtin/apply.c:4372
+#: builtin/apply.c:4373
 msgid "show number of added and deleted lines in decimal notation"
 msgstr "以十进制数显示添加和删除的行数"
 
-#: builtin/apply.c:4374
+#: builtin/apply.c:4375
 msgid "instead of applying the patch, output a summary for the input"
 msgstr "不应用补丁,而是显示输入的概要"
 
-#: builtin/apply.c:4376
+#: builtin/apply.c:4377
 msgid "instead of applying the patch, see if the patch is applicable"
 msgstr "不应用补丁,而是查看补丁是否可应用"
 
-#: builtin/apply.c:4378
+#: builtin/apply.c:4379
 msgid "make sure the patch is applicable to the current index"
 msgstr "确认补丁可以应用到当前索引"
 
-#: builtin/apply.c:4380
+#: builtin/apply.c:4381
 msgid "apply a patch without touching the working tree"
 msgstr "应用补丁而不修改工作区"
 
-#: builtin/apply.c:4382
+#: builtin/apply.c:4383
 msgid "also apply the patch (use with --stat/--summary/--check)"
 msgstr "还应用此补丁(与 --stat/--summary/--check 选项同时使用)"
 
-#: builtin/apply.c:4384
+#: builtin/apply.c:4385
 msgid "attempt three-way merge if a patch does not apply"
 msgstr "如果一个补丁不能应用则尝试三路合并"
 
-#: builtin/apply.c:4386
+#: builtin/apply.c:4387
 msgid "build a temporary index based on embedded index information"
 msgstr "创建一个临时索引基于嵌入的索引信息"
 
-#: builtin/apply.c:4388 builtin/checkout-index.c:197 builtin/ls-files.c:463
+#: builtin/apply.c:4389 builtin/checkout-index.c:197 builtin/ls-files.c:462
 msgid "paths are separated with NUL character"
 msgstr "路径以 NUL 字符分隔"
 
-#: builtin/apply.c:4391
+#: builtin/apply.c:4392
 msgid "ensure at least <n> lines of context match"
 msgstr "确保至少匹配 <n> 行上下文"
 
-#: builtin/apply.c:4392
+#: builtin/apply.c:4393
 msgid "action"
 msgstr "动作"
 
-#: builtin/apply.c:4393
+#: builtin/apply.c:4394
 msgid "detect new or modified lines that have whitespace errors"
 msgstr "检查新增和修改的行中间的空白字符滥用"
 
-#: builtin/apply.c:4396 builtin/apply.c:4399
+#: builtin/apply.c:4397 builtin/apply.c:4400
 msgid "ignore changes in whitespace when finding context"
 msgstr "查找上下文时忽略空白字符的变更"
 
-#: builtin/apply.c:4402
+#: builtin/apply.c:4403
 msgid "apply the patch in reverse"
 msgstr "反向应用补丁"
 
-#: builtin/apply.c:4404
+#: builtin/apply.c:4405
 msgid "don't expect at least one line of context"
 msgstr "无需至少一行上下文"
 
-#: builtin/apply.c:4406
+#: builtin/apply.c:4407
 msgid "leave the rejected hunks in corresponding *.rej files"
 msgstr "将拒绝的补丁片段保存在对应的 *.rej 文件中"
 
-#: builtin/apply.c:4408
+#: builtin/apply.c:4409
 msgid "allow overlapping hunks"
 msgstr "允许重叠的补丁片段"
 
-#: builtin/apply.c:4411
+#: builtin/apply.c:4412
 msgid "tolerate incorrectly detected missing new-line at the end of file"
 msgstr "允许不正确的文件末尾换行符"
 
-#: builtin/apply.c:4414
+#: builtin/apply.c:4415
 msgid "do not trust the line counts in the hunk headers"
 msgstr "不信任补丁片段的头信息中的行号"
 
-#: builtin/apply.c:4416
+#: builtin/apply.c:4417
 msgid "root"
 msgstr "根目录"
 
-#: builtin/apply.c:4417
+#: builtin/apply.c:4418
 msgid "prepend <root> to all filenames"
 msgstr "为所有文件名前添加 <根目录>"
 
-#: builtin/apply.c:4439
+#: builtin/apply.c:4440
 msgid "--3way outside a repository"
 msgstr "--3way 在一个版本库之外"
 
-#: builtin/apply.c:4447
+#: builtin/apply.c:4448
 msgid "--index outside a repository"
 msgstr "--index 在一个版本库之外"
 
-#: builtin/apply.c:4450
+#: builtin/apply.c:4451
 msgid "--cached outside a repository"
 msgstr "--cached 在一个版本库之外"
 
-#: builtin/apply.c:4466
+#: builtin/apply.c:4467
 #, c-format
 msgid "can't open patch '%s'"
 msgstr "不能打开补丁 '%s'"
 
-#: builtin/apply.c:4480
+#: builtin/apply.c:4481
 #, c-format
 msgid "squelched %d whitespace error"
 msgid_plural "squelched %d whitespace errors"
 msgstr[0] "抑制下仍有 %d 个空白字符误用"
 msgstr[1] "抑制下仍有 %d 个空白字符误用"
 
-#: builtin/apply.c:4486 builtin/apply.c:4496
+#: builtin/apply.c:4487 builtin/apply.c:4497
 #, c-format
 msgid "%d line adds whitespace errors."
 msgid_plural "%d lines add whitespace errors."
@@ -2248,103 +2447,103 @@
 msgid "update BISECT_HEAD instead of checking out the current commit"
 msgstr "更新 BISECT_HEAD 而非检出当前提交"
 
-#: builtin/blame.c:25
+#: builtin/blame.c:26
 msgid "git blame [options] [rev-opts] [rev] [--] file"
 msgstr "git blame [选项] [版本选项] [版本] [--] 文件"
 
-#: builtin/blame.c:30 builtin/shortlog.c:15
+#: builtin/blame.c:31
 msgid "[rev-opts] are documented in git-rev-list(1)"
 msgstr "[版本选项] 的文档记录在 git-rev-list(1) 中"
 
-#: builtin/blame.c:2350
+#: builtin/blame.c:2276
 msgid "Show blame entries as we find them, incrementally"
 msgstr "增量式地显示发现的 blame 条目"
 
-#: builtin/blame.c:2351
+#: builtin/blame.c:2277
 msgid "Show blank SHA-1 for boundary commits (Default: off)"
 msgstr "边界提交显示空的 SHA-1(默认:关闭)"
 
-#: builtin/blame.c:2352
+#: builtin/blame.c:2278
 msgid "Do not treat root commits as boundaries (Default: off)"
 msgstr "不把根提交作为边界(默认:关闭)"
 
-#: builtin/blame.c:2353
+#: builtin/blame.c:2279
 msgid "Show work cost statistics"
 msgstr "显示命令消耗统计"
 
-#: builtin/blame.c:2354
+#: builtin/blame.c:2280
 msgid "Show output score for blame entries"
 msgstr "显示判断 blame 条目位移的得分诊断信息"
 
-#: builtin/blame.c:2355
+#: builtin/blame.c:2281
 msgid "Show original filename (Default: auto)"
 msgstr "显示原始文件名(默认:自动)"
 
-#: builtin/blame.c:2356
+#: builtin/blame.c:2282
 msgid "Show original linenumber (Default: off)"
 msgstr "显示原始的行号(默认:关闭)"
 
-#: builtin/blame.c:2357
+#: builtin/blame.c:2283
 msgid "Show in a format designed for machine consumption"
 msgstr "显示为一个适合机器读取的格式"
 
-#: builtin/blame.c:2358
+#: builtin/blame.c:2284
 msgid "Show porcelain format with per-line commit information"
 msgstr "为每一行显示机器适用的提交信息"
 
-#: builtin/blame.c:2359
+#: builtin/blame.c:2285
 msgid "Use the same output mode as git-annotate (Default: off)"
 msgstr "使用和 git-annotate 相同的输出模式(默认:关闭)"
 
-#: builtin/blame.c:2360
+#: builtin/blame.c:2286
 msgid "Show raw timestamp (Default: off)"
 msgstr "显示原始时间戳(默认:关闭)"
 
-#: builtin/blame.c:2361
+#: builtin/blame.c:2287
 msgid "Show long commit SHA1 (Default: off)"
 msgstr "显示长的SHA1提交号(默认:关闭)"
 
-#: builtin/blame.c:2362
+#: builtin/blame.c:2288
 msgid "Suppress author name and timestamp (Default: off)"
 msgstr "隐藏作者名字和时间戳(默认:关闭)"
 
-#: builtin/blame.c:2363
+#: builtin/blame.c:2289
 msgid "Show author email instead of name (Default: off)"
 msgstr "显示作者的邮箱而不是名字(默认:关闭)"
 
-#: builtin/blame.c:2364
+#: builtin/blame.c:2290
 msgid "Ignore whitespace differences"
 msgstr "忽略空白差异"
 
-#: builtin/blame.c:2365
+#: builtin/blame.c:2291
 msgid "Spend extra cycles to find better match"
 msgstr "花费额外的循环来找到更好的匹配"
 
-#: builtin/blame.c:2366
+#: builtin/blame.c:2292
 msgid "Use revisions from <file> instead of calling git-rev-list"
 msgstr "使用来自 <file> 的修订集而不是调用 git-rev-list"
 
-#: builtin/blame.c:2367
+#: builtin/blame.c:2293
 msgid "Use <file>'s contents as the final image"
 msgstr "使用 <file> 的内容作为最终的图片"
 
-#: builtin/blame.c:2368 builtin/blame.c:2369
+#: builtin/blame.c:2294 builtin/blame.c:2295
 msgid "score"
 msgstr "得分"
 
-#: builtin/blame.c:2368
+#: builtin/blame.c:2294
 msgid "Find line copies within and across files"
 msgstr "找到文件内及跨文件的行拷贝"
 
-#: builtin/blame.c:2369
+#: builtin/blame.c:2295
 msgid "Find line movements within and across files"
 msgstr "找到文件内及跨文件的行移动"
 
-#: builtin/blame.c:2370
+#: builtin/blame.c:2296
 msgid "n,m"
 msgstr "n,m"
 
-#: builtin/blame.c:2370
+#: builtin/blame.c:2296
 msgid "Process only line range n,m, counting from 1"
 msgstr "只处理行范围在 n 和 m 之间的,从 1 开始"
 
@@ -2365,7 +2564,7 @@
 msgstr "git branch [选项] (-m | -M) [<旧分支>] <新分支>"
 
 #  译者:保持原换行格式,在输出时 %s 的替代内容会让字符串变长
-#: builtin/branch.c:146
+#: builtin/branch.c:150
 #, c-format
 msgid ""
 "deleting branch '%s' that has been merged to\n"
@@ -2375,7 +2574,7 @@
 "         '%s',但未合并到 HEAD。"
 
 #  译者:保持原换行格式,在输出时 %s 的替代内容会让字符串变长
-#: builtin/branch.c:150
+#: builtin/branch.c:154
 #, c-format
 msgid ""
 "not deleting branch '%s' that is not yet merged to\n"
@@ -2384,12 +2583,12 @@
 "并未删除分支 '%s', 虽然它已经合并到 HEAD,\n"
 "         然而却尚未被合并到分支 '%s' 。"
 
-#: builtin/branch.c:164
+#: builtin/branch.c:168
 #, c-format
 msgid "Couldn't look up commit object for '%s'"
 msgstr "无法查询 '%s' 指向的提交对象"
 
-#: builtin/branch.c:168
+#: builtin/branch.c:172
 #, c-format
 msgid ""
 "The branch '%s' is not fully merged.\n"
@@ -2398,327 +2597,327 @@
 "分支 '%s' 没有完全合并。\n"
 "如果您确认要删除它,执行 'git branch -D %s'。"
 
-#: builtin/branch.c:181
+#: builtin/branch.c:185
 msgid "Update of config-file failed"
 msgstr "无法更新 config 文件"
 
-#: builtin/branch.c:209
+#: builtin/branch.c:213
 msgid "cannot use -a with -d"
 msgstr "不能将 -a 和 -d 同时使用"
 
-#: builtin/branch.c:215
+#: builtin/branch.c:219
 msgid "Couldn't look up commit object for HEAD"
 msgstr "无法查询 HEAD 指向的提交对象"
 
-#: builtin/branch.c:223
+#: builtin/branch.c:227
 #, c-format
 msgid "Cannot delete the branch '%s' which you are currently on."
 msgstr "无法删除您当前所在的分支 '%s'。"
 
-#: builtin/branch.c:236
+#: builtin/branch.c:240
 #, c-format
 msgid "remote branch '%s' not found."
 msgstr "远程分支 '%s' 未发现。"
 
-#: builtin/branch.c:237
+#: builtin/branch.c:241
 #, c-format
 msgid "branch '%s' not found."
 msgstr "分支 '%s' 未发现。"
 
-#: builtin/branch.c:251
+#: builtin/branch.c:255
 #, c-format
 msgid "Error deleting remote branch '%s'"
 msgstr "删除远程分支 '%s' 时出错"
 
-#: builtin/branch.c:252
+#: builtin/branch.c:256
 #, c-format
 msgid "Error deleting branch '%s'"
 msgstr "删除分支 '%s' 时出错"
 
-#: builtin/branch.c:259
+#: builtin/branch.c:263
 #, c-format
 msgid "Deleted remote branch %s (was %s).\n"
 msgstr "已删除远程分支 %s(曾为 %s)。\n"
 
-#: builtin/branch.c:260
+#: builtin/branch.c:264
 #, c-format
 msgid "Deleted branch %s (was %s).\n"
 msgstr "已删除分支 %s(曾为 %s)。\n"
 
-#: builtin/branch.c:362
+#: builtin/branch.c:366
 #, c-format
 msgid "branch '%s' does not point at a commit"
 msgstr "分支 '%s' 未指向一个提交"
 
-#: builtin/branch.c:434
+#: builtin/branch.c:453
 #, c-format
 msgid "[%s: behind %d]"
 msgstr "[%s:落后 %d]"
 
-#: builtin/branch.c:436
+#: builtin/branch.c:455
 #, c-format
 msgid "[behind %d]"
 msgstr "[落后 %d]"
 
-#: builtin/branch.c:440
+#: builtin/branch.c:459
 #, c-format
 msgid "[%s: ahead %d]"
 msgstr "[%s:领先 %d]"
 
-#: builtin/branch.c:442
+#: builtin/branch.c:461
 #, c-format
 msgid "[ahead %d]"
 msgstr "[领先 %d]"
 
-#: builtin/branch.c:445
+#: builtin/branch.c:464
 #, c-format
 msgid "[%s: ahead %d, behind %d]"
 msgstr "[%s:领先 %d,落后 %d]"
 
-#: builtin/branch.c:448
+#: builtin/branch.c:467
 #, c-format
 msgid "[ahead %d, behind %d]"
 msgstr "[领先 %d,落后 %d]"
 
-#: builtin/branch.c:470
+#: builtin/branch.c:490
 msgid " **** invalid ref ****"
 msgstr " **** 无效引用 ****"
 
-#: builtin/branch.c:562
+#: builtin/branch.c:582
 #, c-format
 msgid "(no branch, rebasing %s)"
 msgstr "(非分支,正变基 %s)"
 
-#: builtin/branch.c:565
+#: builtin/branch.c:585
 #, c-format
 msgid "(no branch, bisect started on %s)"
 msgstr "(非分支,二分查找开始于 %s)"
 
-#: builtin/branch.c:568
+#: builtin/branch.c:588
 #, c-format
 msgid "(detached from %s)"
 msgstr "(分离自 %s)"
 
-#: builtin/branch.c:571
+#: builtin/branch.c:591
 msgid "(no branch)"
 msgstr "(非分支)"
 
-#: builtin/branch.c:617
+#: builtin/branch.c:637
 #, c-format
 msgid "object '%s' does not point to a commit"
 msgstr "对象 '%s' 没有指向一个提交"
 
-#: builtin/branch.c:649
+#: builtin/branch.c:669
 msgid "some refs could not be read"
 msgstr "一些引用不能读取"
 
-#: builtin/branch.c:662
+#: builtin/branch.c:682
 msgid "cannot rename the current branch while not on any."
 msgstr "无法重命名当前分支因为不处于任何分支上。"
 
-#: builtin/branch.c:672
+#: builtin/branch.c:692
 #, c-format
 msgid "Invalid branch name: '%s'"
 msgstr "无效的分支名:'%s'"
 
-#: builtin/branch.c:687
+#: builtin/branch.c:707
 msgid "Branch rename failed"
 msgstr "分支重命名失败"
 
-#: builtin/branch.c:691
+#: builtin/branch.c:711
 #, c-format
 msgid "Renamed a misnamed branch '%s' away"
 msgstr "重命名掉一个错误命名的旧分支 '%s'"
 
-#: builtin/branch.c:695
+#: builtin/branch.c:715
 #, c-format
 msgid "Branch renamed to %s, but HEAD is not updated!"
 msgstr "分支重命名为 %s,但 HEAD 没有更新!"
 
-#: builtin/branch.c:702
+#: builtin/branch.c:722
 msgid "Branch is renamed, but update of config-file failed"
 msgstr "分支被重命名,但更新 config 文件失败"
 
-#: builtin/branch.c:717
+#: builtin/branch.c:737
 #, c-format
 msgid "malformed object name %s"
 msgstr "非法的对象名 %s"
 
-#: builtin/branch.c:741
+#: builtin/branch.c:761
 #, c-format
 msgid "could not write branch description template: %s"
 msgstr "不能写分支描述模版:%s"
 
-#: builtin/branch.c:771
+#: builtin/branch.c:791
 msgid "Generic options"
 msgstr "通用选项"
 
-#: builtin/branch.c:773
+#: builtin/branch.c:793
 msgid "show hash and subject, give twice for upstream branch"
 msgstr "显示哈希值和主题,若参数出现两次则显示上游分支"
 
-#: builtin/branch.c:774
+#: builtin/branch.c:794
 msgid "suppress informational messages"
 msgstr "不显示信息"
 
-#: builtin/branch.c:775
+#: builtin/branch.c:795
 msgid "set up tracking mode (see git-pull(1))"
 msgstr "设置跟踪模式(参见 git-pull(1))"
 
-#: builtin/branch.c:777
+#: builtin/branch.c:797
 msgid "change upstream info"
 msgstr "改变上游信息"
 
-#: builtin/branch.c:781
+#: builtin/branch.c:801
 msgid "use colored output"
 msgstr "使用彩色输出"
 
-#: builtin/branch.c:782
+#: builtin/branch.c:802
 msgid "act on remote-tracking branches"
 msgstr "作用于远程跟踪分支"
 
-#: builtin/branch.c:785 builtin/branch.c:791 builtin/branch.c:812
-#: builtin/branch.c:818 builtin/commit.c:1368 builtin/commit.c:1369
-#: builtin/commit.c:1370 builtin/commit.c:1371 builtin/tag.c:468
+#: builtin/branch.c:805 builtin/branch.c:811 builtin/branch.c:832
+#: builtin/branch.c:838 builtin/commit.c:1433 builtin/commit.c:1434
+#: builtin/commit.c:1435 builtin/commit.c:1436 builtin/tag.c:468
 msgid "commit"
 msgstr "提交"
 
-#: builtin/branch.c:786 builtin/branch.c:792
+#: builtin/branch.c:806 builtin/branch.c:812
 msgid "print only branches that contain the commit"
 msgstr "只打印包含该提交的分支"
 
-#: builtin/branch.c:798
+#: builtin/branch.c:818
 msgid "Specific git-branch actions:"
 msgstr "具体的 git-branch 动作:"
 
-#: builtin/branch.c:799
+#: builtin/branch.c:819
 msgid "list both remote-tracking and local branches"
 msgstr "列出远程跟踪及本地分支"
 
-#: builtin/branch.c:801
+#: builtin/branch.c:821
 msgid "delete fully merged branch"
 msgstr "删除完全合并的分支"
 
-#: builtin/branch.c:802
+#: builtin/branch.c:822
 msgid "delete branch (even if not merged)"
 msgstr "删除分支(即使没有合并)"
 
-#: builtin/branch.c:803
+#: builtin/branch.c:823
 msgid "move/rename a branch and its reflog"
 msgstr "移动/重命名一个分支,以及它的引用日志"
 
-#: builtin/branch.c:804
+#: builtin/branch.c:824
 msgid "move/rename a branch, even if target exists"
 msgstr "移动/重命名一个分支,即使目标已存在"
 
-#: builtin/branch.c:805
+#: builtin/branch.c:825
 msgid "list branch names"
 msgstr "列出分支名"
 
-#: builtin/branch.c:806
+#: builtin/branch.c:826
 msgid "create the branch's reflog"
 msgstr "创建分支的引用日志"
 
-#: builtin/branch.c:808
+#: builtin/branch.c:828
 msgid "edit the description for the branch"
 msgstr "标记分支的描述"
 
-#: builtin/branch.c:809
+#: builtin/branch.c:829
 msgid "force creation (when already exists)"
 msgstr "强制创建(当已经存在)"
 
-#: builtin/branch.c:812
+#: builtin/branch.c:832
 msgid "print only not merged branches"
 msgstr "只打印没有合并的分支"
 
-#: builtin/branch.c:818
+#: builtin/branch.c:838
 msgid "print only merged branches"
 msgstr "只打印合并的分支"
 
-#: builtin/branch.c:822
+#: builtin/branch.c:842
 msgid "list branches in columns"
 msgstr "以列的方式显示分支"
 
-#: builtin/branch.c:835
+#: builtin/branch.c:855
 msgid "Failed to resolve HEAD as a valid ref."
 msgstr "无法将 HEAD 解析为有效引用。"
 
-#: builtin/branch.c:840 builtin/clone.c:609
+#: builtin/branch.c:860 builtin/clone.c:630
 msgid "HEAD not found below refs/heads!"
 msgstr "HEAD 没有位于 /refs/heads 之下!"
 
-#: builtin/branch.c:863
+#: builtin/branch.c:883
 msgid "--column and --verbose are incompatible"
 msgstr "--column 和 --verbose 不兼容"
 
-#: builtin/branch.c:869 builtin/branch.c:908
+#: builtin/branch.c:889 builtin/branch.c:928
 msgid "branch name required"
 msgstr "必须提供分支名"
 
-#: builtin/branch.c:884
+#: builtin/branch.c:904
 msgid "Cannot give description to detached HEAD"
 msgstr "不能向分离头指针提供描述"
 
-#: builtin/branch.c:889
+#: builtin/branch.c:909
 msgid "cannot edit description of more than one branch"
 msgstr "不能为一个以上的分支编辑描述"
 
-#: builtin/branch.c:896
+#: builtin/branch.c:916
 #, c-format
 msgid "No commit on branch '%s' yet."
 msgstr "分支 '%s' 尚无提交。"
 
-#: builtin/branch.c:899
+#: builtin/branch.c:919
 #, c-format
 msgid "No branch named '%s'."
 msgstr "没有分支 '%s'。"
 
-#: builtin/branch.c:914
+#: builtin/branch.c:934
 msgid "too many branches for a rename operation"
 msgstr "为重命名操作提供了太多的分支名"
 
-#: builtin/branch.c:919
+#: builtin/branch.c:939
 msgid "too many branches to set new upstream"
 msgstr "为设置新上游提供了太多的分支名"
 
-#: builtin/branch.c:923
+#: builtin/branch.c:943
 #, c-format
 msgid ""
 "could not set upstream of HEAD to %s when it does not point to any branch."
 msgstr "无法设置 HEAD 的上游为 %s,因为 HEAD 没有指向任何分支。"
 
-#: builtin/branch.c:926 builtin/branch.c:948 builtin/branch.c:970
+#: builtin/branch.c:946 builtin/branch.c:968 builtin/branch.c:990
 #, c-format
 msgid "no such branch '%s'"
 msgstr "没有此分支 '%s'"
 
-#: builtin/branch.c:930
+#: builtin/branch.c:950
 #, c-format
 msgid "branch '%s' does not exist"
 msgstr "分支 '%s' 不存在"
 
-#: builtin/branch.c:942
+#: builtin/branch.c:962
 msgid "too many branches to unset upstream"
 msgstr "为取消上游设置操作提供了太多的分支名"
 
-#: builtin/branch.c:946
+#: builtin/branch.c:966
 msgid "could not unset upstream of HEAD when it does not point to any branch."
 msgstr "无法取消 HEAD 的上游设置因为它没有指向一个分支"
 
-#: builtin/branch.c:952
+#: builtin/branch.c:972
 #, c-format
 msgid "Branch '%s' has no upstream information"
 msgstr "分支 '%s' 没有上游信息"
 
-#: builtin/branch.c:967
+#: builtin/branch.c:987
 msgid "it does not make sense to create 'HEAD' manually"
 msgstr "手工创建 'HEAD' 没有意义"
 
-#: builtin/branch.c:973
+#: builtin/branch.c:993
 msgid "-a and -r options to 'git branch' do not make sense with a branch name"
 msgstr "'git branch' 的 -a 和 -r 选项带一个分支名参数没有意义"
 
-#: builtin/branch.c:976
+#: builtin/branch.c:996
 #, c-format
 msgid ""
 "The --set-upstream flag is deprecated and will be removed. Consider using --"
@@ -2726,7 +2925,7 @@
 msgstr ""
 "选项 --set-upstream 已弃用并将被移除。考虑使用 --track 或 --set-upstream-to\n"
 
-#: builtin/branch.c:993
+#: builtin/branch.c:1013
 #, c-format
 msgid ""
 "\n"
@@ -2737,12 +2936,12 @@
 "如果你想用 '%s' 跟踪 '%s', 这么做:\n"
 "\n"
 
-#: builtin/branch.c:994
+#: builtin/branch.c:1014
 #, c-format
 msgid "    git branch -d %s\n"
 msgstr "    git branch -d %s\n"
 
-#: builtin/branch.c:995
+#: builtin/branch.c:1015
 #, c-format
 msgid "    git branch --set-upstream-to %s\n"
 msgstr "    git branch --set-upstream-to %s\n"
@@ -2760,43 +2959,43 @@
 msgid "Need a repository to unbundle."
 msgstr "需要一个版本库来解包。"
 
-#: builtin/cat-file.c:247
+#: builtin/cat-file.c:285
 msgid "git cat-file (-t|-s|-e|-p|<type>|--textconv) <object>"
 msgstr "git cat-file (-t|-s|-e|-p|<类型>|--textconv) <对象>"
 
-#: builtin/cat-file.c:248
+#: builtin/cat-file.c:286
 msgid "git cat-file (--batch|--batch-check) < <list_of_objects>"
 msgstr "git cat-file (--batch|--batch-check) < <对象列表>"
 
-#: builtin/cat-file.c:266
+#: builtin/cat-file.c:323
 msgid "<type> can be one of: blob, tree, commit, tag"
 msgstr "<类型> 可以是其中之一:blob、tree、commit、tag"
 
-#: builtin/cat-file.c:267
+#: builtin/cat-file.c:324
 msgid "show object type"
 msgstr "显示对象类型"
 
-#: builtin/cat-file.c:268
+#: builtin/cat-file.c:325
 msgid "show object size"
 msgstr "显示对象大小"
 
-#: builtin/cat-file.c:270
+#: builtin/cat-file.c:327
 msgid "exit with zero when there's no error"
 msgstr "当没有错误时退出并返回零"
 
-#: builtin/cat-file.c:271
+#: builtin/cat-file.c:328
 msgid "pretty-print object's content"
 msgstr "美观地打印对象的内容"
 
-#: builtin/cat-file.c:273
+#: builtin/cat-file.c:330
 msgid "for blob objects, run textconv on object's content"
 msgstr "对于数据(blob)对象,对其内容执行 textconv"
 
-#: builtin/cat-file.c:275
+#: builtin/cat-file.c:332
 msgid "show info and content of objects fed from the standard input"
 msgstr "显示从标准输入提供的对象的信息和内容"
 
-#: builtin/cat-file.c:278
+#: builtin/cat-file.c:335
 msgid "show info about objects fed from the standard input"
 msgstr "显示从标准输入提供的对象的信息"
 
@@ -2824,30 +3023,55 @@
 msgid "input paths are terminated by a null character"
 msgstr "输入路径以null字符终止"
 
-#: builtin/check-ignore.c:18 builtin/checkout.c:1041 builtin/gc.c:177
+#: builtin/check-ignore.c:18 builtin/checkout.c:1054 builtin/gc.c:177
 msgid "suppress progress reporting"
 msgstr "不显示进度报告"
 
-#: builtin/check-ignore.c:151
+#: builtin/check-ignore.c:26
+msgid "show non-matching input paths"
+msgstr "显示未匹配的输入路径"
+
+#: builtin/check-ignore.c:143
 msgid "cannot specify pathnames with --stdin"
 msgstr "不能同时提供路径及 --stdin 参数"
 
-#: builtin/check-ignore.c:154
+#: builtin/check-ignore.c:146
 msgid "-z only makes sense with --stdin"
 msgstr "-z 需要和 --stdin 参数共用才有意义"
 
-#: builtin/check-ignore.c:156
+#: builtin/check-ignore.c:148
 msgid "no path specified"
 msgstr "未指定路径"
 
-#: builtin/check-ignore.c:160
+#: builtin/check-ignore.c:152
 msgid "--quiet is only valid with a single pathname"
 msgstr "参数 --quiet 只在提供一个路径名时有效"
 
-#: builtin/check-ignore.c:162
+#: builtin/check-ignore.c:154
 msgid "cannot have both --quiet and --verbose"
 msgstr "不能同时提供 --quiet 和 --verbose 参数"
 
+#: builtin/check-ignore.c:157
+msgid "--non-matching is only valid with --verbose"
+msgstr "--non-matching 选项只在使用 --verbose 时有效"
+
+#: builtin/check-mailmap.c:8
+msgid "git check-mailmap [options] <contact>..."
+msgstr "git check-mailmap [选项] <联系地址>..."
+
+#: builtin/check-mailmap.c:13
+msgid "also read contacts from stdin"
+msgstr "还从标准输入读取联系地址"
+
+#: builtin/check-mailmap.c:24
+#, c-format
+msgid "unable to parse contact: %s"
+msgstr "不能解析联系地址:%s"
+
+#: builtin/check-mailmap.c:47
+msgid "no contacts specified"
+msgstr "未指定联系地址"
+
 #: builtin/checkout-index.c:126
 msgid "git checkout-index [options] [--] [<file>...]"
 msgstr "git checkout-index [选项] [--] [<文件>...]"
@@ -2900,107 +3124,107 @@
 msgid "git checkout [options] [<branch>] -- <file>..."
 msgstr "git checkout [选项] [<分支>] -- <文件>..."
 
-#: builtin/checkout.c:116 builtin/checkout.c:149
+#: builtin/checkout.c:117 builtin/checkout.c:150
 #, c-format
 msgid "path '%s' does not have our version"
 msgstr "路径 '%s' 没有我们的版本"
 
-#: builtin/checkout.c:118 builtin/checkout.c:151
+#: builtin/checkout.c:119 builtin/checkout.c:152
 #, c-format
 msgid "path '%s' does not have their version"
 msgstr "路径 '%s' 没有他们的版本"
 
-#: builtin/checkout.c:134
+#: builtin/checkout.c:135
 #, c-format
 msgid "path '%s' does not have all necessary versions"
 msgstr "路径 '%s' 没有全部必须的版本"
 
-#: builtin/checkout.c:178
+#: builtin/checkout.c:179
 #, c-format
 msgid "path '%s' does not have necessary versions"
 msgstr "路径 '%s' 没有必须的版本"
 
-#: builtin/checkout.c:195
+#: builtin/checkout.c:196
 #, c-format
 msgid "path '%s': cannot merge"
 msgstr "path '%s':无法合并"
 
-#: builtin/checkout.c:212
+#: builtin/checkout.c:213
 #, c-format
 msgid "Unable to add merge result for '%s'"
 msgstr "无法为 '%s' 添加合并结果"
 
-#: builtin/checkout.c:236 builtin/checkout.c:239 builtin/checkout.c:242
-#: builtin/checkout.c:245
+#: builtin/checkout.c:237 builtin/checkout.c:240 builtin/checkout.c:243
+#: builtin/checkout.c:246
 #, c-format
 msgid "'%s' cannot be used with updating paths"
 msgstr "'%s' 不能在更新路径时使用"
 
-#: builtin/checkout.c:248 builtin/checkout.c:251
+#: builtin/checkout.c:249 builtin/checkout.c:252
 #, c-format
 msgid "'%s' cannot be used with %s"
 msgstr "'%s' 不能和 %s 同时使用"
 
-#: builtin/checkout.c:254
+#: builtin/checkout.c:255
 #, c-format
 msgid "Cannot update paths and switch to branch '%s' at the same time."
 msgstr "不能同时更新路径并切换到分支'%s'。"
 
-#: builtin/checkout.c:265 builtin/checkout.c:455
+#: builtin/checkout.c:266 builtin/checkout.c:458
 msgid "corrupt index file"
 msgstr "损坏的索引文件"
 
-#: builtin/checkout.c:326 builtin/checkout.c:333
+#: builtin/checkout.c:329 builtin/checkout.c:336
 #, c-format
 msgid "path '%s' is unmerged"
 msgstr "路径 '%s' 未合并"
 
-#: builtin/checkout.c:477
+#: builtin/checkout.c:480
 msgid "you need to resolve your current index first"
 msgstr "您需要先解决当前索引的冲突"
 
-#: builtin/checkout.c:598
+#: builtin/checkout.c:601
 #, c-format
 msgid "Can not do reflog for '%s'\n"
 msgstr "不能对 '%s' 执行 reflog 操作\n"
 
-#: builtin/checkout.c:631
+#: builtin/checkout.c:639
 msgid "HEAD is now at"
 msgstr "HEAD 目前位于"
 
-#: builtin/checkout.c:638
+#: builtin/checkout.c:646
 #, c-format
 msgid "Reset branch '%s'\n"
 msgstr "重置分支 '%s'\n"
 
-#: builtin/checkout.c:641
+#: builtin/checkout.c:649
 #, c-format
 msgid "Already on '%s'\n"
 msgstr "已经位于 '%s'\n"
 
-#: builtin/checkout.c:645
+#: builtin/checkout.c:653
 #, c-format
 msgid "Switched to and reset branch '%s'\n"
 msgstr "切换并重置分支 '%s'\n"
 
-#: builtin/checkout.c:647 builtin/checkout.c:984
+#: builtin/checkout.c:655 builtin/checkout.c:997
 #, c-format
 msgid "Switched to a new branch '%s'\n"
 msgstr "切换到一个新分支 '%s'\n"
 
-#: builtin/checkout.c:649
+#: builtin/checkout.c:657
 #, c-format
 msgid "Switched to branch '%s'\n"
 msgstr "切换到分支 '%s'\n"
 
 #  译者:注意保持前导空格
-#: builtin/checkout.c:705
+#: builtin/checkout.c:713
 #, c-format
 msgid " ... and %d more.\n"
 msgstr " ... 及其它 %d 个。\n"
 
 #. The singular version
-#: builtin/checkout.c:711
+#: builtin/checkout.c:719
 #, c-format
 msgid ""
 "Warning: you are leaving %d commit behind, not connected to\n"
@@ -3021,7 +3245,7 @@
 "\n"
 "%s\n"
 
-#: builtin/checkout.c:729
+#: builtin/checkout.c:737
 #, c-format
 msgid ""
 "If you want to keep them by creating a new branch, this may be a good time\n"
@@ -3036,132 +3260,136 @@
 " git branch new_branch_name %s\n"
 "\n"
 
-#: builtin/checkout.c:759
+#: builtin/checkout.c:767
 msgid "internal error in revision walk"
 msgstr "在版本遍历时遇到内部错误"
 
-#: builtin/checkout.c:763
+#: builtin/checkout.c:771
 msgid "Previous HEAD position was"
 msgstr "之前的 HEAD 位置是"
 
-#: builtin/checkout.c:790 builtin/checkout.c:979
+#: builtin/checkout.c:798 builtin/checkout.c:992
 msgid "You are on a branch yet to be born"
 msgstr "您位于一个尚未初始化的分支"
 
 #. case (1)
-#: builtin/checkout.c:915
+#: builtin/checkout.c:928
 #, c-format
 msgid "invalid reference: %s"
 msgstr "无效引用:%s"
 
 #. case (1): want a tree
-#: builtin/checkout.c:954
+#: builtin/checkout.c:967
 #, c-format
 msgid "reference is not a tree: %s"
 msgstr "引用不是一个树:%s"
 
-#: builtin/checkout.c:993
+#: builtin/checkout.c:1006
 msgid "paths cannot be used with switching branches"
 msgstr "路径不能和切换分支同时使用"
 
-#: builtin/checkout.c:996 builtin/checkout.c:1000
+#: builtin/checkout.c:1009 builtin/checkout.c:1013
 #, c-format
 msgid "'%s' cannot be used with switching branches"
 msgstr "'%s' 不能和切换分支同时使用"
 
-#: builtin/checkout.c:1004 builtin/checkout.c:1007 builtin/checkout.c:1012
-#: builtin/checkout.c:1015
+#: builtin/checkout.c:1017 builtin/checkout.c:1020 builtin/checkout.c:1025
+#: builtin/checkout.c:1028
 #, c-format
 msgid "'%s' cannot be used with '%s'"
 msgstr "'%s' 不能和 '%s' 同时使用"
 
-#: builtin/checkout.c:1020
+#: builtin/checkout.c:1033
 #, c-format
 msgid "Cannot switch branch to a non-commit '%s'"
 msgstr "不能切换分支到一个非提交 '%s'"
 
-#: builtin/checkout.c:1042 builtin/checkout.c:1044 builtin/clone.c:90
+#: builtin/checkout.c:1055 builtin/checkout.c:1057 builtin/clone.c:89
 #: builtin/remote.c:169 builtin/remote.c:171
 msgid "branch"
 msgstr "分支"
 
-#: builtin/checkout.c:1043
+#: builtin/checkout.c:1056
 msgid "create and checkout a new branch"
 msgstr "创建并检出一个新的分支"
 
-#: builtin/checkout.c:1045
+#: builtin/checkout.c:1058
 msgid "create/reset and checkout a branch"
 msgstr "创建/重置并检出一个分支"
 
-#: builtin/checkout.c:1046
+#: builtin/checkout.c:1059
 msgid "create reflog for new branch"
 msgstr "为新的分支创建引用日志"
 
-#: builtin/checkout.c:1047
+#: builtin/checkout.c:1060
 msgid "detach the HEAD at named commit"
 msgstr "成为指向该提交的分离头指针"
 
-#: builtin/checkout.c:1048
+#: builtin/checkout.c:1061
 msgid "set upstream info for new branch"
 msgstr "为新的分支设置上游信息"
 
-#: builtin/checkout.c:1050
+#: builtin/checkout.c:1063
 msgid "new branch"
 msgstr "新分支"
 
-#: builtin/checkout.c:1050
+#: builtin/checkout.c:1063
 msgid "new unparented branch"
 msgstr "新的没有父提交的分支"
 
-#: builtin/checkout.c:1051
+#: builtin/checkout.c:1064
 msgid "checkout our version for unmerged files"
 msgstr "对尚未合并的文件检出我们的版本"
 
-#: builtin/checkout.c:1053
+#: builtin/checkout.c:1066
 msgid "checkout their version for unmerged files"
 msgstr "对尚未合并的文件检出他们的版本"
 
-#: builtin/checkout.c:1055
+#: builtin/checkout.c:1068
 msgid "force checkout (throw away local modifications)"
 msgstr "强制检出(丢弃本地修改)"
 
-#: builtin/checkout.c:1056
+#: builtin/checkout.c:1069
 msgid "perform a 3-way merge with the new branch"
 msgstr "和新的分支执行三路合并"
 
-#: builtin/checkout.c:1057 builtin/merge.c:217
+#: builtin/checkout.c:1070 builtin/merge.c:232
 msgid "update ignored files (default)"
 msgstr "更新忽略的文件(默认)"
 
-#: builtin/checkout.c:1058 builtin/log.c:1149 parse-options.h:245
+#: builtin/checkout.c:1071 builtin/log.c:1208 parse-options.h:249
 msgid "style"
 msgstr "风格"
 
-#: builtin/checkout.c:1059
+#: builtin/checkout.c:1072
 msgid "conflict style (merge or diff3)"
 msgstr "冲突输出风格(merge 或 diff3)"
 
-#: builtin/checkout.c:1062
+#: builtin/checkout.c:1075
+msgid "do not limit pathspecs to sparse entries only"
+msgstr "对路径不做稀疏检出的限制"
+
+#: builtin/checkout.c:1077
 msgid "second guess 'git checkout no-such-branch'"
 msgstr "再者猜测'git checkout no-such-branch'"
 
-#: builtin/checkout.c:1086
+#: builtin/checkout.c:1101
 msgid "-b, -B and --orphan are mutually exclusive"
 msgstr "-b、-B 和 --orphan 是互斥的"
 
-#: builtin/checkout.c:1103
+#: builtin/checkout.c:1118
 msgid "--track needs a branch name"
 msgstr "--track 需要一个分支名"
 
-#: builtin/checkout.c:1110
+#: builtin/checkout.c:1125
 msgid "Missing branch name; try -b"
 msgstr "缺少分支名;尝试 -b"
 
-#: builtin/checkout.c:1145
+#: builtin/checkout.c:1160
 msgid "invalid path specification"
 msgstr "无效的路径规格"
 
-#: builtin/checkout.c:1152
+#: builtin/checkout.c:1167
 #, c-format
 msgid ""
 "Cannot update paths and switch to branch '%s' at the same time.\n"
@@ -3170,227 +3398,330 @@
 "不能同时更新路径并切换到分支'%s'。\n"
 "您是想要检出 '%s' 但其未能解析为提交么?"
 
-#: builtin/checkout.c:1157
+#: builtin/checkout.c:1172
 #, c-format
 msgid "git checkout: --detach does not take a path argument '%s'"
 msgstr "git checkout:--detach 不能接收路径参数 '%s'"
 
-#: builtin/checkout.c:1161
+#: builtin/checkout.c:1176
 msgid ""
 "git checkout: --ours/--theirs, --force and --merge are incompatible when\n"
 "checking out of the index."
 msgstr ""
 "git checkout:在从索引检出时,--ours/--theirs、--force 和 --merge 不兼容。"
 
-#: builtin/clean.c:20
-msgid "git clean [-d] [-f] [-n] [-q] [-e <pattern>] [-x | -X] [--] <paths>..."
-msgstr "git clean [-d] [-f] [-n] [-q] [-e <模式>] [-x | -X] [--] <路径>..."
+#: builtin/clean.c:25
+msgid ""
+"git clean [-d] [-f] [-i] [-n] [-q] [-e <pattern>] [-x | -X] [--] <paths>..."
+msgstr ""
+"git clean [-d] [-f] [-i] [-n] [-q] [-e <模式>] [-x | -X] [--] <路径>..."
 
-#: builtin/clean.c:24
+#: builtin/clean.c:29
 #, c-format
 msgid "Removing %s\n"
 msgstr "正删除 %s\n"
 
-#: builtin/clean.c:25
+#: builtin/clean.c:30
 #, c-format
 msgid "Would remove %s\n"
 msgstr "将删除 %s\n"
 
-#: builtin/clean.c:26
+#: builtin/clean.c:31
 #, c-format
 msgid "Skipping repository %s\n"
 msgstr "忽略版本库 %s\n"
 
-#: builtin/clean.c:27
+#: builtin/clean.c:32
 #, c-format
 msgid "Would skip repository %s\n"
 msgstr "将忽略版本库 %s\n"
 
-#: builtin/clean.c:28
+#: builtin/clean.c:33
 #, c-format
 msgid "failed to remove %s"
 msgstr "无法删除 %s"
 
-#: builtin/clean.c:160
+#: builtin/clean.c:293
+msgid ""
+"Prompt help:\n"
+"1          - select a numbered item\n"
+"foo        - select item based on unique prefix\n"
+"           - (empty) select nothing"
+msgstr ""
+"帮助:\n"
+"1          - 通过编号选择一个选项\n"
+"foo        - 通过标题选择一个选项\n"
+"           - (空)什么也不选择"
+
+#: builtin/clean.c:297
+msgid ""
+"Prompt help:\n"
+"1          - select a single item\n"
+"3-5        - select a range of items\n"
+"2-3,6-9    - select multiple ranges\n"
+"foo        - select item based on unique prefix\n"
+"-...       - unselect specified items\n"
+"*          - choose all items\n"
+"           - (empty) finish selecting"
+msgstr ""
+"帮助:\n"
+"1          - 选择一个选项\n"
+"3-5        - 选择一个范围内的所有选项\n"
+"2-3,6-9    - 选择多个范围内的所有选项\n"
+"foo        - 通过标题选择一个选项\n"
+"-...       - 反选特定的选项\n"
+"*          - 选择所有选项\n"
+"           - (空)结束选择"
+
+#: builtin/clean.c:515
+#, c-format
+msgid "Huh (%s)?"
+msgstr "嗯(%s)?"
+
+#: builtin/clean.c:658
+#, c-format
+msgid "Input ignore patterns>> "
+msgstr "输入模版以排除条目>> "
+
+#: builtin/clean.c:695
+#, c-format
+msgid "WARNING: Cannot find items matched by: %s"
+msgstr "警告:无法找到和 %s 匹配的条目"
+
+#: builtin/clean.c:716
+msgid "Select items to delete"
+msgstr "选择要删除的条目"
+
+#: builtin/clean.c:756
+#, c-format
+msgid "remove %s? "
+msgstr "删除 %s?"
+
+#: builtin/clean.c:781
+msgid "Bye."
+msgstr "再见。"
+
+#: builtin/clean.c:789
+msgid ""
+"clean               - start cleaning\n"
+"filter by pattern   - exclude items from deletion\n"
+"select by numbers   - select items to be deleted by numbers\n"
+"ask each            - confirm each deletion (like \"rm -i\")\n"
+"quit                - stop cleaning\n"
+"help                - this screen\n"
+"?                   - help for prompt selection"
+msgstr ""
+"clean               - 开始清理\n"
+"filter by pattern   - 通过模版排除要删除的条目\n"
+"select by numbers   - 通过数字选择要删除的条目\n"
+"ask each            - 针对删除逐一询问(就像 \"rm -i\")\n"
+"quit                - 停止删除并退出\n"
+"help                - 显示本帮助\n"
+"?                   - 显示如何在提示符下选择的帮助"
+
+#: builtin/clean.c:816
+msgid "*** Commands ***"
+msgstr "*** 命令 ***"
+
+#: builtin/clean.c:817
+msgid "What now"
+msgstr "请选择"
+
+#: builtin/clean.c:825
+msgid "Would remove the following item:"
+msgid_plural "Would remove the following items:"
+msgstr[0] "将删除如下条目:"
+msgstr[1] "将删除如下条目:"
+
+#: builtin/clean.c:842
+msgid "No more files to clean, exiting."
+msgstr "没有要清理的文件,退出。"
+
+#: builtin/clean.c:874
 msgid "do not print names of files removed"
 msgstr "不打印删除文件的名称"
 
-#: builtin/clean.c:162
+#: builtin/clean.c:876
 msgid "force"
 msgstr "强制"
 
-#: builtin/clean.c:164
+#: builtin/clean.c:877
+msgid "interactive cleaning"
+msgstr "交互式清除"
+
+#: builtin/clean.c:879
 msgid "remove whole directories"
 msgstr "删除整个目录"
 
-#: builtin/clean.c:165 builtin/describe.c:412 builtin/grep.c:717
-#: builtin/ls-files.c:494 builtin/name-rev.c:231 builtin/show-ref.c:182
+#: builtin/clean.c:880 builtin/describe.c:420 builtin/grep.c:716
+#: builtin/ls-files.c:493 builtin/name-rev.c:315 builtin/show-ref.c:186
 msgid "pattern"
 msgstr "模式"
 
-#: builtin/clean.c:166
+#: builtin/clean.c:881
 msgid "add <pattern> to ignore rules"
 msgstr "添加<模式>到忽略规则"
 
-#: builtin/clean.c:167
+#: builtin/clean.c:882
 msgid "remove ignored files, too"
 msgstr "也删除忽略的文件"
 
-#: builtin/clean.c:169
+#: builtin/clean.c:884
 msgid "remove only ignored files"
 msgstr "只删除忽略的文件"
 
-#: builtin/clean.c:187
+#: builtin/clean.c:902
 msgid "-x and -X cannot be used together"
 msgstr "-x 和 -X 不能同时使用"
 
-#: builtin/clean.c:191
+#: builtin/clean.c:906
 msgid ""
-"clean.requireForce set to true and neither -n nor -f given; refusing to clean"
-msgstr ""
-"clean.requireForce 设置为 true 且未提供 -n 或 -f 选项,拒绝执行清理动作"
-
-#: builtin/clean.c:194
-msgid ""
-"clean.requireForce defaults to true and neither -n nor -f given; refusing to "
+"clean.requireForce set to true and neither -i, -n nor -f given; refusing to "
 "clean"
 msgstr ""
-"clean.requireForce 默认为 true 且未提供 -n 或 -f 选项,拒绝执行清理动作"
+"clean.requireForce 设置为 true 且未提供 -i、-n 或 -f 选项,拒绝执行清理动作"
 
-#: builtin/clone.c:37
+#: builtin/clean.c:909
+msgid ""
+"clean.requireForce defaults to true and neither -i, -n nor -f given; "
+"refusing to clean"
+msgstr ""
+"clean.requireForce 默认为 true 且未提供 -i、-n 或 -f 选项,拒绝执行清理动作"
+
+#: builtin/clone.c:36
 msgid "git clone [options] [--] <repo> [<dir>]"
 msgstr "git clone [选项] [--] <版本库> [<路径>]"
 
-#: builtin/clone.c:65 builtin/fetch.c:82 builtin/merge.c:214
-#: builtin/push.c:436
+#: builtin/clone.c:64 builtin/fetch.c:82 builtin/merge.c:229
+#: builtin/push.c:462
 msgid "force progress reporting"
 msgstr "强制显示进度报告"
 
-#: builtin/clone.c:67
+#: builtin/clone.c:66
 msgid "don't create a checkout"
 msgstr "不创建一个检出"
 
-#: builtin/clone.c:68 builtin/clone.c:70 builtin/init-db.c:488
+#: builtin/clone.c:67 builtin/clone.c:69 builtin/init-db.c:488
 msgid "create a bare repository"
 msgstr "创建一个裸版本库"
 
-#: builtin/clone.c:73
+#: builtin/clone.c:72
 msgid "create a mirror repository (implies bare)"
 msgstr "创建一个镜像版本库(也是裸版本库)"
 
-#: builtin/clone.c:75
+#: builtin/clone.c:74
 msgid "to clone from a local repository"
 msgstr "从本地版本库克隆"
 
-#: builtin/clone.c:77
+#: builtin/clone.c:76
 msgid "don't use local hardlinks, always copy"
 msgstr "不使用本地硬链接,始终复制"
 
-#: builtin/clone.c:79
+#: builtin/clone.c:78
 msgid "setup as shared repository"
 msgstr "设置为共享版本库"
 
-#: builtin/clone.c:81 builtin/clone.c:83
+#: builtin/clone.c:80 builtin/clone.c:82
 msgid "initialize submodules in the clone"
 msgstr "在克隆时初始化子模组"
 
-#: builtin/clone.c:84 builtin/init-db.c:485
+#: builtin/clone.c:83 builtin/init-db.c:485
 msgid "template-directory"
 msgstr "模板目录"
 
-#: builtin/clone.c:85 builtin/init-db.c:486
+#: builtin/clone.c:84 builtin/init-db.c:486
 msgid "directory from which templates will be used"
 msgstr "模板目录将被使用"
 
-#: builtin/clone.c:87
+#: builtin/clone.c:86
 msgid "reference repository"
 msgstr "引用版本库"
 
-#: builtin/clone.c:88 builtin/column.c:26 builtin/merge-file.c:44
+#: builtin/clone.c:87 builtin/column.c:26 builtin/merge-file.c:44
 msgid "name"
 msgstr "名称"
 
-#: builtin/clone.c:89
+#: builtin/clone.c:88
 msgid "use <name> instead of 'origin' to track upstream"
 msgstr "使用<名称>而不是 'origin' 去跟踪上游"
 
-#: builtin/clone.c:91
+#: builtin/clone.c:90
 msgid "checkout <branch> instead of the remote's HEAD"
 msgstr "检出<分支>而不是远程HEAD"
 
-#: builtin/clone.c:93
+#: builtin/clone.c:92
 msgid "path to git-upload-pack on the remote"
 msgstr "远程 git-upload-pack 路径"
 
-#: builtin/clone.c:94 builtin/fetch.c:83 builtin/grep.c:662
+#: builtin/clone.c:93 builtin/fetch.c:83 builtin/grep.c:661
 msgid "depth"
 msgstr "深度"
 
-#: builtin/clone.c:95
+#: builtin/clone.c:94
 msgid "create a shallow clone of that depth"
 msgstr "创建一个指定深度的浅克隆"
 
-#: builtin/clone.c:97
+#: builtin/clone.c:96
 msgid "clone only one branch, HEAD or --branch"
 msgstr "只克隆一个分支、HEAD 或 --branch"
 
-#: builtin/clone.c:98 builtin/init-db.c:494
+#: builtin/clone.c:97 builtin/init-db.c:494
 msgid "gitdir"
 msgstr "git目录"
 
-#: builtin/clone.c:99 builtin/init-db.c:495
+#: builtin/clone.c:98 builtin/init-db.c:495
 msgid "separate git dir from working tree"
 msgstr "git目录和工作区分离"
 
-#: builtin/clone.c:100
+#: builtin/clone.c:99
 msgid "key=value"
 msgstr "key=value"
 
-#: builtin/clone.c:101
+#: builtin/clone.c:100
 msgid "set config inside the new repository"
 msgstr "在新版本库中设置配置信息"
 
-#: builtin/clone.c:244
+#: builtin/clone.c:253
 #, c-format
-msgid "reference repository '%s' is not a local directory."
-msgstr "引用版本库 '%s' 不是一个本地目录。"
+msgid "reference repository '%s' is not a local repository."
+msgstr "引用版本库 '%s' 不是一个本地版本库。"
 
-#: builtin/clone.c:307
+#: builtin/clone.c:316
 #, c-format
 msgid "failed to create directory '%s'"
 msgstr "无法创建目录 '%s'"
 
-#: builtin/clone.c:309 builtin/diff.c:77
+#: builtin/clone.c:318 builtin/diff.c:77
 #, c-format
 msgid "failed to stat '%s'"
 msgstr "无法枚举 '%s' 状态"
 
-#: builtin/clone.c:311
+#: builtin/clone.c:320
 #, c-format
 msgid "%s exists and is not a directory"
 msgstr "%s 存在且不是一个目录"
 
-#: builtin/clone.c:325
+#: builtin/clone.c:334
 #, c-format
 msgid "failed to stat %s\n"
 msgstr "无法枚举 %s 状态\n"
 
-#: builtin/clone.c:347
+#: builtin/clone.c:356
 #, c-format
 msgid "failed to create link '%s'"
 msgstr "无法创建链接 '%s'"
 
-#: builtin/clone.c:351
+#: builtin/clone.c:360
 #, c-format
 msgid "failed to copy file to '%s'"
 msgstr "无法拷贝文件至 '%s'"
 
-#: builtin/clone.c:374
+#: builtin/clone.c:383
 #, c-format
 msgid "done.\n"
 msgstr "完成。\n"
 
-#: builtin/clone.c:387
+#: builtin/clone.c:396
 msgid ""
 "Clone succeeded, but checkout failed.\n"
 "You can inspect what was checked out with 'git status'\n"
@@ -3400,90 +3731,104 @@
 "您可以通过 'git status' 检查哪些已被检出,然后使用命令\n"
 "'git checkout -f HEAD' 重试\n"
 
-#: builtin/clone.c:466
+#: builtin/clone.c:475
 #, c-format
 msgid "Could not find remote branch %s to clone."
 msgstr "不能发现要克隆的远程分支 %s。"
 
-#: builtin/clone.c:540
+#: builtin/clone.c:555
+#, c-format
+msgid "Checking connectivity... "
+msgstr "检查连接... "
+
+#: builtin/clone.c:558
 msgid "remote did not send all necessary objects"
 msgstr "远程没有发送所有必须的对象"
 
-#: builtin/clone.c:600
+#: builtin/clone.c:560
+#, c-format
+msgid "done\n"
+msgstr "完成\n"
+
+#: builtin/clone.c:621
 msgid "remote HEAD refers to nonexistent ref, unable to checkout.\n"
 msgstr "远程 HEAD 指向一个不存在的引用,无法检出。\n"
 
-#: builtin/clone.c:631
+#: builtin/clone.c:652
 msgid "unable to checkout working tree"
 msgstr "不能检出工作区"
 
-#: builtin/clone.c:739
+#: builtin/clone.c:760
 msgid "Too many arguments."
 msgstr "太多参数。"
 
-#: builtin/clone.c:743
+#: builtin/clone.c:764
 msgid "You must specify a repository to clone."
 msgstr "您必须指定一个版本库来克隆。"
 
-#: builtin/clone.c:754
+#: builtin/clone.c:775
 #, c-format
 msgid "--bare and --origin %s options are incompatible."
 msgstr "--bare 和 --origin %s 选项不兼容。"
 
-#: builtin/clone.c:757
+#: builtin/clone.c:778
 msgid "--bare and --separate-git-dir are incompatible."
 msgstr "--bare 和 --separate-git-dir 选项不兼容。"
 
-#: builtin/clone.c:770
+#: builtin/clone.c:791
 #, c-format
 msgid "repository '%s' does not exist"
 msgstr "版本库 '%s' 不存在"
 
-#: builtin/clone.c:775
+#: builtin/clone.c:796
 msgid "--depth is ignored in local clones; use file:// instead."
 msgstr "--depth 在本地克隆被忽略,改为 file:// 协议试试。"
 
-#: builtin/clone.c:785
+#: builtin/clone.c:798
+msgid "--local is ignored"
+msgstr "--local 被忽略"
+
+#: builtin/clone.c:808
 #, c-format
 msgid "destination path '%s' already exists and is not an empty directory."
 msgstr "目标路径 '%s' 已经存在,并且不是一个空目录。"
 
-#: builtin/clone.c:795
+#: builtin/clone.c:818
 #, c-format
 msgid "working tree '%s' already exists."
 msgstr "工作区 '%s' 已经存在。"
 
-#: builtin/clone.c:808 builtin/clone.c:820
+#: builtin/clone.c:831 builtin/clone.c:843
 #, c-format
 msgid "could not create leading directories of '%s'"
 msgstr "不能为 '%s' 创建先导目录"
 
-#: builtin/clone.c:811
+#: builtin/clone.c:834
 #, c-format
 msgid "could not create work tree dir '%s'."
 msgstr "不能为 '%s' 创建工作区目录。"
 
-#: builtin/clone.c:830
+#: builtin/clone.c:853
 #, c-format
 msgid "Cloning into bare repository '%s'...\n"
 msgstr "克隆到裸版本库 '%s'...\n"
 
-#: builtin/clone.c:832
+#: builtin/clone.c:855
 #, c-format
 msgid "Cloning into '%s'...\n"
 msgstr "正克隆到 '%s'...\n"
 
-#: builtin/clone.c:867
+#: builtin/clone.c:890
 #, c-format
 msgid "Don't know how to clone %s"
 msgstr "不知道如何克隆 %s"
 
-#: builtin/clone.c:916
+#: builtin/clone.c:942
 #, c-format
 msgid "Remote branch %s not found in upstream %s"
 msgstr "远程分支 %s 在上游 %s 未发现"
 
-#: builtin/clone.c:923
+#: builtin/clone.c:949
 msgid "You appear to have cloned an empty repository."
 msgstr "您似乎克隆了一个空版本库。"
 
@@ -3519,15 +3864,15 @@
 msgid "--command must be the first argument"
 msgstr "--command 必须是第一个参数"
 
-#: builtin/commit.c:34
+#: builtin/commit.c:35
 msgid "git commit [options] [--] <pathspec>..."
 msgstr "git commit [选项] [--] <路径匹配>..."
 
-#: builtin/commit.c:39
+#: builtin/commit.c:40
 msgid "git status [options] [--] <pathspec>..."
 msgstr "git status [选项] [--] <路径匹配>..."
 
-#: builtin/commit.c:44
+#: builtin/commit.c:45
 msgid ""
 "Your name and email address were configured automatically based\n"
 "on your username and hostname. Please check that they are accurate.\n"
@@ -3550,7 +3895,7 @@
 "\n"
 "    git commit --amend --reset-author\n"
 
-#: builtin/commit.c:56
+#: builtin/commit.c:57
 msgid ""
 "You asked to amend the most recent commit, but doing so would make\n"
 "it empty. You can repeat your command with --allow-empty, or you can\n"
@@ -3559,109 +3904,127 @@
 "您要修补最近的提交,但这么做会让它成为空提交。您可以重复您的命令并带上\n"
 "--allow-empty 选项,或者您可用命令 \"git reset HEAD^\" 整个删除该提交。\n"
 
-#: builtin/commit.c:61
+#: builtin/commit.c:62
 msgid ""
 "The previous cherry-pick is now empty, possibly due to conflict resolution.\n"
 "If you wish to commit it anyway, use:\n"
 "\n"
 "    git commit --allow-empty\n"
 "\n"
-"Otherwise, please use 'git reset'\n"
 msgstr ""
 "之前的拣选操作现在是一个空提交,可能是由冲突解决导致的。如果您无论如何\n"
 "也要提交,使用命令:\n"
 "\n"
 "    git commit --allow-empty\n"
 "\n"
-"否则,请使用命令 'git reset'\n"
 
-#: builtin/commit.c:260
+#: builtin/commit.c:69
+msgid "Otherwise, please use 'git reset'\n"
+msgstr "否则,请使用命令 'git reset'\n"
+
+#: builtin/commit.c:72
+msgid ""
+"If you wish to skip this commit, use:\n"
+"\n"
+"    git reset\n"
+"\n"
+"Then \"git cherry-pick --continue\" will resume cherry-picking\n"
+"the remaining commits.\n"
+msgstr ""
+"如果您想跳过这个提交,使用命令:\n"
+"\n"
+"    git reset\n"
+"\n"
+"然后执行 \"git cherry-pick --continue\" 继续对其余提交执行拣选\n"
+"操作。\n"
+
+#: builtin/commit.c:279
 msgid "failed to unpack HEAD tree object"
 msgstr "无法解包 HEAD 树对象"
 
-#: builtin/commit.c:302
+#: builtin/commit.c:321
 msgid "unable to create temporary index"
 msgstr "不能创建临时索引"
 
-#: builtin/commit.c:308
+#: builtin/commit.c:327
 msgid "interactive add failed"
 msgstr "交互式添加失败"
 
-#: builtin/commit.c:341 builtin/commit.c:362 builtin/commit.c:412
+#: builtin/commit.c:360 builtin/commit.c:381 builtin/commit.c:431
 msgid "unable to write new_index file"
 msgstr "无法写 new_index 文件"
 
-#: builtin/commit.c:393
+#: builtin/commit.c:412
 msgid "cannot do a partial commit during a merge."
 msgstr "在合并过程中不能做部分提交。"
 
-#: builtin/commit.c:395
+#: builtin/commit.c:414
 msgid "cannot do a partial commit during a cherry-pick."
 msgstr "在拣选过程中不能做部分提交。"
 
-#: builtin/commit.c:405
+#: builtin/commit.c:424
 msgid "cannot read the index"
 msgstr "无法读取索引"
 
-#: builtin/commit.c:425
+#: builtin/commit.c:444
 msgid "unable to write temporary index file"
 msgstr "无法写临时索引文件"
 
-#: builtin/commit.c:513 builtin/commit.c:519
+#: builtin/commit.c:535 builtin/commit.c:541
 #, c-format
 msgid "invalid commit: %s"
 msgstr "无效的提交:%s"
 
-#: builtin/commit.c:542
+#: builtin/commit.c:563
 msgid "malformed --author parameter"
 msgstr "非法的 --author 参数"
 
-#: builtin/commit.c:562
+#: builtin/commit.c:583
 #, c-format
 msgid "Malformed ident string: '%s'"
 msgstr "非法的身份字符串:'%s'"
 
-#: builtin/commit.c:600 builtin/commit.c:633 builtin/commit.c:956
+#: builtin/commit.c:621 builtin/commit.c:654 builtin/commit.c:982
 #, c-format
 msgid "could not lookup commit %s"
 msgstr "不能查询提交 %s"
 
-#: builtin/commit.c:612 builtin/shortlog.c:272
+#: builtin/commit.c:633 builtin/shortlog.c:271
 #, c-format
 msgid "(reading log message from standard input)\n"
 msgstr "(正从标准输入中读取日志信息)\n"
 
-#: builtin/commit.c:614
+#: builtin/commit.c:635
 msgid "could not read log from standard input"
 msgstr "不能从标准输入中读取日志信息"
 
-#: builtin/commit.c:618
+#: builtin/commit.c:639
 #, c-format
 msgid "could not read log file '%s'"
 msgstr "不能读取日志文件 '%s'"
 
-#: builtin/commit.c:624
+#: builtin/commit.c:645
 msgid "commit has empty message"
 msgstr "提交说明为空"
 
-#: builtin/commit.c:640
+#: builtin/commit.c:661
 msgid "could not read MERGE_MSG"
 msgstr "不能读取 MERGE_MSG"
 
-#: builtin/commit.c:644
+#: builtin/commit.c:665
 msgid "could not read SQUASH_MSG"
 msgstr "不能读取 SQUASH_MSG"
 
-#: builtin/commit.c:648
+#: builtin/commit.c:669
 #, c-format
 msgid "could not read '%s'"
 msgstr "不能读取 '%s'"
 
-#: builtin/commit.c:709
+#: builtin/commit.c:730
 msgid "could not write commit template"
 msgstr "不能写提交模版"
 
-#: builtin/commit.c:720
+#: builtin/commit.c:741
 #, c-format
 msgid ""
 "\n"
@@ -3675,7 +4038,7 @@
 "\t%s\n"
 "然后重试。\n"
 
-#: builtin/commit.c:725
+#: builtin/commit.c:746
 #, c-format
 msgid ""
 "\n"
@@ -3689,7 +4052,7 @@
 "\t%s\n"
 "然后重试。\n"
 
-#: builtin/commit.c:737
+#: builtin/commit.c:758
 #, c-format
 msgid ""
 "Please enter the commit message for your changes. Lines starting\n"
@@ -3698,7 +4061,7 @@
 "请为您的变更输入提交说明。以 '%c' 开始的行将被忽略,而一个空的提交\n"
 "说明将会终止提交。\n"
 
-#: builtin/commit.c:742
+#: builtin/commit.c:763
 #, c-format
 msgid ""
 "Please enter the commit message for your changes. Lines starting\n"
@@ -3709,355 +4072,355 @@
 "也可以删除它们。一个空的提交说明将会终止提交。\n"
 
 #  译者:为保证在输出中对齐,注意调整句中空格!
-#: builtin/commit.c:755
+#: builtin/commit.c:776
 #, c-format
 msgid "%sAuthor:    %s"
 msgstr "%s作者:     %s"
 
 #  译者:为保证在输出中对齐,注意调整句中空格!
-#: builtin/commit.c:762
+#: builtin/commit.c:783
 #, c-format
 msgid "%sCommitter: %s"
 msgstr "%s提交者:   %s"
 
-#: builtin/commit.c:782
+#: builtin/commit.c:803
 msgid "Cannot read index"
 msgstr "无法读取索引"
 
-#: builtin/commit.c:819
+#: builtin/commit.c:845
 msgid "Error building trees"
 msgstr "无法创建树对象"
 
-#: builtin/commit.c:834 builtin/tag.c:359
+#: builtin/commit.c:860 builtin/tag.c:359
 #, c-format
 msgid "Please supply the message using either -m or -F option.\n"
 msgstr "请使用 -m 或 -F 选项提供提交说明。\n"
 
-#: builtin/commit.c:931
+#: builtin/commit.c:957
 #, c-format
 msgid "No existing author found with '%s'"
 msgstr "没有找到匹配 '%s' 的作者"
 
-#: builtin/commit.c:946 builtin/commit.c:1140
+#: builtin/commit.c:972 builtin/commit.c:1208
 #, c-format
 msgid "Invalid untracked files mode '%s'"
 msgstr "无效的未追踪文件参数 '%s'"
 
-#: builtin/commit.c:976
+#: builtin/commit.c:1009
+msgid "--long and -z are incompatible"
+msgstr "--long 和 -z 选项不兼容"
+
+#: builtin/commit.c:1039
 msgid "Using both --reset-author and --author does not make sense"
 msgstr "同时使用 --reset-author 和 --author 没有意义"
 
-#: builtin/commit.c:987
+#: builtin/commit.c:1050
 msgid "You have nothing to amend."
 msgstr "您没有可修补的提交。"
 
-#: builtin/commit.c:990
+#: builtin/commit.c:1053
 msgid "You are in the middle of a merge -- cannot amend."
 msgstr "您正处于一个合并过程中 -- 无法修补提交。"
 
-#: builtin/commit.c:992
+#: builtin/commit.c:1055
 msgid "You are in the middle of a cherry-pick -- cannot amend."
 msgstr "您正处于一个拣选过程中 -- 无法修补提交。"
 
-#: builtin/commit.c:995
+#: builtin/commit.c:1058
 msgid "Options --squash and --fixup cannot be used together"
 msgstr "选项 --squash 和 --fixup 不能同时使用"
 
-#: builtin/commit.c:1005
+#: builtin/commit.c:1068
 msgid "Only one of -c/-C/-F/--fixup can be used."
 msgstr "只能用一个 -c/-C/-F/--fixup 选项。"
 
-#: builtin/commit.c:1007
+#: builtin/commit.c:1070
 msgid "Option -m cannot be combined with -c/-C/-F/--fixup."
 msgstr "选项 -m 不能和 -c/-C/-F/--fixup 同时使用。"
 
-#: builtin/commit.c:1015
+#: builtin/commit.c:1078
 msgid "--reset-author can be used only with -C, -c or --amend."
 msgstr "--reset-author 只能和 -C、-c 或 --amend 同时使用。"
 
-#: builtin/commit.c:1032
+#: builtin/commit.c:1095
 msgid "Only one of --include/--only/--all/--interactive/--patch can be used."
 msgstr "只能用一个 --include/--only/--all/--interactive/--patch 选项。"
 
-#: builtin/commit.c:1034
+#: builtin/commit.c:1097
 msgid "No paths with --include/--only does not make sense."
 msgstr "参数 --include/--only 不跟路径没有意义。"
 
-#: builtin/commit.c:1036
+#: builtin/commit.c:1099
 msgid "Clever... amending the last one with dirty index."
 msgstr "聪明... 在索引不干净下修补最后的提交。"
 
-#: builtin/commit.c:1038
+#: builtin/commit.c:1101
 msgid "Explicit paths specified without -i nor -o; assuming --only paths..."
 msgstr "指定了明确的路径而没有使用 -i 或 -o 选项;认为是 --only paths..."
 
-#: builtin/commit.c:1048 builtin/tag.c:575
+#: builtin/commit.c:1111 builtin/tag.c:575
 #, c-format
 msgid "Invalid cleanup mode %s"
 msgstr "无效的清理模式 %s"
 
-#: builtin/commit.c:1053
+#: builtin/commit.c:1116
 msgid "Paths with -a does not make sense."
 msgstr "路径和 -a 选项同时使用没有意义。"
 
-#: builtin/commit.c:1059 builtin/commit.c:1194
-msgid "--long and -z are incompatible"
-msgstr "--long 和 -z 选项不兼容"
-
-#: builtin/commit.c:1154 builtin/commit.c:1390
+#: builtin/commit.c:1222 builtin/commit.c:1455
 msgid "show status concisely"
 msgstr "以简洁的格式显示状态"
 
-#: builtin/commit.c:1156 builtin/commit.c:1392
+#: builtin/commit.c:1224 builtin/commit.c:1457
 msgid "show branch information"
 msgstr "显示分支信息"
 
-#: builtin/commit.c:1158 builtin/commit.c:1394 builtin/push.c:426
+#: builtin/commit.c:1226 builtin/commit.c:1459 builtin/push.c:452
 msgid "machine-readable output"
 msgstr "机器可读的输出"
 
-#: builtin/commit.c:1161 builtin/commit.c:1396
+#: builtin/commit.c:1229 builtin/commit.c:1461
 msgid "show status in long format (default)"
 msgstr "以长格式显示状态(默认)"
 
-#: builtin/commit.c:1164 builtin/commit.c:1399
+#: builtin/commit.c:1232 builtin/commit.c:1464
 msgid "terminate entries with NUL"
 msgstr "条目以NUL字符结尾"
 
-#: builtin/commit.c:1166 builtin/commit.c:1402 builtin/fast-export.c:653
-#: builtin/fast-export.c:656 builtin/tag.c:459
+#: builtin/commit.c:1234 builtin/commit.c:1467 builtin/fast-export.c:667
+#: builtin/fast-export.c:670 builtin/tag.c:459
 msgid "mode"
 msgstr "模式"
 
-#: builtin/commit.c:1167 builtin/commit.c:1402
+#: builtin/commit.c:1235 builtin/commit.c:1467
 msgid "show untracked files, optional modes: all, normal, no. (Default: all)"
 msgstr "显示未跟踪的文件,“模式”的可选参数:all、normal、no。(默认:all)"
 
-#: builtin/commit.c:1170
+#: builtin/commit.c:1238
 msgid "show ignored files"
 msgstr "显示忽略的文件"
 
-#: builtin/commit.c:1171 parse-options.h:151
+#: builtin/commit.c:1239 parse-options.h:154
 msgid "when"
 msgstr "何时"
 
-#: builtin/commit.c:1172
+#: builtin/commit.c:1240
 msgid ""
 "ignore changes to submodules, optional when: all, dirty, untracked. "
 "(Default: all)"
 msgstr ""
 "忽略子模组的更改,“何时”的可选参数:all、dirty、untracked。(默认:all)"
 
-#: builtin/commit.c:1174
+#: builtin/commit.c:1242
 msgid "list untracked files in columns"
 msgstr "以列的方式显示未跟踪的文件"
 
-#: builtin/commit.c:1248
+#: builtin/commit.c:1313
 msgid "couldn't look up newly created commit"
 msgstr "无法找到新创建的提交"
 
-#: builtin/commit.c:1250
+#: builtin/commit.c:1315
 msgid "could not parse newly created commit"
 msgstr "不能解析新创建的提交"
 
-#: builtin/commit.c:1291
+#: builtin/commit.c:1356
 msgid "detached HEAD"
 msgstr "分离头指针"
 
 #  译者:中文字符串拼接,可删除前导空格
-#: builtin/commit.c:1293
+#: builtin/commit.c:1358
 msgid " (root-commit)"
 msgstr "(根提交)"
 
-#: builtin/commit.c:1360
+#: builtin/commit.c:1425
 msgid "suppress summary after successful commit"
 msgstr "提交成功后不显示概述信息"
 
-#: builtin/commit.c:1361
+#: builtin/commit.c:1426
 msgid "show diff in commit message template"
 msgstr "在提交说明模板里显示差异"
 
-#: builtin/commit.c:1363
+#: builtin/commit.c:1428
 msgid "Commit message options"
 msgstr "提交说明选项"
 
-#: builtin/commit.c:1364 builtin/tag.c:457
+#: builtin/commit.c:1429 builtin/tag.c:457
 msgid "read message from file"
 msgstr "从文件中读取提交说明"
 
-#: builtin/commit.c:1365
+#: builtin/commit.c:1430
 msgid "author"
 msgstr "作者"
 
-#: builtin/commit.c:1365
+#: builtin/commit.c:1430
 msgid "override author for commit"
 msgstr "提交时覆盖作者"
 
-#: builtin/commit.c:1366 builtin/gc.c:178
+#: builtin/commit.c:1431 builtin/gc.c:178
 msgid "date"
 msgstr "日期"
 
-#: builtin/commit.c:1366
+#: builtin/commit.c:1431
 msgid "override date for commit"
 msgstr "提交时覆盖日期"
 
-#: builtin/commit.c:1367 builtin/merge.c:208 builtin/notes.c:533
-#: builtin/notes.c:690 builtin/tag.c:455
+#: builtin/commit.c:1432 builtin/merge.c:223 builtin/notes.c:405
+#: builtin/notes.c:562 builtin/tag.c:455
 msgid "message"
 msgstr "说明"
 
-#: builtin/commit.c:1367
+#: builtin/commit.c:1432
 msgid "commit message"
 msgstr "提交说明"
 
-#: builtin/commit.c:1368
+#: builtin/commit.c:1433
 msgid "reuse and edit message from specified commit"
 msgstr "重用并编辑指定提交的提交说明"
 
-#: builtin/commit.c:1369
+#: builtin/commit.c:1434
 msgid "reuse message from specified commit"
 msgstr "重用指定提交的提交说明"
 
-#: builtin/commit.c:1370
+#: builtin/commit.c:1435
 msgid "use autosquash formatted message to fixup specified commit"
 msgstr "使用 autosquash 格式的提交说明用以修正指定的提交"
 
-#: builtin/commit.c:1371
+#: builtin/commit.c:1436
 msgid "use autosquash formatted message to squash specified commit"
 msgstr "使用 autosquash 格式的提交说明用以压缩至指定的提交"
 
-#: builtin/commit.c:1372
+#: builtin/commit.c:1437
 msgid "the commit is authored by me now (used with -C/-c/--amend)"
 msgstr "现在将该提交的作者改为我(和 -C/-c/--amend 参数共用)"
 
-#: builtin/commit.c:1373 builtin/log.c:1104 builtin/revert.c:109
+#: builtin/commit.c:1438 builtin/log.c:1160 builtin/revert.c:111
 msgid "add Signed-off-by:"
 msgstr "添加 Signed-off-by: 签名"
 
-#: builtin/commit.c:1374
+#: builtin/commit.c:1439
 msgid "use specified template file"
 msgstr "使用指定的模板文件"
 
-#: builtin/commit.c:1375
+#: builtin/commit.c:1440
 msgid "force edit of commit"
 msgstr "强制编辑提交"
 
 #  译者:可选值,不能翻译(或是原文中笔误,应为 mode)
-#: builtin/commit.c:1376
+#: builtin/commit.c:1441
 msgid "default"
 msgstr "default"
 
-#: builtin/commit.c:1376 builtin/tag.c:460
+#: builtin/commit.c:1441 builtin/tag.c:460
 msgid "how to strip spaces and #comments from message"
 msgstr "设置如何删除提交说明里的空格和#注释"
 
-#: builtin/commit.c:1377
+#: builtin/commit.c:1442
 msgid "include status in commit message template"
 msgstr "在提交说明模板里包含状态信息"
 
-#: builtin/commit.c:1378 builtin/merge.c:215 builtin/tag.c:461
+#: builtin/commit.c:1443 builtin/merge.c:230 builtin/tag.c:461
 msgid "key id"
 msgstr "key id"
 
-#: builtin/commit.c:1379 builtin/merge.c:216
+#: builtin/commit.c:1444 builtin/merge.c:231
 msgid "GPG sign commit"
 msgstr "GPG 提交签名"
 
 #. end commit message options
-#: builtin/commit.c:1382
+#: builtin/commit.c:1447
 msgid "Commit contents options"
 msgstr "提交内容选项"
 
-#: builtin/commit.c:1383
+#: builtin/commit.c:1448
 msgid "commit all changed files"
 msgstr "提交所有改动的文件"
 
-#: builtin/commit.c:1384
+#: builtin/commit.c:1449
 msgid "add specified files to index for commit"
 msgstr "添加指定的文件到索引区等待提交"
 
-#: builtin/commit.c:1385
+#: builtin/commit.c:1450
 msgid "interactively add files"
 msgstr "交互式添加文件"
 
-#: builtin/commit.c:1386
+#: builtin/commit.c:1451
 msgid "interactively add changes"
 msgstr "交互式添加变更"
 
-#: builtin/commit.c:1387
+#: builtin/commit.c:1452
 msgid "commit only specified files"
 msgstr "只提交指定的文件"
 
-#: builtin/commit.c:1388
+#: builtin/commit.c:1453
 msgid "bypass pre-commit hook"
 msgstr "绕过 pre-commit 钩子"
 
-#: builtin/commit.c:1389
+#: builtin/commit.c:1454
 msgid "show what would be committed"
 msgstr "显示将要提交的内容"
 
-#: builtin/commit.c:1400
+#: builtin/commit.c:1465
 msgid "amend previous commit"
 msgstr "修改先前的提交"
 
-#: builtin/commit.c:1401
+#: builtin/commit.c:1466
 msgid "bypass post-rewrite hook"
 msgstr "绕过 post-rewrite 钩子"
 
-#: builtin/commit.c:1406
+#: builtin/commit.c:1471
 msgid "ok to record an empty change"
 msgstr "允许一个空提交"
 
-#: builtin/commit.c:1409
+#: builtin/commit.c:1474
 msgid "ok to record a change with an empty message"
 msgstr "允许空的提交说明"
 
-#: builtin/commit.c:1441
+#: builtin/commit.c:1507
 msgid "could not parse HEAD commit"
 msgstr "不能解析 HEAD 提交"
 
-#: builtin/commit.c:1479 builtin/merge.c:510
+#: builtin/commit.c:1545 builtin/merge.c:525
 #, c-format
 msgid "could not open '%s' for reading"
 msgstr "不能为读入打开 '%s'"
 
-#: builtin/commit.c:1486
+#: builtin/commit.c:1552
 #, c-format
 msgid "Corrupt MERGE_HEAD file (%s)"
 msgstr "损坏的 MERGE_HEAD 文件(%s)"
 
-#: builtin/commit.c:1493
+#: builtin/commit.c:1559
 msgid "could not read MERGE_MODE"
 msgstr "不能读取 MERGE_MODE"
 
-#: builtin/commit.c:1512
+#: builtin/commit.c:1578
 #, c-format
 msgid "could not read commit message: %s"
 msgstr "不能读取提交说明:%s"
 
-#: builtin/commit.c:1526
+#: builtin/commit.c:1592
 #, c-format
 msgid "Aborting commit; you did not edit the message.\n"
 msgstr "终止提交;您未更改来自模版的提交说明。\n"
 
-#: builtin/commit.c:1531
+#: builtin/commit.c:1597
 #, c-format
 msgid "Aborting commit due to empty commit message.\n"
 msgstr "终止提交因为提交说明为空。\n"
 
-#: builtin/commit.c:1546 builtin/merge.c:847 builtin/merge.c:872
+#: builtin/commit.c:1612 builtin/merge.c:861 builtin/merge.c:886
 msgid "failed to write commit object"
 msgstr "无法写提交对象"
 
-#: builtin/commit.c:1567
+#: builtin/commit.c:1633
 msgid "cannot lock HEAD ref"
 msgstr "无法锁定 HEAD 引用"
 
-#: builtin/commit.c:1571
+#: builtin/commit.c:1637
 msgid "cannot update HEAD ref"
 msgstr "无法更新 HEAD 引用"
 
-#: builtin/commit.c:1582
+#: builtin/commit.c:1648
 msgid ""
 "Repository has been updated, but unable to write\n"
 "new_index file. Check that disk is not full or quota is\n"
@@ -4070,171 +4433,183 @@
 msgid "git config [options]"
 msgstr "git config [选项]"
 
-#: builtin/config.c:51
+#: builtin/config.c:52
 msgid "Config file location"
 msgstr "配置文件位置"
 
-#: builtin/config.c:52
+#: builtin/config.c:53
 msgid "use global config file"
 msgstr "使用全局配置文件"
 
-#: builtin/config.c:53
+#: builtin/config.c:54
 msgid "use system config file"
 msgstr "使用系统级配置文件"
 
-#: builtin/config.c:54
+#: builtin/config.c:55
 msgid "use repository config file"
 msgstr "使用版本库级配置文件"
 
-#: builtin/config.c:55
+#: builtin/config.c:56
 msgid "use given config file"
 msgstr "使用指定的配置文件"
 
-#: builtin/config.c:56
+#: builtin/config.c:57
+msgid "blob-id"
+msgstr "数据对象ID"
+
+#: builtin/config.c:57
+msgid "read config from given blob object"
+msgstr "从给定的数据对象读取配置"
+
+#: builtin/config.c:58
 msgid "Action"
 msgstr "操作"
 
-#: builtin/config.c:57
+#: builtin/config.c:59
 msgid "get value: name [value-regex]"
 msgstr "获取值:name [value-regex]"
 
-#: builtin/config.c:58
+#: builtin/config.c:60
 msgid "get all values: key [value-regex]"
 msgstr "获得所有的值:key [value-regex]"
 
-#: builtin/config.c:59
+#: builtin/config.c:61
 msgid "get values for regexp: name-regex [value-regex]"
 msgstr "根据正则表达式获得值:name-regex [value-regex]"
 
-#: builtin/config.c:60
+#: builtin/config.c:62
 msgid "replace all matching variables: name value [value_regex]"
 msgstr "替换所有匹配的变量:name value [value_regex]"
 
-#: builtin/config.c:61
+#: builtin/config.c:63
 msgid "add a new variable: name value"
 msgstr "添加一个新的变量:name value"
 
-#: builtin/config.c:62
+#: builtin/config.c:64
 msgid "remove a variable: name [value-regex]"
 msgstr "删除一个变量:name [value-regex]"
 
-#: builtin/config.c:63
+#: builtin/config.c:65
 msgid "remove all matches: name [value-regex]"
 msgstr "删除所有匹配项:name [value-regex]"
 
-#: builtin/config.c:64
+#: builtin/config.c:66
 msgid "rename section: old-name new-name"
 msgstr "重命名小节:old-name new-name"
 
-#: builtin/config.c:65
+#: builtin/config.c:67
 msgid "remove a section: name"
 msgstr "删除一个小节:name"
 
-#: builtin/config.c:66
+#: builtin/config.c:68
 msgid "list all"
 msgstr "列出所有"
 
-#: builtin/config.c:67
+#: builtin/config.c:69
 msgid "open an editor"
 msgstr "打开一个编辑器"
 
-#: builtin/config.c:68 builtin/config.c:69
+#: builtin/config.c:70 builtin/config.c:71
 msgid "slot"
 msgstr "slot"
 
-#: builtin/config.c:68
+#: builtin/config.c:70
 msgid "find the color configured: [default]"
 msgstr "找到配置的颜色:[默认]"
 
-#: builtin/config.c:69
+#: builtin/config.c:71
 msgid "find the color setting: [stdout-is-tty]"
 msgstr "找到颜色设置:[stdout-is-tty]"
 
-#: builtin/config.c:70
+#: builtin/config.c:72
 msgid "Type"
 msgstr "类型"
 
-#: builtin/config.c:71
+#: builtin/config.c:73
 msgid "value is \"true\" or \"false\""
 msgstr "值是 \"true\" 或 \"false\""
 
-#: builtin/config.c:72
+#: builtin/config.c:74
 msgid "value is decimal number"
 msgstr "值是十进制数"
 
-#: builtin/config.c:73
+#: builtin/config.c:75
 msgid "value is --bool or --int"
 msgstr "值是 --bool or --int"
 
-#: builtin/config.c:74
+#: builtin/config.c:76
 msgid "value is a path (file or directory name)"
 msgstr "值是一个路径(文件或目录名)"
 
-#: builtin/config.c:75
+#: builtin/config.c:77
 msgid "Other"
 msgstr "其它"
 
-#: builtin/config.c:76
+#: builtin/config.c:78
 msgid "terminate values with NUL byte"
 msgstr "终止值是NUL字节"
 
-#: builtin/config.c:77
+#: builtin/config.c:79
 msgid "respect include directives on lookup"
 msgstr "查询时参照 include 指令递归查找"
 
 #: builtin/count-objects.c:82
-msgid "git count-objects [-v]"
-msgstr "git count-objects [-v]"
+msgid "git count-objects [-v] [-H | --human-readable]"
+msgstr "git count-objects [-v] [-H | --human-readable]"
 
-#: builtin/describe.c:15
+#: builtin/count-objects.c:97
+msgid "print sizes in human readable format"
+msgstr "以用户可读的格式显示大小"
+
+#: builtin/describe.c:16
 msgid "git describe [options] <committish>*"
 msgstr "git describe [选项] <提交号>*"
 
-#: builtin/describe.c:16
+#: builtin/describe.c:17
 msgid "git describe [options] --dirty"
 msgstr "git describe [选项] --dirty"
 
-#: builtin/describe.c:233
+#: builtin/describe.c:237
 #, c-format
 msgid "annotated tag %s not available"
 msgstr "注释 tag %s 无效"
 
-#: builtin/describe.c:237
+#: builtin/describe.c:241
 #, c-format
 msgid "annotated tag %s has no embedded name"
 msgstr "注释 tag %s 没有嵌入名称"
 
-#: builtin/describe.c:239
+#: builtin/describe.c:243
 #, c-format
 msgid "tag '%s' is really '%s' here"
 msgstr "tag '%s' 的确是在 '%s'"
 
-#: builtin/describe.c:266
+#: builtin/describe.c:270
 #, c-format
 msgid "Not a valid object name %s"
 msgstr "不是一个有效的对象名 %s"
 
-#: builtin/describe.c:269
+#: builtin/describe.c:273
 #, c-format
 msgid "%s is not a valid '%s' object"
 msgstr "%s 不是一个有效的 '%s' 对象"
 
-#: builtin/describe.c:286
+#: builtin/describe.c:290
 #, c-format
 msgid "no tag exactly matches '%s'"
 msgstr "没有 tag 准确匹配 '%s'"
 
-#: builtin/describe.c:288
+#: builtin/describe.c:292
 #, c-format
 msgid "searching to describe %s\n"
 msgstr "搜索描述 %s\n"
 
-#: builtin/describe.c:328
+#: builtin/describe.c:332
 #, c-format
 msgid "finished search at %s\n"
 msgstr "完成搜索 %s\n"
 
-#: builtin/describe.c:352
+#: builtin/describe.c:359
 #, c-format
 msgid ""
 "No annotated tags can describe '%s'.\n"
@@ -4243,7 +4618,7 @@
 "没有注释 tag 能描述 '%s'。\n"
 "然而,有非注释 tag:尝试 --tags。"
 
-#: builtin/describe.c:356
+#: builtin/describe.c:363
 #, c-format
 msgid ""
 "No tags can describe '%s'.\n"
@@ -4252,12 +4627,12 @@
 "没有注释 tag 能描述 '%s'。\n"
 "尝试 --always,或者创建一些 tag。"
 
-#: builtin/describe.c:377
+#: builtin/describe.c:384
 #, c-format
 msgid "traversed %lu commits\n"
 msgstr "已遍历 %lu 个提交\n"
 
-#: builtin/describe.c:380
+#: builtin/describe.c:387
 #, c-format
 msgid ""
 "more than %i tags found; listed %i most recent\n"
@@ -4266,59 +4641,63 @@
 "发现多于 %i 个 tag,列出最近的 %i 个\n"
 "在 %s 放弃搜索\n"
 
-#: builtin/describe.c:402
+#: builtin/describe.c:409
 msgid "find the tag that comes after the commit"
 msgstr "寻找提交之后的 tag(用于描述提交)"
 
-#: builtin/describe.c:403
+#: builtin/describe.c:410
 msgid "debug search strategy on stderr"
 msgstr "在标准错误上调试搜索策略"
 
-#: builtin/describe.c:404
+#: builtin/describe.c:411
 msgid "use any ref"
 msgstr "使用任意引用"
 
-#: builtin/describe.c:405
+#: builtin/describe.c:412
 msgid "use any tag, even unannotated"
 msgstr "使用任意 tag,即使未带注解"
 
-#: builtin/describe.c:406
+#: builtin/describe.c:413
 msgid "always use long format"
 msgstr "始终使用长提交号格式"
 
-#: builtin/describe.c:409
+#: builtin/describe.c:414
+msgid "only follow first parent"
+msgstr "只跟随第一个父提交"
+
+#: builtin/describe.c:417
 msgid "only output exact matches"
 msgstr "只输出精确匹配"
 
-#: builtin/describe.c:411
+#: builtin/describe.c:419
 msgid "consider <n> most recent tags (default: 10)"
 msgstr "考虑最近 <n> 个 tags(默认:10)"
 
-#: builtin/describe.c:413
+#: builtin/describe.c:421
 msgid "only consider tags matching <pattern>"
 msgstr "只考虑匹配 <模式> 的 tags"
 
-#: builtin/describe.c:415 builtin/name-rev.c:238
+#: builtin/describe.c:423 builtin/name-rev.c:322
 msgid "show abbreviated commit object as fallback"
 msgstr "显示简写的提交号作为后备"
 
-#: builtin/describe.c:416
+#: builtin/describe.c:424
 msgid "mark"
 msgstr "标记"
 
-#: builtin/describe.c:417
+#: builtin/describe.c:425
 msgid "append <mark> on dirty working tree (default: \"-dirty\")"
 msgstr "若工作区脏(有变更)在结尾添加 <标记>(默认:\"-dirty\")"
 
-#: builtin/describe.c:435
+#: builtin/describe.c:443
 msgid "--long is incompatible with --abbrev=0"
 msgstr "--long 与 --abbrev=0 不兼容"
 
-#: builtin/describe.c:461
+#: builtin/describe.c:469
 msgid "No names found, cannot describe anything."
 msgstr "没有发现名称,无法描述任何东西。"
 
-#: builtin/describe.c:481
+#: builtin/describe.c:489
 msgid "--dirty is incompatible with committishes"
 msgstr "--dirty 不能与提交同时使用"
 
@@ -4327,31 +4706,26 @@
 msgid "'%s': not a regular file or symlink"
 msgstr "'%s':不是一个正规文件或符号链接"
 
-#: builtin/diff.c:228
+#: builtin/diff.c:230
 #, c-format
 msgid "invalid option: %s"
 msgstr "无效选项:%s"
 
-#: builtin/diff.c:305
+#: builtin/diff.c:307
 msgid "Not a git repository"
 msgstr "不是一个 git 版本库"
 
-#: builtin/diff.c:348
+#: builtin/diff.c:350
 #, c-format
 msgid "invalid object '%s' given."
 msgstr "提供了无效对象 '%s'。"
 
-#: builtin/diff.c:353
-#, c-format
-msgid "more than %d trees given: '%s'"
-msgstr "提供了超过 %d 个树对象:'%s'"
-
-#: builtin/diff.c:363
+#: builtin/diff.c:359
 #, c-format
 msgid "more than two blobs given: '%s'"
 msgstr "提供了超过两个数据(blob)对象:'%s'"
 
-#: builtin/diff.c:371
+#: builtin/diff.c:366
 #, c-format
 msgid "unhandled object '%s' given."
 msgstr "提供了无法处理的对象 '%s'。"
@@ -4360,39 +4734,39 @@
 msgid "git fast-export [rev-list-opts]"
 msgstr "git fast-export [rev-list-opts]"
 
-#: builtin/fast-export.c:652
+#: builtin/fast-export.c:666
 msgid "show progress after <n> objects"
 msgstr "在 <n> 个对象之后显示进度"
 
-#: builtin/fast-export.c:654
+#: builtin/fast-export.c:668
 msgid "select handling of signed tags"
 msgstr "选择如何处理签名 tags"
 
-#: builtin/fast-export.c:657
+#: builtin/fast-export.c:671
 msgid "select handling of tags that tag filtered objects"
 msgstr "选择当 tag 指向被过滤时 tags 的处理方式"
 
-#: builtin/fast-export.c:660
+#: builtin/fast-export.c:674
 msgid "Dump marks to this file"
 msgstr "把标记存储到这个文件"
 
-#: builtin/fast-export.c:662
+#: builtin/fast-export.c:676
 msgid "Import marks from this file"
 msgstr "从这个文件导入标记"
 
-#: builtin/fast-export.c:664
+#: builtin/fast-export.c:678
 msgid "Fake a tagger when tags lack one"
 msgstr "当 tags 缺少标记者字段时,假装提供一个"
 
-#: builtin/fast-export.c:666
+#: builtin/fast-export.c:680
 msgid "Output full tree for each commit"
 msgstr "每次提交都输出整个树"
 
-#: builtin/fast-export.c:668
+#: builtin/fast-export.c:682
 msgid "Use the done feature to terminate the stream"
 msgstr "使用 done 功能来终止流"
 
-#: builtin/fast-export.c:669
+#: builtin/fast-export.c:683
 msgid "Skip output of blob data"
 msgstr "跳过数据对象的输出"
 
@@ -4469,7 +4843,7 @@
 msgid "convert to a complete repository"
 msgstr "转换为一个完整的版本库"
 
-#: builtin/fetch.c:88 builtin/log.c:1121
+#: builtin/fetch.c:88 builtin/log.c:1177
 msgid "dir"
 msgstr "目录"
 
@@ -4481,77 +4855,77 @@
 msgid "default mode for recursion"
 msgstr "递归的默认模式"
 
-#: builtin/fetch.c:204
+#: builtin/fetch.c:220
 msgid "Couldn't find remote ref HEAD"
 msgstr "无法发现远程 HEAD 引用"
 
-#: builtin/fetch.c:257
+#: builtin/fetch.c:273
 #, c-format
 msgid "object %s not found"
 msgstr "对象 %s 未发现"
 
-#: builtin/fetch.c:262
+#: builtin/fetch.c:278
 msgid "[up to date]"
 msgstr "[最新]"
 
-#: builtin/fetch.c:276
+#: builtin/fetch.c:292
 #, c-format
 msgid "! %-*s %-*s -> %s  (can't fetch in current branch)"
 msgstr "! %-*s %-*s -> %s  (在当前分支下不能获取)"
 
-#: builtin/fetch.c:277 builtin/fetch.c:363
+#: builtin/fetch.c:293 builtin/fetch.c:379
 msgid "[rejected]"
 msgstr "[已拒绝]"
 
-#: builtin/fetch.c:288
+#: builtin/fetch.c:304
 msgid "[tag update]"
 msgstr "[tag更新]"
 
 #  译者:注意保持前导空格
-#: builtin/fetch.c:290 builtin/fetch.c:325 builtin/fetch.c:343
+#: builtin/fetch.c:306 builtin/fetch.c:341 builtin/fetch.c:359
 msgid "  (unable to update local ref)"
 msgstr "  (不能更新本地引用)"
 
-#: builtin/fetch.c:308
+#: builtin/fetch.c:324
 msgid "[new tag]"
 msgstr "[新tag]"
 
-#: builtin/fetch.c:311
+#: builtin/fetch.c:327
 msgid "[new branch]"
 msgstr "[新分支]"
 
-#: builtin/fetch.c:314
+#: builtin/fetch.c:330
 msgid "[new ref]"
 msgstr "[新引用]"
 
-#: builtin/fetch.c:359
+#: builtin/fetch.c:375
 msgid "unable to update local ref"
 msgstr "不能更新本地引用"
 
-#: builtin/fetch.c:359
+#: builtin/fetch.c:375
 msgid "forced update"
 msgstr "强制更新"
 
-#: builtin/fetch.c:365
+#: builtin/fetch.c:381
 msgid "(non-fast-forward)"
 msgstr "(非快进式)"
 
-#: builtin/fetch.c:396 builtin/fetch.c:688
+#: builtin/fetch.c:412 builtin/fetch.c:718
 #, c-format
 msgid "cannot open %s: %s\n"
 msgstr "无法打开 %s:%s\n"
 
-#: builtin/fetch.c:405
+#: builtin/fetch.c:421
 #, c-format
 msgid "%s did not send all necessary objects\n"
 msgstr "%s 未发送所有必须的对象\n"
 
-#: builtin/fetch.c:491
+#: builtin/fetch.c:520
 #, c-format
 msgid "From %.*s\n"
 msgstr "来自 %.*s\n"
 
-#: builtin/fetch.c:502
+#: builtin/fetch.c:531
 #, c-format
 msgid ""
 "some local refs could not be updated; try running\n"
@@ -4561,87 +4935,87 @@
 " 'git remote prune %s' 来删除旧的、有冲突的分支"
 
 #  译者:注意保持前导空格
-#: builtin/fetch.c:552
+#: builtin/fetch.c:581
 #, c-format
 msgid "   (%s will become dangling)"
 msgstr "   (%s 将成为摇摆状态)"
 
 #  译者:注意保持前导空格
-#: builtin/fetch.c:553
+#: builtin/fetch.c:582
 #, c-format
 msgid "   (%s has become dangling)"
 msgstr "   (%s 已成为摇摆状态)"
 
-#: builtin/fetch.c:560
+#: builtin/fetch.c:589
 msgid "[deleted]"
 msgstr "[已删除]"
 
-#: builtin/fetch.c:561 builtin/remote.c:1055
+#: builtin/fetch.c:590 builtin/remote.c:1055
 msgid "(none)"
 msgstr "(无)"
 
-#: builtin/fetch.c:678
+#: builtin/fetch.c:708
 #, c-format
 msgid "Refusing to fetch into current branch %s of non-bare repository"
 msgstr "拒绝获取到非裸版本库的当前分支 %s"
 
-#: builtin/fetch.c:712
+#: builtin/fetch.c:742
 #, c-format
 msgid "Don't know how to fetch from %s"
 msgstr "不知道如何从 %s 获取"
 
-#: builtin/fetch.c:789
+#: builtin/fetch.c:823
 #, c-format
 msgid "Option \"%s\" value \"%s\" is not valid for %s"
 msgstr "选项 \"%s\" 的值 \"%s\" 对于 %s 是无效的"
 
-#: builtin/fetch.c:792
+#: builtin/fetch.c:826
 #, c-format
 msgid "Option \"%s\" is ignored for %s\n"
 msgstr "选项 \"%s\" 为 %s 所忽略\n"
 
-#: builtin/fetch.c:894
+#: builtin/fetch.c:928
 #, c-format
 msgid "Fetching %s\n"
 msgstr "正在获取 %s\n"
 
-#: builtin/fetch.c:896 builtin/remote.c:100
+#: builtin/fetch.c:930 builtin/remote.c:100
 #, c-format
 msgid "Could not fetch %s"
 msgstr "不能获取 %s"
 
-#: builtin/fetch.c:915
+#: builtin/fetch.c:949
 msgid ""
 "No remote repository specified.  Please, specify either a URL or a\n"
 "remote name from which new revisions should be fetched."
 msgstr "未指定远程版本库。请通过一个URL或远程版本库名指定,用以获取新提交。"
 
-#: builtin/fetch.c:935
+#: builtin/fetch.c:969
 msgid "You need to specify a tag name."
 msgstr "您需要指定一个 tag 名称。"
 
-#: builtin/fetch.c:981
+#: builtin/fetch.c:1015
 msgid "--depth and --unshallow cannot be used together"
 msgstr "--depth 和 --unshallow 不能同时使用"
 
-#: builtin/fetch.c:983
+#: builtin/fetch.c:1017
 msgid "--unshallow on a complete repository does not make sense"
 msgstr "对于一个完整的版本库,参数 --unshallow 没有意义"
 
-#: builtin/fetch.c:1002
+#: builtin/fetch.c:1036
 msgid "fetch --all does not take a repository argument"
 msgstr "fetch --all 不能带一个版本库参数"
 
-#: builtin/fetch.c:1004
+#: builtin/fetch.c:1038
 msgid "fetch --all does not make sense with refspecs"
 msgstr "fetch --all 带引用表达式没有任何意义"
 
-#: builtin/fetch.c:1015
+#: builtin/fetch.c:1049
 #, c-format
 msgid "No such remote or remote group: %s"
 msgstr "没有这样的远程或远程组:%s"
 
-#: builtin/fetch.c:1023
+#: builtin/fetch.c:1057
 msgid "Fetching a group and specifying refspecs does not make sense"
 msgstr "获取组并指定引用表达式没有意义"
 
@@ -4650,29 +5024,29 @@
 msgstr ""
 "git fmt-merge-msg [-m <message>] [--log[=<n>]|--no-log] [--file <file>]"
 
-#: builtin/fmt-merge-msg.c:659 builtin/fmt-merge-msg.c:662 builtin/grep.c:701
-#: builtin/merge.c:188 builtin/show-branch.c:656 builtin/show-ref.c:175
-#: builtin/tag.c:446 parse-options.h:133 parse-options.h:239
+#: builtin/fmt-merge-msg.c:663 builtin/fmt-merge-msg.c:666 builtin/grep.c:700
+#: builtin/merge.c:203 builtin/show-branch.c:655 builtin/show-ref.c:179
+#: builtin/tag.c:446 parse-options.h:133 parse-options.h:243
 msgid "n"
 msgstr "n"
 
-#: builtin/fmt-merge-msg.c:660
+#: builtin/fmt-merge-msg.c:664
 msgid "populate log with at most <n> entries from shortlog"
 msgstr "向提交说明中最多复制指定条目(合并而来的提交)的简短说明"
 
-#: builtin/fmt-merge-msg.c:663
+#: builtin/fmt-merge-msg.c:667
 msgid "alias for --log (deprecated)"
 msgstr "参数 --log 的别名(已弃用)"
 
-#: builtin/fmt-merge-msg.c:666
+#: builtin/fmt-merge-msg.c:670
 msgid "text"
 msgstr "文本"
 
-#: builtin/fmt-merge-msg.c:667
+#: builtin/fmt-merge-msg.c:671
 msgid "use <text> as start of message"
 msgstr "使用 <文本> 作为提交说明的开始"
 
-#: builtin/fmt-merge-msg.c:668
+#: builtin/fmt-merge-msg.c:672
 msgid "file to read from"
 msgstr "从文件中读取"
 
@@ -4809,221 +5183,221 @@
 msgid "grep: failed to create thread: %s"
 msgstr "grep:无法创建线程:%s"
 
-#: builtin/grep.c:365
+#: builtin/grep.c:364
 #, c-format
 msgid "Failed to chdir: %s"
 msgstr "无法切换目录:%s"
 
-#: builtin/grep.c:443 builtin/grep.c:478
+#: builtin/grep.c:442 builtin/grep.c:477
 #, c-format
 msgid "unable to read tree (%s)"
 msgstr "无法读取树(%s)"
 
-#: builtin/grep.c:493
+#: builtin/grep.c:492
 #, c-format
 msgid "unable to grep from object of type %s"
 msgstr "无法抓取来自于 %s 类型的对象"
 
-#: builtin/grep.c:551
+#: builtin/grep.c:550
 #, c-format
 msgid "switch `%c' expects a numerical value"
 msgstr "开关 `%c' 期望一个数字值"
 
-#: builtin/grep.c:568
+#: builtin/grep.c:567
 #, c-format
 msgid "cannot open '%s'"
 msgstr "不能打开 '%s'"
 
-#: builtin/grep.c:643
+#: builtin/grep.c:642
 msgid "search in index instead of in the work tree"
 msgstr "在索引区搜索而不是在工作区"
 
-#: builtin/grep.c:645
+#: builtin/grep.c:644
 msgid "find in contents not managed by git"
 msgstr "在未被 git 管理的内容中查找"
 
 #  译者:中文字符串拼接,可删除前导空格
-#: builtin/grep.c:647
+#: builtin/grep.c:646
 msgid "search in both tracked and untracked files"
 msgstr "在跟踪和未跟踪的文件中搜索"
 
-#: builtin/grep.c:649
+#: builtin/grep.c:648
 msgid "search also in ignored files"
 msgstr "也在忽略的文件中搜索"
 
-#: builtin/grep.c:652
+#: builtin/grep.c:651
 msgid "show non-matching lines"
 msgstr "显示未匹配的行"
 
-#: builtin/grep.c:654
+#: builtin/grep.c:653
 msgid "case insensitive matching"
 msgstr "不区分大小写匹配"
 
-#: builtin/grep.c:656
+#: builtin/grep.c:655
 msgid "match patterns only at word boundaries"
 msgstr "只在单词边界匹配模式"
 
-#: builtin/grep.c:658
+#: builtin/grep.c:657
 msgid "process binary files as text"
 msgstr "把二进制文件当做文本处理"
 
-#: builtin/grep.c:660
+#: builtin/grep.c:659
 msgid "don't match patterns in binary files"
 msgstr "不在二进制文件中匹配模式"
 
-#: builtin/grep.c:663
+#: builtin/grep.c:662
 msgid "descend at most <depth> levels"
 msgstr "最多以指定的深度向下寻找"
 
-#: builtin/grep.c:667
+#: builtin/grep.c:666
 msgid "use extended POSIX regular expressions"
 msgstr "使用扩展的 POSIX 正则表达式"
 
-#: builtin/grep.c:670
+#: builtin/grep.c:669
 msgid "use basic POSIX regular expressions (default)"
 msgstr "使用基本的 POSIX 正则表达式(默认)"
 
-#: builtin/grep.c:673
+#: builtin/grep.c:672
 msgid "interpret patterns as fixed strings"
 msgstr "把模式解析为固定的字符串"
 
-#: builtin/grep.c:676
+#: builtin/grep.c:675
 msgid "use Perl-compatible regular expressions"
 msgstr "使用 Perl 兼容的正则表达式"
 
-#: builtin/grep.c:679
+#: builtin/grep.c:678
 msgid "show line numbers"
 msgstr "显示行号"
 
-#: builtin/grep.c:680
+#: builtin/grep.c:679
 msgid "don't show filenames"
 msgstr "不显示文件名"
 
-#: builtin/grep.c:681
+#: builtin/grep.c:680
 msgid "show filenames"
 msgstr "显示文件名"
 
-#: builtin/grep.c:683
+#: builtin/grep.c:682
 msgid "show filenames relative to top directory"
 msgstr "显示相对于顶级目录的文件名"
 
-#: builtin/grep.c:685
+#: builtin/grep.c:684
 msgid "show only filenames instead of matching lines"
 msgstr "只显示文件名而不显示匹配的行"
 
-#: builtin/grep.c:687
+#: builtin/grep.c:686
 msgid "synonym for --files-with-matches"
 msgstr "和 --files-with-matches 同义"
 
-#: builtin/grep.c:690
+#: builtin/grep.c:689
 msgid "show only the names of files without match"
 msgstr "只显示未匹配的文件名"
 
-#: builtin/grep.c:692
+#: builtin/grep.c:691
 msgid "print NUL after filenames"
 msgstr "在文件名后输出 NUL 字符"
 
-#: builtin/grep.c:694
+#: builtin/grep.c:693
 msgid "show the number of matches instead of matching lines"
 msgstr "显示总匹配行数,而不显示匹配的行"
 
-#: builtin/grep.c:695
+#: builtin/grep.c:694
 msgid "highlight matches"
 msgstr "高亮显示匹配项"
 
-#: builtin/grep.c:697
+#: builtin/grep.c:696
 msgid "print empty line between matches from different files"
 msgstr "在不同文件的匹配项之间打印空行"
 
-#: builtin/grep.c:699
+#: builtin/grep.c:698
 msgid "show filename only once above matches from same file"
 msgstr "只在同一文件的匹配项的上面显示一次文件名"
 
-#: builtin/grep.c:702
+#: builtin/grep.c:701
 msgid "show <n> context lines before and after matches"
 msgstr "显示匹配项前后的 <n> 行上下文"
 
-#: builtin/grep.c:705
+#: builtin/grep.c:704
 msgid "show <n> context lines before matches"
 msgstr "显示匹配项前 <n> 行上下文"
 
-#: builtin/grep.c:707
+#: builtin/grep.c:706
 msgid "show <n> context lines after matches"
 msgstr "显示匹配项后 <n> 行上下文"
 
-#: builtin/grep.c:708
+#: builtin/grep.c:707
 msgid "shortcut for -C NUM"
 msgstr "快捷键 -C 数字"
 
-#: builtin/grep.c:711
+#: builtin/grep.c:710
 msgid "show a line with the function name before matches"
 msgstr "在匹配的前面显示一行函数名"
 
-#: builtin/grep.c:713
+#: builtin/grep.c:712
 msgid "show the surrounding function"
 msgstr "显示所在函数的前后内容"
 
-#: builtin/grep.c:716
+#: builtin/grep.c:715
 msgid "read patterns from file"
 msgstr "从文件读取模式"
 
-#: builtin/grep.c:718
+#: builtin/grep.c:717
 msgid "match <pattern>"
 msgstr "匹配 <模式>"
 
-#: builtin/grep.c:720
+#: builtin/grep.c:719
 msgid "combine patterns specified with -e"
 msgstr "组合用 -e 参数设定的模式"
 
-#: builtin/grep.c:732
+#: builtin/grep.c:731
 msgid "indicate hit with exit status without output"
 msgstr "不输出,而用退出码标识命中状态"
 
-#: builtin/grep.c:734
+#: builtin/grep.c:733
 msgid "show only matches from files that match all patterns"
 msgstr "只显示匹配所有模式的文件中的匹配"
 
-#: builtin/grep.c:736
+#: builtin/grep.c:735
 msgid "show parse tree for grep expression"
 msgstr "显示 grep 表达式的解析树"
 
-#: builtin/grep.c:740
+#: builtin/grep.c:739
 msgid "pager"
 msgstr "分页"
 
-#: builtin/grep.c:740
+#: builtin/grep.c:739
 msgid "show matching files in the pager"
 msgstr "分页显示匹配的文件"
 
-#: builtin/grep.c:743
+#: builtin/grep.c:742
 msgid "allow calling of grep(1) (ignored by this build)"
 msgstr "允许调用 grep(1)(本次构建忽略)"
 
-#: builtin/grep.c:744 builtin/show-ref.c:184
+#: builtin/grep.c:743 builtin/show-ref.c:188
 msgid "show usage"
 msgstr "显示用法"
 
-#: builtin/grep.c:811
+#: builtin/grep.c:810
 msgid "no pattern given."
 msgstr "未提供模式匹配。"
 
-#: builtin/grep.c:866
+#: builtin/grep.c:865
 msgid "--open-files-in-pager only works on the worktree"
 msgstr "--open-files-in-pager 仅用于工作区"
 
-#: builtin/grep.c:889
+#: builtin/grep.c:888
 msgid "--cached or --untracked cannot be used with --no-index."
 msgstr "--cached 或 --untracked 不能与 --no-index 同时使用。"
 
-#: builtin/grep.c:894
+#: builtin/grep.c:893
 msgid "--no-index or --untracked cannot be used with revs."
 msgstr "--no-index 或 --untracked 不能和版本同时使用。"
 
-#: builtin/grep.c:897
+#: builtin/grep.c:896
 msgid "--[no-]exclude-standard cannot be used for tracked contents."
 msgstr "--[no-]exclude-standard 不能用于已跟踪内容。"
 
-#: builtin/grep.c:905
+#: builtin/grep.c:904
 msgid "both --cached and trees are given."
 msgstr "同时给出了 --cached 和树对象。"
 
@@ -5063,10 +5437,14 @@
 msgid "process file as it were from this path"
 msgstr "处理文件并假设其来自于此路径"
 
-#: builtin/help.c:42
+#: builtin/help.c:41
 msgid "print all available commands"
 msgstr "打印所有可用的命令"
 
+#: builtin/help.c:42
+msgid "print list of useful guides"
+msgstr "显示有用的指南列表"
+
 #: builtin/help.c:43
 msgid "show man page"
 msgstr "显示 man 手册"
@@ -5080,8 +5458,8 @@
 msgstr "显示 info 手册"
 
 #: builtin/help.c:52
-msgid "git help [--all] [--man|--web|--info] [command]"
-msgstr "git help [--all] [--man|--web|--info] [命令]"
+msgid "git help [--all] [--guides] [--man|--web|--info] [command]"
+msgstr "git help [--all] [--guides] [--man|--web|--info] [命令]"
 
 #: builtin/help.c:64
 #, c-format
@@ -5137,290 +5515,322 @@
 msgid "no info viewer handled the request"
 msgstr "没有 info 查看器处理此请求"
 
-#: builtin/help.c:429 builtin/help.c:436
+#: builtin/help.c:420
+msgid "Defining attributes per path"
+msgstr "定义路径的属性"
+
+#: builtin/help.c:421
+msgid "A Git glossary"
+msgstr "Git 词汇表"
+
+#: builtin/help.c:422
+msgid "Specifies intentionally untracked files to ignore"
+msgstr "忽略指定的未跟踪文件"
+
+#: builtin/help.c:423
+msgid "Defining submodule properties"
+msgstr "定义子模组属性"
+
+#: builtin/help.c:424
+msgid "Specifying revisions and ranges for Git"
+msgstr "指定 Git 的版本和版本范围"
+
+#: builtin/help.c:425
+msgid "A tutorial introduction to Git (for version 1.5.1 or newer)"
+msgstr "一个 Git 教程(针对 1.5.1 或更新版本)"
+
+#: builtin/help.c:426
+msgid "An overview of recommended workflows with Git"
+msgstr "Git 推荐的工作流概览"
+
+#: builtin/help.c:438
+msgid "The common Git guides are:\n"
+msgstr "最常用的 Git 向导有:\n"
+
+#: builtin/help.c:460 builtin/help.c:476
 #, c-format
 msgid "usage: %s%s"
 msgstr "用法:%s%s"
 
-#: builtin/help.c:452
+#: builtin/help.c:492
 #, c-format
 msgid "`git %s' is aliased to `%s'"
 msgstr "`git %s' 是 `%s' 的别名"
 
-#: builtin/index-pack.c:182
+#: builtin/index-pack.c:184
 #, c-format
 msgid "object type mismatch at %s"
 msgstr "%s 的对象类型不匹配"
 
-#: builtin/index-pack.c:202
+#: builtin/index-pack.c:204
 msgid "object of unexpected type"
 msgstr "意外的类型的对象"
 
-#: builtin/index-pack.c:239
+#: builtin/index-pack.c:244
 #, c-format
 msgid "cannot fill %d byte"
 msgid_plural "cannot fill %d bytes"
 msgstr[0] "无法填充 %d 字节"
 msgstr[1] "无法填充 %d 字节"
 
-#: builtin/index-pack.c:249
+#: builtin/index-pack.c:254
 msgid "early EOF"
 msgstr "过早的文件结束符(EOF)"
 
-#: builtin/index-pack.c:250
+#: builtin/index-pack.c:255
 msgid "read error on input"
 msgstr "输入上的读错误"
 
-#: builtin/index-pack.c:262
+#: builtin/index-pack.c:267
 msgid "used more bytes than were available"
 msgstr "用掉了超过可用的字节"
 
-#: builtin/index-pack.c:269
+#: builtin/index-pack.c:274
 msgid "pack too large for current definition of off_t"
 msgstr "包太大超过了当前 off_t 的定义"
 
-#: builtin/index-pack.c:285
+#: builtin/index-pack.c:290
 #, c-format
 msgid "unable to create '%s'"
 msgstr "不能创建 '%s'"
 
-#: builtin/index-pack.c:290
+#: builtin/index-pack.c:295
 #, c-format
 msgid "cannot open packfile '%s'"
 msgstr "无法打开包文件 '%s'"
 
-#: builtin/index-pack.c:304
+#: builtin/index-pack.c:309
 msgid "pack signature mismatch"
 msgstr "包签名不匹配"
 
-#: builtin/index-pack.c:306
+#: builtin/index-pack.c:311
 #, c-format
 msgid "pack version %<PRIu32> unsupported"
 msgstr "不支持包版本 %<PRIu32>"
 
-#: builtin/index-pack.c:324
+#: builtin/index-pack.c:329
 #, c-format
 msgid "pack has bad object at offset %lu: %s"
 msgstr "包中有错误的对象位于 %lu:%s"
 
-#: builtin/index-pack.c:446
+#: builtin/index-pack.c:451
 #, c-format
 msgid "inflate returned %d"
 msgstr "解压缩返回 %d"
 
-#: builtin/index-pack.c:495
+#: builtin/index-pack.c:500
 msgid "offset value overflow for delta base object"
 msgstr "偏移值覆盖了 delta 基准对象"
 
-#: builtin/index-pack.c:503
+#: builtin/index-pack.c:508
 msgid "delta base offset is out of bound"
 msgstr "delta 基准偏移越界"
 
-#: builtin/index-pack.c:511
+#: builtin/index-pack.c:516
 #, c-format
 msgid "unknown object type %d"
 msgstr "未知对象类型 %d"
 
-#: builtin/index-pack.c:542
+#: builtin/index-pack.c:547
 msgid "cannot pread pack file"
 msgstr "无法读取包文件"
 
-#: builtin/index-pack.c:544
+#: builtin/index-pack.c:549
 #, c-format
 msgid "premature end of pack file, %lu byte missing"
 msgid_plural "premature end of pack file, %lu bytes missing"
 msgstr[0] "包文件过早结束,缺少 %lu 字节"
 msgstr[1] "包文件过早结束,缺少 %lu 字节"
 
-#: builtin/index-pack.c:570
+#: builtin/index-pack.c:575
 msgid "serious inflate inconsistency"
 msgstr "解压缩严重的不一致"
 
-#: builtin/index-pack.c:661 builtin/index-pack.c:667 builtin/index-pack.c:690
-#: builtin/index-pack.c:724 builtin/index-pack.c:733
+#: builtin/index-pack.c:666 builtin/index-pack.c:672 builtin/index-pack.c:695
+#: builtin/index-pack.c:729 builtin/index-pack.c:738
 #, c-format
 msgid "SHA1 COLLISION FOUND WITH %s !"
 msgstr "发现 %s 出现 SHA1 冲突!"
 
-#: builtin/index-pack.c:664 builtin/pack-objects.c:170
+#: builtin/index-pack.c:669 builtin/pack-objects.c:170
 #: builtin/pack-objects.c:262
 #, c-format
 msgid "unable to read %s"
 msgstr "不能读 %s"
 
-#: builtin/index-pack.c:730
+#: builtin/index-pack.c:735
 #, c-format
 msgid "cannot read existing object %s"
 msgstr "不能读取现存对象 %s"
 
-#: builtin/index-pack.c:744
+#: builtin/index-pack.c:749
 #, c-format
 msgid "invalid blob object %s"
 msgstr "无效的数据(blob)对象 %s"
 
-#: builtin/index-pack.c:759
+#: builtin/index-pack.c:763
 #, c-format
 msgid "invalid %s"
 msgstr "无效的 %s"
 
-#: builtin/index-pack.c:761
+#: builtin/index-pack.c:766
 msgid "Error in object"
 msgstr "对象中出错"
 
-#: builtin/index-pack.c:763
+#: builtin/index-pack.c:768
 #, c-format
 msgid "Not all child objects of %s are reachable"
 msgstr "%s 的所有子对象并非都可达"
 
-#: builtin/index-pack.c:833 builtin/index-pack.c:863
+#: builtin/index-pack.c:838 builtin/index-pack.c:868
 msgid "failed to apply delta"
 msgstr "无法应用 delta"
 
-#: builtin/index-pack.c:1004
+#: builtin/index-pack.c:1009
 msgid "Receiving objects"
 msgstr "接收对象中"
 
-#: builtin/index-pack.c:1004
+#: builtin/index-pack.c:1009
 msgid "Indexing objects"
 msgstr "索引对象中"
 
-#: builtin/index-pack.c:1030
+#: builtin/index-pack.c:1035
 msgid "pack is corrupted (SHA1 mismatch)"
 msgstr "包冲突(SHA1 不匹配)"
 
-#: builtin/index-pack.c:1035
+#: builtin/index-pack.c:1040
 msgid "cannot fstat packfile"
 msgstr "不能枚举包文件状态"
 
-#: builtin/index-pack.c:1038
+#: builtin/index-pack.c:1043
 msgid "pack has junk at the end"
 msgstr "包的结尾有垃圾数据"
 
-#: builtin/index-pack.c:1049
+#: builtin/index-pack.c:1054
 msgid "confusion beyond insanity in parse_pack_objects()"
 msgstr "parse_pack_objects() 中遇到不可理喻的问题"
 
-#: builtin/index-pack.c:1072
+#: builtin/index-pack.c:1077
 msgid "Resolving deltas"
 msgstr "处理 delta 中"
 
-#: builtin/index-pack.c:1082
+#: builtin/index-pack.c:1087
 #, c-format
 msgid "unable to create thread: %s"
 msgstr "不能创建线程:%s"
 
-#: builtin/index-pack.c:1124
+#: builtin/index-pack.c:1129
 msgid "confusion beyond insanity"
 msgstr "不可理喻"
 
-#: builtin/index-pack.c:1132
+#: builtin/index-pack.c:1137
 #, c-format
 msgid "completed with %d local objects"
 msgstr "完成 %d 个本地对象"
 
-#: builtin/index-pack.c:1142
+#: builtin/index-pack.c:1147
 #, c-format
 msgid "Unexpected tail checksum for %s (disk corruption?)"
 msgstr "对 %s 的尾部校验出现意外(磁盘损坏?)"
 
-#: builtin/index-pack.c:1146
+#: builtin/index-pack.c:1151
 #, c-format
 msgid "pack has %d unresolved delta"
 msgid_plural "pack has %d unresolved deltas"
 msgstr[0] "包有 %d 个未解决的 delta"
 msgstr[1] "包有 %d 个未解决的 delta"
 
-#: builtin/index-pack.c:1171
+#: builtin/index-pack.c:1176
 #, c-format
 msgid "unable to deflate appended object (%d)"
 msgstr "不能压缩附加对象(%d)"
 
-#: builtin/index-pack.c:1250
+#: builtin/index-pack.c:1255
 #, c-format
 msgid "local object %s is corrupt"
 msgstr "本地对象 %s 已损坏"
 
-#: builtin/index-pack.c:1274
+#: builtin/index-pack.c:1279
 msgid "error while closing pack file"
 msgstr "关闭包文件时出错"
 
-#: builtin/index-pack.c:1287
+#: builtin/index-pack.c:1292
 #, c-format
 msgid "cannot write keep file '%s'"
 msgstr "无法写保留文件 '%s'"
 
-#: builtin/index-pack.c:1295
+#: builtin/index-pack.c:1300
 #, c-format
 msgid "cannot close written keep file '%s'"
 msgstr "无法关闭保留文件 '%s'"
 
-#: builtin/index-pack.c:1308
+#: builtin/index-pack.c:1313
 msgid "cannot store pack file"
 msgstr "无法存储包文件"
 
-#: builtin/index-pack.c:1319
+#: builtin/index-pack.c:1324
 msgid "cannot store index file"
 msgstr "无法存储索引文件"
 
-#: builtin/index-pack.c:1352
+#: builtin/index-pack.c:1357
 #, c-format
 msgid "bad pack.indexversion=%<PRIu32>"
 msgstr "坏的 pack.indexversion=%<PRIu32>"
 
-#: builtin/index-pack.c:1358
+#: builtin/index-pack.c:1363
 #, c-format
 msgid "invalid number of threads specified (%d)"
 msgstr "指定的线程数无效(%d)"
 
-#: builtin/index-pack.c:1362 builtin/index-pack.c:1535
+#: builtin/index-pack.c:1367 builtin/index-pack.c:1545
 #, c-format
 msgid "no threads support, ignoring %s"
 msgstr "没有线程支持,忽略 %s"
 
-#: builtin/index-pack.c:1420
+#: builtin/index-pack.c:1425
 #, c-format
 msgid "Cannot open existing pack file '%s'"
 msgstr "无法打开现存包文件 '%s'"
 
-#: builtin/index-pack.c:1422
+#: builtin/index-pack.c:1427
 #, c-format
 msgid "Cannot open existing pack idx file for '%s'"
 msgstr "无法为 %s 打开包索引文件"
 
-#: builtin/index-pack.c:1469
+#: builtin/index-pack.c:1474
 #, c-format
 msgid "non delta: %d object"
 msgid_plural "non delta: %d objects"
 msgstr[0] "非 delta:%d 个对象"
 msgstr[1] "非 delta:%d 个对象"
 
-#: builtin/index-pack.c:1476
+#: builtin/index-pack.c:1481
 #, c-format
 msgid "chain length = %d: %lu object"
 msgid_plural "chain length = %d: %lu objects"
 msgstr[0] "链长 = %d: %lu 对象"
 msgstr[1] "链长 = %d: %lu 对象"
 
-#: builtin/index-pack.c:1503
+#: builtin/index-pack.c:1509
 msgid "Cannot come back to cwd"
 msgstr "无法返回当前工作目录"
 
-#: builtin/index-pack.c:1547 builtin/index-pack.c:1550
-#: builtin/index-pack.c:1562 builtin/index-pack.c:1566
+#: builtin/index-pack.c:1557 builtin/index-pack.c:1560
+#: builtin/index-pack.c:1572 builtin/index-pack.c:1576
 #, c-format
 msgid "bad %s"
 msgstr "错误选项 %s"
 
-#: builtin/index-pack.c:1580
+#: builtin/index-pack.c:1590
 msgid "--fix-thin cannot be used without --stdin"
 msgstr "--fix-thin 不能和 --stdin 同时使用"
 
-#: builtin/index-pack.c:1584 builtin/index-pack.c:1594
+#: builtin/index-pack.c:1594 builtin/index-pack.c:1604
 #, c-format
 msgid "packfile name '%s' does not end with '.pack'"
 msgstr "包名 '%s' 没有以 '.pack' 结尾"
 
-#: builtin/index-pack.c:1603
+#: builtin/index-pack.c:1613
 msgid "--verify with no packfile name given"
 msgstr "--verify 没有提供包名参数"
 
@@ -5557,7 +5967,7 @@
 msgid "specify that the git repository is to be shared amongst several users"
 msgstr "指定 git 版本库是多个用户之间共享的"
 
-#: builtin/init-db.c:493 builtin/prune-packed.c:77
+#: builtin/init-db.c:493 builtin/prune-packed.c:75
 msgid "be quiet"
 msgstr "保持安静"
 
@@ -5589,340 +5999,353 @@
 msgid "Cannot access work tree '%s'"
 msgstr "不能访问工作区 '%s'"
 
-#: builtin/log.c:40
-msgid "git log [<options>] [<since>..<until>] [[--] <path>...]\n"
-msgstr "git log [<选项>] [<从>..<到>] [[--] <路径>...]\n"
-
 #: builtin/log.c:41
+msgid "git log [<options>] [<revision range>] [[--] <path>...]\n"
+msgstr "git log [<选项>] [<版本范围>] [[--] <路径>...]\n"
+
+#: builtin/log.c:42
 msgid "   or: git show [options] <object>..."
 msgstr "   或者:git show [选项] <对象>..."
 
-#: builtin/log.c:103
+#: builtin/log.c:124
 msgid "suppress diff output"
 msgstr "不显示差异输出"
 
-#: builtin/log.c:104
+#: builtin/log.c:125
 msgid "show source"
 msgstr "显示源"
 
-#: builtin/log.c:105
+#: builtin/log.c:126
 msgid "Use mail map file"
 msgstr "使用邮件映射文件"
 
-#: builtin/log.c:106
+#: builtin/log.c:127
 msgid "decorate options"
 msgstr "修饰选项"
 
-#: builtin/log.c:199
+#: builtin/log.c:230
 #, c-format
 msgid "Final output: %d %s\n"
 msgstr "最终输出:%d %s\n"
 
-#: builtin/log.c:422 builtin/log.c:514
+#: builtin/log.c:453 builtin/log.c:545
 #, c-format
 msgid "Could not read object %s"
 msgstr "不能读取对象 %s"
 
-#: builtin/log.c:538
+#: builtin/log.c:569
 #, c-format
 msgid "Unknown type: %d"
 msgstr "未知类型:%d"
 
-#: builtin/log.c:630
+#: builtin/log.c:669
 msgid "format.headers without value"
 msgstr "format.headers 没有值"
 
-#: builtin/log.c:704
+#: builtin/log.c:751
 msgid "name of output directory is too long"
 msgstr "输出目录名太长"
 
-#: builtin/log.c:720
+#: builtin/log.c:767
 #, c-format
 msgid "Cannot open patch file %s"
 msgstr "无法打开补丁文件 %s"
 
-#: builtin/log.c:734
+#: builtin/log.c:781
 msgid "Need exactly one range."
 msgstr "只需要一个范围。"
 
-#: builtin/log.c:742
+#: builtin/log.c:789
 msgid "Not a range."
 msgstr "不是一个范围。"
 
-#: builtin/log.c:815
+#: builtin/log.c:891
 msgid "Cover letter needs email format"
 msgstr "信封需要邮件地址格式"
 
-#: builtin/log.c:888
+#: builtin/log.c:967
 #, c-format
 msgid "insane in-reply-to: %s"
 msgstr "不正常的 in-reply-to:%s"
 
-#: builtin/log.c:916
+#: builtin/log.c:995
 msgid "git format-patch [options] [<since> | <revision range>]"
 msgstr "git format-patch [选项] [<从> | <修订集范围>]"
 
-#: builtin/log.c:961
+#: builtin/log.c:1040
 msgid "Two output directories?"
 msgstr "两个输出目录?"
 
-#: builtin/log.c:1099
+#: builtin/log.c:1155
 msgid "use [PATCH n/m] even with a single patch"
 msgstr "使用 [PATCH n/m],即使只有一个补丁"
 
-#: builtin/log.c:1102
+#: builtin/log.c:1158
 msgid "use [PATCH] even with multiple patches"
 msgstr "使用 [PATCH],即使有多个补丁"
 
-#: builtin/log.c:1106
+#: builtin/log.c:1162
 msgid "print patches to standard out"
 msgstr "打印补丁到标准输出"
 
-#: builtin/log.c:1108
+#: builtin/log.c:1164
 msgid "generate a cover letter"
 msgstr "生成一封附信"
 
-#: builtin/log.c:1110
+#: builtin/log.c:1166
 msgid "use simple number sequence for output file names"
 msgstr "使用简单的数字序列作为输出文件名"
 
-#: builtin/log.c:1111
+#: builtin/log.c:1167
 msgid "sfx"
 msgstr "后缀"
 
-#: builtin/log.c:1112
+#: builtin/log.c:1168
 msgid "use <sfx> instead of '.patch'"
 msgstr "使用 <后缀> 代替 '.patch'"
 
-#: builtin/log.c:1114
+#: builtin/log.c:1170
 msgid "start numbering patches at <n> instead of 1"
 msgstr "补丁以 <n> 开始编号,而不是1"
 
-#: builtin/log.c:1116
+#: builtin/log.c:1172
 msgid "mark the series as Nth re-roll"
 msgstr "标记补丁系列是第几次重制"
 
-#: builtin/log.c:1118
+#: builtin/log.c:1174
 msgid "Use [<prefix>] instead of [PATCH]"
 msgstr "使用 [<前缀>] 代替 [PATCH]"
 
-#: builtin/log.c:1121
+#: builtin/log.c:1177
 msgid "store resulting files in <dir>"
 msgstr "把结果文件存储在 <dir>"
 
-#: builtin/log.c:1124
+#: builtin/log.c:1180
 msgid "don't strip/add [PATCH]"
 msgstr "不删除/添加 [PATCH]"
 
-#: builtin/log.c:1127
+#: builtin/log.c:1183
 msgid "don't output binary diffs"
 msgstr "不输出二进制差异"
 
-#: builtin/log.c:1129
+#: builtin/log.c:1185
 msgid "don't include a patch matching a commit upstream"
 msgstr "不包含已在上游提交中的补丁"
 
-#: builtin/log.c:1131
+#: builtin/log.c:1187
 msgid "show patch format instead of default (patch + stat)"
 msgstr "显示纯补丁格式而非默认的(补丁+状态)"
 
-#: builtin/log.c:1133
+#: builtin/log.c:1189
 msgid "Messaging"
 msgstr "邮件发送"
 
-#: builtin/log.c:1134
+#: builtin/log.c:1190
 msgid "header"
 msgstr "header"
 
-#: builtin/log.c:1135
+#: builtin/log.c:1191
 msgid "add email header"
 msgstr "添加邮件头"
 
-#: builtin/log.c:1136 builtin/log.c:1138
+#: builtin/log.c:1192 builtin/log.c:1194
 msgid "email"
 msgstr "邮件地址"
 
-#: builtin/log.c:1136
+#: builtin/log.c:1192
 msgid "add To: header"
 msgstr "添加收件人"
 
-#: builtin/log.c:1138
+#: builtin/log.c:1194
 msgid "add Cc: header"
 msgstr "添加抄送"
 
-#: builtin/log.c:1140
+#: builtin/log.c:1196
+msgid "ident"
+msgstr "ident"
+
+#: builtin/log.c:1197
+msgid "set From address to <ident> (or committer ident if absent)"
+msgstr "设置 From 地址为 <ident>(如若不提供,用提交者ID做为地址)"
+
+#: builtin/log.c:1199
 msgid "message-id"
 msgstr "message-id"
 
-#: builtin/log.c:1141
+#: builtin/log.c:1200
 msgid "make first mail a reply to <message-id>"
 msgstr "使第一封邮件作为对 <message-id> 的回复"
 
-#: builtin/log.c:1142 builtin/log.c:1145
+#: builtin/log.c:1201 builtin/log.c:1204
 msgid "boundary"
 msgstr "边界"
 
-#: builtin/log.c:1143
+#: builtin/log.c:1202
 msgid "attach the patch"
 msgstr "附件方式添加补丁"
 
-#: builtin/log.c:1146
+#: builtin/log.c:1205
 msgid "inline the patch"
 msgstr "内联显示补丁"
 
-#: builtin/log.c:1150
+#: builtin/log.c:1209
 msgid "enable message threading, styles: shallow, deep"
 msgstr "启用邮件线索,风格:浅,深"
 
-#: builtin/log.c:1152
+#: builtin/log.c:1211
 msgid "signature"
 msgstr "签名"
 
-#: builtin/log.c:1153
+#: builtin/log.c:1212
 msgid "add a signature"
 msgstr "添加一个签名"
 
-#: builtin/log.c:1155
+#: builtin/log.c:1214
 msgid "don't print the patch filenames"
 msgstr "不要打印补丁文件名"
 
-#: builtin/log.c:1239
+#: builtin/log.c:1288
+#, c-format
+msgid "invalid ident line: %s"
+msgstr "包含无效的身份标识:%s"
+
+#: builtin/log.c:1303
 msgid "-n and -k are mutually exclusive."
 msgstr "-n 和 -k 互斥。"
 
-#: builtin/log.c:1241
+#: builtin/log.c:1305
 msgid "--subject-prefix and -k are mutually exclusive."
 msgstr "--subject-prefix 和 -k 互斥。"
 
-#: builtin/log.c:1249
+#: builtin/log.c:1313
 msgid "--name-only does not make sense"
 msgstr "--name-only 无意义"
 
-#: builtin/log.c:1251
+#: builtin/log.c:1315
 msgid "--name-status does not make sense"
 msgstr "--name-status 无意义"
 
-#: builtin/log.c:1253
+#: builtin/log.c:1317
 msgid "--check does not make sense"
 msgstr "--check 无意义"
 
-#: builtin/log.c:1276
+#: builtin/log.c:1340
 msgid "standard output, or directory, which one?"
 msgstr "标准输出或目录,哪一个?"
 
-#: builtin/log.c:1278
+#: builtin/log.c:1342
 #, c-format
 msgid "Could not create directory '%s'"
 msgstr "不能创建目录 '%s'"
 
-#: builtin/log.c:1431
+#: builtin/log.c:1490
 msgid "Failed to create output files"
 msgstr "无法创建输出文件"
 
-#: builtin/log.c:1480
+#: builtin/log.c:1539
 msgid "git cherry [-v] [<upstream> [<head> [<limit>]]]"
 msgstr "git cherry [-v] [<上游> [<头> [<限制>]]]"
 
-#: builtin/log.c:1535
+#: builtin/log.c:1594
 #, c-format
 msgid ""
 "Could not find a tracked remote branch, please specify <upstream> manually.\n"
 msgstr "不能找到跟踪的远程分支,请手工指定 <upstream>。\n"
 
-#: builtin/log.c:1548 builtin/log.c:1550 builtin/log.c:1562
+#: builtin/log.c:1607 builtin/log.c:1609 builtin/log.c:1621
 #, c-format
 msgid "Unknown commit %s"
 msgstr "未知提交 %s"
 
-#: builtin/ls-files.c:409
+#: builtin/ls-files.c:408
 msgid "git ls-files [options] [<file>...]"
 msgstr "git ls-files [选项] [<文件>...]"
 
-#: builtin/ls-files.c:466
+#: builtin/ls-files.c:465
 msgid "identify the file status with tags"
 msgstr "用标签标识文件的状态"
 
-#: builtin/ls-files.c:468
+#: builtin/ls-files.c:467
 msgid "use lowercase letters for 'assume unchanged' files"
 msgstr "使用小写字母表示 '假设未改变的' 文件"
 
-#: builtin/ls-files.c:470
+#: builtin/ls-files.c:469
 msgid "show cached files in the output (default)"
 msgstr "显示缓存的文件(默认)"
 
-#: builtin/ls-files.c:472
+#: builtin/ls-files.c:471
 msgid "show deleted files in the output"
 msgstr "显示已删除的文件"
 
-#: builtin/ls-files.c:474
+#: builtin/ls-files.c:473
 msgid "show modified files in the output"
 msgstr "显示已修改的文件"
 
-#: builtin/ls-files.c:476
+#: builtin/ls-files.c:475
 msgid "show other files in the output"
 msgstr "显示其它文件"
 
-#: builtin/ls-files.c:478
+#: builtin/ls-files.c:477
 msgid "show ignored files in the output"
 msgstr "显示忽略的文件"
 
-#: builtin/ls-files.c:481
+#: builtin/ls-files.c:480
 msgid "show staged contents' object name in the output"
 msgstr "显示暂存区内容的对象名称"
 
-#: builtin/ls-files.c:483
+#: builtin/ls-files.c:482
 msgid "show files on the filesystem that need to be removed"
 msgstr "显示文件系统需要删除的文件"
 
-#: builtin/ls-files.c:485
+#: builtin/ls-files.c:484
 msgid "show 'other' directories' name only"
 msgstr "只显示“其他”目录的名称"
 
-#: builtin/ls-files.c:488
+#: builtin/ls-files.c:487
 msgid "don't show empty directories"
 msgstr "不显示空目录"
 
-#: builtin/ls-files.c:491
+#: builtin/ls-files.c:490
 msgid "show unmerged files in the output"
 msgstr "显示未合并的文件"
 
-#: builtin/ls-files.c:493
+#: builtin/ls-files.c:492
 msgid "show resolve-undo information"
 msgstr "显示 resolve-undo 信息"
 
-#: builtin/ls-files.c:495
+#: builtin/ls-files.c:494
 msgid "skip files matching pattern"
 msgstr "匹配排除文件的模式"
 
-#: builtin/ls-files.c:498
+#: builtin/ls-files.c:497
 msgid "exclude patterns are read from <file>"
 msgstr "从 <文件> 中读取排除模式"
 
-#: builtin/ls-files.c:501
+#: builtin/ls-files.c:500
 msgid "read additional per-directory exclude patterns in <file>"
 msgstr "从 <文件> 读取额外的每个目录的排除模式"
 
-#: builtin/ls-files.c:503
+#: builtin/ls-files.c:502
 msgid "add the standard git exclusions"
 msgstr "添加标准的 git 排除"
 
-#: builtin/ls-files.c:506
+#: builtin/ls-files.c:505
 msgid "make the output relative to the project top directory"
 msgstr "显示相对于顶级目录的文件名"
 
-#: builtin/ls-files.c:509
+#: builtin/ls-files.c:508
 msgid "if any <file> is not in the index, treat this as an error"
 msgstr "如果任何 <文件> 都不在索引区,视为错误"
 
-#: builtin/ls-files.c:510
+#: builtin/ls-files.c:509
 msgid "tree-ish"
 msgstr "树或提交"
 
-#: builtin/ls-files.c:511
+#: builtin/ls-files.c:510
 msgid "pretend that paths removed since <tree-ish> are still present"
 msgstr "假装自从 <树或提交> 之后删除的路径仍然存在"
 
-#: builtin/ls-files.c:513
+#: builtin/ls-files.c:512
 msgid "show debugging data"
 msgstr "显示调试数据"
 
@@ -5974,168 +6397,168 @@
 msgid "git merge --abort"
 msgstr "git merge --abort"
 
-#: builtin/merge.c:90
+#: builtin/merge.c:98
 msgid "switch `m' requires a value"
 msgstr "开关 `m' 需要一个值"
 
-#: builtin/merge.c:127
+#: builtin/merge.c:135
 #, c-format
 msgid "Could not find merge strategy '%s'.\n"
 msgstr "不能找到合并策略 '%s'。\n"
 
-#: builtin/merge.c:128
+#: builtin/merge.c:136
 #, c-format
 msgid "Available strategies are:"
 msgstr "可用的策略有:"
 
-#: builtin/merge.c:133
+#: builtin/merge.c:141
 #, c-format
 msgid "Available custom strategies are:"
 msgstr "可用的自定义策略有:"
 
-#: builtin/merge.c:183
+#: builtin/merge.c:198
 msgid "do not show a diffstat at the end of the merge"
 msgstr "在合并的最后不显示差异统计"
 
-#: builtin/merge.c:186
+#: builtin/merge.c:201
 msgid "show a diffstat at the end of the merge"
 msgstr "在合并的最后显示差异统计"
 
-#: builtin/merge.c:187
+#: builtin/merge.c:202
 msgid "(synonym to --stat)"
 msgstr "(和 --stat 同义)"
 
-#: builtin/merge.c:189
+#: builtin/merge.c:204
 msgid "add (at most <n>) entries from shortlog to merge commit message"
 msgstr "在合并提交信息中添加(最多 <n> 条)精简提交记录"
 
-#: builtin/merge.c:192
+#: builtin/merge.c:207
 msgid "create a single commit instead of doing a merge"
 msgstr "创建一个单独的提交而不是做一次合并"
 
-#: builtin/merge.c:194
+#: builtin/merge.c:209
 msgid "perform a commit if the merge succeeds (default)"
 msgstr "如果合并成功,执行一次提交(默认)"
 
-#: builtin/merge.c:196
+#: builtin/merge.c:211
 msgid "edit message before committing"
 msgstr "在提交前编辑提交说明"
 
-#: builtin/merge.c:198
+#: builtin/merge.c:212
 msgid "allow fast-forward (default)"
 msgstr "允许快进(默认)"
 
-#: builtin/merge.c:200
+#: builtin/merge.c:214
 msgid "abort if fast-forward is not possible"
 msgstr "如果不能快进就放弃合并"
 
-#: builtin/merge.c:203
+#: builtin/merge.c:218
 msgid "Verify that the named commit has a valid GPG signature"
 msgstr "验证指定的提交是否包含一个有效的 GPG 签名"
 
-#: builtin/merge.c:204 builtin/notes.c:866 builtin/revert.c:112
+#: builtin/merge.c:219 builtin/notes.c:738 builtin/revert.c:114
 msgid "strategy"
 msgstr "策略"
 
-#: builtin/merge.c:205
+#: builtin/merge.c:220
 msgid "merge strategy to use"
 msgstr "要使用的合并策略"
 
-#: builtin/merge.c:206
+#: builtin/merge.c:221
 msgid "option=value"
 msgstr "option=value"
 
-#: builtin/merge.c:207
+#: builtin/merge.c:222
 msgid "option for selected merge strategy"
 msgstr "所选的合并策略的选项"
 
-#: builtin/merge.c:209
+#: builtin/merge.c:224
 msgid "merge commit message (for a non-fast-forward merge)"
 msgstr "合并的提交说明(针对非快进式合并)"
 
-#: builtin/merge.c:213
+#: builtin/merge.c:228
 msgid "abort the current in-progress merge"
 msgstr "放弃当前正在进行的合并"
 
-#: builtin/merge.c:242
+#: builtin/merge.c:257
 msgid "could not run stash."
 msgstr "不能进行进度保存。"
 
-#: builtin/merge.c:247
+#: builtin/merge.c:262
 msgid "stash failed"
 msgstr "进度保存失败"
 
-#: builtin/merge.c:252
+#: builtin/merge.c:267
 #, c-format
 msgid "not a valid object: %s"
 msgstr "不是一个有效对象:%s"
 
-#: builtin/merge.c:271 builtin/merge.c:288
+#: builtin/merge.c:286 builtin/merge.c:303
 msgid "read-tree failed"
 msgstr "读取树失败"
 
 #  译者:注意保持前导空格
-#: builtin/merge.c:318
+#: builtin/merge.c:333
 msgid " (nothing to squash)"
 msgstr " (无可压缩)"
 
-#: builtin/merge.c:331
+#: builtin/merge.c:346
 #, c-format
 msgid "Squash commit -- not updating HEAD\n"
 msgstr "压缩提交 -- 未更新 HEAD\n"
 
-#: builtin/merge.c:363
+#: builtin/merge.c:378
 msgid "Writing SQUASH_MSG"
 msgstr "写入 SQUASH_MSG"
 
-#: builtin/merge.c:365
+#: builtin/merge.c:380
 msgid "Finishing SQUASH_MSG"
 msgstr "完成 SQUASH_MSG"
 
-#: builtin/merge.c:388
+#: builtin/merge.c:403
 #, c-format
 msgid "No merge message -- not updating HEAD\n"
 msgstr "无合并信息 -- 未更新 HEAD\n"
 
-#: builtin/merge.c:438
+#: builtin/merge.c:453
 #, c-format
 msgid "'%s' does not point to a commit"
 msgstr "'%s' 没有指向一个提交"
 
-#: builtin/merge.c:550
+#: builtin/merge.c:565
 #, c-format
 msgid "Bad branch.%s.mergeoptions string: %s"
 msgstr "坏的 branch.%s.mergeoptions 字符串:%s"
 
-#: builtin/merge.c:643
+#: builtin/merge.c:657
 msgid "git write-tree failed to write a tree"
 msgstr "git write-tree 无法写入一树对象"
 
-#: builtin/merge.c:671
+#: builtin/merge.c:685
 msgid "Not handling anything other than two heads merge."
 msgstr "不能处理两个头合并之外的任何操作。"
 
-#: builtin/merge.c:685
+#: builtin/merge.c:699
 #, c-format
 msgid "Unknown option for merge-recursive: -X%s"
 msgstr "merge-recursive 的未知选项:-X%s"
 
-#: builtin/merge.c:699
+#: builtin/merge.c:713
 #, c-format
 msgid "unable to write %s"
 msgstr "不能写 %s"
 
-#: builtin/merge.c:788
+#: builtin/merge.c:802
 #, c-format
 msgid "Could not read from '%s'"
 msgstr "不能从 '%s' 读取"
 
-#: builtin/merge.c:797
+#: builtin/merge.c:811
 #, c-format
 msgid "Not committing merge; use 'git commit' to complete the merge.\n"
 msgstr "未提交合并,使用 'git commit' 完成此次合并。\n"
 
-#: builtin/merge.c:803
+#: builtin/merge.c:817
 #, c-format
 msgid ""
 "Please enter a commit message to explain why this merge is necessary,\n"
@@ -6149,52 +6572,47 @@
 "\n"
 "以 '%c' 开头的行将被忽略,而且空提交说明将会终止提交。\n"
 
-#: builtin/merge.c:827
+#: builtin/merge.c:841
 msgid "Empty commit message."
 msgstr "空提交信息。"
 
-#: builtin/merge.c:839
+#: builtin/merge.c:853
 #, c-format
 msgid "Wonderful.\n"
 msgstr "太棒了。\n"
 
-#: builtin/merge.c:904
+#: builtin/merge.c:918
 #, c-format
 msgid "Automatic merge failed; fix conflicts and then commit the result.\n"
 msgstr "自动合并失败,修正冲突然后提交修正的结果。\n"
 
-#: builtin/merge.c:920
+#: builtin/merge.c:934
 #, c-format
 msgid "'%s' is not a commit"
 msgstr "'%s' 不是一个提交"
 
-#: builtin/merge.c:961
+#: builtin/merge.c:975
 msgid "No current branch."
 msgstr "没有当前分支。"
 
-#: builtin/merge.c:963
+#: builtin/merge.c:977
 msgid "No remote for the current branch."
 msgstr "当前分支没有对应的远程版本库。"
 
-#: builtin/merge.c:965
+#: builtin/merge.c:979
 msgid "No default upstream defined for the current branch."
 msgstr "当前分支没有定义默认的上游分支。"
 
-#: builtin/merge.c:970
+#: builtin/merge.c:984
 #, c-format
-msgid "No remote tracking branch for %s from %s"
-msgstr "%s 没有来自 %s 的远程跟踪分支"
+msgid "No remote-tracking branch for %s from %s"
+msgstr "对于 %s 没有来自 %s 的远程跟踪分支"
 
-#: builtin/merge.c:1057 builtin/merge.c:1214
-#, c-format
-msgid "%s - not something we can merge"
-msgstr "%s - 不能被合并"
-
-#: builtin/merge.c:1125
+#: builtin/merge.c:1140
 msgid "There is no merge to abort (MERGE_HEAD missing)."
 msgstr "没有要终止的合并(MERGE_HEAD 丢失)。"
 
-#: builtin/merge.c:1141 git-pull.sh:31
+#: builtin/merge.c:1156 git-pull.sh:31
 msgid ""
 "You have not concluded your merge (MERGE_HEAD exists).\n"
 "Please, commit your changes before you can merge."
@@ -6202,11 +6620,11 @@
 "您尚未结束您的合并(存在 MERGE_HEAD)。\n"
 "请在合并前先提交您的修改。"
 
-#: builtin/merge.c:1144 git-pull.sh:34
+#: builtin/merge.c:1159 git-pull.sh:34
 msgid "You have not concluded your merge (MERGE_HEAD exists)."
 msgstr "您尚未结束您的合并(存在 MERGE_HEAD)。"
 
-#: builtin/merge.c:1148
+#: builtin/merge.c:1163
 msgid ""
 "You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists).\n"
 "Please, commit your changes before you can merge."
@@ -6214,100 +6632,101 @@
 "您尚未结束您的拣选(存在 CHERRY_PICK_HEAD)。\n"
 "请在合并前先提交您的修改。"
 
-#: builtin/merge.c:1151
+#: builtin/merge.c:1166
 msgid "You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists)."
 msgstr "您尚未结束您的拣选(存在 CHERRY_PICK_HEAD)。"
 
-#: builtin/merge.c:1160
+#: builtin/merge.c:1175
 msgid "You cannot combine --squash with --no-ff."
 msgstr "您不能将 --squash 与 --no-ff 同时使用。"
 
-#: builtin/merge.c:1165
-msgid "You cannot combine --no-ff with --ff-only."
-msgstr "您不能将 --no-ff 与 --ff-only 同时使用。"
-
-#: builtin/merge.c:1172
+#: builtin/merge.c:1184
 msgid "No commit specified and merge.defaultToUpstream not set."
 msgstr "未指定提交并且 merge.defaultToUpstream 未设置。"
 
-#: builtin/merge.c:1204
+#: builtin/merge.c:1216
 msgid "Can merge only exactly one commit into empty head"
 msgstr "只能将一个提交合并到空分支上"
 
-#: builtin/merge.c:1207
+#: builtin/merge.c:1219
 msgid "Squash commit into empty head not supported yet"
 msgstr "尚不支持到空分支的压缩提交"
 
-#: builtin/merge.c:1209
+#: builtin/merge.c:1221
 msgid "Non-fast-forward commit does not make sense into an empty head"
 msgstr "到空分支的非快进式提交没有意义"
 
-#: builtin/merge.c:1265
+#: builtin/merge.c:1226
+#, c-format
+msgid "%s - not something we can merge"
+msgstr "%s - 不能被合并"
+
+#: builtin/merge.c:1277
 #, c-format
 msgid "Commit %s has an untrusted GPG signature, allegedly by %s."
 msgstr "提交 %s 有一个非可信的声称来自 %s 的 GPG 签名。"
 
-#: builtin/merge.c:1268
+#: builtin/merge.c:1280
 #, c-format
 msgid "Commit %s has a bad GPG signature allegedly by %s."
 msgstr "提交 %s 有一个错误的声称来自 %s 的 GPG 签名。"
 
 #. 'N'
-#: builtin/merge.c:1271
+#: builtin/merge.c:1283
 #, c-format
 msgid "Commit %s does not have a GPG signature."
 msgstr "提交 %s 没有一个 GPG 签名。"
 
-#: builtin/merge.c:1274
+#: builtin/merge.c:1286
 #, c-format
 msgid "Commit %s has a good GPG signature by %s\n"
 msgstr "提交 %s 有一个来自 %s 的好的 GPG 签名。\n"
 
-#: builtin/merge.c:1358
+#: builtin/merge.c:1370
 #, c-format
 msgid "Updating %s..%s\n"
 msgstr "更新 %s..%s\n"
 
-#: builtin/merge.c:1397
+#: builtin/merge.c:1409
 #, c-format
 msgid "Trying really trivial in-index merge...\n"
 msgstr "尝试非常小的索引内合并...\n"
 
-#: builtin/merge.c:1404
+#: builtin/merge.c:1416
 #, c-format
 msgid "Nope.\n"
 msgstr "无。\n"
 
-#: builtin/merge.c:1436
+#: builtin/merge.c:1448
 msgid "Not possible to fast-forward, aborting."
 msgstr "无法快进,终止。"
 
-#: builtin/merge.c:1459 builtin/merge.c:1538
+#: builtin/merge.c:1471 builtin/merge.c:1550
 #, c-format
 msgid "Rewinding the tree to pristine...\n"
 msgstr "将树回滚至原始状态...\n"
 
-#: builtin/merge.c:1463
+#: builtin/merge.c:1475
 #, c-format
 msgid "Trying merge strategy %s...\n"
 msgstr "尝试合并策略 %s...\n"
 
-#: builtin/merge.c:1529
+#: builtin/merge.c:1541
 #, c-format
 msgid "No merge strategy handled the merge.\n"
 msgstr "没有合并策略处理此合并。\n"
 
-#: builtin/merge.c:1531
+#: builtin/merge.c:1543
 #, c-format
 msgid "Merge with strategy %s failed.\n"
 msgstr "使用策略 %s 合并失败。\n"
 
-#: builtin/merge.c:1540
+#: builtin/merge.c:1552
 #, c-format
 msgid "Using the %s to prepare resolving by hand.\n"
 msgstr "使用 %s 以准备手工解决。\n"
 
-#: builtin/merge.c:1552
+#: builtin/merge.c:1564
 #, c-format
 msgid "Automatic merge went well; stopped before committing as requested\n"
 msgstr "自动合并进展顺利,按要求在提交前停止\n"
@@ -6473,47 +6892,51 @@
 msgid "renaming '%s' failed"
 msgstr "重命名 '%s' 失败"
 
-#: builtin/name-rev.c:175
+#: builtin/name-rev.c:259
 msgid "git name-rev [options] <commit>..."
 msgstr "git name-rev [选项] <提交>..."
 
-#: builtin/name-rev.c:176
+#: builtin/name-rev.c:260
 msgid "git name-rev [options] --all"
 msgstr "git name-rev [选项] --all"
 
-#: builtin/name-rev.c:177
+#: builtin/name-rev.c:261
 msgid "git name-rev [options] --stdin"
 msgstr "git name-rev [选项] --stdin"
 
-#: builtin/name-rev.c:229
+#: builtin/name-rev.c:313
 msgid "print only names (no SHA-1)"
 msgstr "只打印名称(无 SHA-1)"
 
-#: builtin/name-rev.c:230
+#: builtin/name-rev.c:314
 msgid "only use tags to name the commits"
 msgstr "只使用 tags 来命名提交"
 
-#: builtin/name-rev.c:232
+#: builtin/name-rev.c:316
 msgid "only use refs matching <pattern>"
 msgstr "只使用和 <模式> 相匹配的引用"
 
-#: builtin/name-rev.c:234
+#: builtin/name-rev.c:318
 msgid "list all commits reachable from all refs"
 msgstr "列出可以从所有引用访问的提交"
 
-#: builtin/name-rev.c:235
+#: builtin/name-rev.c:319
 msgid "read from stdin"
 msgstr "从标准输入读取"
 
-#: builtin/name-rev.c:236
+#: builtin/name-rev.c:320
 msgid "allow to print `undefined` names"
 msgstr "允许打印 `未定义` 的名称"
 
-#: builtin/notes.c:26
+#: builtin/name-rev.c:326
+msgid "dereference tags in the input (internal use)"
+msgstr "反向解析输入中的 tags(内部使用)"
+
+#: builtin/notes.c:24
 msgid "git notes [--ref <notes_ref>] [list [<object>]]"
 msgstr "git notes [--ref <注解引用>] [list [<对象>]]"
 
-#: builtin/notes.c:27
+#: builtin/notes.c:25
 msgid ""
 "git notes [--ref <notes_ref>] add [-f] [-m <msg> | -F <file> | (-c | -C) "
 "<object>] [<object>]"
@@ -6521,11 +6944,11 @@
 "git notes [--ref <注解引用>] add [-f] [-m <说明> | -F <文件> | (-c | -C) <对"
 "象>] [<对象>]"
 
-#: builtin/notes.c:28
+#: builtin/notes.c:26
 msgid "git notes [--ref <notes_ref>] copy [-f] <from-object> <to-object>"
 msgstr "git notes [--ref <注解引用>] copy [-f] <源对象> <目标对象>"
 
-#: builtin/notes.c:29
+#: builtin/notes.c:27
 msgid ""
 "git notes [--ref <notes_ref>] append [-m <msg> | -F <file> | (-c | -C) "
 "<object>] [<object>]"
@@ -6533,255 +6956,234 @@
 "git notes [--ref <注解引用>] append [-m <说明> | -F <文件> | (-c | -C) <对象"
 ">] [<对象>]"
 
-#: builtin/notes.c:30
+#: builtin/notes.c:28
 msgid "git notes [--ref <notes_ref>] edit [<object>]"
 msgstr "git notes [--ref <注解引用>] edit [<对象>]"
 
-#: builtin/notes.c:31
+#: builtin/notes.c:29
 msgid "git notes [--ref <notes_ref>] show [<object>]"
 msgstr "git notes [--ref <注解引用>] show [<对象>]"
 
-#: builtin/notes.c:32
+#: builtin/notes.c:30
 msgid ""
 "git notes [--ref <notes_ref>] merge [-v | -q] [-s <strategy> ] <notes_ref>"
 msgstr "git notes [--ref <注解引用>] merge [-v | -q] [-s <策略> ] <注解引用>"
 
-#: builtin/notes.c:33
+#: builtin/notes.c:31
 msgid "git notes merge --commit [-v | -q]"
 msgstr "git notes merge --commit [-v | -q]"
 
-#: builtin/notes.c:34
+#: builtin/notes.c:32
 msgid "git notes merge --abort [-v | -q]"
 msgstr "git notes merge --abort [-v | -q]"
 
-#: builtin/notes.c:35
+#: builtin/notes.c:33
 msgid "git notes [--ref <notes_ref>] remove [<object>...]"
 msgstr "git notes [--ref <注解引用>] remove [<对象>...]"
 
-#: builtin/notes.c:36
+#: builtin/notes.c:34
 msgid "git notes [--ref <notes_ref>] prune [-n | -v]"
 msgstr "git notes [--ref <注解引用>] prune [-n | -v]"
 
-#: builtin/notes.c:37
+#: builtin/notes.c:35
 msgid "git notes [--ref <notes_ref>] get-ref"
 msgstr "git notes [--ref <注解引用>] get-ref"
 
-#: builtin/notes.c:42
+#: builtin/notes.c:40
 msgid "git notes [list [<object>]]"
 msgstr "git notes [list [<对象>]]"
 
-#: builtin/notes.c:47
+#: builtin/notes.c:45
 msgid "git notes add [<options>] [<object>]"
 msgstr "git notes add [<选项>] [<对象>]"
 
-#: builtin/notes.c:52
+#: builtin/notes.c:50
 msgid "git notes copy [<options>] <from-object> <to-object>"
 msgstr "git notes copy [<选项>] <源对象> <目标对象>"
 
-#: builtin/notes.c:53
+#: builtin/notes.c:51
 msgid "git notes copy --stdin [<from-object> <to-object>]..."
 msgstr "git notes copy --stdin [<源对象> <目标对象>]..."
 
-#: builtin/notes.c:58
+#: builtin/notes.c:56
 msgid "git notes append [<options>] [<object>]"
 msgstr "git notes append [<选项>] [<对象>]"
 
-#: builtin/notes.c:63
+#: builtin/notes.c:61
 msgid "git notes edit [<object>]"
 msgstr "git notes edit [<对象>]"
 
-#: builtin/notes.c:68
+#: builtin/notes.c:66
 msgid "git notes show [<object>]"
 msgstr "git notes show [<对象>]"
 
-#: builtin/notes.c:73
+#: builtin/notes.c:71
 msgid "git notes merge [<options>] <notes_ref>"
 msgstr "git notes merge [<选项>] <注解引用>"
 
-#: builtin/notes.c:74
+#: builtin/notes.c:72
 msgid "git notes merge --commit [<options>]"
 msgstr "git notes merge --commit [<选项>]"
 
-#: builtin/notes.c:75
+#: builtin/notes.c:73
 msgid "git notes merge --abort [<options>]"
 msgstr "git notes merge --abort [<选项>]"
 
-#: builtin/notes.c:80
+#: builtin/notes.c:78
 msgid "git notes remove [<object>]"
 msgstr "git notes remove [<对象>]"
 
-#: builtin/notes.c:85
+#: builtin/notes.c:83
 msgid "git notes prune [<options>]"
 msgstr "git notes prune [<选项>]"
 
-#: builtin/notes.c:90
+#: builtin/notes.c:88
 msgid "git notes get-ref"
 msgstr "git notes get-ref"
 
-#: builtin/notes.c:139
+#: builtin/notes.c:137
 #, c-format
 msgid "unable to start 'show' for object '%s'"
 msgstr "不能为对象 '%s' 开始 'show'"
 
-#: builtin/notes.c:143
+#: builtin/notes.c:141
 msgid "could not read 'show' output"
 msgstr "不能读取 'show' 的输出"
 
-#: builtin/notes.c:151
+#: builtin/notes.c:149
 #, c-format
 msgid "failed to finish 'show' for object '%s'"
 msgstr "无法为对象 '%s' 完成 'show'"
 
-#: builtin/notes.c:169 builtin/tag.c:341
+#: builtin/notes.c:167 builtin/tag.c:341
 #, c-format
 msgid "could not create file '%s'"
 msgstr "不能创建文件 '%s'"
 
-#: builtin/notes.c:188
+#: builtin/notes.c:186
 msgid "Please supply the note contents using either -m or -F option"
 msgstr "请通过 -m 或 -F 选项为注解提供内容"
 
-#: builtin/notes.c:209 builtin/notes.c:972
+#: builtin/notes.c:207 builtin/notes.c:844
 #, c-format
 msgid "Removing note for object %s\n"
 msgstr "删除对象 %s 的注解\n"
 
-#: builtin/notes.c:214
+#: builtin/notes.c:212
 msgid "unable to write note object"
 msgstr "不能写注解对象"
 
-#: builtin/notes.c:216
+#: builtin/notes.c:214
 #, c-format
 msgid "The note contents has been left in %s"
 msgstr "注解内容被留在文件 %s 中"
 
-#: builtin/notes.c:250 builtin/tag.c:540
+#: builtin/notes.c:248 builtin/tag.c:540
 #, c-format
 msgid "cannot read '%s'"
 msgstr "不能读取 '%s'"
 
-#: builtin/notes.c:252 builtin/tag.c:543
+#: builtin/notes.c:250 builtin/tag.c:543
 #, c-format
 msgid "could not open or read '%s'"
 msgstr "不能打开或读取 '%s'"
 
-#: builtin/notes.c:271 builtin/notes.c:444 builtin/notes.c:446
-#: builtin/notes.c:506 builtin/notes.c:560 builtin/notes.c:643
-#: builtin/notes.c:648 builtin/notes.c:723 builtin/notes.c:765
-#: builtin/notes.c:967 builtin/tag.c:556
+#: builtin/notes.c:269 builtin/notes.c:316 builtin/notes.c:318
+#: builtin/notes.c:378 builtin/notes.c:432 builtin/notes.c:515
+#: builtin/notes.c:520 builtin/notes.c:595 builtin/notes.c:637
+#: builtin/notes.c:839 builtin/tag.c:556
 #, c-format
 msgid "Failed to resolve '%s' as a valid ref."
 msgstr "无法解析 '%s' 为一个有效引用。"
 
-#: builtin/notes.c:274
+#: builtin/notes.c:272
 #, c-format
 msgid "Failed to read object '%s'."
 msgstr "无法读取对象 '%s'。"
 
-#: builtin/notes.c:298
-msgid "Cannot commit uninitialized/unreferenced notes tree"
-msgstr "不能提交未初始化/未引用的注解树"
-
-#: builtin/notes.c:339
-#, c-format
-msgid "Bad notes.rewriteMode value: '%s'"
-msgstr "坏的 notes.rewriteMode 值:'%s'"
-
-#: builtin/notes.c:349
-#, c-format
-msgid "Refusing to rewrite notes in %s (outside of refs/notes/)"
-msgstr "拒绝向 %s(在 refs/notes/ 之外)写入注解"
-
-#. TRANSLATORS: The first %s is the name of the
-#. environment variable, the second %s is its value
-#: builtin/notes.c:376
-#, c-format
-msgid "Bad %s value: '%s'"
-msgstr "坏的 %s 值:'%s'"
-
-#: builtin/notes.c:440
+#: builtin/notes.c:312
 #, c-format
 msgid "Malformed input line: '%s'."
 msgstr "非法的输入行:'%s'。"
 
-#: builtin/notes.c:455
+#: builtin/notes.c:327
 #, c-format
 msgid "Failed to copy notes from '%s' to '%s'"
 msgstr "无法从 '%s' 到 '%s' 拷贝注解"
 
-#: builtin/notes.c:499 builtin/notes.c:553 builtin/notes.c:626
-#: builtin/notes.c:638 builtin/notes.c:711 builtin/notes.c:758
-#: builtin/notes.c:1032
+#: builtin/notes.c:371 builtin/notes.c:425 builtin/notes.c:498
+#: builtin/notes.c:510 builtin/notes.c:583 builtin/notes.c:630
+#: builtin/notes.c:904
 msgid "too many parameters"
 msgstr "参数太多"
 
-#: builtin/notes.c:512 builtin/notes.c:771
+#: builtin/notes.c:384 builtin/notes.c:643
 #, c-format
 msgid "No note found for object %s."
 msgstr "未发现对象 %s 的注解。"
 
-#: builtin/notes.c:534 builtin/notes.c:691
+#: builtin/notes.c:406 builtin/notes.c:563
 msgid "note contents as a string"
 msgstr "注解内容作为一个字符串"
 
-#: builtin/notes.c:537 builtin/notes.c:694
+#: builtin/notes.c:409 builtin/notes.c:566
 msgid "note contents in a file"
 msgstr "注解内容到一个文件中"
 
-#: builtin/notes.c:539 builtin/notes.c:542 builtin/notes.c:696
-#: builtin/notes.c:699 builtin/tag.c:474
+#: builtin/notes.c:411 builtin/notes.c:414 builtin/notes.c:568
+#: builtin/notes.c:571 builtin/tag.c:474
 msgid "object"
 msgstr "对象"
 
-#: builtin/notes.c:540 builtin/notes.c:697
+#: builtin/notes.c:412 builtin/notes.c:569
 msgid "reuse and edit specified note object"
 msgstr "重用和编辑指定的注解对象"
 
-#: builtin/notes.c:543 builtin/notes.c:700
+#: builtin/notes.c:415 builtin/notes.c:572
 msgid "reuse specified note object"
 msgstr "重用指定的注解对象"
 
-#: builtin/notes.c:545 builtin/notes.c:613
+#: builtin/notes.c:417 builtin/notes.c:485
 msgid "replace existing notes"
 msgstr "替换已存在的注解"
 
-#: builtin/notes.c:579
+#: builtin/notes.c:451
 #, c-format
 msgid ""
 "Cannot add notes. Found existing notes for object %s. Use '-f' to overwrite "
 "existing notes"
 msgstr "不能添加注解。发现对象 %s 已存在注解。使用 '-f' 覆盖现存注解"
 
-#: builtin/notes.c:584 builtin/notes.c:661
+#: builtin/notes.c:456 builtin/notes.c:533
 #, c-format
 msgid "Overwriting existing notes for object %s\n"
 msgstr "覆盖对象 %s 现存注解\n"
 
-#: builtin/notes.c:614
+#: builtin/notes.c:486
 msgid "read objects from stdin"
 msgstr "从标准输入读取对象"
 
-#: builtin/notes.c:616
+#: builtin/notes.c:488
 msgid "load rewriting config for <command> (implies --stdin)"
 msgstr "重新加载 <命令> 的配置(隐含 --stdin)"
 
-#: builtin/notes.c:634
+#: builtin/notes.c:506
 msgid "too few parameters"
 msgstr "参数太少"
 
-#: builtin/notes.c:655
+#: builtin/notes.c:527
 #, c-format
 msgid ""
 "Cannot copy notes. Found existing notes for object %s. Use '-f' to overwrite "
 "existing notes"
 msgstr "不能拷贝注解。发现对象 %s 已存在注解。使用 '-f' 覆盖现存注解"
 
-#: builtin/notes.c:667
+#: builtin/notes.c:539
 #, c-format
 msgid "Missing notes on source object %s. Cannot copy."
 msgstr "源对象 %s 缺少注解。不能拷贝。"
 
-#: builtin/notes.c:716
+#: builtin/notes.c:588
 #, c-format
 msgid ""
 "The -m/-F/-c/-C options have been deprecated for the 'edit' subcommand.\n"
@@ -6790,58 +7192,58 @@
 "子命令 'edit' 的选项 -m/-F/-c/-C 已弃用。\n"
 "请换用 'git notes add -f -m/-F/-c/-C'。\n"
 
-#: builtin/notes.c:863
+#: builtin/notes.c:735
 msgid "General options"
 msgstr "通用选项"
 
-#: builtin/notes.c:865
+#: builtin/notes.c:737
 msgid "Merge options"
 msgstr "合并选项"
 
-#: builtin/notes.c:867
+#: builtin/notes.c:739
 msgid ""
 "resolve notes conflicts using the given strategy (manual/ours/theirs/union/"
 "cat_sort_uniq)"
 msgstr "使用指定的策略解决注解冲突 (manual/ours/theirs/union/cat_sort_uniq)"
 
-#: builtin/notes.c:869
+#: builtin/notes.c:741
 msgid "Committing unmerged notes"
 msgstr "提交未合并的注解"
 
-#: builtin/notes.c:871
+#: builtin/notes.c:743
 msgid "finalize notes merge by committing unmerged notes"
 msgstr "通过提交未合并的注解来完成注解合并"
 
-#: builtin/notes.c:873
+#: builtin/notes.c:745
 msgid "Aborting notes merge resolution"
 msgstr "中止注解合并的方案"
 
-#: builtin/notes.c:875
+#: builtin/notes.c:747
 msgid "abort notes merge"
 msgstr "中止注解合并"
 
-#: builtin/notes.c:970
+#: builtin/notes.c:842
 #, c-format
 msgid "Object %s has no note\n"
 msgstr "对象 %s 没有注解\n"
 
-#: builtin/notes.c:982
+#: builtin/notes.c:854
 msgid "attempt to remove non-existent note is not an error"
 msgstr "尝试删除不存在的注解不是一个错误"
 
-#: builtin/notes.c:985
+#: builtin/notes.c:857
 msgid "read object names from the standard input"
 msgstr "从标准输入读取对象名称"
 
-#: builtin/notes.c:1066
+#: builtin/notes.c:938
 msgid "notes_ref"
 msgstr "注解引用"
 
-#: builtin/notes.c:1067
+#: builtin/notes.c:939
 msgid "use notes from <notes_ref>"
 msgstr "从 <注解引用> 使用注解"
 
-#: builtin/notes.c:1102 builtin/remote.c:1598
+#: builtin/notes.c:974 builtin/remote.c:1598
 #, c-format
 msgid "Unknown subcommand: %s"
 msgstr "未知子命令:%s"
@@ -7075,7 +7477,7 @@
 "    git push %s %s\n"
 "%s"
 
-#: builtin/push.c:121
+#: builtin/push.c:117
 #, c-format
 msgid ""
 "You are not currently on a branch.\n"
@@ -7089,7 +7491,7 @@
 "\n"
 "    git push %s HEAD:<name-of-remote-branch>\n"
 
-#: builtin/push.c:128
+#: builtin/push.c:131
 #, c-format
 msgid ""
 "The current branch %s has no upstream branch.\n"
@@ -7102,12 +7504,12 @@
 "\n"
 "    git push --set-upstream %s %s\n"
 
-#: builtin/push.c:136
+#: builtin/push.c:139
 #, c-format
 msgid "The current branch %s has multiple upstream branches, refusing to push."
 msgstr "当前分支 %s 有多个上游分支,拒绝推送。"
 
-#: builtin/push.c:139
+#: builtin/push.c:142
 #, c-format
 msgid ""
 "You are pushing to remote '%s', which is not the upstream of\n"
@@ -7118,7 +7520,7 @@
 "而没有告诉我要推送什么、更新哪个远程分支。"
 
 #  译者:字符串首行行首要添加“warning: ”字串,故此首行要较其余行短
-#: builtin/push.c:151
+#: builtin/push.c:165
 msgid ""
 "push.default is unset; its implicit value is changing in\n"
 "Git 2.0 from 'matching' to 'simple'. To squelch this message\n"
@@ -7149,23 +7551,23 @@
 "('simple' 模式由 Git 1.7.11 版本引入。如果您有时要使用老版本的 Git,\n"
 "为保持兼容,请用 'current' 代替 'simple' 模式)"
 
-#: builtin/push.c:199
+#: builtin/push.c:225
 msgid ""
 "You didn't specify any refspecs to push, and push.default is \"nothing\"."
 msgstr "您没有为推送指定任何引用表达式,并且 push.default 为 \"nothing\"。"
 
-#: builtin/push.c:206
+#: builtin/push.c:232
 msgid ""
 "Updates were rejected because the tip of your current branch is behind\n"
-"its remote counterpart. Merge the remote changes (e.g. 'git pull')\n"
-"before pushing again.\n"
+"its remote counterpart. Integrate the remote changes (e.g.\n"
+"'git pull ...') before pushing again.\n"
 "See the 'Note about fast-forwards' in 'git push --help' for details."
 msgstr ""
 "更新被拒绝,因为您当前分支的最新提交落后于其对应的远程分支。\n"
-"再次推送前,先与远程变更合并(如 'git pull')。详见\n"
+"再次推送前,先与远程变更合并(如 'git pull ...')。详见\n"
 "'git push --help' 中的 'Note about fast-forwards' 小节。"
 
-#: builtin/push.c:212
+#: builtin/push.c:238
 msgid ""
 "Updates were rejected because a pushed branch tip is behind its remote\n"
 "counterpart. If you did not intend to push that branch, you may want to\n"
@@ -7177,35 +7579,35 @@
 "配置变量 'push.default' 设置为 'simple'、'current' 或 'upstream'\n"
 "以便只推送当前分支。"
 
-#: builtin/push.c:218
+#: builtin/push.c:244
 msgid ""
 "Updates were rejected because a pushed branch tip is behind its remote\n"
-"counterpart. Check out this branch and merge the remote changes\n"
-"(e.g. 'git pull') before pushing again.\n"
+"counterpart. Check out this branch and integrate the remote changes\n"
+"(e.g. 'git pull ...') before pushing again.\n"
 "See the 'Note about fast-forwards' in 'git push --help' for details."
 msgstr ""
 "更新被拒绝,因为推送的一个分支的最新提交落后于其对应的远程分支。\n"
-"检出该分支并与远程变更合并(如 'git pull'),然后再推送。详见\n"
+"检出该分支并整合远程变更(如 'git pull ...'),然后再推送。详见\n"
 "'git push --help' 中的 'Note about fast-forwards' 小节。"
 
-#: builtin/push.c:224
+#: builtin/push.c:250
 msgid ""
 "Updates were rejected because the remote contains work that you do\n"
 "not have locally. This is usually caused by another repository pushing\n"
-"to the same ref. You may want to first merge the remote changes (e.g.,\n"
-"'git pull') before pushing again.\n"
+"to the same ref. You may want to first integrate the remote changes\n"
+"(e.g., 'git pull ...') before pushing again.\n"
 "See the 'Note about fast-forwards' in 'git push --help' for details."
 msgstr ""
 "更新被拒绝,因为远程版本库包含您本地尚不存在的提交。这通常是因为另外\n"
-"一个版本库已推送了相同的引用。再次推送前,您可能需要先合并远程变更\n"
-"(如 'git pull')。\n"
+"一个版本库已向该引用进行了推送。再次推送前,您可能需要先整合远程变更\n"
+"(如 'git pull ...')。\n"
 "详见 'git push --help' 中的 'Note about fast-forwards' 小节。"
 
-#: builtin/push.c:231
+#: builtin/push.c:257
 msgid "Updates were rejected because the tag already exists in the remote."
 msgstr "更新被拒绝因为 tag 在远程已经存在。"
 
-#: builtin/push.c:234
+#: builtin/push.c:260
 msgid ""
 "You cannot update a remote ref that points at a non-commit object,\n"
 "or update a remote ref to make it point at a non-commit object,\n"
@@ -7214,22 +7616,22 @@
 "如果不使用 '--force' 参数,您不能更新一个指向非提交对象的远程引用,\n"
 "也不能更新远程引用让其指向一个非提交对象。\n"
 
-#: builtin/push.c:294
+#: builtin/push.c:320
 #, c-format
 msgid "Pushing to %s\n"
 msgstr "推送到 %s\n"
 
-#: builtin/push.c:298
+#: builtin/push.c:324
 #, c-format
 msgid "failed to push some refs to '%s'"
 msgstr "无法推送一些引用到 '%s'"
 
-#: builtin/push.c:331
+#: builtin/push.c:357
 #, c-format
 msgid "bad repository '%s'"
 msgstr "坏的版本库 '%s'"
 
-#: builtin/push.c:332
+#: builtin/push.c:358
 msgid ""
 "No configured push destination.\n"
 "Either specify the URL from the command-line or configure a remote "
@@ -7250,87 +7652,87 @@
 "\n"
 "    git push <name>\n"
 
-#: builtin/push.c:347
+#: builtin/push.c:373
 msgid "--all and --tags are incompatible"
 msgstr "--all 和 --tags 不兼容"
 
-#: builtin/push.c:348
+#: builtin/push.c:374
 msgid "--all can't be combined with refspecs"
 msgstr "--all 不能和引用表达式同时使用"
 
-#: builtin/push.c:353
+#: builtin/push.c:379
 msgid "--mirror and --tags are incompatible"
 msgstr "--mirror 和 --tags 不兼容"
 
-#: builtin/push.c:354
+#: builtin/push.c:380
 msgid "--mirror can't be combined with refspecs"
 msgstr "--mirror 不能和引用表达式同时使用"
 
-#: builtin/push.c:359
+#: builtin/push.c:385
 msgid "--all and --mirror are incompatible"
 msgstr "--all 和 --mirror 不兼容"
 
-#: builtin/push.c:419
+#: builtin/push.c:445
 msgid "repository"
 msgstr "版本库"
 
-#: builtin/push.c:420
+#: builtin/push.c:446
 msgid "push all refs"
 msgstr "推送所有引用"
 
-#: builtin/push.c:421
+#: builtin/push.c:447
 msgid "mirror all refs"
 msgstr "镜像所有引用"
 
-#: builtin/push.c:423
+#: builtin/push.c:449
 msgid "delete refs"
 msgstr "删除引用"
 
-#: builtin/push.c:424
+#: builtin/push.c:450
 msgid "push tags (can't be used with --all or --mirror)"
 msgstr "推送 tags(不能使用 --all or --mirror)"
 
-#: builtin/push.c:427
+#: builtin/push.c:453
 msgid "force updates"
 msgstr "强制更新"
 
-#: builtin/push.c:428
+#: builtin/push.c:454
 msgid "check"
 msgstr "检查"
 
-#: builtin/push.c:429
+#: builtin/push.c:455
 msgid "control recursive pushing of submodules"
 msgstr "控制子模组的递归推送"
 
-#: builtin/push.c:431
+#: builtin/push.c:457
 msgid "use thin pack"
 msgstr "使用精简打包"
 
-#: builtin/push.c:432 builtin/push.c:433
+#: builtin/push.c:458 builtin/push.c:459
 msgid "receive pack program"
 msgstr "接收包程序"
 
-#: builtin/push.c:434
+#: builtin/push.c:460
 msgid "set upstream for git pull/status"
 msgstr "设置 git pull/status 的上游"
 
-#: builtin/push.c:437
+#: builtin/push.c:463
 msgid "prune locally removed refs"
 msgstr "清除本地删除的引用"
 
-#: builtin/push.c:439
+#: builtin/push.c:465
 msgid "bypass pre-push hook"
 msgstr "绕过 pre-push 钩子"
 
-#: builtin/push.c:440
+#: builtin/push.c:466
 msgid "push missing but relevant tags"
 msgstr "推送缺失的有关的 tags"
 
-#: builtin/push.c:450
+#: builtin/push.c:476
 msgid "--delete is incompatible with --all, --mirror and --tags"
 msgstr "--delete 与 --all、--mirror 及 --tags 不兼容"
 
-#: builtin/push.c:452
+#: builtin/push.c:478
 msgid "--delete doesn't make sense without any refs"
 msgstr "--delete 未接任何引用没有意义"
 
@@ -7344,70 +7746,80 @@
 "u [--exclude-per-directory=<gitignore>] | -i]] [--no-sparse-checkout] [--"
 "index-output=<文件>] (--empty | <树或提交1> [<树或提交2> [<树或提交3>]])"
 
-#: builtin/read-tree.c:108
+#: builtin/read-tree.c:109
 msgid "write resulting index to <file>"
 msgstr "将索引结果写入 <file>"
 
-#: builtin/read-tree.c:111
+#: builtin/read-tree.c:112
 msgid "only empty the index"
 msgstr "只是清空索引"
 
-#: builtin/read-tree.c:113
+#: builtin/read-tree.c:114
 msgid "Merging"
 msgstr "合并"
 
-#: builtin/read-tree.c:115
+#: builtin/read-tree.c:116
 msgid "perform a merge in addition to a read"
 msgstr "读取之余再执行一个合并"
 
-#: builtin/read-tree.c:117
+#: builtin/read-tree.c:118
 msgid "3-way merge if no file level merging required"
 msgstr "如果没有文件级合并需要,执行三路合并"
 
-#: builtin/read-tree.c:119
+#: builtin/read-tree.c:120
 msgid "3-way merge in presence of adds and removes"
 msgstr "存在添加和删除时,也执行三路合并"
 
-#: builtin/read-tree.c:121
+#: builtin/read-tree.c:122
 msgid "same as -m, but discard unmerged entries"
 msgstr "类似于 -m,但丢弃未合并的条目"
 
-#: builtin/read-tree.c:122
+#: builtin/read-tree.c:123
 msgid "<subdirectory>/"
 msgstr "<子目录>/"
 
-#: builtin/read-tree.c:123
+#: builtin/read-tree.c:124
 msgid "read the tree into the index under <subdirectory>/"
 msgstr "读取树对象到索引的 <子目录>/ 下"
 
-#: builtin/read-tree.c:126
+#: builtin/read-tree.c:127
 msgid "update working tree with merge result"
 msgstr "用合并的结果更新工作区"
 
-#: builtin/read-tree.c:128
+#: builtin/read-tree.c:129
 msgid "gitignore"
 msgstr "gitignore"
 
-#: builtin/read-tree.c:129
+#: builtin/read-tree.c:130
 msgid "allow explicitly ignored files to be overwritten"
 msgstr "允许忽略文件中设定的文件可以被覆盖"
 
-#: builtin/read-tree.c:132
+#: builtin/read-tree.c:133
 msgid "don't check the working tree after merging"
 msgstr "合并后不检查工作区"
 
-#: builtin/read-tree.c:133
+#: builtin/read-tree.c:134
 msgid "don't update the index or the work tree"
 msgstr "不更新索引区和工作区"
 
-#: builtin/read-tree.c:135
+#: builtin/read-tree.c:136
 msgid "skip applying sparse checkout filter"
 msgstr "跳过应用稀疏检出过滤器"
 
-#: builtin/read-tree.c:137
+#: builtin/read-tree.c:138
 msgid "debug unpack-trees"
 msgstr "调试 unpack-trees"
 
+#: builtin/reflog.c:500
+#, c-format
+msgid "%s' for '%s' is not a valid timestamp"
+msgstr "'%2$s' 的值 '%1$s' 不是一个有效的时间戳"
+
+#: builtin/reflog.c:616 builtin/reflog.c:621
+#, c-format
+msgid "'%s' is not a valid timestamp"
+msgstr "'%s' 不是一个有效的时间戳"
+
 #: builtin/remote.c:11
 msgid "git remote [-v | --verbose]"
 msgstr "git remote [-v | --verbose]"
@@ -7978,98 +8390,98 @@
 msgid "Failed to find tree of %s."
 msgstr "无法找到 %s 指向的树。"
 
-#: builtin/reset.c:98
+#: builtin/reset.c:99
 #, c-format
 msgid "HEAD is now at %s"
 msgstr "HEAD 现在位于 %s"
 
 #  译者:汉字之间无空格,故删除%s前后空格
-#: builtin/reset.c:169
+#: builtin/reset.c:172
 #, c-format
 msgid "Cannot do a %s reset in the middle of a merge."
 msgstr "在合并过程中不能做%s重置操作。"
 
-#: builtin/reset.c:248
+#: builtin/reset.c:251
 msgid "be quiet, only report errors"
 msgstr "安静模式,只报告错误"
 
-#: builtin/reset.c:250
+#: builtin/reset.c:253
 msgid "reset HEAD and index"
 msgstr "重置 HEAD 和索引"
 
-#: builtin/reset.c:251
+#: builtin/reset.c:254
 msgid "reset only HEAD"
 msgstr "只重置 HEAD"
 
-#: builtin/reset.c:253 builtin/reset.c:255
+#: builtin/reset.c:256 builtin/reset.c:258
 msgid "reset HEAD, index and working tree"
 msgstr "重置 HEAD、索引和工作区"
 
-#: builtin/reset.c:257
+#: builtin/reset.c:260
 msgid "reset HEAD but keep local changes"
 msgstr "重置 HEAD 但保存本地变更"
 
-#: builtin/reset.c:275
+#: builtin/reset.c:278
 #, c-format
 msgid "Failed to resolve '%s' as a valid revision."
 msgstr "无法将 '%s' 解析为一个有效的版本。"
 
-#: builtin/reset.c:278 builtin/reset.c:286
+#: builtin/reset.c:281 builtin/reset.c:289
 #, c-format
 msgid "Could not parse object '%s'."
 msgstr "不能解析对象 '%s'。"
 
-#: builtin/reset.c:283
+#: builtin/reset.c:286
 #, c-format
 msgid "Failed to resolve '%s' as a valid tree."
 msgstr "无法将 '%s' 解析为一个有效的树对象。"
 
-#: builtin/reset.c:292
+#: builtin/reset.c:295
 msgid "--patch is incompatible with --{hard,mixed,soft}"
 msgstr "--patch 与 --{hard、mixed、soft} 选项不兼容"
 
-#: builtin/reset.c:301
+#: builtin/reset.c:304
 msgid "--mixed with paths is deprecated; use 'git reset -- <paths>' instead."
 msgstr "--mixed 带路径已弃用,而是用 'git reset -- <paths>'。"
 
 #  译者:汉字之间无空格,故删除%s前后空格
-#: builtin/reset.c:303
+#: builtin/reset.c:306
 #, c-format
 msgid "Cannot do %s reset with paths."
 msgstr "不能带路径进行%s重置。"
 
 #  译者:汉字之间无空格,故删除%s前后空格
-#: builtin/reset.c:313
+#: builtin/reset.c:316
 #, c-format
 msgid "%s reset is not allowed in a bare repository"
 msgstr "不能对裸版本库进行%s重置"
 
-#: builtin/reset.c:333
+#: builtin/reset.c:336
 #, c-format
 msgid "Could not reset index file to revision '%s'."
 msgstr "不能重置索引文件至版本 '%s'。"
 
-#: builtin/reset.c:339
+#: builtin/reset.c:342
 msgid "Unstaged changes after reset:"
 msgstr "重置后撤出暂存区的变更:"
 
-#: builtin/reset.c:344
+#: builtin/reset.c:347
 msgid "Could not write new index file."
 msgstr "不能写入新的索引文件。"
 
-#: builtin/rev-parse.c:339
+#: builtin/rev-parse.c:345
 msgid "git rev-parse --parseopt [options] -- [<args>...]"
 msgstr "git rev-parse --parseopt [选项] -- [<参数>...]"
 
-#: builtin/rev-parse.c:344
+#: builtin/rev-parse.c:350
 msgid "keep the `--` passed as an arg"
 msgstr "保持 `--` 作为一个参数传递"
 
-#: builtin/rev-parse.c:346
+#: builtin/rev-parse.c:352
 msgid "stop parsing after the first non-option argument"
 msgstr "遇到第一个非选项参数后停止解析"
 
-#: builtin/rev-parse.c:464
+#: builtin/rev-parse.c:470
 msgid ""
 "git rev-parse --parseopt [options] -- [<args>...]\n"
 "   or: git rev-parse --sq-quote [<arg>...]\n"
@@ -8084,190 +8496,210 @@
 "初次使用时执行 \"git rev-parse --parseopt -h\" 来获得更多信息。"
 
 #: builtin/revert.c:22
-msgid "git revert [options] <commit-ish>"
-msgstr "git revert [选项] <提交号>"
+msgid "git revert [options] <commit-ish>..."
+msgstr "git revert [选项] <提交号>..."
 
 #: builtin/revert.c:23
 msgid "git revert <subcommand>"
 msgstr "git revert <子命令>"
 
 #: builtin/revert.c:28
-msgid "git cherry-pick [options] <commit-ish>"
-msgstr "git cherry-pick [选项] <提交号>"
+msgid "git cherry-pick [options] <commit-ish>..."
+msgstr "git cherry-pick [选项] <提交号>..."
 
 #: builtin/revert.c:29
 msgid "git cherry-pick <subcommand>"
 msgstr "git cherry-pick <子命令>"
 
-#: builtin/revert.c:70 builtin/revert.c:92
+#: builtin/revert.c:71 builtin/revert.c:94
 #, c-format
 msgid "%s: %s cannot be used with %s"
 msgstr "%s:%s 不能和 %s 同时使用"
 
-#: builtin/revert.c:103
+#: builtin/revert.c:105
 msgid "end revert or cherry-pick sequence"
 msgstr "终止反转或拣选操作"
 
-#: builtin/revert.c:104
+#: builtin/revert.c:106
 msgid "resume revert or cherry-pick sequence"
 msgstr "继续反转或拣选操作"
 
-#: builtin/revert.c:105
+#: builtin/revert.c:107
 msgid "cancel revert or cherry-pick sequence"
 msgstr "取消反转或拣选操作"
 
-#: builtin/revert.c:106
+#: builtin/revert.c:108
 msgid "don't automatically commit"
 msgstr "不要自动提交"
 
-#: builtin/revert.c:107
+#: builtin/revert.c:109
 msgid "edit the commit message"
 msgstr "编辑提交说明"
 
-#: builtin/revert.c:110
+#: builtin/revert.c:112
 msgid "parent number"
 msgstr "父编号"
 
-#: builtin/revert.c:112
+#: builtin/revert.c:114
 msgid "merge strategy"
 msgstr "合并策略"
 
-#: builtin/revert.c:113
+#: builtin/revert.c:115
 msgid "option"
 msgstr "选项"
 
-#: builtin/revert.c:114
+#: builtin/revert.c:116
 msgid "option for merge strategy"
 msgstr "合并策略的选项"
 
-#: builtin/revert.c:125
+#: builtin/revert.c:127
 msgid "append commit name"
 msgstr "追加提交名称"
 
-#: builtin/revert.c:126
+#: builtin/revert.c:128
 msgid "allow fast-forward"
 msgstr "允许快进式"
 
-#: builtin/revert.c:127
+#: builtin/revert.c:129
 msgid "preserve initially empty commits"
 msgstr "保留初始化的空提交"
 
-#: builtin/revert.c:128
+#: builtin/revert.c:130
 msgid "allow commits with empty messages"
 msgstr "允许提交说明为空"
 
-#: builtin/revert.c:129
+#: builtin/revert.c:131
 msgid "keep redundant, empty commits"
 msgstr "保持多余的、空的提交"
 
-#: builtin/revert.c:133
+#: builtin/revert.c:135
 msgid "program error"
 msgstr "程序错误"
 
-#: builtin/revert.c:223
+#: builtin/revert.c:225
 msgid "revert failed"
 msgstr "还原失败"
 
-#: builtin/revert.c:238
+#: builtin/revert.c:240
 msgid "cherry-pick failed"
 msgstr "拣选失败"
 
-#: builtin/rm.c:15
+#: builtin/rm.c:16
 msgid "git rm [options] [--] <file>..."
 msgstr "git rm [选项] [--] <文件>..."
 
-#: builtin/rm.c:64 builtin/rm.c:186
-#, c-format
+#: builtin/rm.c:64
 msgid ""
-"submodule '%s' (or one of its nested submodules) uses a .git directory\n"
+"the following submodule (or one of its nested submodules)\n"
+"uses a .git directory:"
+msgid_plural ""
+"the following submodules (or one of its nested submodules)\n"
+"use a .git directory:"
+msgstr[0] "如下子模组(或一个其嵌套子模组)使用了一个 .git 目录:"
+msgstr[1] "如下子模组(或一个其嵌套子模组)使用了一个 .git 目录:"
+
+#: builtin/rm.c:70
+msgid ""
+"\n"
 "(use 'rm -rf' if you really want to remove it including all of its history)"
 msgstr ""
-"子模组 '%s'(或者它的一个嵌套子模组)使用一个 .git 目录\n"
+"\n"
 "(使用 'rm -rf' 命令如果您真的想删除它及其全部历史)"
 
-#: builtin/rm.c:174
-#, c-format
+#: builtin/rm.c:230
 msgid ""
-"'%s' has staged content different from both the file and the HEAD\n"
+"the following file has staged content different from both the\n"
+"file and the HEAD:"
+msgid_plural ""
+"the following files have staged content different from both the\n"
+"file and the HEAD:"
+msgstr[0] "如下文件其暂存的内容和工作区及 HEAD 中的都不一样:"
+msgstr[1] "如下文件其暂存的内容和工作区及 HEAD 中的都不一样:"
+
+#: builtin/rm.c:235
+msgid ""
+"\n"
 "(use -f to force removal)"
 msgstr ""
-"'%s' 暂存的内容和工作区及 HEAD 中的都不一样\n"
+"\n"
 "(使用 -f 强制删除)"
 
-#: builtin/rm.c:180
-#, c-format
+#: builtin/rm.c:239
+msgid "the following file has changes staged in the index:"
+msgid_plural "the following files have changes staged in the index:"
+msgstr[0] "如下文件相对索引区的内容有修改"
+msgstr[1] "如下文件相对索引区的内容有修改"
+
+#: builtin/rm.c:243 builtin/rm.c:254
 msgid ""
-"'%s' has changes staged in the index\n"
+"\n"
 "(use --cached to keep the file, or -f to force removal)"
 msgstr ""
-"'%s' 有变更已暂存至索引中\n"
-"(使用 --cached 保存文件,或用 -f 强制删除)"
+"\n"
+"(使用 --cached 保留本地文件,或用 -f 强制删除)"
 
-#: builtin/rm.c:191
-#, c-format
-msgid ""
-"'%s' has local modifications\n"
-"(use --cached to keep the file, or -f to force removal)"
-msgstr ""
-"'%s' 有本地修改\n"
-"(使用 --cached 保存文件,或用 -f 强制删除)"
+#: builtin/rm.c:251
+msgid "the following file has local modifications:"
+msgid_plural "the following files have local modifications:"
+msgstr[0] "如下文件有本地修改:"
+msgstr[1] "如下文件有本地修改:"
 
-#: builtin/rm.c:207
+#: builtin/rm.c:269
 msgid "do not list removed files"
 msgstr "不列出删除的文件"
 
-#: builtin/rm.c:208
+#: builtin/rm.c:270
 msgid "only remove from the index"
 msgstr "只从索引区删除"
 
-#: builtin/rm.c:209
+#: builtin/rm.c:271
 msgid "override the up-to-date check"
 msgstr "忽略文件更新状态检查"
 
-#: builtin/rm.c:210
+#: builtin/rm.c:272
 msgid "allow recursive removal"
 msgstr "允许递归删除"
 
-#: builtin/rm.c:212
+#: builtin/rm.c:274
 msgid "exit with a zero status even if nothing matched"
 msgstr "即使没有匹配,也以零状态退出"
 
-#: builtin/rm.c:283
+#: builtin/rm.c:345
 #, c-format
 msgid "not removing '%s' recursively without -r"
 msgstr "未提供 -r 选项不会递归删除 '%s'"
 
-#: builtin/rm.c:322
+#: builtin/rm.c:384
 #, c-format
 msgid "git rm: unable to remove %s"
 msgstr "git rm:不能删除 %s"
 
 #: builtin/shortlog.c:13
-msgid "git shortlog [-n] [-s] [-e] [-w] [rev-opts] [--] [<commit-id>... ]"
-msgstr "git shortlog [-n] [-s] [-e] [-w] [版本选项] [--] [<提交号>... ]"
+msgid "git shortlog [<options>] [<revision range>] [[--] [<path>...]]"
+msgstr "git shortlog [<选项>] [<版本范围>] [[--] [<路径>...]]"
 
-#: builtin/shortlog.c:133
+#: builtin/shortlog.c:131
 #, c-format
 msgid "Missing author: %s"
 msgstr "缺少作者:%s"
 
-#: builtin/shortlog.c:229
+#: builtin/shortlog.c:228
 msgid "sort output according to the number of commits per author"
 msgstr "根据每个作者的提交数量排序"
 
-#: builtin/shortlog.c:231
+#: builtin/shortlog.c:230
 msgid "Suppress commit descriptions, only provides commit count"
 msgstr "隐藏提交说明,只提供提交数量"
 
-#: builtin/shortlog.c:233
+#: builtin/shortlog.c:232
 msgid "Show the email address of each author"
 msgstr "显示每个作者的电子邮件地址"
 
-#: builtin/shortlog.c:234
+#: builtin/shortlog.c:233
 msgid "w[,i1[,i2]]"
 msgstr "w[,i1[,i2]]"
 
-#: builtin/shortlog.c:235
+#: builtin/shortlog.c:234
 msgid "Linewrap output"
 msgstr "折行输出"
 
@@ -8287,47 +8719,47 @@
 msgid "git show-branch (-g|--reflog)[=<n>[,<base>]] [--list] [<ref>]"
 msgstr "git show-branch (-g|--reflog)[=<n>[,<base>]] [--list] [<ref>]"
 
-#: builtin/show-branch.c:651
+#: builtin/show-branch.c:650
 msgid "show remote-tracking and local branches"
 msgstr "显示远程跟踪的和本地的分支"
 
-#: builtin/show-branch.c:653
+#: builtin/show-branch.c:652
 msgid "show remote-tracking branches"
 msgstr "显示远程跟踪的分支"
 
-#: builtin/show-branch.c:655
+#: builtin/show-branch.c:654
 msgid "color '*!+-' corresponding to the branch"
 msgstr "着色 '*!+-' 到相应的分支"
 
-#: builtin/show-branch.c:657
+#: builtin/show-branch.c:656
 msgid "show <n> more commits after the common ancestor"
 msgstr "显示共同祖先后的 <n> 个提交"
 
-#: builtin/show-branch.c:659
+#: builtin/show-branch.c:658
 msgid "synonym to more=-1"
 msgstr "和 more=-1 同义"
 
-#: builtin/show-branch.c:660
+#: builtin/show-branch.c:659
 msgid "suppress naming strings"
 msgstr "不显示字符串命名"
 
-#: builtin/show-branch.c:662
+#: builtin/show-branch.c:661
 msgid "include the current branch"
 msgstr "包括当前分支"
 
-#: builtin/show-branch.c:664
+#: builtin/show-branch.c:663
 msgid "name commits with their object names"
 msgstr "以对象名字命名提交"
 
-#: builtin/show-branch.c:666
+#: builtin/show-branch.c:665
 msgid "show possible merge bases"
 msgstr "显示可能合并的基线"
 
-#: builtin/show-branch.c:668
+#: builtin/show-branch.c:667
 msgid "show refs unreachable from any other ref"
 msgstr "显示没有任何引用的的引用"
 
-#: builtin/show-branch.c:670
+#: builtin/show-branch.c:669
 msgid "show commits in topological order"
 msgstr "以拓扑顺序显示提交"
 
@@ -8340,14 +8772,14 @@
 msgstr "显示仅一个分支可访问的合并提交"
 
 #: builtin/show-branch.c:676
-msgid "show commits where no parent comes before its children"
-msgstr "显示提交时以时间为序且父提交不能领先子提交"
+msgid "topologically sort, maintaining date order where possible"
+msgstr "拓扑方式排序,并尽可能地保持日期顺序"
 
-#: builtin/show-branch.c:678
+#: builtin/show-branch.c:679
 msgid "<n>[,<base>]"
 msgstr "<n>[,<base>]"
 
-#: builtin/show-branch.c:679
+#: builtin/show-branch.c:680
 msgid "show <n> most recent ref-log entries starting at base"
 msgstr "显示从 base 开始的 <n> 条最近的引用日志记录"
 
@@ -8363,35 +8795,35 @@
 msgid "git show-ref --exclude-existing[=pattern] < ref-list"
 msgstr "git show-ref --exclude-existing[=模式] < 引用列表"
 
-#: builtin/show-ref.c:165
+#: builtin/show-ref.c:168
 msgid "only show tags (can be combined with heads)"
 msgstr "只显示 tags(可以和头共用)"
 
-#: builtin/show-ref.c:166
+#: builtin/show-ref.c:169
 msgid "only show heads (can be combined with tags)"
 msgstr "只显示头(可以和 tags 共用)"
 
-#: builtin/show-ref.c:167
+#: builtin/show-ref.c:170
 msgid "stricter reference checking, requires exact ref path"
 msgstr "更严格的引用检测,需要精确的引用路径"
 
-#: builtin/show-ref.c:170 builtin/show-ref.c:172
-msgid "show the HEAD reference"
-msgstr "显示 HEAD 引用"
+#: builtin/show-ref.c:173 builtin/show-ref.c:176
+msgid "show the HEAD reference, even if it would be filtered out"
+msgstr "显示 HEAD 引用,即使被过滤掉"
 
-#: builtin/show-ref.c:174
+#: builtin/show-ref.c:178
 msgid "dereference tags into object IDs"
 msgstr "转换 tags 到对象ID"
 
-#: builtin/show-ref.c:176
+#: builtin/show-ref.c:180
 msgid "only show SHA1 hash using <n> digits"
 msgstr "只显示使用 <n> 个数字的 SHA1 哈希"
 
-#: builtin/show-ref.c:180
+#: builtin/show-ref.c:184
 msgid "do not print results to stdout (useful with --verify)"
 msgstr "不打印结果到标准输出(例如与 --verify 参数共用)"
 
-#: builtin/show-ref.c:182
+#: builtin/show-ref.c:186
 msgid "show refs from stdin that aren't in local repository"
 msgstr "显示从标准输入中读入的不在本地版本库中的引用"
 
@@ -8803,23 +9235,32 @@
 msgid "only useful for debugging"
 msgstr "只对调试有用"
 
-#: git.c:16
-msgid "See 'git help <command>' for more information on a specific command."
-msgstr "参见 'git help <command>' 以获得该特定命令的详细信息。"
+#: git.c:17
+msgid ""
+"'git help -a' and 'git help -g' lists available subcommands and some\n"
+"concept guides. See 'git help <command>' or 'git help <concept>'\n"
+"to read about a specific subcommand or concept."
+msgstr ""
+"命令 'git help -a' 和 'git help -g' 显示可用的子命令和一些指南。参见\n"
+"'git help <命令>' 或 'git help <指南>' 来查看给定的子命令帮助或指南。"
 
-#: parse-options.h:156
+#: parse-options.h:144
+msgid "expiry date"
+msgstr "逾期日期"
+
+#: parse-options.h:159
 msgid "no-op (backward compatibility)"
 msgstr "空操作(向后兼容)"
 
-#: parse-options.h:232
+#: parse-options.h:236
 msgid "be more verbose"
 msgstr "更加详细"
 
-#: parse-options.h:234
+#: parse-options.h:238
 msgid "be more quiet"
 msgstr "更加安静"
 
-#: parse-options.h:240
+#: parse-options.h:244
 msgid "use <n> digits to display SHA-1s"
 msgstr "用 <n> 位数字显示 SHA-1 哈希值"
 
@@ -8876,8 +9317,8 @@
 msgstr "移动或重命名一个文件、目录或符号链接"
 
 #: common-cmds.h:21
-msgid "Fetch from and merge with another repository or a local branch"
-msgstr "获取并合并另外的版本库或一个本地分支"
+msgid "Fetch from and integrate with another repository or a local branch"
+msgstr "获取并整合另外的版本库或一个本地分支"
 
 #: common-cmds.h:22
 msgid "Update remote refs along with associated objects"
@@ -8920,11 +9361,11 @@
 #: git-am.sh:105
 #, sh-format
 msgid ""
-"When you have resolved this problem, run \"$cmdline --resolved\".\n"
+"When you have resolved this problem, run \"$cmdline --continue\".\n"
 "If you prefer to skip this patch, run \"$cmdline --skip\" instead.\n"
 "To restore the original branch and stop patching, run \"$cmdline --abort\"."
 msgstr ""
-"当您解决了此问题后,执行 \"$cmdline --resolved\"。\n"
+"当您解决了此问题后,执行 \"$cmdline --continue\"。\n"
 "如果您想跳过此补丁,则执行 \"$cmdline --skip\"。\n"
 "要恢复原分支并停止打补丁,执行 \"$cmdline --abort\"。"
 
@@ -8977,25 +9418,34 @@
 "参数 -b/--binary 已经很长时间不做任何实质操作了,并且将被删除。\n"
 "请不要再使用它了。"
 
-#: git-am.sh:477
+#: git-am.sh:479
 #, sh-format
 msgid "previous rebase directory $dotest still exists but mbox given."
-msgstr "之前的变基目录 $dotest 仍然存在但给出了mbox。"
+msgstr "之前的变基目录 $dotest 仍然存在,但却提供了 mbox。"
 
-#: git-am.sh:482
+#: git-am.sh:484
 msgid "Please make up your mind. --skip or --abort?"
 msgstr "请下决心。--skip 或是 --abort ?"
 
-#: git-am.sh:509
+#: git-am.sh:520
+#, sh-format
+msgid ""
+"Stray $dotest directory found.\n"
+"Use \"git am --abort\" to remove it."
+msgstr ""
+"发现了错误的 $dotest 目录。\n"
+"使用 \"git am --abort\" 删除它。"
+
+#: git-am.sh:528
 msgid "Resolve operation not in progress, we are not resuming."
 msgstr "解决操作未进行,我们不会继续。"
 
-#: git-am.sh:575
+#: git-am.sh:594
 #, sh-format
 msgid "Dirty index: cannot apply patches (dirty: $files)"
 msgstr "脏的索引:不能应用补丁(脏文件:$files)"
 
-#: git-am.sh:679
+#: git-am.sh:698
 #, sh-format
 msgid ""
 "Patch is empty.  Was it split wrong?\n"
@@ -9006,15 +9456,15 @@
 "如果您想要跳过这个补丁,执行 \"$cmdline --skip\"。\n"
 "要恢复原分支并停止打补丁,执行 \"$cmdline --abort\"。"
 
-#: git-am.sh:706
+#: git-am.sh:725
 msgid "Patch does not have a valid e-mail address."
 msgstr "补丁中没有一个有效的邮件地址。"
 
-#: git-am.sh:753
+#: git-am.sh:772
 msgid "cannot be interactive without stdin connected to a terminal."
 msgstr "标准输入没有和终端关联,不能进行交互式操作。"
 
-#: git-am.sh:757
+#: git-am.sh:776
 msgid "Commit Body is:"
 msgstr "提交内容为:"
 
@@ -9022,16 +9472,16 @@
 #. TRANSLATORS: Make sure to include [y], [n], [e], [v] and [a]
 #. in your translation. The program will only accept English
 #. input at this point.
-#: git-am.sh:764
+#: git-am.sh:783
 msgid "Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all "
 msgstr "应用?[y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all "
 
-#: git-am.sh:800
+#: git-am.sh:819
 #, sh-format
 msgid "Applying: $FIRSTLINE"
 msgstr "正应用:$FIRSTLINE"
 
-#: git-am.sh:821
+#: git-am.sh:840
 msgid ""
 "No changes - did you forget to use 'git add'?\n"
 "If there is nothing left to stage, chances are that something else\n"
@@ -9041,22 +9491,22 @@
 "如果没有什么要添加到暂存区的,则很可能是其它提交已经引入了相同的变更。\n"
 "您也许想要跳过这个补丁。"
 
-#: git-am.sh:829
+#: git-am.sh:848
 msgid ""
 "You still have unmerged paths in your index\n"
 "did you forget to use 'git add'?"
 msgstr "您的索引中仍有未合并的路径。您是否忘了执行 'git add'?"
 
-#: git-am.sh:845
+#: git-am.sh:864
 msgid "No changes -- Patch already applied."
 msgstr "没有变更 —— 补丁已经应用过。"
 
-#: git-am.sh:855
+#: git-am.sh:874
 #, sh-format
 msgid "Patch failed at $msgnum $FIRSTLINE"
 msgstr "补丁失败于 $msgnum $FIRSTLINE"
 
-#: git-am.sh:858
+#: git-am.sh:877
 #, sh-format
 msgid ""
 "The copy of the patch that failed is found in:\n"
@@ -9065,7 +9515,7 @@
 "失败的补丁文件副本位于:\n"
 "   $dotest/patch"
 
-#: git-am.sh:876
+#: git-am.sh:895
 msgid "applying to an empty history"
 msgstr "正应用到一个空历史上"
 
@@ -9164,16 +9614,16 @@
 "然后需要提供我至少一个好版本和一个坏版本。\n"
 "(您可以用 \"git bisect bad\" 和 \"git bisect good\" 命令来标识。)"
 
-#: git-bisect.sh:347 git-bisect.sh:474
+#: git-bisect.sh:363 git-bisect.sh:490
 msgid "We are not bisecting."
 msgstr "我们没有在二分查找。"
 
-#: git-bisect.sh:354
+#: git-bisect.sh:370
 #, sh-format
 msgid "'$invalid' is not a valid commit"
 msgstr "'$invalid' 不是一个有效的提交"
 
-#: git-bisect.sh:363
+#: git-bisect.sh:379
 #, sh-format
 msgid ""
 "Could not check out original HEAD '$branch'.\n"
@@ -9182,25 +9632,25 @@
 "不能检出原始 HEAD '$branch'。\n"
 "尝试 'git bisect reset <提交>'。"
 
-#: git-bisect.sh:390
+#: git-bisect.sh:406
 msgid "No logfile given"
 msgstr "未提供日志文件"
 
-#: git-bisect.sh:391
+#: git-bisect.sh:407
 #, sh-format
 msgid "cannot read $file for replaying"
 msgstr "不能读取 $file 来重放"
 
-#: git-bisect.sh:408
+#: git-bisect.sh:424
 msgid "?? what are you talking about?"
 msgstr "?? 您在说什么?"
 
-#: git-bisect.sh:420
+#: git-bisect.sh:436
 #, sh-format
 msgid "running $command"
 msgstr "运行 $command"
 
-#: git-bisect.sh:427
+#: git-bisect.sh:443
 #, sh-format
 msgid ""
 "bisect run failed:\n"
@@ -9209,11 +9659,11 @@
 "二分查找运行失败:\n"
 "命令 '$command' 的退出码 $res 小于 0 或大于等于 128"
 
-#: git-bisect.sh:453
+#: git-bisect.sh:469
 msgid "bisect run cannot continue any more"
 msgstr "二分查找不能继续运行"
 
-#: git-bisect.sh:459
+#: git-bisect.sh:475
 #, sh-format
 msgid ""
 "bisect run failed:\n"
@@ -9222,7 +9672,7 @@
 "二分查找运行失败:\n"
 "'bisect_state $state' 退出码为 $res"
 
-#: git-bisect.sh:466
+#: git-bisect.sh:482
 msgid "bisect run success"
 msgstr "二分查找运行成功"
 
@@ -9266,7 +9716,7 @@
 msgid "Cannot rebase onto multiple branches"
 msgstr "无法变基到多个分支"
 
-#: git-rebase.sh:53
+#: git-rebase.sh:54
 msgid ""
 "When you have resolved this problem, run \"git rebase --continue\".\n"
 "If you prefer to skip this patch, run \"git rebase --skip\" instead.\n"
@@ -9277,31 +9727,50 @@
 "如果您想跳过此补丁,则执行 \"git rebase --skip\"。\n"
 "要恢复原分支并停止变基,执行 \"git rebase --abort\"。"
 
+#: git-rebase.sh:156
+msgid "Applied autostash."
+msgstr "成功应用 autostash。"
+
+#: git-rebase.sh:159
+#, sh-format
+msgid "Cannot store $stash_sha1"
+msgstr "无法保存 $stash_sha1"
+
 #: git-rebase.sh:160
+msgid ""
+"Applying autostash resulted in conflicts.\n"
+"Your changes are safe in the stash.\n"
+"You can run \"git stash pop\" or \"git stash drop\" at any time.\n"
+msgstr ""
+"应用 autostash 导致冲突。\n"
+"您的修改安全地保存在 stash 中。\n"
+"您可以在任何时候运行 \"git stash pop\" 或 \"git stash drop\"。\n"
+
+#: git-rebase.sh:190
 msgid "The pre-rebase hook refused to rebase."
 msgstr "钩子 pre-rebase 拒绝变基。"
 
-#: git-rebase.sh:165
+#: git-rebase.sh:195
 msgid "It looks like git-am is in progress. Cannot rebase."
 msgstr "似乎正处于在 git-am 的执行过程中。无法变基。"
 
-#: git-rebase.sh:296
+#: git-rebase.sh:329
 msgid "The --exec option must be used with the --interactive option"
 msgstr "选项 --exec 必须和选项 --interactive 同时使用"
 
-#: git-rebase.sh:301
+#: git-rebase.sh:334
 msgid "No rebase in progress?"
 msgstr "没有正在进行的变基?"
 
-#: git-rebase.sh:312
+#: git-rebase.sh:345
 msgid "The --edit-todo action can only be used during interactive rebase."
 msgstr "动作 --edit-todo 只能用在交互式变基过程中。"
 
-#: git-rebase.sh:319
+#: git-rebase.sh:352
 msgid "Cannot read HEAD"
 msgstr "不能读取 HEAD"
 
-#: git-rebase.sh:322
+#: git-rebase.sh:355
 msgid ""
 "You must edit all merge conflicts and then\n"
 "mark them as resolved using git add"
@@ -9309,12 +9778,12 @@
 "您必须编辑所有的合并冲突,然后通过 git add\n"
 "命令将它们标记为已解决"
 
-#: git-rebase.sh:340
+#: git-rebase.sh:373
 #, sh-format
 msgid "Could not move back to $head_name"
 msgstr "无法移回 $head_name"
 
-#: git-rebase.sh:359
+#: git-rebase.sh:392
 #, sh-format
 msgid ""
 "It seems that there is already a $state_dir_base directory, and\n"
@@ -9333,56 +9802,65 @@
 "\t$cmd_clear_stale_rebase\n"
 "然后再重新执行变基。为避免您丢失重要数据,我已经停止当前操作。"
 
-#: git-rebase.sh:404
+#: git-rebase.sh:437
 #, sh-format
 msgid "invalid upstream $upstream_name"
 msgstr "无效的上游 $upstream_name"
 
-#: git-rebase.sh:428
+#: git-rebase.sh:461
 #, sh-format
 msgid "$onto_name: there are more than one merge bases"
 msgstr "$onto_name: 有一个以上的合并基准"
 
-#: git-rebase.sh:431 git-rebase.sh:435
+#: git-rebase.sh:464 git-rebase.sh:468
 #, sh-format
 msgid "$onto_name: there is no merge base"
 msgstr "$onto_name: 没有合并基准"
 
-#: git-rebase.sh:440
+#: git-rebase.sh:473
 #, sh-format
 msgid "Does not point to a valid commit: $onto_name"
 msgstr "没有指向一个有效的提交:$onto_name"
 
-#: git-rebase.sh:463
+#: git-rebase.sh:496
 #, sh-format
 msgid "fatal: no such branch: $branch_name"
 msgstr "严重错误:无此分支:$branch_name"
 
-#: git-rebase.sh:483
+#: git-rebase.sh:519
+msgid "Cannot autostash"
+msgstr "无法 autostash"
+
+#: git-rebase.sh:524
+#, sh-format
+msgid "Created autostash: $stash_abbrev"
+msgstr "创建了 autostash: $stash_abbrev"
+
+#: git-rebase.sh:528
 msgid "Please commit or stash them."
 msgstr "请提交或为它们保存进度。"
 
-#: git-rebase.sh:501
+#: git-rebase.sh:548
 #, sh-format
 msgid "Current branch $branch_name is up to date."
 msgstr "当前分支 $branch_name 是最新的。"
 
-#: git-rebase.sh:504
+#: git-rebase.sh:552
 #, sh-format
 msgid "Current branch $branch_name is up to date, rebase forced."
 msgstr "当前分支 $branch_name 是最新的,强制变基。"
 
-#: git-rebase.sh:515
+#: git-rebase.sh:563
 #, sh-format
 msgid "Changes from $mb to $onto:"
 msgstr "变更从 $mb 到 $onto:"
 
 #. Detach HEAD and reset the tree
-#: git-rebase.sh:524
+#: git-rebase.sh:572
 msgid "First, rewinding head to replay your work on top of it..."
 msgstr "首先,重置头指针以便在上面重放您的工作..."
 
-#: git-rebase.sh:532
+#: git-rebase.sh:582
 #, sh-format
 msgid "Fast-forwarded $branch_name to $onto_name."
 msgstr "快进 $branch_name 至 $onto_name。"
@@ -9415,6 +9893,11 @@
 msgid "Cannot record working tree state"
 msgstr "不能记录工作区状态"
 
+#: git-stash.sh:190
+#, sh-format
+msgid "Cannot update $ref_stash with $w_commit"
+msgstr "无法用 $w_commit 更新 $ref_stash"
+
 #. TRANSLATORS: $option is an invalid option, like
 #. `--blah-blah'. The 7 spaces at the beginning of the
 #. second line correspond to "error: ". So you should line
@@ -9425,7 +9908,7 @@
 #. $ git stash save --blah-blah 2>&1 | head -n 2
 #. error: unknown option for 'stash save': --blah-blah
 #. To provide a message, use git stash save -- '--blah-blah'
-#: git-stash.sh:202
+#: git-stash.sh:241
 #, sh-format
 msgid ""
 "error: unknown option for 'stash save': $option\n"
@@ -9434,119 +9917,134 @@
 "错误:'stash save' 的未知选项:$option\n"
 "      要提供一个描述信息,使用 git stash save -- '$option'"
 
-#: git-stash.sh:223
+#: git-stash.sh:262
 msgid "No local changes to save"
 msgstr "没有要保存的本地修改"
 
-#: git-stash.sh:227
+#: git-stash.sh:268
+msgid ""
+"The following untracked files would NOT be saved but need to be removed by "
+"stash save:"
+msgstr "如下未跟踪文件将不会被保存但是将会因为进度保存而需要被删除:"
+
+#: git-stash.sh:270
+msgid ""
+"Aborting. Consider using either the --force or --include-untracked option."
+msgstr "终止。考虑使用 --force 或者 --include-untracked 选项。"
+
+#: git-stash.sh:274
 msgid "Cannot initialize stash"
 msgstr "无法初始化 stash"
 
-#: git-stash.sh:235
+#: git-stash.sh:278
 msgid "Cannot save the current status"
 msgstr "无法保存当前状态"
 
-#: git-stash.sh:253
+#: git-stash.sh:296
 msgid "Cannot remove worktree changes"
 msgstr "无法删除工作区变更"
 
-#: git-stash.sh:352
+#: git-stash.sh:395
 msgid "No stash found."
 msgstr "未发现 stash。"
 
-#: git-stash.sh:359
+#: git-stash.sh:402
 #, sh-format
 msgid "Too many revisions specified: $REV"
 msgstr "指定了太多的版本:$REV"
 
-#: git-stash.sh:365
+#: git-stash.sh:408
 #, sh-format
 msgid "$reference is not valid reference"
 msgstr "$reference 不是有效的引用"
 
-#: git-stash.sh:393
+#: git-stash.sh:436
 #, sh-format
 msgid "'$args' is not a stash-like commit"
 msgstr "'$args' 不是 stash 样提交"
 
-#: git-stash.sh:404
+#: git-stash.sh:447
 #, sh-format
 msgid "'$args' is not a stash reference"
 msgstr "'$args' 不是一个 stash 引用"
 
-#: git-stash.sh:412
+#: git-stash.sh:455
 msgid "unable to refresh index"
 msgstr "无法刷新索引"
 
-#: git-stash.sh:416
+#: git-stash.sh:459
 msgid "Cannot apply a stash in the middle of a merge"
 msgstr "无法在合并过程中恢复进度"
 
-#: git-stash.sh:424
+#: git-stash.sh:467
 msgid "Conflicts in index. Try without --index."
 msgstr "索引中有冲突。尝试不使用 --index。"
 
-#: git-stash.sh:426
+#: git-stash.sh:469
 msgid "Could not save index tree"
 msgstr "不能保存索引树"
 
-#: git-stash.sh:460
+#: git-stash.sh:503
 msgid "Cannot unstage modified files"
 msgstr "无法还原修改的文件"
 
-#: git-stash.sh:475
+#: git-stash.sh:518
 msgid "Index was not unstashed."
 msgstr "索引的进度没有被恢复。"
 
-#: git-stash.sh:492
+#: git-stash.sh:535
 #, sh-format
 msgid "Dropped ${REV} ($s)"
 msgstr "丢弃了 ${REV} ($s)"
 
-#: git-stash.sh:493
+#: git-stash.sh:536
 #, sh-format
 msgid "${REV}: Could not drop stash entry"
 msgstr "${REV}:不能丢弃进度条目"
 
-#: git-stash.sh:500
+#: git-stash.sh:543
 msgid "No branch name specified"
 msgstr "未指定分支名"
 
-#: git-stash.sh:571
+#: git-stash.sh:615
 msgid "(To restore them type \"git stash apply\")"
 msgstr "(为恢复数据输入 \"git stash apply\")"
 
-#: git-submodule.sh:91
+#: git-submodule.sh:95
 #, sh-format
 msgid "cannot strip one component off url '$remoteurl'"
 msgstr "无法从 url '$remoteurl' 剥离一个组件"
 
-#: git-submodule.sh:196
+#: git-submodule.sh:237
 #, sh-format
 msgid "No submodule mapping found in .gitmodules for path '$sm_path'"
 msgstr "未在 .gitmodules 中发现路径 '$sm_path' 的子模组映射"
 
-#: git-submodule.sh:239
+#: git-submodule.sh:281
 #, sh-format
 msgid "Clone of '$url' into submodule path '$sm_path' failed"
 msgstr "无法克隆 '$url' 到子模组路径 '$sm_path'"
 
-#: git-submodule.sh:251
+#: git-submodule.sh:293
 #, sh-format
 msgid "Gitdir '$a' is part of the submodule path '$b' or vice versa"
 msgstr "Gitdir '$a' 在子模组路径 '$b' 之下或相反"
 
-#: git-submodule.sh:349
+#: git-submodule.sh:403
+msgid "Relative path can only be used from the toplevel of the working tree"
+msgstr "只能在工作区的顶级目录中使用相对路径"
+
+#: git-submodule.sh:413
 #, sh-format
 msgid "repo URL: '$repo' must be absolute or begin with ./|../"
 msgstr "版本库URL:'$repo' 必须是绝对路径或以 ./|../ 起始"
 
-#: git-submodule.sh:366
+#: git-submodule.sh:430
 #, sh-format
 msgid "'$sm_path' already exists in the index"
 msgstr "'$sm_path' 已经存在于索引中"
 
-#: git-submodule.sh:370
+#: git-submodule.sh:434
 #, sh-format
 msgid ""
 "The following path is ignored by one of your .gitignore files:\n"
@@ -9557,245 +10055,365 @@
 "$sm_path\n"
 "如果您确实想添加它,使用 -f 参数。"
 
-#: git-submodule.sh:388
+#: git-submodule.sh:452
 #, sh-format
 msgid "Adding existing repo at '$sm_path' to the index"
 msgstr "添加位于 '$sm_path' 的现存版本库到索引"
 
-#: git-submodule.sh:390
+#: git-submodule.sh:454
 #, sh-format
 msgid "'$sm_path' already exists and is not a valid git repo"
 msgstr "'$sm_path' 已存在且不是一个有效的 git 版本库"
 
-#: git-submodule.sh:398
+#: git-submodule.sh:462
 #, sh-format
 msgid "A git directory for '$sm_name' is found locally with remote(s):"
 msgstr "本地发现 '$sm_name' 的一个 git 目录,与其对应的远程版本库:"
 
-#: git-submodule.sh:400
+#: git-submodule.sh:464
 #, sh-format
 msgid ""
 "If you want to reuse this local git directory instead of cloning again from"
 msgstr "如果您想重用此本地 git 目录而不是重新克隆自"
 
-#: git-submodule.sh:402
+#: git-submodule.sh:466
 #, sh-format
 msgid ""
 "use the '--force' option. If the local git directory is not the correct repo"
 msgstr "使用 '--force' 参数。如果本地 git 目录不是正确的版本库"
 
-#: git-submodule.sh:403
+#: git-submodule.sh:467
 #, sh-format
 msgid ""
 "or you are unsure what this means choose another name with the '--name' "
 "option."
 msgstr "或者您不确定其中含义使用 '--name' 参数选择另外一个名称。"
 
-#: git-submodule.sh:405
+#: git-submodule.sh:469
 #, sh-format
 msgid "Reactivating local git directory for submodule '$sm_name'."
 msgstr "激活本地 git 目录到子模组 '$sm_name'。"
 
-#: git-submodule.sh:417
+#: git-submodule.sh:481
 #, sh-format
 msgid "Unable to checkout submodule '$sm_path'"
 msgstr "不能检出子模组 '$sm_path'"
 
-#: git-submodule.sh:422
+#: git-submodule.sh:486
 #, sh-format
 msgid "Failed to add submodule '$sm_path'"
 msgstr "无法添加子模组 '$sm_path'"
 
-#: git-submodule.sh:431
+#: git-submodule.sh:495
 #, sh-format
 msgid "Failed to register submodule '$sm_path'"
 msgstr "无法注册子模组 '$sm_path'"
 
-#: git-submodule.sh:474
+#: git-submodule.sh:539
 #, sh-format
-msgid "Entering '$prefix$sm_path'"
-msgstr "正在进入 '$prefix$sm_path'"
+msgid "Entering '$prefix$displaypath'"
+msgstr "正在进入 '$prefix$displaypath'"
 
-#: git-submodule.sh:488
+#: git-submodule.sh:554
 #, sh-format
-msgid "Stopping at '$sm_path'; script returned non-zero status."
-msgstr "停止于 '$sm_path',脚本返回非零值。"
+msgid "Stopping at '$prefix$displaypath'; script returned non-zero status."
+msgstr "停止于 '$prefix$displaypath',脚本返回非零值。"
 
-#: git-submodule.sh:532
+#: git-submodule.sh:600
 #, sh-format
-msgid "No url found for submodule path '$sm_path' in .gitmodules"
-msgstr "在 .gitmodules 中未找到子模组路径 '$sm_path' 的 url"
+msgid "No url found for submodule path '$displaypath' in .gitmodules"
+msgstr "在 .gitmodules 中未找到子模组路径 '$displaypath' 的 url"
 
-#: git-submodule.sh:541
+#: git-submodule.sh:609
 #, sh-format
-msgid "Failed to register url for submodule path '$sm_path'"
-msgstr "无法为子模组路径 '$sm_path' 注册 url"
+msgid "Failed to register url for submodule path '$displaypath'"
+msgstr "无法为子模组路径 '$displaypath' 注册 url"
 
-#: git-submodule.sh:543
+#: git-submodule.sh:611
 #, sh-format
-msgid "Submodule '$name' ($url) registered for path '$sm_path'"
-msgstr "子模组 '$name' ($url) 已为路径 '$sm_path' 注册"
+msgid "Submodule '$name' ($url) registered for path '$displaypath'"
+msgstr "子模组 '$name' ($url) 未对路径 '$displaypath' 注册"
 
-#: git-submodule.sh:551
+#: git-submodule.sh:619
 #, sh-format
-msgid "Failed to register update mode for submodule path '$sm_path'"
-msgstr "无法为子模组路径 '$sm_path' 注册更新模式"
+msgid "Failed to register update mode for submodule path '$displaypath'"
+msgstr "无法为子模组路径 '$displaypath' 注册更新模式"
 
-#: git-submodule.sh:588
+#: git-submodule.sh:656
 #, sh-format
 msgid "Use '.' if you really want to deinitialize all submodules"
 msgstr "使用 '.' 如果您真的想要对所有子模组取消初始化"
 
-#: git-submodule.sh:603
+#: git-submodule.sh:673
 #, sh-format
-msgid "Submodule work tree '$sm_path' contains a .git directory"
-msgstr "子模组工作区 '$sm_path' 包含一个 .git 目录"
+msgid "Submodule work tree '$displaypath' contains a .git directory"
+msgstr "子模组工作区 '$displaypath' 包含一个 .git 目录"
 
-#: git-submodule.sh:604
+#: git-submodule.sh:674
 #, sh-format
 msgid ""
 "(use 'rm -rf' if you really want to remove it including all of its history)"
 msgstr "(使用 'rm -rf' 命令如果您真的想删除它及其全部历史)"
 
-#: git-submodule.sh:610
+#: git-submodule.sh:680
 #, sh-format
 msgid ""
-"Submodule work tree '$sm_path' contains local modifications; use '-f' to "
+"Submodule work tree '$displaypath' contains local modifications; use '-f' to "
 "discard them"
-msgstr "子模组工作区 '$sm_path' 包含本地修改;使用 '-f' 丢弃它们"
+msgstr "子模组工作区 '$displaypath' 包含本地修改;使用 '-f' 丢弃它们"
 
-#: git-submodule.sh:613
+#: git-submodule.sh:683
 #, sh-format
-msgid "Cleared directory '$sm_path'"
-msgstr "已清除目录 '$sm_path'"
+msgid "Cleared directory '$displaypath'"
+msgstr "已清除目录 '$displaypath'"
 
-#: git-submodule.sh:614
+#: git-submodule.sh:684
 #, sh-format
-msgid "Could not remove submodule work tree '$sm_path'"
-msgstr "无法移除子模组工作区 '$sm_path'"
+msgid "Could not remove submodule work tree '$displaypath'"
+msgstr "无法移除子模组工作区 '$displaypath'"
 
-#: git-submodule.sh:617
+#: git-submodule.sh:687
 #, sh-format
-msgid "Could not create empty submodule directory '$sm_path'"
-msgstr "不能创建空的子模组目录 '$sm_path'"
+msgid "Could not create empty submodule directory '$displaypath'"
+msgstr "不能创建空的子模组目录 '$displaypath'"
 
-#: git-submodule.sh:626
+#: git-submodule.sh:696
 #, sh-format
-msgid "Submodule '$name' ($url) unregistered for path '$sm_path'"
-msgstr "子模组 '$name' ($url) 未对路径 '$sm_path' 注册"
+msgid "Submodule '$name' ($url) unregistered for path '$displaypath'"
+msgstr "子模组 '$name' ($url) 未对路径 '$displaypath' 注册"
 
-#: git-submodule.sh:731
+#: git-submodule.sh:811
 #, sh-format
 msgid ""
-"Submodule path '$prefix$sm_path' not initialized\n"
+"Submodule path '$displaypath' not initialized\n"
 "Maybe you want to use 'update --init'?"
 msgstr ""
-"子模组路径 '$prefix$sm_path' 没有初始化\n"
+"子模组路径 '$displaypath' 没有初始化\n"
 "也许您想用 'update --init'?"
 
-#: git-submodule.sh:744
+#: git-submodule.sh:824
 #, sh-format
-msgid "Unable to find current revision in submodule path '$prefix$sm_path'"
-msgstr "无法在子模组路径 '$prefix$sm_path' 中找到当前版本"
+msgid "Unable to find current revision in submodule path '$displaypath'"
+msgstr "无法在子模组路径 '$displaypath' 中找到当前版本"
 
-#: git-submodule.sh:753
+#: git-submodule.sh:833
 #, sh-format
 msgid "Unable to fetch in submodule path '$sm_path'"
 msgstr "无法在子模组路径 '$sm_path' 中获取"
 
-#: git-submodule.sh:777
+#: git-submodule.sh:857
 #, sh-format
-msgid "Unable to fetch in submodule path '$prefix$sm_path'"
-msgstr "无法在子模组路径 '$prefix$sm_path' 中获取"
+msgid "Unable to fetch in submodule path '$displaypath'"
+msgstr "无法在子模组路径 '$displaypath' 中获取"
 
-#: git-submodule.sh:791
+#: git-submodule.sh:871
 #, sh-format
-msgid "Unable to rebase '$sha1' in submodule path '$prefix$sm_path'"
-msgstr "无法在子模组路径 '$prefix$sm_path' 中变基 '$sha1'"
+msgid "Unable to rebase '$sha1' in submodule path '$displaypath'"
+msgstr "无法在子模组路径 '$displaypath' 中变基 '$sha1'"
 
-#: git-submodule.sh:792
+#: git-submodule.sh:872
 #, sh-format
-msgid "Submodule path '$prefix$sm_path': rebased into '$sha1'"
-msgstr "子模组路径 '$prefix$sm_path':变基至 '$sha1'"
+msgid "Submodule path '$displaypath': rebased into '$sha1'"
+msgstr "子模组路径 '$displaypath':变基至 '$sha1'"
 
-#: git-submodule.sh:797
+#: git-submodule.sh:877
 #, sh-format
-msgid "Unable to merge '$sha1' in submodule path '$prefix$sm_path'"
-msgstr "无法合并 '$sha1' 到子模组路径 '$prefix$sm_path' 中"
+msgid "Unable to merge '$sha1' in submodule path '$displaypath'"
+msgstr "无法合并 '$sha1' 到子模组路径 '$displaypath' 中"
 
-#: git-submodule.sh:798
+#: git-submodule.sh:878
 #, sh-format
-msgid "Submodule path '$prefix$sm_path': merged in '$sha1'"
-msgstr "子模组路径 '$prefix$sm_path':已合并入 '$sha1'"
+msgid "Submodule path '$displaypath': merged in '$sha1'"
+msgstr "子模组路径 '$displaypath':已合并入 '$sha1'"
 
-#: git-submodule.sh:803
+#: git-submodule.sh:883
 #, sh-format
-msgid "Unable to checkout '$sha1' in submodule path '$prefix$sm_path'"
-msgstr "无法在子模组路径 '$prefix$sm_path' 中检出 '$sha1'"
+msgid ""
+"Execution of '$command $sha1' failed in submodule  path '$prefix$sm_path'"
+msgstr "在子模组路径 '$prefix$sm_path' 中执行 '$command $sha1' 失败"
 
-#: git-submodule.sh:804
+#: git-submodule.sh:884
 #, sh-format
-msgid "Submodule path '$prefix$sm_path': checked out '$sha1'"
-msgstr "子模组路径 '$prefix$sm_path':检出 '$sha1'"
+msgid "Submodule path '$prefix$sm_path': '$command $sha1'"
+msgstr "子模组路径 '$prefix$sm_path': '$command $sha1'"
 
-#: git-submodule.sh:831
+#: git-submodule.sh:889
 #, sh-format
-msgid "Failed to recurse into submodule path '$prefix$sm_path'"
-msgstr "无法递归进子模组路径 '$prefix$sm_path'"
+msgid "Unable to checkout '$sha1' in submodule path '$displaypath'"
+msgstr "无法在子模组路径 '$displaypath' 中检出 '$sha1'"
 
-#: git-submodule.sh:939
+#: git-submodule.sh:890
+#, sh-format
+msgid "Submodule path '$displaypath': checked out '$sha1'"
+msgstr "子模组路径 '$displaypath':检出 '$sha1'"
+
+#: git-submodule.sh:917
+#, sh-format
+msgid "Failed to recurse into submodule path '$displaypath'"
+msgstr "无法递归进子模组路径 '$displaypath'"
+
+#: git-submodule.sh:1025
 msgid "The --cached option cannot be used with the --files option"
 msgstr "选项 --cached 不能和选项 --files 同时使用"
 
 #. unexpected type
-#: git-submodule.sh:979
+#: git-submodule.sh:1066
 #, sh-format
 msgid "unexpected mode $mod_dst"
 msgstr "意外的模式 $mod_dst"
 
 #  译者:注意保持前导空格
-#: git-submodule.sh:997
+#: git-submodule.sh:1086
 #, sh-format
-msgid "  Warn: $name doesn't contain commit $sha1_src"
-msgstr "  警告:$name 未包含提交 $sha1_src"
+msgid "  Warn: $display_name doesn't contain commit $sha1_src"
+msgstr "  警告:$display_name 未包含提交 $sha1_src"
 
 #  译者:注意保持前导空格
-#: git-submodule.sh:1000
+#: git-submodule.sh:1089
 #, sh-format
-msgid "  Warn: $name doesn't contain commit $sha1_dst"
-msgstr "  警告:$name 未包含提交 $sha1_dst"
+msgid "  Warn: $display_name doesn't contain commit $sha1_dst"
+msgstr "  警告:$display_name 未包含提交 $sha1_dst"
 
 #  译者:注意保持前导空格
-#: git-submodule.sh:1003
+#: git-submodule.sh:1092
 #, sh-format
-msgid "  Warn: $name doesn't contain commits $sha1_src and $sha1_dst"
-msgstr "  警告:$name 未包含提交 $sha1_src 和 $sha1_dst"
+msgid "  Warn: $display_name doesn't contain commits $sha1_src and $sha1_dst"
+msgstr "  警告:$display_name 未包含提交 $sha1_src 和 $sha1_dst"
 
-#: git-submodule.sh:1028
+#: git-submodule.sh:1117
 msgid "blob"
 msgstr "数据对象"
 
-#: git-submodule.sh:1066
+#: git-submodule.sh:1155
 msgid "Submodules changed but not updated:"
 msgstr "子模组已修改但尚未更新:"
 
-#: git-submodule.sh:1068
+#: git-submodule.sh:1157
 msgid "Submodule changes to be committed:"
 msgstr "要提交的子模组变更:"
 
-#: git-submodule.sh:1153
+#: git-submodule.sh:1242
 #, sh-format
 msgid "Failed to recurse into submodule path '$sm_path'"
 msgstr "无法递归进子模组路径 '$sm_path'"
 
-#: git-submodule.sh:1216
+#: git-submodule.sh:1306
 #, sh-format
-msgid "Synchronizing submodule url for '$prefix$sm_path'"
-msgstr "为 '$prefix$sm_path' 同步子模组 url"
+msgid "Synchronizing submodule url for '$displaypath'"
+msgstr "为 '$displaypath' 同步子模组 url"
 
-#, fuzzy
-#~ msgid "aaaSynchronizing submodule url for '$prefix$sm_path'"
-#~ msgstr "为 '$prefix$sm_path' 同步子模组 url"
+#~ msgid ""
+#~ "the following submodule (or one of its nested submodule)\n"
+#~ "uses a .git directory:"
+#~ msgid_plural ""
+#~ "the following submodules (or one of its nested submodule)\n"
+#~ "use a .git directory:"
+#~ msgstr[0] "如下子模组(或一个其嵌套的子模组)使用了一个 .git 目录:"
+#~ msgstr[1] "如下子模组(或一个其嵌套的子模组)使用了一个 .git 目录:"
+
+#~ msgid "Cannot change unmerged .gitmodules, resolve merge conflicts first"
+#~ msgstr "无法修改未合并的 .gitmodules,先解决合并冲突"
+
+#~ msgid "Could not find section in .gitmodules where path=%s"
+#~ msgstr "无法在 .gitmodules 中找到 path=%s 的小节"
+
+#~ msgid "Could not update .gitmodules entry %s"
+#~ msgstr "不能更新 .gitmodules 条目 %s"
+
+#~ msgid "Could not remove .gitmodules entry for %s"
+#~ msgstr "无法移除 %s 的 .gitmodules 条目"
+
+#~ msgid "could not find .gitmodules in index"
+#~ msgstr "无法在索引中找到 .gitmodules"
+
+#~ msgid "reading updated .gitmodules failed"
+#~ msgstr "读取更新后的 .gitmodules 失败"
+
+#~ msgid "unable to stat updated .gitmodules"
+#~ msgstr "不能枚举更新后的 .gitmodules"
+
+#~ msgid "unable to remove .gitmodules from index"
+#~ msgstr "不能从索引中移除 .gitmodules"
+
+#~ msgid "adding updated .gitmodules failed"
+#~ msgstr "添加更新后的 .gitmodules 失败"
+
+#~ msgid "staging updated .gitmodules failed"
+#~ msgstr "将更新后 .gitmodules 添加暂存区失败"
+
+#~ msgid "Could not set core.worktree in %s"
+#~ msgstr "不能在 %s 中设置 core.worktree"
+
+#  译者:注意保持前导空格
+#~ msgid "  (fix conflicts and then run \"git am --resolved\")"
+#~ msgstr "  (解决冲突,然后运行 \"git am --resolved\")"
+
+#  译者:注意保持前导空格
+#~ msgid "  (all conflicts fixed: run \"git commit\")"
+#~ msgstr "  (解决所有冲突后,执行 \"git commit\")"
+
+#~ msgid "more than %d trees given: '%s'"
+#~ msgstr "提供了超过 %d 个树对象:'%s'"
+
+#~ msgid "You cannot combine --no-ff with --ff-only."
+#~ msgstr "您不能将 --no-ff 与 --ff-only 同时使用。"
+
+#~ msgid "Huh? Directory %s is in index and no submodule?"
+#~ msgstr "嗯?目录 %s 在索引中并且不是子模组?"
+
+#~ msgid ""
+#~ "submodule '%s' (or one of its nested submodules) uses a .git directory\n"
+#~ "(use 'rm -rf' if you really want to remove it including all of its "
+#~ "history)"
+#~ msgstr ""
+#~ "子模组 '%s'(或者它的一个嵌套子模组)使用一个 .git 目录\n"
+#~ "(使用 'rm -rf' 命令如果您真的想删除它及其全部历史)"
+
+#~ msgid ""
+#~ "'%s' has changes staged in the index\n"
+#~ "(use --cached to keep the file, or -f to force removal)"
+#~ msgstr ""
+#~ "'%s' 有变更已暂存至索引中\n"
+#~ "(使用 --cached 保存文件,或用 -f 强制删除)"
+
+#~ msgid "show commits where no parent comes before its children"
+#~ msgstr "显示提交时以时间为序且父提交不能领先子提交"
+
+#~ msgid "show the HEAD reference"
+#~ msgstr "显示 HEAD 引用"
+
+#~ msgid "Submodule '$name' ($url) registered for path '$sm_path'"
+#~ msgstr "子模组 '$name' ($url) 已为路径 '$sm_path' 注册"
+
+#~ msgid "Change flags"
+#~ msgstr "修改参数"
+
+#~ msgid ""
+#~ "NOTE: no more files to clean; press \"t\" to toggle flags of git-clean."
+#~ msgstr "注意:没有要清理的文件;尝试按 \"t\" 切换 git-clean 的选项。"
+
+#~ msgid "Failed to recurse into submodule path '$prefix$sm_path'"
+#~ msgstr "无法递归进子模组路径 '$prefix$sm_path'"
+
+#~ msgid "git shortlog [-n] [-s] [-e] [-w] [rev-opts] [--] [<commit-id>... ]"
+#~ msgstr "git shortlog [-n] [-s] [-e] [-w] [版本选项] [--] [<提交号>... ]"
+
+#~ msgid "See 'git help <command>' for more information on a specific command."
+#~ msgstr "参见 'git help <command>' 以获得该特定命令的详细信息。"
+
+#~ msgid "BUG: impossible combination of %d and %p"
+#~ msgstr "BUG: 无法组合 %d 和 %p"
+
+#  译者:以下三条实际为一个段落
+#~ msgid "It took %.2f seconds to enumerate untracked files.  'status -uno'"
+#~ msgstr "耗费了 %.2f 秒以枚举未跟踪的文件。'status -uno'"
+
+#  译者:为对齐,下面两句内容有调整
+#~ msgid "may speed it up, but you have to be careful not to forget to add"
+#~ msgstr "也许能提高速度,但您需要小心不要忘了添加新文件"
+
+#~ msgid "new files yourself (see 'git help status')."
+#~ msgstr "(参见 'git help status')。"
 
 #~ msgid "use any ref in .git/refs"
 #~ msgstr "使用 .git/refs 里的任意引用"
diff --git a/pretty.c b/pretty.c
index 9e43154..74563c9 100644
--- a/pretty.c
+++ b/pretty.c
@@ -406,7 +406,7 @@
 	return show_date(date, tz, mode);
 }
 
-void pp_user_info(const struct pretty_print_context *pp,
+void pp_user_info(struct pretty_print_context *pp,
 		  const char *what, struct strbuf *sb,
 		  const char *line, const char *encoding)
 {
@@ -432,6 +432,23 @@
 		map_user(pp->mailmap, &mailbuf, &maillen, &namebuf, &namelen);
 
 	if (pp->fmt == CMIT_FMT_EMAIL) {
+		if (pp->from_ident) {
+			struct strbuf buf = STRBUF_INIT;
+
+			strbuf_addstr(&buf, "From: ");
+			strbuf_add(&buf, namebuf, namelen);
+			strbuf_addstr(&buf, " <");
+			strbuf_add(&buf, mailbuf, maillen);
+			strbuf_addstr(&buf, ">\n");
+			string_list_append(&pp->in_body_headers,
+					   strbuf_detach(&buf, NULL));
+
+			mailbuf = pp->from_ident->mail_begin;
+			maillen = pp->from_ident->mail_end - mailbuf;
+			namebuf = pp->from_ident->name_begin;
+			namelen = pp->from_ident->name_end - namebuf;
+		}
+
 		strbuf_addstr(sb, "From: ");
 		if (needs_rfc2047_encoding(namebuf, namelen, RFC2047_ADDRESS)) {
 			add_rfc2047(sb, namebuf, namelen,
@@ -1514,7 +1531,7 @@
 	free(context.signature_check.signer);
 }
 
-static void pp_header(const struct pretty_print_context *pp,
+static void pp_header(struct pretty_print_context *pp,
 		      const char *encoding,
 		      const struct commit *commit,
 		      const char **msg_p,
@@ -1575,7 +1592,7 @@
 	}
 }
 
-void pp_title_line(const struct pretty_print_context *pp,
+void pp_title_line(struct pretty_print_context *pp,
 		   const char **msg_p,
 		   struct strbuf *sb,
 		   const char *encoding,
@@ -1602,6 +1619,16 @@
 	}
 	strbuf_addch(sb, '\n');
 
+	if (need_8bit_cte == 0) {
+		int i;
+		for (i = 0; i < pp->in_body_headers.nr; i++) {
+			if (has_non_ascii(pp->in_body_headers.items[i].string)) {
+				need_8bit_cte = 1;
+				break;
+			}
+		}
+	}
+
 	if (need_8bit_cte > 0) {
 		const char *header_fmt =
 			"MIME-Version: 1.0\n"
@@ -1615,10 +1642,21 @@
 	if (pp->fmt == CMIT_FMT_EMAIL) {
 		strbuf_addch(sb, '\n');
 	}
+
+	if (pp->in_body_headers.nr) {
+		int i;
+		for (i = 0; i < pp->in_body_headers.nr; i++) {
+			strbuf_addstr(sb, pp->in_body_headers.items[i].string);
+			free(pp->in_body_headers.items[i].string);
+		}
+		string_list_clear(&pp->in_body_headers, 0);
+		strbuf_addch(sb, '\n');
+	}
+
 	strbuf_release(&title);
 }
 
-void pp_remainder(const struct pretty_print_context *pp,
+void pp_remainder(struct pretty_print_context *pp,
 		  const char **msg_p,
 		  struct strbuf *sb,
 		  int indent)
@@ -1650,7 +1688,7 @@
 	}
 }
 
-void pretty_print_commit(const struct pretty_print_context *pp,
+void pretty_print_commit(struct pretty_print_context *pp,
 			 const struct commit *commit,
 			 struct strbuf *sb)
 {
diff --git a/prio-queue.c b/prio-queue.c
new file mode 100644
index 0000000..c9f8c6d
--- /dev/null
+++ b/prio-queue.c
@@ -0,0 +1,84 @@
+#include "cache.h"
+#include "commit.h"
+#include "prio-queue.h"
+
+void prio_queue_reverse(struct prio_queue *queue)
+{
+	int i, j;
+
+	if (queue->compare != NULL)
+		die("BUG: prio_queue_reverse() on non-LIFO queue");
+	for (i = 0; i <= (j = (queue->nr - 1) - i); i++) {
+		struct commit *swap = queue->array[i];
+		queue->array[i] = queue->array[j];
+		queue->array[j] = swap;
+	}
+}
+
+void clear_prio_queue(struct prio_queue *queue)
+{
+	free(queue->array);
+	queue->nr = 0;
+	queue->alloc = 0;
+	queue->array = NULL;
+}
+
+void prio_queue_put(struct prio_queue *queue, void *thing)
+{
+	prio_queue_compare_fn compare = queue->compare;
+	int ix, parent;
+
+	/* Append at the end */
+	ALLOC_GROW(queue->array, queue->nr + 1, queue->alloc);
+	queue->array[queue->nr++] = thing;
+	if (!compare)
+		return; /* LIFO */
+
+	/* Bubble up the new one */
+	for (ix = queue->nr - 1; ix; ix = parent) {
+		parent = (ix - 1) / 2;
+		if (compare(queue->array[parent], queue->array[ix],
+			    queue->cb_data) <= 0)
+			break;
+
+		thing = queue->array[parent];
+		queue->array[parent] = queue->array[ix];
+		queue->array[ix] = thing;
+	}
+}
+
+void *prio_queue_get(struct prio_queue *queue)
+{
+	void *result, *swap;
+	int ix, child;
+	prio_queue_compare_fn compare = queue->compare;
+
+	if (!queue->nr)
+		return NULL;
+	if (!compare)
+		return queue->array[--queue->nr]; /* LIFO */
+
+	result = queue->array[0];
+	if (!--queue->nr)
+		return result;
+
+	queue->array[0] = queue->array[queue->nr];
+
+	/* Push down the one at the root */
+	for (ix = 0; ix * 2 + 1 < queue->nr; ix = child) {
+		child = ix * 2 + 1; /* left */
+		if ((child + 1 < queue->nr) &&
+		    (compare(queue->array[child], queue->array[child + 1],
+			     queue->cb_data) >= 0))
+			child++; /* use right child */
+
+		if (compare(queue->array[ix], queue->array[child],
+			    queue->cb_data) <= 0)
+			break;
+
+		swap = queue->array[child];
+		queue->array[child] = queue->array[ix];
+		queue->array[ix] = swap;
+	}
+	return result;
+}
diff --git a/prio-queue.h b/prio-queue.h
new file mode 100644
index 0000000..9c3cd1f
--- /dev/null
+++ b/prio-queue.h
@@ -0,0 +1,48 @@
+#ifndef PRIO_QUEUE_H
+#define PRIO_QUEUE_H
+
+/*
+ * A priority queue implementation, primarily for keeping track of
+ * commits in the 'date-order' so that we process them from new to old
+ * as they are discovered, but can be used to hold any pointer to
+ * struct.  The caller is responsible for supplying a function to
+ * compare two "things".
+ *
+ * Alternatively, this data structure can also be used as a LIFO stack
+ * by specifying NULL as the comparison function.
+ */
+
+/*
+ * Compare two "things", one and two; the third parameter is cb_data
+ * in the prio_queue structure.  The result is returned as a sign of
+ * the return value, being the same as the sign of the result of
+ * subtracting "two" from "one" (i.e. negative if "one" sorts earlier
+ * than "two").
+ */
+typedef int (*prio_queue_compare_fn)(const void *one, const void *two, void *cb_data);
+
+struct prio_queue {
+	prio_queue_compare_fn compare;
+	void *cb_data;
+	int alloc, nr;
+	void **array;
+};
+
+/*
+ * Add the "thing" to the queue.
+ */
+extern void prio_queue_put(struct prio_queue *, void *thing);
+
+/*
+ * Extract the "thing" that compares the smallest out of the queue,
+ * or NULL.  If compare function is NULL, the queue acts as a LIFO
+ * stack.
+ */
+extern void *prio_queue_get(struct prio_queue *);
+
+extern void clear_prio_queue(struct prio_queue *);
+
+/* Reverse the LIFO elements */
+extern void prio_queue_reverse(struct prio_queue *);
+
+#endif /* PRIO_QUEUE_H */
diff --git a/quote.c b/quote.c
index 911229f..5c88081 100644
--- a/quote.c
+++ b/quote.c
@@ -312,82 +312,27 @@
 	fputc(terminator, fp);
 }
 
-static const char *path_relative(const char *in, int len,
-				 struct strbuf *sb, const char *prefix,
-				 int prefix_len);
-
-void write_name_quoted_relative(const char *name, size_t len,
-				const char *prefix, size_t prefix_len,
+void write_name_quoted_relative(const char *name, const char *prefix,
 				FILE *fp, int terminator)
 {
 	struct strbuf sb = STRBUF_INIT;
 
-	name = path_relative(name, len, &sb, prefix, prefix_len);
+	name = relative_path(name, prefix, &sb);
 	write_name_quoted(name, fp, terminator);
 
 	strbuf_release(&sb);
 }
 
-/*
- * Give path as relative to prefix.
- *
- * The strbuf may or may not be used, so do not assume it contains the
- * returned path.
- */
-static const char *path_relative(const char *in, int len,
-				 struct strbuf *sb, const char *prefix,
-				 int prefix_len)
-{
-	int off, i;
-
-	if (len < 0)
-		len = strlen(in);
-	if (prefix_len < 0) {
-		if (prefix)
-			prefix_len = strlen(prefix);
-		else
-			prefix_len = 0;
-	}
-
-	off = 0;
-	i = 0;
-	while (i < prefix_len && i < len && prefix[i] == in[i]) {
-		if (prefix[i] == '/')
-			off = i + 1;
-		i++;
-	}
-	in += off;
-	len -= off;
-
-	if (i >= prefix_len)
-		return in;
-
-	strbuf_reset(sb);
-	strbuf_grow(sb, len);
-
-	while (i < prefix_len) {
-		if (prefix[i] == '/')
-			strbuf_addstr(sb, "../");
-		i++;
-	}
-	strbuf_add(sb, in, len);
-
-	return sb->buf;
-}
-
 /* quote path as relative to the given prefix */
-char *quote_path_relative(const char *in, int len,
-			  struct strbuf *out, const char *prefix)
+char *quote_path_relative(const char *in, const char *prefix,
+			  struct strbuf *out)
 {
 	struct strbuf sb = STRBUF_INIT;
-	const char *rel = path_relative(in, len, &sb, prefix, -1);
+	const char *rel = relative_path(in, prefix, &sb);
 	strbuf_reset(out);
 	quote_c_style_counted(rel, strlen(rel), out, NULL, 0);
 	strbuf_release(&sb);
 
-	if (!out->len)
-		strbuf_addstr(out, "./");
-
 	return out->buf;
 }
 
diff --git a/quote.h b/quote.h
index 133155a..ed110a5 100644
--- a/quote.h
+++ b/quote.h
@@ -60,13 +60,12 @@
 extern void write_name_quoted(const char *name, FILE *, int terminator);
 extern void write_name_quotedpfx(const char *pfx, size_t pfxlen,
                                  const char *name, FILE *, int terminator);
-extern void write_name_quoted_relative(const char *name, size_t len,
-		const char *prefix, size_t prefix_len,
+extern void write_name_quoted_relative(const char *name, const char *prefix,
 		FILE *fp, int terminator);
 
 /* quote path as relative to the given prefix */
-extern char *quote_path_relative(const char *in, int len,
-			  struct strbuf *out, const char *prefix);
+extern char *quote_path_relative(const char *in, const char *prefix,
+			  struct strbuf *out);
 
 /* quoting as a string literal for other languages */
 extern void perl_quote_print(FILE *stream, const char *src);
diff --git a/read-cache.c b/read-cache.c
index 04ed561..c3d5e35 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -67,6 +67,61 @@
 	add_index_entry(istate, new, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE);
 }
 
+void fill_stat_data(struct stat_data *sd, struct stat *st)
+{
+	sd->sd_ctime.sec = (unsigned int)st->st_ctime;
+	sd->sd_mtime.sec = (unsigned int)st->st_mtime;
+	sd->sd_ctime.nsec = ST_CTIME_NSEC(*st);
+	sd->sd_mtime.nsec = ST_MTIME_NSEC(*st);
+	sd->sd_dev = st->st_dev;
+	sd->sd_ino = st->st_ino;
+	sd->sd_uid = st->st_uid;
+	sd->sd_gid = st->st_gid;
+	sd->sd_size = st->st_size;
+}
+
+int match_stat_data(const struct stat_data *sd, struct stat *st)
+{
+	int changed = 0;
+
+	if (sd->sd_mtime.sec != (unsigned int)st->st_mtime)
+		changed |= MTIME_CHANGED;
+	if (trust_ctime && check_stat &&
+	    sd->sd_ctime.sec != (unsigned int)st->st_ctime)
+		changed |= CTIME_CHANGED;
+
+#ifdef USE_NSEC
+	if (check_stat && sd->sd_mtime.nsec != ST_MTIME_NSEC(*st))
+		changed |= MTIME_CHANGED;
+	if (trust_ctime && check_stat &&
+	    sd->sd_ctime.nsec != ST_CTIME_NSEC(*st))
+		changed |= CTIME_CHANGED;
+#endif
+
+	if (check_stat) {
+		if (sd->sd_uid != (unsigned int) st->st_uid ||
+			sd->sd_gid != (unsigned int) st->st_gid)
+			changed |= OWNER_CHANGED;
+		if (sd->sd_ino != (unsigned int) st->st_ino)
+			changed |= INODE_CHANGED;
+	}
+
+#ifdef USE_STDEV
+	/*
+	 * st_dev breaks on network filesystems where different
+	 * clients will have different views of what "device"
+	 * the filesystem is on
+	 */
+	if (check_stat && sd->sd_dev != (unsigned int) st->st_dev)
+			changed |= INODE_CHANGED;
+#endif
+
+	if (sd->sd_size != (unsigned int) st->st_size)
+		changed |= DATA_CHANGED;
+
+	return changed;
+}
+
 /*
  * This only updates the "non-critical" parts of the directory
  * cache, ie the parts that aren't tracked by GIT, and only used
@@ -74,15 +129,7 @@
  */
 void fill_stat_cache_info(struct cache_entry *ce, struct stat *st)
 {
-	ce->ce_ctime.sec = (unsigned int)st->st_ctime;
-	ce->ce_mtime.sec = (unsigned int)st->st_mtime;
-	ce->ce_ctime.nsec = ST_CTIME_NSEC(*st);
-	ce->ce_mtime.nsec = ST_MTIME_NSEC(*st);
-	ce->ce_dev = st->st_dev;
-	ce->ce_ino = st->st_ino;
-	ce->ce_uid = st->st_uid;
-	ce->ce_gid = st->st_gid;
-	ce->ce_size = st->st_size;
+	fill_stat_data(&ce->ce_stat_data, st);
 
 	if (assume_unchanged)
 		ce->ce_flags |= CE_VALID;
@@ -91,7 +138,7 @@
 		ce_mark_uptodate(ce);
 }
 
-static int ce_compare_data(struct cache_entry *ce, struct stat *st)
+static int ce_compare_data(const struct cache_entry *ce, struct stat *st)
 {
 	int match = -1;
 	int fd = open(ce->name, O_RDONLY);
@@ -105,7 +152,7 @@
 	return match;
 }
 
-static int ce_compare_link(struct cache_entry *ce, size_t expected_size)
+static int ce_compare_link(const struct cache_entry *ce, size_t expected_size)
 {
 	int match = -1;
 	void *buffer;
@@ -126,7 +173,7 @@
 	return match;
 }
 
-static int ce_compare_gitlink(struct cache_entry *ce)
+static int ce_compare_gitlink(const struct cache_entry *ce)
 {
 	unsigned char sha1[20];
 
@@ -143,7 +190,7 @@
 	return hashcmp(sha1, ce->sha1);
 }
 
-static int ce_modified_check_fs(struct cache_entry *ce, struct stat *st)
+static int ce_modified_check_fs(const struct cache_entry *ce, struct stat *st)
 {
 	switch (st->st_mode & S_IFMT) {
 	case S_IFREG:
@@ -163,7 +210,7 @@
 	return 0;
 }
 
-static int ce_match_stat_basic(struct cache_entry *ce, struct stat *st)
+static int ce_match_stat_basic(const struct cache_entry *ce, struct stat *st)
 {
 	unsigned int changed = 0;
 
@@ -195,43 +242,11 @@
 	default:
 		die("internal error: ce_mode is %o", ce->ce_mode);
 	}
-	if (ce->ce_mtime.sec != (unsigned int)st->st_mtime)
-		changed |= MTIME_CHANGED;
-	if (trust_ctime && check_stat &&
-	    ce->ce_ctime.sec != (unsigned int)st->st_ctime)
-		changed |= CTIME_CHANGED;
 
-#ifdef USE_NSEC
-	if (check_stat && ce->ce_mtime.nsec != ST_MTIME_NSEC(*st))
-		changed |= MTIME_CHANGED;
-	if (trust_ctime && check_stat &&
-	    ce->ce_ctime.nsec != ST_CTIME_NSEC(*st))
-		changed |= CTIME_CHANGED;
-#endif
-
-	if (check_stat) {
-		if (ce->ce_uid != (unsigned int) st->st_uid ||
-			ce->ce_gid != (unsigned int) st->st_gid)
-			changed |= OWNER_CHANGED;
-		if (ce->ce_ino != (unsigned int) st->st_ino)
-			changed |= INODE_CHANGED;
-	}
-
-#ifdef USE_STDEV
-	/*
-	 * st_dev breaks on network filesystems where different
-	 * clients will have different views of what "device"
-	 * the filesystem is on
-	 */
-	if (check_stat && ce->ce_dev != (unsigned int) st->st_dev)
-			changed |= INODE_CHANGED;
-#endif
-
-	if (ce->ce_size != (unsigned int) st->st_size)
-		changed |= DATA_CHANGED;
+	changed |= match_stat_data(&ce->ce_stat_data, st);
 
 	/* Racily smudged entry? */
-	if (!ce->ce_size) {
+	if (!ce->ce_stat_data.sd_size) {
 		if (!is_empty_blob_sha1(ce->sha1))
 			changed |= DATA_CHANGED;
 	}
@@ -239,23 +254,24 @@
 	return changed;
 }
 
-static int is_racy_timestamp(const struct index_state *istate, struct cache_entry *ce)
+static int is_racy_timestamp(const struct index_state *istate,
+			     const struct cache_entry *ce)
 {
 	return (!S_ISGITLINK(ce->ce_mode) &&
 		istate->timestamp.sec &&
 #ifdef USE_NSEC
 		 /* nanosecond timestamped files can also be racy! */
-		(istate->timestamp.sec < ce->ce_mtime.sec ||
-		 (istate->timestamp.sec == ce->ce_mtime.sec &&
-		  istate->timestamp.nsec <= ce->ce_mtime.nsec))
+		(istate->timestamp.sec < ce->ce_stat_data.sd_mtime.sec ||
+		 (istate->timestamp.sec == ce->ce_stat_data.sd_mtime.sec &&
+		  istate->timestamp.nsec <= ce->ce_stat_data.sd_mtime.nsec))
 #else
-		istate->timestamp.sec <= ce->ce_mtime.sec
+		istate->timestamp.sec <= ce->ce_stat_data.sd_mtime.sec
 #endif
 		 );
 }
 
 int ie_match_stat(const struct index_state *istate,
-		  struct cache_entry *ce, struct stat *st,
+		  const struct cache_entry *ce, struct stat *st,
 		  unsigned int options)
 {
 	unsigned int changed;
@@ -311,7 +327,8 @@
 }
 
 int ie_modified(const struct index_state *istate,
-		struct cache_entry *ce, struct stat *st, unsigned int options)
+		const struct cache_entry *ce,
+		struct stat *st, unsigned int options)
 {
 	int changed, changed_fs;
 
@@ -340,7 +357,7 @@
 	 * then we know it is.
 	 */
 	if ((changed & DATA_CHANGED) &&
-	    (S_ISGITLINK(ce->ce_mode) || ce->ce_size != 0))
+	    (S_ISGITLINK(ce->ce_mode) || ce->ce_stat_data.sd_size != 0))
 		return changed;
 
 	changed_fs = ce_modified_check_fs(ce, st);
@@ -472,7 +489,7 @@
 }
 
 /*
- * Remove all cache ententries marked for removal, that is where
+ * Remove all cache entries marked for removal, that is where
  * CE_REMOVE is set in ce_flags.  This is much more effective than
  * calling remove_index_entry_at() for each entry to be removed.
  */
@@ -626,7 +643,7 @@
 			if (*ptr == '/') {
 				struct cache_entry *foundce;
 				++ptr;
-				foundce = index_name_exists(&the_index, ce->name, ptr - ce->name, ignore_case);
+				foundce = index_name_exists(istate, ce->name, ptr - ce->name, ignore_case);
 				if (foundce) {
 					memcpy((void *)startPtr, foundce->name + (startPtr - ce->name), ptr - startPtr);
 					startPtr = ptr;
@@ -705,7 +722,7 @@
 	return ce;
 }
 
-int ce_same_name(struct cache_entry *a, struct cache_entry *b)
+int ce_same_name(const struct cache_entry *a, const struct cache_entry *b)
 {
 	int len = ce_namelen(a);
 	return ce_namelen(b) == len && !memcmp(a->name, b->name, len);
@@ -979,7 +996,7 @@
 	if (istate->cache_nr == istate->cache_alloc) {
 		istate->cache_alloc = alloc_nr(istate->cache_alloc);
 		istate->cache = xrealloc(istate->cache,
-					istate->cache_alloc * sizeof(struct cache_entry *));
+					istate->cache_alloc * sizeof(*istate->cache));
 	}
 
 	/* Add it in.. */
@@ -1322,16 +1339,16 @@
 {
 	struct cache_entry *ce = xmalloc(cache_entry_size(len));
 
-	ce->ce_ctime.sec = ntoh_l(ondisk->ctime.sec);
-	ce->ce_mtime.sec = ntoh_l(ondisk->mtime.sec);
-	ce->ce_ctime.nsec = ntoh_l(ondisk->ctime.nsec);
-	ce->ce_mtime.nsec = ntoh_l(ondisk->mtime.nsec);
-	ce->ce_dev   = ntoh_l(ondisk->dev);
-	ce->ce_ino   = ntoh_l(ondisk->ino);
+	ce->ce_stat_data.sd_ctime.sec = ntoh_l(ondisk->ctime.sec);
+	ce->ce_stat_data.sd_mtime.sec = ntoh_l(ondisk->mtime.sec);
+	ce->ce_stat_data.sd_ctime.nsec = ntoh_l(ondisk->ctime.nsec);
+	ce->ce_stat_data.sd_mtime.nsec = ntoh_l(ondisk->mtime.nsec);
+	ce->ce_stat_data.sd_dev   = ntoh_l(ondisk->dev);
+	ce->ce_stat_data.sd_ino   = ntoh_l(ondisk->ino);
 	ce->ce_mode  = ntoh_l(ondisk->mode);
-	ce->ce_uid   = ntoh_l(ondisk->uid);
-	ce->ce_gid   = ntoh_l(ondisk->gid);
-	ce->ce_size  = ntoh_l(ondisk->size);
+	ce->ce_stat_data.sd_uid   = ntoh_l(ondisk->uid);
+	ce->ce_stat_data.sd_gid   = ntoh_l(ondisk->gid);
+	ce->ce_stat_data.sd_size  = ntoh_l(ondisk->size);
 	ce->ce_flags = flags & ~CE_NAMEMASK;
 	ce->ce_namelen = len;
 	hashcpy(ce->sha1, ondisk->sha1);
@@ -1449,7 +1466,7 @@
 	istate->version = ntohl(hdr->hdr_version);
 	istate->cache_nr = ntohl(hdr->hdr_entries);
 	istate->cache_alloc = alloc_nr(istate->cache_nr);
-	istate->cache = xcalloc(istate->cache_alloc, sizeof(struct cache_entry *));
+	istate->cache = xcalloc(istate->cache_alloc, sizeof(*istate->cache));
 	istate->initialized = 1;
 
 	if (istate->version == 4)
@@ -1518,8 +1535,9 @@
 	free_name_hash(istate);
 	cache_tree_free(&(istate->cache_tree));
 	istate->initialized = 0;
-
-	/* no need to throw away allocated active_cache */
+	free(istate->cache);
+	istate->cache = NULL;
+	istate->cache_alloc = 0;
 	return 0;
 }
 
@@ -1608,7 +1626,7 @@
 	 * The only thing we care about in this function is to smudge the
 	 * falsely clean entry due to touch-update-touch race, so we leave
 	 * everything else as they are.  We are called for entries whose
-	 * ce_mtime match the index file mtime.
+	 * ce_stat_data.sd_mtime match the index file mtime.
 	 *
 	 * Note that this actually does not do much for gitlinks, for
 	 * which ce_match_stat_basic() always goes to the actual
@@ -1647,7 +1665,7 @@
 		 * file, and never calls us, so the cached size information
 		 * for "frotz" stays 6 which does not match the filesystem.
 		 */
-		ce->ce_size = 0;
+		ce->ce_stat_data.sd_size = 0;
 	}
 }
 
@@ -1657,16 +1675,16 @@
 {
 	short flags;
 
-	ondisk->ctime.sec = htonl(ce->ce_ctime.sec);
-	ondisk->mtime.sec = htonl(ce->ce_mtime.sec);
-	ondisk->ctime.nsec = htonl(ce->ce_ctime.nsec);
-	ondisk->mtime.nsec = htonl(ce->ce_mtime.nsec);
-	ondisk->dev  = htonl(ce->ce_dev);
-	ondisk->ino  = htonl(ce->ce_ino);
+	ondisk->ctime.sec = htonl(ce->ce_stat_data.sd_ctime.sec);
+	ondisk->mtime.sec = htonl(ce->ce_stat_data.sd_mtime.sec);
+	ondisk->ctime.nsec = htonl(ce->ce_stat_data.sd_ctime.nsec);
+	ondisk->mtime.nsec = htonl(ce->ce_stat_data.sd_mtime.nsec);
+	ondisk->dev  = htonl(ce->ce_stat_data.sd_dev);
+	ondisk->ino  = htonl(ce->ce_stat_data.sd_ino);
 	ondisk->mode = htonl(ce->ce_mode);
-	ondisk->uid  = htonl(ce->ce_uid);
-	ondisk->gid  = htonl(ce->ce_gid);
-	ondisk->size = htonl(ce->ce_size);
+	ondisk->uid  = htonl(ce->ce_stat_data.sd_uid);
+	ondisk->gid  = htonl(ce->ce_stat_data.sd_gid);
+	ondisk->size = htonl(ce->ce_stat_data.sd_size);
 	hashcpy(ondisk->sha1, ce->sha1);
 
 	flags = ce->ce_flags;
@@ -1742,7 +1760,7 @@
 }
 
 /*
- * Opportunisticly update the index but do not complain if we can't
+ * Opportunistically update the index but do not complain if we can't
  */
 void update_index_if_able(struct index_state *istate, struct lock_file *lockfile)
 {
@@ -1933,3 +1951,33 @@
 		*size = sz;
 	return data;
 }
+
+void stat_validity_clear(struct stat_validity *sv)
+{
+	free(sv->sd);
+	sv->sd = NULL;
+}
+
+int stat_validity_check(struct stat_validity *sv, const char *path)
+{
+	struct stat st;
+
+	if (stat(path, &st) < 0)
+		return sv->sd == NULL;
+	if (!sv->sd)
+		return 0;
+	return S_ISREG(st.st_mode) && !match_stat_data(sv->sd, &st);
+}
+
+void stat_validity_update(struct stat_validity *sv, int fd)
+{
+	struct stat st;
+
+	if (fstat(fd, &st) < 0 || !S_ISREG(st.st_mode))
+		stat_validity_clear(sv);
+	else {
+		if (!sv->sd)
+			sv->sd = xcalloc(1, sizeof(struct stat_data));
+		fill_stat_data(sv->sd, &st);
+	}
+}
diff --git a/refs.c b/refs.c
index de2d8eb..7922261 100644
--- a/refs.c
+++ b/refs.c
@@ -109,7 +109,20 @@
  * (ref_entry->flag & REF_DIR) is zero.
  */
 struct ref_value {
+	/*
+	 * The name of the object to which this reference resolves
+	 * (which may be a tag object).  If REF_ISBROKEN, this is
+	 * null.  If REF_ISSYMREF, then this is the name of the object
+	 * referred to by the last reference in the symlink chain.
+	 */
 	unsigned char sha1[20];
+
+	/*
+	 * If REF_KNOWS_PEELED, then this field holds the peeled value
+	 * of this reference, or null if the reference is known not to
+	 * be peelable.  See the documentation for peel_ref() for an
+	 * exact definition of "peelable".
+	 */
 	unsigned char peeled[20];
 };
 
@@ -158,7 +171,17 @@
 	struct ref_entry **entries;
 };
 
-/* ISSYMREF=0x01, ISPACKED=0x02, and ISBROKEN=0x04 are public interfaces */
+/*
+ * Bit values for ref_entry::flag.  REF_ISSYMREF=0x01,
+ * REF_ISPACKED=0x02, and REF_ISBROKEN=0x04 are public values; see
+ * refs.h.
+ */
+
+/*
+ * The field ref_entry->u.value.peeled of this value entry contains
+ * the correct peeled value for the reference, which might be
+ * null_sha1 if the reference is not a tag or if it is broken.
+ */
 #define REF_KNOWS_PEELED 0x08
 
 /* ref_entry represents a directory of references */
@@ -343,18 +366,17 @@
 }
 
 /*
- * Return the entry with the given refname from the ref_dir
- * (non-recursively), sorting dir if necessary.  Return NULL if no
- * such entry is found.  dir must already be complete.
+ * Return the index of the entry with the given refname from the
+ * ref_dir (non-recursively), sorting dir if necessary.  Return -1 if
+ * no such entry is found.  dir must already be complete.
  */
-static struct ref_entry *search_ref_dir(struct ref_dir *dir,
-					const char *refname, size_t len)
+static int search_ref_dir(struct ref_dir *dir, const char *refname, size_t len)
 {
 	struct ref_entry **r;
 	struct string_slice key;
 
 	if (refname == NULL || !dir->nr)
-		return NULL;
+		return -1;
 
 	sort_ref_dir(dir);
 	key.len = len;
@@ -363,9 +385,9 @@
 		    ref_entry_cmp_sslice);
 
 	if (r == NULL)
-		return NULL;
+		return -1;
 
-	return *r;
+	return r - dir->entries;
 }
 
 /*
@@ -379,8 +401,9 @@
 					 const char *subdirname, size_t len,
 					 int mkdir)
 {
-	struct ref_entry *entry = search_ref_dir(dir, subdirname, len);
-	if (!entry) {
+	int entry_index = search_ref_dir(dir, subdirname, len);
+	struct ref_entry *entry;
+	if (entry_index == -1) {
 		if (!mkdir)
 			return NULL;
 		/*
@@ -391,6 +414,8 @@
 		 */
 		entry = create_dir_entry(dir->ref_cache, subdirname, len, 0);
 		add_entry_to_dir(dir, entry);
+	} else {
+		entry = dir->entries[entry_index];
 	}
 	return get_ref_dir(entry);
 }
@@ -429,12 +454,67 @@
  */
 static struct ref_entry *find_ref(struct ref_dir *dir, const char *refname)
 {
+	int entry_index;
 	struct ref_entry *entry;
 	dir = find_containing_dir(dir, refname, 0);
 	if (!dir)
 		return NULL;
-	entry = search_ref_dir(dir, refname, strlen(refname));
-	return (entry && !(entry->flag & REF_DIR)) ? entry : NULL;
+	entry_index = search_ref_dir(dir, refname, strlen(refname));
+	if (entry_index == -1)
+		return NULL;
+	entry = dir->entries[entry_index];
+	return (entry->flag & REF_DIR) ? NULL : entry;
+}
+
+/*
+ * Remove the entry with the given name from dir, recursing into
+ * subdirectories as necessary.  If refname is the name of a directory
+ * (i.e., ends with '/'), then remove the directory and its contents.
+ * If the removal was successful, return the number of entries
+ * remaining in the directory entry that contained the deleted entry.
+ * If the name was not found, return -1.  Please note that this
+ * function only deletes the entry from the cache; it does not delete
+ * it from the filesystem or ensure that other cache entries (which
+ * might be symbolic references to the removed entry) are updated.
+ * Nor does it remove any containing dir entries that might be made
+ * empty by the removal.  dir must represent the top-level directory
+ * and must already be complete.
+ */
+static int remove_entry(struct ref_dir *dir, const char *refname)
+{
+	int refname_len = strlen(refname);
+	int entry_index;
+	struct ref_entry *entry;
+	int is_dir = refname[refname_len - 1] == '/';
+	if (is_dir) {
+		/*
+		 * refname represents a reference directory.  Remove
+		 * the trailing slash; otherwise we will get the
+		 * directory *representing* refname rather than the
+		 * one *containing* it.
+		 */
+		char *dirname = xmemdupz(refname, refname_len - 1);
+		dir = find_containing_dir(dir, dirname, 0);
+		free(dirname);
+	} else {
+		dir = find_containing_dir(dir, refname, 0);
+	}
+	if (!dir)
+		return -1;
+	entry_index = search_ref_dir(dir, refname, refname_len);
+	if (entry_index == -1)
+		return -1;
+	entry = dir->entries[entry_index];
+
+	memmove(&dir->entries[entry_index],
+		&dir->entries[entry_index + 1],
+		(dir->nr - entry_index - 1) * sizeof(*dir->entries)
+		);
+	dir->nr--;
+	if (dir->sorted > entry_index)
+		dir->sorted--;
+	free_ref_entry(entry);
+	return dir->nr;
 }
 
 /*
@@ -503,28 +583,69 @@
 	dir->sorted = dir->nr = i;
 }
 
-#define DO_FOR_EACH_INCLUDE_BROKEN 01
+/* Include broken references in a do_for_each_ref*() iteration: */
+#define DO_FOR_EACH_INCLUDE_BROKEN 0x01
 
+/*
+ * Return true iff the reference described by entry can be resolved to
+ * an object in the database.  Emit a warning if the referred-to
+ * object does not exist.
+ */
+static int ref_resolves_to_object(struct ref_entry *entry)
+{
+	if (entry->flag & REF_ISBROKEN)
+		return 0;
+	if (!has_sha1_file(entry->u.value.sha1)) {
+		error("%s does not point to a valid object!", entry->name);
+		return 0;
+	}
+	return 1;
+}
+
+/*
+ * current_ref is a performance hack: when iterating over references
+ * using the for_each_ref*() functions, current_ref is set to the
+ * current reference's entry before calling the callback function.  If
+ * the callback function calls peel_ref(), then peel_ref() first
+ * checks whether the reference to be peeled is the current reference
+ * (it usually is) and if so, returns that reference's peeled version
+ * if it is available.  This avoids a refname lookup in a common case.
+ */
 static struct ref_entry *current_ref;
 
-static int do_one_ref(const char *base, each_ref_fn fn, int trim,
-		      int flags, void *cb_data, struct ref_entry *entry)
+typedef int each_ref_entry_fn(struct ref_entry *entry, void *cb_data);
+
+struct ref_entry_cb {
+	const char *base;
+	int trim;
+	int flags;
+	each_ref_fn *fn;
+	void *cb_data;
+};
+
+/*
+ * Handle one reference in a do_for_each_ref*()-style iteration,
+ * calling an each_ref_fn for each entry.
+ */
+static int do_one_ref(struct ref_entry *entry, void *cb_data)
 {
+	struct ref_entry_cb *data = cb_data;
+	struct ref_entry *old_current_ref;
 	int retval;
-	if (prefixcmp(entry->name, base))
+
+	if (prefixcmp(entry->name, data->base))
 		return 0;
 
-	if (!(flags & DO_FOR_EACH_INCLUDE_BROKEN)) {
-		if (entry->flag & REF_ISBROKEN)
-			return 0; /* ignore broken refs e.g. dangling symref */
-		if (!has_sha1_file(entry->u.value.sha1)) {
-			error("%s does not point to a valid object!", entry->name);
-			return 0;
-		}
-	}
+	if (!(data->flags & DO_FOR_EACH_INCLUDE_BROKEN) &&
+	      !ref_resolves_to_object(entry))
+		return 0;
+
+	/* Store the old value, in case this is a recursive call: */
+	old_current_ref = current_ref;
 	current_ref = entry;
-	retval = fn(entry->name + trim, entry->u.value.sha1, entry->flag, cb_data);
-	current_ref = NULL;
+	retval = data->fn(entry->name + data->trim, entry->u.value.sha1,
+			  entry->flag, data->cb_data);
+	current_ref = old_current_ref;
 	return retval;
 }
 
@@ -532,11 +653,11 @@
  * Call fn for each reference in dir that has index in the range
  * offset <= index < dir->nr.  Recurse into subdirectories that are in
  * that index range, sorting them before iterating.  This function
- * does not sort dir itself; it should be sorted beforehand.
+ * does not sort dir itself; it should be sorted beforehand.  fn is
+ * called for all references, including broken ones.
  */
-static int do_for_each_ref_in_dir(struct ref_dir *dir, int offset,
-				  const char *base,
-				  each_ref_fn fn, int trim, int flags, void *cb_data)
+static int do_for_each_entry_in_dir(struct ref_dir *dir, int offset,
+				    each_ref_entry_fn fn, void *cb_data)
 {
 	int i;
 	assert(dir->sorted == dir->nr);
@@ -546,10 +667,9 @@
 		if (entry->flag & REF_DIR) {
 			struct ref_dir *subdir = get_ref_dir(entry);
 			sort_ref_dir(subdir);
-			retval = do_for_each_ref_in_dir(subdir, 0,
-							base, fn, trim, flags, cb_data);
+			retval = do_for_each_entry_in_dir(subdir, 0, fn, cb_data);
 		} else {
-			retval = do_one_ref(base, fn, trim, flags, cb_data, entry);
+			retval = fn(entry, cb_data);
 		}
 		if (retval)
 			return retval;
@@ -562,12 +682,12 @@
  * by refname.  Recurse into subdirectories.  If a value entry appears
  * in both dir1 and dir2, then only process the version that is in
  * dir2.  The input dirs must already be sorted, but subdirs will be
- * sorted as needed.
+ * sorted as needed.  fn is called for all references, including
+ * broken ones.
  */
-static int do_for_each_ref_in_dirs(struct ref_dir *dir1,
-				   struct ref_dir *dir2,
-				   const char *base, each_ref_fn fn, int trim,
-				   int flags, void *cb_data)
+static int do_for_each_entry_in_dirs(struct ref_dir *dir1,
+				     struct ref_dir *dir2,
+				     each_ref_entry_fn fn, void *cb_data)
 {
 	int retval;
 	int i1 = 0, i2 = 0;
@@ -578,12 +698,10 @@
 		struct ref_entry *e1, *e2;
 		int cmp;
 		if (i1 == dir1->nr) {
-			return do_for_each_ref_in_dir(dir2, i2,
-						      base, fn, trim, flags, cb_data);
+			return do_for_each_entry_in_dir(dir2, i2, fn, cb_data);
 		}
 		if (i2 == dir2->nr) {
-			return do_for_each_ref_in_dir(dir1, i1,
-						      base, fn, trim, flags, cb_data);
+			return do_for_each_entry_in_dir(dir1, i1, fn, cb_data);
 		}
 		e1 = dir1->entries[i1];
 		e2 = dir2->entries[i2];
@@ -595,14 +713,13 @@
 				struct ref_dir *subdir2 = get_ref_dir(e2);
 				sort_ref_dir(subdir1);
 				sort_ref_dir(subdir2);
-				retval = do_for_each_ref_in_dirs(
-						subdir1, subdir2,
-						base, fn, trim, flags, cb_data);
+				retval = do_for_each_entry_in_dirs(
+						subdir1, subdir2, fn, cb_data);
 				i1++;
 				i2++;
 			} else if (!(e1->flag & REF_DIR) && !(e2->flag & REF_DIR)) {
 				/* Both are references; ignore the one from dir1. */
-				retval = do_one_ref(base, fn, trim, flags, cb_data, e2);
+				retval = fn(e2, cb_data);
 				i1++;
 				i2++;
 			} else {
@@ -621,26 +738,33 @@
 			if (e->flag & REF_DIR) {
 				struct ref_dir *subdir = get_ref_dir(e);
 				sort_ref_dir(subdir);
-				retval = do_for_each_ref_in_dir(
-						subdir, 0,
-						base, fn, trim, flags, cb_data);
+				retval = do_for_each_entry_in_dir(
+						subdir, 0, fn, cb_data);
 			} else {
-				retval = do_one_ref(base, fn, trim, flags, cb_data, e);
+				retval = fn(e, cb_data);
 			}
 		}
 		if (retval)
 			return retval;
 	}
-	if (i1 < dir1->nr)
-		return do_for_each_ref_in_dir(dir1, i1,
-					      base, fn, trim, flags, cb_data);
-	if (i2 < dir2->nr)
-		return do_for_each_ref_in_dir(dir2, i2,
-					      base, fn, trim, flags, cb_data);
-	return 0;
 }
 
 /*
+ * Load all of the refs from the dir into our in-memory cache. The hard work
+ * of loading loose refs is done by get_ref_dir(), so we just need to recurse
+ * through all of the sub-directories. We do not even need to care about
+ * sorting, as traversal order does not matter to us.
+ */
+static void prime_ref_dir(struct ref_dir *dir)
+{
+	int i;
+	for (i = 0; i < dir->nr; i++) {
+		struct ref_entry *entry = dir->entries[i];
+		if (entry->flag & REF_DIR)
+			prime_ref_dir(get_ref_dir(entry));
+	}
+}
+/*
  * Return true iff refname1 and refname2 conflict with each other.
  * Two reference names conflict if one of them exactly matches the
  * leading components of the other; e.g., "foo/bar" conflicts with
@@ -661,14 +785,13 @@
 	const char *conflicting_refname;
 };
 
-static int name_conflict_fn(const char *existingrefname, const unsigned char *sha1,
-			    int flags, void *cb_data)
+static int name_conflict_fn(struct ref_entry *entry, void *cb_data)
 {
 	struct name_conflict_cb *data = (struct name_conflict_cb *)cb_data;
-	if (data->oldrefname && !strcmp(data->oldrefname, existingrefname))
+	if (data->oldrefname && !strcmp(data->oldrefname, entry->name))
 		return 0;
-	if (names_conflict(data->refname, existingrefname)) {
-		data->conflicting_refname = existingrefname;
+	if (names_conflict(data->refname, entry->name)) {
+		data->conflicting_refname = entry->name;
 		return 1;
 	}
 	return 0;
@@ -676,7 +799,7 @@
 
 /*
  * Return true iff a reference named refname could be created without
- * conflicting with the name of an existing reference in array.  If
+ * conflicting with the name of an existing reference in dir.  If
  * oldrefname is non-NULL, ignore potential conflicts with oldrefname
  * (e.g., because oldrefname is scheduled for deletion in the same
  * operation).
@@ -690,9 +813,7 @@
 	data.conflicting_refname = NULL;
 
 	sort_ref_dir(dir);
-	if (do_for_each_ref_in_dir(dir, 0, "", name_conflict_fn,
-				   0, DO_FOR_EACH_INCLUDE_BROKEN,
-				   &data)) {
+	if (do_for_each_entry_in_dir(dir, 0, name_conflict_fn, &data)) {
 		error("'%s' exists; cannot create '%s'",
 		      data.conflicting_refname, refname);
 		return 0;
@@ -700,6 +821,30 @@
 	return 1;
 }
 
+struct packed_ref_cache {
+	struct ref_entry *root;
+
+	/*
+	 * Count of references to the data structure in this instance,
+	 * including the pointer from ref_cache::packed if any.  The
+	 * data will not be freed as long as the reference count is
+	 * nonzero.
+	 */
+	unsigned int referrers;
+
+	/*
+	 * Iff the packed-refs file associated with this instance is
+	 * currently locked for writing, this points at the associated
+	 * lock (which is owned by somebody else).  The referrer count
+	 * is also incremented when the file is locked and decremented
+	 * when it is unlocked.
+	 */
+	struct lock_file *lock;
+
+	/* The metadata from when this packed-refs cache was read */
+	struct stat_validity validity;
+};
+
 /*
  * Future: need to be in "struct repository"
  * when doing a full libification.
@@ -707,16 +852,51 @@
 static struct ref_cache {
 	struct ref_cache *next;
 	struct ref_entry *loose;
-	struct ref_entry *packed;
-	/* The submodule name, or "" for the main repo. */
-	char name[FLEX_ARRAY];
-} *ref_cache;
+	struct packed_ref_cache *packed;
+	/*
+	 * The submodule name, or "" for the main repo.  We allocate
+	 * length 1 rather than FLEX_ARRAY so that the main ref_cache
+	 * is initialized correctly.
+	 */
+	char name[1];
+} ref_cache, *submodule_ref_caches;
+
+/* Lock used for the main packed-refs file: */
+static struct lock_file packlock;
+
+/*
+ * Increment the reference count of *packed_refs.
+ */
+static void acquire_packed_ref_cache(struct packed_ref_cache *packed_refs)
+{
+	packed_refs->referrers++;
+}
+
+/*
+ * Decrease the reference count of *packed_refs.  If it goes to zero,
+ * free *packed_refs and return true; otherwise return false.
+ */
+static int release_packed_ref_cache(struct packed_ref_cache *packed_refs)
+{
+	if (!--packed_refs->referrers) {
+		free_ref_entry(packed_refs->root);
+		stat_validity_clear(&packed_refs->validity);
+		free(packed_refs);
+		return 1;
+	} else {
+		return 0;
+	}
+}
 
 static void clear_packed_ref_cache(struct ref_cache *refs)
 {
 	if (refs->packed) {
-		free_ref_entry(refs->packed);
+		struct packed_ref_cache *packed_refs = refs->packed;
+
+		if (packed_refs->lock)
+			die("internal error: packed-ref cache cleared while locked");
 		refs->packed = NULL;
+		release_packed_ref_cache(packed_refs);
 	}
 }
 
@@ -748,18 +928,18 @@
  */
 static struct ref_cache *get_ref_cache(const char *submodule)
 {
-	struct ref_cache *refs = ref_cache;
-	if (!submodule)
-		submodule = "";
-	while (refs) {
+	struct ref_cache *refs;
+
+	if (!submodule || !*submodule)
+		return &ref_cache;
+
+	for (refs = submodule_ref_caches; refs; refs = refs->next)
 		if (!strcmp(submodule, refs->name))
 			return refs;
-		refs = refs->next;
-	}
 
 	refs = create_ref_cache(submodule);
-	refs->next = ref_cache;
-	ref_cache = refs;
+	refs->next = submodule_ref_caches;
+	submodule_ref_caches = refs;
 	return refs;
 }
 
@@ -770,6 +950,16 @@
 	clear_loose_ref_cache(refs);
 }
 
+/* The length of a peeled reference line in packed-refs, including EOL: */
+#define PEELED_LINE_LENGTH 42
+
+/*
+ * The packed-refs header line that we write out.  Perhaps other
+ * traits will be added later.  The trailing space is required.
+ */
+static const char PACKED_REFS_HEADER[] =
+	"# pack-refs with: peeled fully-peeled \n";
+
 /*
  * Parse one line from a packed-refs file.  Write the SHA1 to sha1.
  * Return a pointer to the refname within the line (null-terminated),
@@ -862,8 +1052,8 @@
 		}
 		if (last &&
 		    refline[0] == '^' &&
-		    strlen(refline) == 42 &&
-		    refline[41] == '\n' &&
+		    strlen(refline) == PEELED_LINE_LENGTH &&
+		    refline[PEELED_LINE_LENGTH - 1] == '\n' &&
 		    !get_sha1_hex(refline + 1, sha1)) {
 			hashcpy(last->u.value.peeled, sha1);
 			/*
@@ -876,30 +1066,58 @@
 	}
 }
 
-static struct ref_dir *get_packed_refs(struct ref_cache *refs)
+/*
+ * Get the packed_ref_cache for the specified ref_cache, creating it
+ * if necessary.
+ */
+static struct packed_ref_cache *get_packed_ref_cache(struct ref_cache *refs)
 {
+	const char *packed_refs_file;
+
+	if (*refs->name)
+		packed_refs_file = git_path_submodule(refs->name, "packed-refs");
+	else
+		packed_refs_file = git_path("packed-refs");
+
+	if (refs->packed &&
+	    !stat_validity_check(&refs->packed->validity, packed_refs_file))
+		clear_packed_ref_cache(refs);
+
 	if (!refs->packed) {
-		const char *packed_refs_file;
 		FILE *f;
 
-		refs->packed = create_dir_entry(refs, "", 0, 0);
-		if (*refs->name)
-			packed_refs_file = git_path_submodule(refs->name, "packed-refs");
-		else
-			packed_refs_file = git_path("packed-refs");
+		refs->packed = xcalloc(1, sizeof(*refs->packed));
+		acquire_packed_ref_cache(refs->packed);
+		refs->packed->root = create_dir_entry(refs, "", 0, 0);
 		f = fopen(packed_refs_file, "r");
 		if (f) {
-			read_packed_refs(f, get_ref_dir(refs->packed));
+			stat_validity_update(&refs->packed->validity, fileno(f));
+			read_packed_refs(f, get_ref_dir(refs->packed->root));
 			fclose(f);
 		}
 	}
-	return get_ref_dir(refs->packed);
+	return refs->packed;
+}
+
+static struct ref_dir *get_packed_ref_dir(struct packed_ref_cache *packed_ref_cache)
+{
+	return get_ref_dir(packed_ref_cache->root);
+}
+
+static struct ref_dir *get_packed_refs(struct ref_cache *refs)
+{
+	return get_packed_ref_dir(get_packed_ref_cache(refs));
 }
 
 void add_packed_ref(const char *refname, const unsigned char *sha1)
 {
-	add_ref(get_packed_refs(get_ref_cache(NULL)),
-			create_ref_entry(refname, sha1, REF_ISPACKED, 1));
+	struct packed_ref_cache *packed_ref_cache =
+		get_packed_ref_cache(&ref_cache);
+
+	if (!packed_ref_cache->lock)
+		die("internal error: packed refs not locked");
+	add_ref(get_packed_ref_dir(packed_ref_cache),
+		create_ref_entry(refname, sha1, REF_ISPACKED, 1));
 }
 
 /*
@@ -1069,18 +1287,43 @@
 }
 
 /*
- * Try to read ref from the packed references.  On success, set sha1
- * and return 0; otherwise, return -1.
+ * Return the ref_entry for the given refname from the packed
+ * references.  If it does not exist, return NULL.
  */
-static int get_packed_ref(const char *refname, unsigned char *sha1)
+static struct ref_entry *get_packed_ref(const char *refname)
 {
-	struct ref_dir *packed = get_packed_refs(get_ref_cache(NULL));
-	struct ref_entry *entry = find_ref(packed, refname);
+	return find_ref(get_packed_refs(&ref_cache), refname);
+}
+
+/*
+ * A loose ref file doesn't exist; check for a packed ref.  The
+ * options are forwarded from resolve_safe_unsafe().
+ */
+static const char *handle_missing_loose_ref(const char *refname,
+					    unsigned char *sha1,
+					    int reading,
+					    int *flag)
+{
+	struct ref_entry *entry;
+
+	/*
+	 * The loose reference file does not exist; check for a packed
+	 * reference.
+	 */
+	entry = get_packed_ref(refname);
 	if (entry) {
 		hashcpy(sha1, entry->u.value.sha1);
-		return 0;
+		if (flag)
+			*flag |= REF_ISPACKED;
+		return refname;
 	}
-	return -1;
+	/* The reference is not a packed reference, either. */
+	if (reading) {
+		return NULL;
+	} else {
+		hashclr(sha1);
+		return refname;
+	}
 }
 
 const char *resolve_ref_unsafe(const char *refname, unsigned char *sha1, int reading, int *flag)
@@ -1107,32 +1350,34 @@
 
 		git_snpath(path, sizeof(path), "%s", refname);
 
+		/*
+		 * We might have to loop back here to avoid a race
+		 * condition: first we lstat() the file, then we try
+		 * to read it as a link or as a file.  But if somebody
+		 * changes the type of the file (file <-> directory
+		 * <-> symlink) between the lstat() and reading, then
+		 * we don't want to report that as an error but rather
+		 * try again starting with the lstat().
+		 */
+	stat_ref:
 		if (lstat(path, &st) < 0) {
-			if (errno != ENOENT)
+			if (errno == ENOENT)
+				return handle_missing_loose_ref(refname, sha1,
+								reading, flag);
+			else
 				return NULL;
-			/*
-			 * The loose reference file does not exist;
-			 * check for a packed reference.
-			 */
-			if (!get_packed_ref(refname, sha1)) {
-				if (flag)
-					*flag |= REF_ISPACKED;
-				return refname;
-			}
-			/* The reference is not a packed reference, either. */
-			if (reading) {
-				return NULL;
-			} else {
-				hashclr(sha1);
-				return refname;
-			}
 		}
 
 		/* Follow "normalized" - ie "refs/.." symlinks by hand */
 		if (S_ISLNK(st.st_mode)) {
 			len = readlink(path, buffer, sizeof(buffer)-1);
-			if (len < 0)
-				return NULL;
+			if (len < 0) {
+				if (errno == ENOENT || errno == EINVAL)
+					/* inconsistent with lstat; retry */
+					goto stat_ref;
+				else
+					return NULL;
+			}
 			buffer[len] = 0;
 			if (!prefixcmp(buffer, "refs/") &&
 					!check_refname_format(buffer, 0)) {
@@ -1155,8 +1400,13 @@
 		 * a ref
 		 */
 		fd = open(path, O_RDONLY);
-		if (fd < 0)
-			return NULL;
+		if (fd < 0) {
+			if (errno == ENOENT)
+				/* inconsistent with lstat; retry */
+				goto stat_ref;
+			else
+				return NULL;
+		}
 		len = read_in_full(fd, buffer, sizeof(buffer)-1);
 		close(fd);
 		if (len < 0)
@@ -1168,8 +1418,19 @@
 		/*
 		 * Is it a symbolic ref?
 		 */
-		if (prefixcmp(buffer, "ref:"))
-			break;
+		if (prefixcmp(buffer, "ref:")) {
+			/*
+			 * Please note that FETCH_HEAD has a second
+			 * line containing other data.
+			 */
+			if (get_sha1_hex(buffer, sha1) ||
+			    (buffer[40] != '\0' && !isspace(buffer[40]))) {
+				if (flag)
+					*flag |= REF_ISBROKEN;
+				return NULL;
+			}
+			return refname;
+		}
 		if (flag)
 			*flag |= REF_ISSYMREF;
 		buf = buffer + 4;
@@ -1182,13 +1443,6 @@
 		}
 		refname = strcpy(refname_buffer, buf);
 	}
-	/* Please note that FETCH_HEAD has a second line containing other data. */
-	if (get_sha1_hex(buffer, sha1) || (buffer[40] != '\0' && !isspace(buffer[40]))) {
-		if (flag)
-			*flag |= REF_ISBROKEN;
-		return NULL;
-	}
-	return refname;
 }
 
 char *resolve_refdup(const char *ref, unsigned char *sha1, int reading, int *flag)
@@ -1231,54 +1485,130 @@
 	return filter->fn(refname, sha1, flags, filter->cb_data);
 }
 
+enum peel_status {
+	/* object was peeled successfully: */
+	PEEL_PEELED = 0,
+
+	/*
+	 * object cannot be peeled because the named object (or an
+	 * object referred to by a tag in the peel chain), does not
+	 * exist.
+	 */
+	PEEL_INVALID = -1,
+
+	/* object cannot be peeled because it is not a tag: */
+	PEEL_NON_TAG = -2,
+
+	/* ref_entry contains no peeled value because it is a symref: */
+	PEEL_IS_SYMREF = -3,
+
+	/*
+	 * ref_entry cannot be peeled because it is broken (i.e., the
+	 * symbolic reference cannot even be resolved to an object
+	 * name):
+	 */
+	PEEL_BROKEN = -4
+};
+
+/*
+ * Peel the named object; i.e., if the object is a tag, resolve the
+ * tag recursively until a non-tag is found.  If successful, store the
+ * result to sha1 and return PEEL_PEELED.  If the object is not a tag
+ * or is not valid, return PEEL_NON_TAG or PEEL_INVALID, respectively,
+ * and leave sha1 unchanged.
+ */
+static enum peel_status peel_object(const unsigned char *name, unsigned char *sha1)
+{
+	struct object *o = lookup_unknown_object(name);
+
+	if (o->type == OBJ_NONE) {
+		int type = sha1_object_info(name, NULL);
+		if (type < 0)
+			return PEEL_INVALID;
+		o->type = type;
+	}
+
+	if (o->type != OBJ_TAG)
+		return PEEL_NON_TAG;
+
+	o = deref_tag_noverify(o);
+	if (!o)
+		return PEEL_INVALID;
+
+	hashcpy(sha1, o->sha1);
+	return PEEL_PEELED;
+}
+
+/*
+ * Peel the entry (if possible) and return its new peel_status.  If
+ * repeel is true, re-peel the entry even if there is an old peeled
+ * value that is already stored in it.
+ *
+ * It is OK to call this function with a packed reference entry that
+ * might be stale and might even refer to an object that has since
+ * been garbage-collected.  In such a case, if the entry has
+ * REF_KNOWS_PEELED then leave the status unchanged and return
+ * PEEL_PEELED or PEEL_NON_TAG; otherwise, return PEEL_INVALID.
+ */
+static enum peel_status peel_entry(struct ref_entry *entry, int repeel)
+{
+	enum peel_status status;
+
+	if (entry->flag & REF_KNOWS_PEELED) {
+		if (repeel) {
+			entry->flag &= ~REF_KNOWS_PEELED;
+			hashclr(entry->u.value.peeled);
+		} else {
+			return is_null_sha1(entry->u.value.peeled) ?
+				PEEL_NON_TAG : PEEL_PEELED;
+		}
+	}
+	if (entry->flag & REF_ISBROKEN)
+		return PEEL_BROKEN;
+	if (entry->flag & REF_ISSYMREF)
+		return PEEL_IS_SYMREF;
+
+	status = peel_object(entry->u.value.sha1, entry->u.value.peeled);
+	if (status == PEEL_PEELED || status == PEEL_NON_TAG)
+		entry->flag |= REF_KNOWS_PEELED;
+	return status;
+}
+
 int peel_ref(const char *refname, unsigned char *sha1)
 {
 	int flag;
 	unsigned char base[20];
-	struct object *o;
 
 	if (current_ref && (current_ref->name == refname
-		|| !strcmp(current_ref->name, refname))) {
-		if (current_ref->flag & REF_KNOWS_PEELED) {
-			if (is_null_sha1(current_ref->u.value.peeled))
-			    return -1;
-			hashcpy(sha1, current_ref->u.value.peeled);
-			return 0;
-		}
-		hashcpy(base, current_ref->u.value.sha1);
-		goto fallback;
+			    || !strcmp(current_ref->name, refname))) {
+		if (peel_entry(current_ref, 0))
+			return -1;
+		hashcpy(sha1, current_ref->u.value.peeled);
+		return 0;
 	}
 
 	if (read_ref_full(refname, base, 1, &flag))
 		return -1;
 
-	if ((flag & REF_ISPACKED)) {
-		struct ref_dir *dir = get_packed_refs(get_ref_cache(NULL));
-		struct ref_entry *r = find_ref(dir, refname);
-
-		if (r != NULL && r->flag & REF_KNOWS_PEELED) {
+	/*
+	 * If the reference is packed, read its ref_entry from the
+	 * cache in the hope that we already know its peeled value.
+	 * We only try this optimization on packed references because
+	 * (a) forcing the filling of the loose reference cache could
+	 * be expensive and (b) loose references anyway usually do not
+	 * have REF_KNOWS_PEELED.
+	 */
+	if (flag & REF_ISPACKED) {
+		struct ref_entry *r = get_packed_ref(refname);
+		if (r) {
+			if (peel_entry(r, 0))
+				return -1;
 			hashcpy(sha1, r->u.value.peeled);
 			return 0;
 		}
 	}
 
-fallback:
-	o = lookup_unknown_object(base);
-	if (o->type == OBJ_NONE) {
-		int type = sha1_object_info(base, NULL);
-		if (type < 0)
-			return -1;
-		o->type = type;
-	}
-
-	if (o->type == OBJ_TAG) {
-		o = deref_tag_noverify(o);
-		if (o) {
-			hashcpy(sha1, o->sha1);
-			return 0;
-		}
-	}
-	return -1;
+	return peel_object(base, sha1);
 }
 
 struct warn_if_dangling_data {
@@ -1316,40 +1646,84 @@
 	for_each_rawref(warn_if_dangling_symref, &data);
 }
 
-static int do_for_each_ref(const char *submodule, const char *base, each_ref_fn fn,
-			   int trim, int flags, void *cb_data)
+/*
+ * Call fn for each reference in the specified ref_cache, omitting
+ * references not in the containing_dir of base.  fn is called for all
+ * references, including broken ones.  If fn ever returns a non-zero
+ * value, stop the iteration and return that value; otherwise, return
+ * 0.
+ */
+static int do_for_each_entry(struct ref_cache *refs, const char *base,
+			     each_ref_entry_fn fn, void *cb_data)
 {
-	struct ref_cache *refs = get_ref_cache(submodule);
-	struct ref_dir *packed_dir = get_packed_refs(refs);
-	struct ref_dir *loose_dir = get_loose_refs(refs);
+	struct packed_ref_cache *packed_ref_cache;
+	struct ref_dir *loose_dir;
+	struct ref_dir *packed_dir;
 	int retval = 0;
 
+	/*
+	 * We must make sure that all loose refs are read before accessing the
+	 * packed-refs file; this avoids a race condition in which loose refs
+	 * are migrated to the packed-refs file by a simultaneous process, but
+	 * our in-memory view is from before the migration. get_packed_ref_cache()
+	 * takes care of making sure our view is up to date with what is on
+	 * disk.
+	 */
+	loose_dir = get_loose_refs(refs);
+	if (base && *base) {
+		loose_dir = find_containing_dir(loose_dir, base, 0);
+	}
+	if (loose_dir)
+		prime_ref_dir(loose_dir);
+
+	packed_ref_cache = get_packed_ref_cache(refs);
+	acquire_packed_ref_cache(packed_ref_cache);
+	packed_dir = get_packed_ref_dir(packed_ref_cache);
 	if (base && *base) {
 		packed_dir = find_containing_dir(packed_dir, base, 0);
-		loose_dir = find_containing_dir(loose_dir, base, 0);
 	}
 
 	if (packed_dir && loose_dir) {
 		sort_ref_dir(packed_dir);
 		sort_ref_dir(loose_dir);
-		retval = do_for_each_ref_in_dirs(
-				packed_dir, loose_dir,
-				base, fn, trim, flags, cb_data);
+		retval = do_for_each_entry_in_dirs(
+				packed_dir, loose_dir, fn, cb_data);
 	} else if (packed_dir) {
 		sort_ref_dir(packed_dir);
-		retval = do_for_each_ref_in_dir(
-				packed_dir, 0,
-				base, fn, trim, flags, cb_data);
+		retval = do_for_each_entry_in_dir(
+				packed_dir, 0, fn, cb_data);
 	} else if (loose_dir) {
 		sort_ref_dir(loose_dir);
-		retval = do_for_each_ref_in_dir(
-				loose_dir, 0,
-				base, fn, trim, flags, cb_data);
+		retval = do_for_each_entry_in_dir(
+				loose_dir, 0, fn, cb_data);
 	}
 
+	release_packed_ref_cache(packed_ref_cache);
 	return retval;
 }
 
+/*
+ * Call fn for each reference in the specified ref_cache for which the
+ * refname begins with base.  If trim is non-zero, then trim that many
+ * characters off the beginning of each refname before passing the
+ * refname to fn.  flags can be DO_FOR_EACH_INCLUDE_BROKEN to include
+ * broken references in the iteration.  If fn ever returns a non-zero
+ * value, stop the iteration and return that value; otherwise, return
+ * 0.
+ */
+static int do_for_each_ref(struct ref_cache *refs, const char *base,
+			   each_ref_fn fn, int trim, int flags, void *cb_data)
+{
+	struct ref_entry_cb data;
+	data.base = base;
+	data.trim = trim;
+	data.flags = flags;
+	data.fn = fn;
+	data.cb_data = cb_data;
+
+	return do_for_each_entry(refs, base, do_one_ref, &data);
+}
+
 static int do_head_ref(const char *submodule, each_ref_fn fn, void *cb_data)
 {
 	unsigned char sha1[20];
@@ -1380,23 +1754,23 @@
 
 int for_each_ref(each_ref_fn fn, void *cb_data)
 {
-	return do_for_each_ref(NULL, "", fn, 0, 0, cb_data);
+	return do_for_each_ref(&ref_cache, "", fn, 0, 0, cb_data);
 }
 
 int for_each_ref_submodule(const char *submodule, each_ref_fn fn, void *cb_data)
 {
-	return do_for_each_ref(submodule, "", fn, 0, 0, cb_data);
+	return do_for_each_ref(get_ref_cache(submodule), "", fn, 0, 0, cb_data);
 }
 
 int for_each_ref_in(const char *prefix, each_ref_fn fn, void *cb_data)
 {
-	return do_for_each_ref(NULL, prefix, fn, strlen(prefix), 0, cb_data);
+	return do_for_each_ref(&ref_cache, prefix, fn, strlen(prefix), 0, cb_data);
 }
 
 int for_each_ref_in_submodule(const char *submodule, const char *prefix,
 		each_ref_fn fn, void *cb_data)
 {
-	return do_for_each_ref(submodule, prefix, fn, strlen(prefix), 0, cb_data);
+	return do_for_each_ref(get_ref_cache(submodule), prefix, fn, strlen(prefix), 0, cb_data);
 }
 
 int for_each_tag_ref(each_ref_fn fn, void *cb_data)
@@ -1431,7 +1805,7 @@
 
 int for_each_replace_ref(each_ref_fn fn, void *cb_data)
 {
-	return do_for_each_ref(NULL, "refs/replace/", fn, 13, 0, cb_data);
+	return do_for_each_ref(&ref_cache, "refs/replace/", fn, 13, 0, cb_data);
 }
 
 int head_ref_namespaced(each_ref_fn fn, void *cb_data)
@@ -1454,7 +1828,7 @@
 	struct strbuf buf = STRBUF_INIT;
 	int ret;
 	strbuf_addf(&buf, "%srefs/", get_git_namespace());
-	ret = do_for_each_ref(NULL, buf.buf, fn, 0, 0, cb_data);
+	ret = do_for_each_ref(&ref_cache, buf.buf, fn, 0, 0, cb_data);
 	strbuf_release(&buf);
 	return ret;
 }
@@ -1496,7 +1870,7 @@
 
 int for_each_rawref(each_ref_fn fn, void *cb_data)
 {
-	return do_for_each_ref(NULL, "", fn, 0,
+	return do_for_each_ref(&ref_cache, "", fn, 0,
 			       DO_FOR_EACH_INCLUDE_BROKEN, cb_data);
 }
 
@@ -1702,7 +2076,7 @@
 	 * name is a proper prefix of our refname.
 	 */
 	if (missing &&
-	     !is_refname_available(refname, NULL, get_packed_refs(get_ref_cache(NULL)))) {
+	     !is_refname_available(refname, NULL, get_packed_refs(&ref_cache))) {
 		last_errno = ENOTDIR;
 		goto error_return;
 	}
@@ -1754,48 +2128,325 @@
 	return lock_ref_sha1_basic(refname, old_sha1, flags, NULL);
 }
 
-struct repack_without_ref_sb {
-	const char *refname;
-	int fd;
-};
-
-static int repack_without_ref_fn(const char *refname, const unsigned char *sha1,
-				 int flags, void *cb_data)
+/*
+ * Write an entry to the packed-refs file for the specified refname.
+ * If peeled is non-NULL, write it as the entry's peeled value.
+ */
+static void write_packed_entry(int fd, char *refname, unsigned char *sha1,
+			       unsigned char *peeled)
 {
-	struct repack_without_ref_sb *data = cb_data;
 	char line[PATH_MAX + 100];
 	int len;
 
-	if (!strcmp(data->refname, refname))
-		return 0;
 	len = snprintf(line, sizeof(line), "%s %s\n",
 		       sha1_to_hex(sha1), refname);
 	/* this should not happen but just being defensive */
 	if (len > sizeof(line))
 		die("too long a refname '%s'", refname);
-	write_or_die(data->fd, line, len);
+	write_or_die(fd, line, len);
+
+	if (peeled) {
+		if (snprintf(line, sizeof(line), "^%s\n",
+			     sha1_to_hex(peeled)) != PEELED_LINE_LENGTH)
+			die("internal error");
+		write_or_die(fd, line, PEELED_LINE_LENGTH);
+	}
+}
+
+/*
+ * An each_ref_entry_fn that writes the entry to a packed-refs file.
+ */
+static int write_packed_entry_fn(struct ref_entry *entry, void *cb_data)
+{
+	int *fd = cb_data;
+	enum peel_status peel_status = peel_entry(entry, 0);
+
+	if (peel_status != PEEL_PEELED && peel_status != PEEL_NON_TAG)
+		error("internal error: %s is not a valid packed reference!",
+		      entry->name);
+	write_packed_entry(*fd, entry->name, entry->u.value.sha1,
+			   peel_status == PEEL_PEELED ?
+			   entry->u.value.peeled : NULL);
 	return 0;
 }
 
-static struct lock_file packlock;
+int lock_packed_refs(int flags)
+{
+	struct packed_ref_cache *packed_ref_cache;
+
+	if (hold_lock_file_for_update(&packlock, git_path("packed-refs"), flags) < 0)
+		return -1;
+	/*
+	 * Get the current packed-refs while holding the lock.  If the
+	 * packed-refs file has been modified since we last read it,
+	 * this will automatically invalidate the cache and re-read
+	 * the packed-refs file.
+	 */
+	packed_ref_cache = get_packed_ref_cache(&ref_cache);
+	packed_ref_cache->lock = &packlock;
+	/* Increment the reference count to prevent it from being freed: */
+	acquire_packed_ref_cache(packed_ref_cache);
+	return 0;
+}
+
+int commit_packed_refs(void)
+{
+	struct packed_ref_cache *packed_ref_cache =
+		get_packed_ref_cache(&ref_cache);
+	int error = 0;
+
+	if (!packed_ref_cache->lock)
+		die("internal error: packed-refs not locked");
+	write_or_die(packed_ref_cache->lock->fd,
+		     PACKED_REFS_HEADER, strlen(PACKED_REFS_HEADER));
+
+	do_for_each_entry_in_dir(get_packed_ref_dir(packed_ref_cache),
+				 0, write_packed_entry_fn,
+				 &packed_ref_cache->lock->fd);
+	if (commit_lock_file(packed_ref_cache->lock))
+		error = -1;
+	packed_ref_cache->lock = NULL;
+	release_packed_ref_cache(packed_ref_cache);
+	return error;
+}
+
+void rollback_packed_refs(void)
+{
+	struct packed_ref_cache *packed_ref_cache =
+		get_packed_ref_cache(&ref_cache);
+
+	if (!packed_ref_cache->lock)
+		die("internal error: packed-refs not locked");
+	rollback_lock_file(packed_ref_cache->lock);
+	packed_ref_cache->lock = NULL;
+	release_packed_ref_cache(packed_ref_cache);
+	clear_packed_ref_cache(&ref_cache);
+}
+
+struct ref_to_prune {
+	struct ref_to_prune *next;
+	unsigned char sha1[20];
+	char name[FLEX_ARRAY];
+};
+
+struct pack_refs_cb_data {
+	unsigned int flags;
+	struct ref_dir *packed_refs;
+	struct ref_to_prune *ref_to_prune;
+};
+
+/*
+ * An each_ref_entry_fn that is run over loose references only.  If
+ * the loose reference can be packed, add an entry in the packed ref
+ * cache.  If the reference should be pruned, also add it to
+ * ref_to_prune in the pack_refs_cb_data.
+ */
+static int pack_if_possible_fn(struct ref_entry *entry, void *cb_data)
+{
+	struct pack_refs_cb_data *cb = cb_data;
+	enum peel_status peel_status;
+	struct ref_entry *packed_entry;
+	int is_tag_ref = !prefixcmp(entry->name, "refs/tags/");
+
+	/* ALWAYS pack tags */
+	if (!(cb->flags & PACK_REFS_ALL) && !is_tag_ref)
+		return 0;
+
+	/* Do not pack symbolic or broken refs: */
+	if ((entry->flag & REF_ISSYMREF) || !ref_resolves_to_object(entry))
+		return 0;
+
+	/* Add a packed ref cache entry equivalent to the loose entry. */
+	peel_status = peel_entry(entry, 1);
+	if (peel_status != PEEL_PEELED && peel_status != PEEL_NON_TAG)
+		die("internal error peeling reference %s (%s)",
+		    entry->name, sha1_to_hex(entry->u.value.sha1));
+	packed_entry = find_ref(cb->packed_refs, entry->name);
+	if (packed_entry) {
+		/* Overwrite existing packed entry with info from loose entry */
+		packed_entry->flag = REF_ISPACKED | REF_KNOWS_PEELED;
+		hashcpy(packed_entry->u.value.sha1, entry->u.value.sha1);
+	} else {
+		packed_entry = create_ref_entry(entry->name, entry->u.value.sha1,
+						REF_ISPACKED | REF_KNOWS_PEELED, 0);
+		add_ref(cb->packed_refs, packed_entry);
+	}
+	hashcpy(packed_entry->u.value.peeled, entry->u.value.peeled);
+
+	/* Schedule the loose reference for pruning if requested. */
+	if ((cb->flags & PACK_REFS_PRUNE)) {
+		int namelen = strlen(entry->name) + 1;
+		struct ref_to_prune *n = xcalloc(1, sizeof(*n) + namelen);
+		hashcpy(n->sha1, entry->u.value.sha1);
+		strcpy(n->name, entry->name);
+		n->next = cb->ref_to_prune;
+		cb->ref_to_prune = n;
+	}
+	return 0;
+}
+
+/*
+ * Remove empty parents, but spare refs/ and immediate subdirs.
+ * Note: munges *name.
+ */
+static void try_remove_empty_parents(char *name)
+{
+	char *p, *q;
+	int i;
+	p = name;
+	for (i = 0; i < 2; i++) { /* refs/{heads,tags,...}/ */
+		while (*p && *p != '/')
+			p++;
+		/* tolerate duplicate slashes; see check_refname_format() */
+		while (*p == '/')
+			p++;
+	}
+	for (q = p; *q; q++)
+		;
+	while (1) {
+		while (q > p && *q != '/')
+			q--;
+		while (q > p && *(q-1) == '/')
+			q--;
+		if (q == p)
+			break;
+		*q = '\0';
+		if (rmdir(git_path("%s", name)))
+			break;
+	}
+}
+
+/* make sure nobody touched the ref, and unlink */
+static void prune_ref(struct ref_to_prune *r)
+{
+	struct ref_lock *lock = lock_ref_sha1(r->name + 5, r->sha1);
+
+	if (lock) {
+		unlink_or_warn(git_path("%s", r->name));
+		unlock_ref(lock);
+		try_remove_empty_parents(r->name);
+	}
+}
+
+static void prune_refs(struct ref_to_prune *r)
+{
+	while (r) {
+		prune_ref(r);
+		r = r->next;
+	}
+}
+
+int pack_refs(unsigned int flags)
+{
+	struct pack_refs_cb_data cbdata;
+
+	memset(&cbdata, 0, sizeof(cbdata));
+	cbdata.flags = flags;
+
+	lock_packed_refs(LOCK_DIE_ON_ERROR);
+	cbdata.packed_refs = get_packed_refs(&ref_cache);
+
+	do_for_each_entry_in_dir(get_loose_refs(&ref_cache), 0,
+				 pack_if_possible_fn, &cbdata);
+
+	if (commit_packed_refs())
+		die_errno("unable to overwrite old ref-pack file");
+
+	prune_refs(cbdata.ref_to_prune);
+	return 0;
+}
+
+/*
+ * If entry is no longer needed in packed-refs, add it to the string
+ * list pointed to by cb_data.  Reasons for deleting entries:
+ *
+ * - Entry is broken.
+ * - Entry is overridden by a loose ref.
+ * - Entry does not point at a valid object.
+ *
+ * In the first and third cases, also emit an error message because these
+ * are indications of repository corruption.
+ */
+static int curate_packed_ref_fn(struct ref_entry *entry, void *cb_data)
+{
+	struct string_list *refs_to_delete = cb_data;
+
+	if (entry->flag & REF_ISBROKEN) {
+		/* This shouldn't happen to packed refs. */
+		error("%s is broken!", entry->name);
+		string_list_append(refs_to_delete, entry->name);
+		return 0;
+	}
+	if (!has_sha1_file(entry->u.value.sha1)) {
+		unsigned char sha1[20];
+		int flags;
+
+		if (read_ref_full(entry->name, sha1, 0, &flags))
+			/* We should at least have found the packed ref. */
+			die("Internal error");
+		if ((flags & REF_ISSYMREF) || !(flags & REF_ISPACKED)) {
+			/*
+			 * This packed reference is overridden by a
+			 * loose reference, so it is OK that its value
+			 * is no longer valid; for example, it might
+			 * refer to an object that has been garbage
+			 * collected.  For this purpose we don't even
+			 * care whether the loose reference itself is
+			 * invalid, broken, symbolic, etc.  Silently
+			 * remove the packed reference.
+			 */
+			string_list_append(refs_to_delete, entry->name);
+			return 0;
+		}
+		/*
+		 * There is no overriding loose reference, so the fact
+		 * that this reference doesn't refer to a valid object
+		 * indicates some kind of repository corruption.
+		 * Report the problem, then omit the reference from
+		 * the output.
+		 */
+		error("%s does not point to a valid object!", entry->name);
+		string_list_append(refs_to_delete, entry->name);
+		return 0;
+	}
+
+	return 0;
+}
 
 static int repack_without_ref(const char *refname)
 {
-	struct repack_without_ref_sb data;
-	struct ref_cache *refs = get_ref_cache(NULL);
-	struct ref_dir *packed = get_packed_refs(refs);
-	if (find_ref(packed, refname) == NULL)
-		return 0;
-	data.refname = refname;
-	data.fd = hold_lock_file_for_update(&packlock, git_path("packed-refs"), 0);
-	if (data.fd < 0) {
+	struct ref_dir *packed;
+	struct string_list refs_to_delete = STRING_LIST_INIT_DUP;
+	struct string_list_item *ref_to_delete;
+
+	if (!get_packed_ref(refname))
+		return 0; /* refname does not exist in packed refs */
+
+	if (lock_packed_refs(0)) {
 		unable_to_lock_error(git_path("packed-refs"), errno);
 		return error("cannot delete '%s' from packed refs", refname);
 	}
-	clear_packed_ref_cache(refs);
-	packed = get_packed_refs(refs);
-	do_for_each_ref_in_dir(packed, 0, "", repack_without_ref_fn, 0, 0, &data);
-	return commit_lock_file(&packlock);
+	packed = get_packed_refs(&ref_cache);
+
+	/* Remove refname from the cache: */
+	if (remove_entry(packed, refname) == -1) {
+		/*
+		 * The packed entry disappeared while we were
+		 * acquiring the lock.
+		 */
+		rollback_packed_refs();
+		return 0;
+	}
+
+	/* Remove any other accumulated cruft: */
+	do_for_each_entry_in_dir(packed, 0, curate_packed_ref_fn, &refs_to_delete);
+	for_each_string_list_item(ref_to_delete, &refs_to_delete) {
+		if (remove_entry(packed, ref_to_delete->string) == -1)
+			die("internal error");
+	}
+
+	/* Write what remains: */
+	return commit_packed_refs();
 }
 
 int delete_ref(const char *refname, const unsigned char *sha1, int delopt)
@@ -1823,7 +2474,7 @@
 	ret |= repack_without_ref(lock->ref_name);
 
 	unlink_or_warn(git_path("logs/%s", lock->ref_name));
-	invalidate_ref_cache(NULL);
+	clear_loose_ref_cache(&ref_cache);
 	unlock_ref(lock);
 	return ret;
 }
@@ -1845,7 +2496,6 @@
 	struct stat loginfo;
 	int log = !lstat(git_path("logs/%s", oldrefname), &loginfo);
 	const char *symref = NULL;
-	struct ref_cache *refs = get_ref_cache(NULL);
 
 	if (log && S_ISLNK(loginfo.st_mode))
 		return error("reflog for %s is a symlink", oldrefname);
@@ -1857,10 +2507,10 @@
 	if (!symref)
 		return error("refname %s not found", oldrefname);
 
-	if (!is_refname_available(newrefname, oldrefname, get_packed_refs(refs)))
+	if (!is_refname_available(newrefname, oldrefname, get_packed_refs(&ref_cache)))
 		return 1;
 
-	if (!is_refname_available(newrefname, oldrefname, get_loose_refs(refs)))
+	if (!is_refname_available(newrefname, oldrefname, get_loose_refs(&ref_cache)))
 		return 1;
 
 	if (log && rename(git_path("logs/%s", oldrefname), git_path(TMP_RENAMED_LOG)))
@@ -2116,7 +2766,7 @@
 		unlock_ref(lock);
 		return -1;
 	}
-	clear_loose_ref_cache(get_ref_cache(NULL));
+	clear_loose_ref_cache(&ref_cache);
 	if (log_ref_write(lock->ref_name, lock->old_sha1, sha1, logmsg) < 0 ||
 	    (strcmp(lock->ref_name, lock->orig_ref_name) &&
 	     log_ref_write(lock->orig_ref_name, lock->old_sha1, sha1, logmsg) < 0)) {
diff --git a/refs.h b/refs.h
index a35eafc..9e5db3a 100644
--- a/refs.h
+++ b/refs.h
@@ -10,18 +10,41 @@
 	int force_write;
 };
 
+/*
+ * Bit values set in the flags argument passed to each_ref_fn():
+ */
+
+/* Reference is a symbolic reference. */
 #define REF_ISSYMREF 0x01
+
+/* Reference is a packed reference. */
 #define REF_ISPACKED 0x02
+
+/*
+ * Reference cannot be resolved to an object name: dangling symbolic
+ * reference (directly or indirectly), corrupt reference file, or
+ * symbolic reference refers to ill-formatted reference name.
+ */
 #define REF_ISBROKEN 0x04
 
 /*
- * Calls the specified function for each ref file until it returns
- * nonzero, and returns the value.  Please note that it is not safe to
- * modify references while an iteration is in progress, unless the
- * same callback function invocation that modifies the reference also
- * returns a nonzero value to immediately stop the iteration.
+ * The signature for the callback function for the for_each_*()
+ * functions below.  The memory pointed to by the refname and sha1
+ * arguments is only guaranteed to be valid for the duration of a
+ * single callback invocation.
  */
-typedef int each_ref_fn(const char *refname, const unsigned char *sha1, int flags, void *cb_data);
+typedef int each_ref_fn(const char *refname,
+			const unsigned char *sha1, int flags, void *cb_data);
+
+/*
+ * The following functions invoke the specified callback function for
+ * each reference indicated.  If the function ever returns a nonzero
+ * value, stop the iteration and return that value.  Please note that
+ * it is not safe to modify references while an iteration is in
+ * progress, unless the same callback function invocation that
+ * modifies the reference also returns a nonzero value to immediately
+ * stop the iteration.
+ */
 extern int head_ref(each_ref_fn, void *);
 extern int for_each_ref(each_ref_fn, void *);
 extern int for_each_ref_in(const char *, each_ref_fn, void *);
@@ -54,13 +77,57 @@
 extern void warn_dangling_symref(FILE *fp, const char *msg_fmt, const char *refname);
 
 /*
- * Add a reference to the in-memory packed reference cache.  To actually
- * write the reference to the packed-refs file, call pack_refs().
+ * Lock the packed-refs file for writing.  Flags is passed to
+ * hold_lock_file_for_update().  Return 0 on success.
+ */
+extern int lock_packed_refs(int flags);
+
+/*
+ * Add a reference to the in-memory packed reference cache.  This may
+ * only be called while the packed-refs file is locked (see
+ * lock_packed_refs()).  To actually write the packed-refs file, call
+ * commit_packed_refs().
  */
 extern void add_packed_ref(const char *refname, const unsigned char *sha1);
 
+/*
+ * Write the current version of the packed refs cache from memory to
+ * disk.  The packed-refs file must already be locked for writing (see
+ * lock_packed_refs()).  Return zero on success.
+ */
+extern int commit_packed_refs(void);
+
+/*
+ * Rollback the lockfile for the packed-refs file, and discard the
+ * in-memory packed reference cache.  (The packed-refs file will be
+ * read anew if it is needed again after this function is called.)
+ */
+extern void rollback_packed_refs(void);
+
+/*
+ * Flags for controlling behaviour of pack_refs()
+ * PACK_REFS_PRUNE: Prune loose refs after packing
+ * PACK_REFS_ALL:   Pack _all_ refs, not just tags and already packed refs
+ */
+#define PACK_REFS_PRUNE 0x0001
+#define PACK_REFS_ALL   0x0002
+
+/*
+ * Write a packed-refs file for the current repository.
+ * flags: Combination of the above PACK_REFS_* flags.
+ */
+int pack_refs(unsigned int flags);
+
 extern int ref_exists(const char *);
 
+/*
+ * If refname is a non-symbolic reference that refers to a tag object,
+ * and the tag can be (recursively) dereferenced to a non-tag object,
+ * store the SHA1 of the referred-to object to sha1 and return 0.  If
+ * any of these conditions are not met, return a non-zero value.
+ * Symbolic references are considered unpeelable, even if they
+ * ultimately resolve to a peelable tag.
+ */
 extern int peel_ref(const char *refname, unsigned char *sha1);
 
 /** Locks a "refs/" ref returning the lock on success and NULL on failure. **/
diff --git a/remote-curl.c b/remote-curl.c
index 60eda63..5b3ce9e 100644
--- a/remote-curl.c
+++ b/remote-curl.c
@@ -7,6 +7,7 @@
 #include "run-command.h"
 #include "pkt-line.h"
 #include "sideband.h"
+#include "argv-array.h"
 
 static struct remote *remote;
 static const char *url; /* always ends with a trailing slash */
@@ -787,36 +788,35 @@
 static int push_git(struct discovery *heads, int nr_spec, char **specs)
 {
 	struct rpc_state rpc;
-	const char **argv;
-	int argc = 0, i, err;
+	int i, err;
+	struct argv_array args;
 
-	argv = xmalloc((10 + nr_spec) * sizeof(char*));
-	argv[argc++] = "send-pack";
-	argv[argc++] = "--stateless-rpc";
-	argv[argc++] = "--helper-status";
+	argv_array_init(&args);
+	argv_array_pushl(&args, "send-pack", "--stateless-rpc", "--helper-status",
+			 NULL);
+
 	if (options.thin)
-		argv[argc++] = "--thin";
+		argv_array_push(&args, "--thin");
 	if (options.dry_run)
-		argv[argc++] = "--dry-run";
+		argv_array_push(&args, "--dry-run");
 	if (options.verbosity == 0)
-		argv[argc++] = "--quiet";
+		argv_array_push(&args, "--quiet");
 	else if (options.verbosity > 1)
-		argv[argc++] = "--verbose";
-	argv[argc++] = options.progress ? "--progress" : "--no-progress";
-	argv[argc++] = url;
+		argv_array_push(&args, "--verbose");
+	argv_array_push(&args, options.progress ? "--progress" : "--no-progress");
+	argv_array_push(&args, url);
 	for (i = 0; i < nr_spec; i++)
-		argv[argc++] = specs[i];
-	argv[argc++] = NULL;
+		argv_array_push(&args, specs[i]);
 
 	memset(&rpc, 0, sizeof(rpc));
 	rpc.service_name = "git-receive-pack",
-	rpc.argv = argv;
+	rpc.argv = args.argv;
 
 	err = rpc_service(&rpc, heads);
 	if (rpc.result.len)
 		write_or_die(1, rpc.result.buf, rpc.result.len);
 	strbuf_release(&rpc.result);
-	free(argv);
+	argv_array_clear(&args);
 	return err;
 }
 
diff --git a/remote-testsvn.c b/remote-testsvn.c
index 5ddf11c..d7cd5d2 100644
--- a/remote-testsvn.c
+++ b/remote-testsvn.c
@@ -286,7 +286,7 @@
 	return 0;
 }
 
-int main(int argc, const char **argv)
+int main(int argc, char **argv)
 {
 	struct strbuf buf = STRBUF_INIT, url_sb = STRBUF_INIT,
 			private_ref_sb = STRBUF_INIT, marksfilename_sb = STRBUF_INIT,
diff --git a/remote.c b/remote.c
index 68eb99b..efcba93 100644
--- a/remote.c
+++ b/remote.c
@@ -276,10 +276,9 @@
 
 static void read_branches_file(struct remote *remote)
 {
-	const char *slash = strchr(remote->name, '/');
 	char *frag;
 	struct strbuf branch = STRBUF_INIT;
-	int n = slash ? slash - remote->name : 1000;
+	int n = 1000;
 	FILE *f = fopen(git_path("branches/%.*s", n, remote->name), "r");
 	char *s, *p;
 	int len;
@@ -299,21 +298,11 @@
 	while (isspace(p[-1]))
 		*--p = 0;
 	len = p - s;
-	if (slash)
-		len += strlen(slash);
 	p = xmalloc(len + 1);
 	strcpy(p, s);
-	if (slash)
-		strcat(p, slash);
 
 	/*
-	 * With "slash", e.g. "git fetch jgarzik/netdev-2.6" when
-	 * reading from $GIT_DIR/branches/jgarzik fetches "HEAD" from
-	 * the partial URL obtained from the branches file plus
-	 * "/netdev-2.6" and does not store it in any tracking ref.
-	 * #branch specifier in the file is ignored.
-	 *
-	 * Otherwise, the branches file would have URL and optionally
+	 * The branches file would have URL and optionally
 	 * #branch specified.  The "master" (or specified) branch is
 	 * fetched and stored in the local branch of the same name.
 	 */
@@ -323,12 +312,8 @@
 		strbuf_addf(&branch, "refs/heads/%s", frag);
 	} else
 		strbuf_addstr(&branch, "refs/heads/master");
-	if (!slash) {
-		strbuf_addf(&branch, ":refs/heads/%s", remote->name);
-	} else {
-		strbuf_reset(&branch);
-		strbuf_addstr(&branch, "HEAD:");
-	}
+
+	strbuf_addf(&branch, ":refs/heads/%s", remote->name);
 	add_url_alias(remote, p);
 	add_fetch_refspec(remote, strbuf_detach(&branch, NULL));
 	/*
@@ -1317,6 +1302,14 @@
 	free(sent_tips.tip);
 }
 
+static void prepare_ref_index(struct string_list *ref_index, struct ref *ref)
+{
+	for ( ; ref; ref = ref->next)
+		string_list_append_nodup(ref_index, ref->name)->util = ref;
+
+	sort_string_list(ref_index);
+}
+
 /*
  * Given the set of refs the local repository has, the set of refs the
  * remote repository has, and the refspec used for push, determine
@@ -1335,6 +1328,7 @@
 	int errs;
 	static const char *default_refspec[] = { ":", NULL };
 	struct ref *ref, **dst_tail = tail_ref(dst);
+	struct string_list dst_ref_index = STRING_LIST_INIT_NODUP;
 
 	if (!nr_refspec) {
 		nr_refspec = 1;
@@ -1345,6 +1339,7 @@
 
 	/* pick the remainder */
 	for (ref = src; ref; ref = ref->next) {
+		struct string_list_item *dst_item;
 		struct ref *dst_peer;
 		const struct refspec *pat = NULL;
 		char *dst_name;
@@ -1353,7 +1348,11 @@
 		if (!dst_name)
 			continue;
 
-		dst_peer = find_ref_by_name(*dst, dst_name);
+		if (!dst_ref_index.nr)
+			prepare_ref_index(&dst_ref_index, *dst);
+
+		dst_item = string_list_lookup(&dst_ref_index, dst_name);
+		dst_peer = dst_item ? dst_item->util : NULL;
 		if (dst_peer) {
 			if (dst_peer->peer_ref)
 				/* We're already sending something to this ref. */
@@ -1370,6 +1369,8 @@
 			/* Create a new one and link it */
 			dst_peer = make_linked_ref(dst_name, &dst_tail);
 			hashcpy(dst_peer->new_sha1, ref->new_sha1);
+			string_list_insert(&dst_ref_index,
+				dst_peer->name)->util = dst_peer;
 		}
 		dst_peer->peer_ref = copy_ref(ref);
 		dst_peer->force = pat->force;
@@ -1377,10 +1378,13 @@
 		free(dst_name);
 	}
 
+	string_list_clear(&dst_ref_index, 0);
+
 	if (flags & MATCH_REFS_FOLLOW_TAGS)
 		add_missing_tags(src, dst, &dst_tail);
 
 	if (send_prune) {
+		struct string_list src_ref_index = STRING_LIST_INIT_NODUP;
 		/* check for missing refs on the remote */
 		for (ref = *dst; ref; ref = ref->next) {
 			char *src_name;
@@ -1391,11 +1395,15 @@
 
 			src_name = get_ref_match(rs, nr_refspec, ref, send_mirror, FROM_DST, NULL);
 			if (src_name) {
-				if (!find_ref_by_name(src, src_name))
+				if (!src_ref_index.nr)
+					prepare_ref_index(&src_ref_index, src);
+				if (!string_list_has_string(&src_ref_index,
+					    src_name))
 					ref->peer_ref = alloc_delete_ref();
 				free(src_name);
 			}
 		}
+		string_list_clear(&src_ref_index, 0);
 	}
 	if (errs)
 		return -1;
@@ -1474,8 +1482,7 @@
 		ret->remote = remote_get(ret->remote_name);
 		if (ret->merge_nr) {
 			int i;
-			ret->merge = xcalloc(sizeof(*ret->merge),
-					     ret->merge_nr);
+			ret->merge = xcalloc(ret->merge_nr, sizeof(*ret->merge));
 			for (i = 0; i < ret->merge_nr; i++) {
 				ret->merge[i] = xcalloc(1, sizeof(**ret->merge));
 				ret->merge[i]->src = xstrdup(ret->merge_name[i]);
diff --git a/rerere.c b/rerere.c
index 98e3e29..6fde8f9 100644
--- a/rerere.c
+++ b/rerere.c
@@ -299,7 +299,7 @@
 {
 	mmfile_t mmfile[3] = {{NULL}};
 	mmbuffer_t result = {NULL, 0};
-	struct cache_entry *ce;
+	const struct cache_entry *ce;
 	int pos, len, i, hunk_no;
 	struct rerere_io_mem io;
 	int marker_size = ll_merge_marker_size(path);
@@ -359,7 +359,7 @@
 
 static int check_one_conflict(int i, int *type)
 {
-	struct cache_entry *e = active_cache[i];
+	const struct cache_entry *e = active_cache[i];
 
 	if (!ce_stage(e)) {
 		*type = RESOLVED;
@@ -374,8 +374,8 @@
 
 	/* Only handle regular files with both stages #2 and #3 */
 	if (i + 1 < active_nr) {
-		struct cache_entry *e2 = active_cache[i];
-		struct cache_entry *e3 = active_cache[i + 1];
+		const struct cache_entry *e2 = active_cache[i];
+		const struct cache_entry *e3 = active_cache[i + 1];
 		if (ce_stage(e2) == 2 &&
 		    ce_stage(e3) == 3 &&
 		    ce_same_name(e, e3) &&
@@ -398,7 +398,7 @@
 
 	for (i = 0; i < active_nr;) {
 		int conflict_type;
-		struct cache_entry *e = active_cache[i];
+		const struct cache_entry *e = active_cache[i];
 		i = check_one_conflict(i, &conflict_type);
 		if (conflict_type == THREE_STAGED)
 			string_list_insert(conflict, (const char *)e->name);
@@ -414,7 +414,7 @@
 
 	for (i = 0; i < active_nr;) {
 		int conflict_type;
-		struct cache_entry *e = active_cache[i];
+		const struct cache_entry *e = active_cache[i];
 		i = check_one_conflict(i, &conflict_type);
 		if (conflict_type == PUNTED)
 			string_list_insert(merge_rr, (const char *)e->name);
diff --git a/resolve-undo.c b/resolve-undo.c
index 639eb9c..77101f5 100644
--- a/resolve-undo.c
+++ b/resolve-undo.c
@@ -115,7 +115,7 @@
 
 int unmerge_index_entry_at(struct index_state *istate, int pos)
 {
-	struct cache_entry *ce;
+	const struct cache_entry *ce;
 	struct string_list_item *item;
 	struct resolve_undo_info *ru;
 	int i, err = 0, matched;
@@ -167,7 +167,7 @@
 		return;
 
 	for (i = 0; i < istate->cache_nr; i++) {
-		struct cache_entry *ce = istate->cache[i];
+		const struct cache_entry *ce = istate->cache[i];
 		if (ce->ce_flags & CE_MATCHED)
 			i = unmerge_index_entry_at(istate, i);
 	}
@@ -181,7 +181,7 @@
 		return;
 
 	for (i = 0; i < istate->cache_nr; i++) {
-		struct cache_entry *ce = istate->cache[i];
+		const struct cache_entry *ce = istate->cache[i];
 		if (!match_pathspec(pathspec, ce->name, ce_namelen(ce), 0, NULL))
 			continue;
 		i = unmerge_index_entry_at(istate, i);
diff --git a/revision.c b/revision.c
index a67b615..ac20d1a 100644
--- a/revision.c
+++ b/revision.c
@@ -13,7 +13,9 @@
 #include "decorate.h"
 #include "log-tree.h"
 #include "string-list.h"
+#include "line-log.h"
 #include "mailmap.h"
+#include "commit-slab.h"
 
 volatile show_early_output_fn_t show_early_output;
 
@@ -70,7 +72,8 @@
 	return ours || emitted;
 }
 
-void show_object_with_name(FILE *out, struct object *obj, const struct name_path *path, const char *component)
+void show_object_with_name(FILE *out, struct object *obj,
+			   const struct name_path *path, const char *component)
 {
 	struct name_path leaf;
 	leaf.up = (struct name_path *)path;
@@ -87,7 +90,9 @@
 		struct name_path *path,
 		const char *name)
 {
-	add_object_array(obj, path_name(path, name), p);
+	char *pn = path_name(path, name);
+	add_object_array(obj, pn, p);
+	free(pn);
 }
 
 static void mark_blob_uninteresting(struct blob *blob)
@@ -186,7 +191,9 @@
 	}
 }
 
-static void add_pending_object_with_mode(struct rev_info *revs, struct object *obj, const char *name, unsigned mode)
+static void add_pending_object_with_mode(struct rev_info *revs,
+					 struct object *obj,
+					 const char *name, unsigned mode)
 {
 	if (!obj)
 		return;
@@ -209,7 +216,8 @@
 	add_object_array_with_mode(obj, name, &revs->pending, mode);
 }
 
-void add_pending_object(struct rev_info *revs, struct object *obj, const char *name)
+void add_pending_object(struct rev_info *revs,
+			struct object *obj, const char *name)
 {
 	add_pending_object_with_mode(revs, obj, name, S_IFINVALID);
 }
@@ -226,7 +234,9 @@
 	add_pending_object(revs, obj, "HEAD");
 }
 
-static struct object *get_reference(struct rev_info *revs, const char *name, const unsigned char *sha1, unsigned int flags)
+static struct object *get_reference(struct rev_info *revs, const char *name,
+				    const unsigned char *sha1,
+				    unsigned int flags)
 {
 	struct object *object;
 
@@ -247,7 +257,8 @@
 	add_pending_object(revs, object, name);
 }
 
-static struct commit *handle_commit(struct rev_info *revs, struct object *object, const char *name)
+static struct commit *handle_commit(struct rev_info *revs,
+				    struct object *object, const char *name)
 {
 	unsigned long flags = object->flags;
 
@@ -333,6 +344,80 @@
 }
 
 /*
+ * A definition of "relevant" commit that we can use to simplify limited graphs
+ * by eliminating side branches.
+ *
+ * A "relevant" commit is one that is !UNINTERESTING (ie we are including it
+ * in our list), or that is a specified BOTTOM commit. Then after computing
+ * a limited list, during processing we can generally ignore boundary merges
+ * coming from outside the graph, (ie from irrelevant parents), and treat
+ * those merges as if they were single-parent. TREESAME is defined to consider
+ * only relevant parents, if any. If we are TREESAME to our on-graph parents,
+ * we don't care if we were !TREESAME to non-graph parents.
+ *
+ * Treating bottom commits as relevant ensures that a limited graph's
+ * connection to the actual bottom commit is not viewed as a side branch, but
+ * treated as part of the graph. For example:
+ *
+ *   ....Z...A---X---o---o---B
+ *        .     /
+ *         W---Y
+ *
+ * When computing "A..B", the A-X connection is at least as important as
+ * Y-X, despite A being flagged UNINTERESTING.
+ *
+ * And when computing --ancestry-path "A..B", the A-X connection is more
+ * important than Y-X, despite both A and Y being flagged UNINTERESTING.
+ */
+static inline int relevant_commit(struct commit *commit)
+{
+	return (commit->object.flags & (UNINTERESTING | BOTTOM)) != UNINTERESTING;
+}
+
+/*
+ * Return a single relevant commit from a parent list. If we are a TREESAME
+ * commit, and this selects one of our parents, then we can safely simplify to
+ * that parent.
+ */
+static struct commit *one_relevant_parent(const struct rev_info *revs,
+					  struct commit_list *orig)
+{
+	struct commit_list *list = orig;
+	struct commit *relevant = NULL;
+
+	if (!orig)
+		return NULL;
+
+	/*
+	 * For 1-parent commits, or if first-parent-only, then return that
+	 * first parent (even if not "relevant" by the above definition).
+	 * TREESAME will have been set purely on that parent.
+	 */
+	if (revs->first_parent_only || !orig->next)
+		return orig->item;
+
+	/*
+	 * For multi-parent commits, identify a sole relevant parent, if any.
+	 * If we have only one relevant parent, then TREESAME will be set purely
+	 * with regard to that parent, and we can simplify accordingly.
+	 *
+	 * If we have more than one relevant parent, or no relevant parents
+	 * (and multiple irrelevant ones), then we can't select a parent here
+	 * and return NULL.
+	 */
+	while (list) {
+		struct commit *commit = list->item;
+		list = list->next;
+		if (relevant_commit(commit)) {
+			if (relevant)
+				return NULL;
+			relevant = commit;
+		}
+	}
+	return relevant;
+}
+
+/*
  * The goal is to get REV_TREE_NEW as the result only if the
  * diff consists of all '+' (and no other changes), REV_TREE_OLD
  * if the whole diff is removal of old data, and otherwise
@@ -368,7 +453,8 @@
 	DIFF_OPT_SET(options, HAS_CHANGES);
 }
 
-static int rev_compare_tree(struct rev_info *revs, struct commit *parent, struct commit *commit)
+static int rev_compare_tree(struct rev_info *revs,
+			    struct commit *parent, struct commit *commit)
 {
 	struct tree *t1 = parent->tree;
 	struct tree *t2 = commit->tree;
@@ -429,10 +515,125 @@
 	return retval >= 0 && (tree_difference == REV_TREE_SAME);
 }
 
+struct treesame_state {
+	unsigned int nparents;
+	unsigned char treesame[FLEX_ARRAY];
+};
+
+static struct treesame_state *initialise_treesame(struct rev_info *revs, struct commit *commit)
+{
+	unsigned n = commit_list_count(commit->parents);
+	struct treesame_state *st = xcalloc(1, sizeof(*st) + n);
+	st->nparents = n;
+	add_decoration(&revs->treesame, &commit->object, st);
+	return st;
+}
+
+/*
+ * Must be called immediately after removing the nth_parent from a commit's
+ * parent list, if we are maintaining the per-parent treesame[] decoration.
+ * This does not recalculate the master TREESAME flag - update_treesame()
+ * should be called to update it after a sequence of treesame[] modifications
+ * that may have affected it.
+ */
+static int compact_treesame(struct rev_info *revs, struct commit *commit, unsigned nth_parent)
+{
+	struct treesame_state *st;
+	int old_same;
+
+	if (!commit->parents) {
+		/*
+		 * Have just removed the only parent from a non-merge.
+		 * Different handling, as we lack decoration.
+		 */
+		if (nth_parent != 0)
+			die("compact_treesame %u", nth_parent);
+		old_same = !!(commit->object.flags & TREESAME);
+		if (rev_same_tree_as_empty(revs, commit))
+			commit->object.flags |= TREESAME;
+		else
+			commit->object.flags &= ~TREESAME;
+		return old_same;
+	}
+
+	st = lookup_decoration(&revs->treesame, &commit->object);
+	if (!st || nth_parent >= st->nparents)
+		die("compact_treesame %u", nth_parent);
+
+	old_same = st->treesame[nth_parent];
+	memmove(st->treesame + nth_parent,
+		st->treesame + nth_parent + 1,
+		st->nparents - nth_parent - 1);
+
+	/*
+	 * If we've just become a non-merge commit, update TREESAME
+	 * immediately, and remove the no-longer-needed decoration.
+	 * If still a merge, defer update until update_treesame().
+	 */
+	if (--st->nparents == 1) {
+		if (commit->parents->next)
+			die("compact_treesame parents mismatch");
+		if (st->treesame[0] && revs->dense)
+			commit->object.flags |= TREESAME;
+		else
+			commit->object.flags &= ~TREESAME;
+		free(add_decoration(&revs->treesame, &commit->object, NULL));
+	}
+
+	return old_same;
+}
+
+static unsigned update_treesame(struct rev_info *revs, struct commit *commit)
+{
+	if (commit->parents && commit->parents->next) {
+		unsigned n;
+		struct treesame_state *st;
+		struct commit_list *p;
+		unsigned relevant_parents;
+		unsigned relevant_change, irrelevant_change;
+
+		st = lookup_decoration(&revs->treesame, &commit->object);
+		if (!st)
+			die("update_treesame %s", sha1_to_hex(commit->object.sha1));
+		relevant_parents = 0;
+		relevant_change = irrelevant_change = 0;
+		for (p = commit->parents, n = 0; p; n++, p = p->next) {
+			if (relevant_commit(p->item)) {
+				relevant_change |= !st->treesame[n];
+				relevant_parents++;
+			} else
+				irrelevant_change |= !st->treesame[n];
+		}
+		if (relevant_parents ? relevant_change : irrelevant_change)
+			commit->object.flags &= ~TREESAME;
+		else
+			commit->object.flags |= TREESAME;
+	}
+
+	return commit->object.flags & TREESAME;
+}
+
+static inline int limiting_can_increase_treesame(const struct rev_info *revs)
+{
+	/*
+	 * TREESAME is irrelevant unless prune && dense;
+	 * if simplify_history is set, we can't have a mixture of TREESAME and
+	 *    !TREESAME INTERESTING parents (and we don't have treesame[]
+	 *    decoration anyway);
+	 * if first_parent_only is set, then the TREESAME flag is locked
+	 *    against the first parent (and again we lack treesame[] decoration).
+	 */
+	return revs->prune && revs->dense &&
+	       !revs->simplify_history &&
+	       !revs->first_parent_only;
+}
+
 static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit)
 {
 	struct commit_list **pp, *parent;
-	int tree_changed = 0, tree_same = 0, nth_parent = 0;
+	struct treesame_state *ts = NULL;
+	int relevant_change = 0, irrelevant_change = 0;
+	int relevant_parents, nth_parent;
 
 	/*
 	 * If we don't do pruning, everything is interesting
@@ -456,33 +657,54 @@
 	if (!revs->dense && !commit->parents->next)
 		return;
 
-	pp = &commit->parents;
-	while ((parent = *pp) != NULL) {
+	for (pp = &commit->parents, nth_parent = 0, relevant_parents = 0;
+	     (parent = *pp) != NULL;
+	     pp = &parent->next, nth_parent++) {
 		struct commit *p = parent->item;
+		if (relevant_commit(p))
+			relevant_parents++;
 
-		/*
-		 * Do not compare with later parents when we care only about
-		 * the first parent chain, in order to avoid derailing the
-		 * traversal to follow a side branch that brought everything
-		 * in the path we are limited to by the pathspec.
-		 */
-		if (revs->first_parent_only && nth_parent++)
-			break;
+		if (nth_parent == 1) {
+			/*
+			 * This our second loop iteration - so we now know
+			 * we're dealing with a merge.
+			 *
+			 * Do not compare with later parents when we care only about
+			 * the first parent chain, in order to avoid derailing the
+			 * traversal to follow a side branch that brought everything
+			 * in the path we are limited to by the pathspec.
+			 */
+			if (revs->first_parent_only)
+				break;
+			/*
+			 * If this will remain a potentially-simplifiable
+			 * merge, remember per-parent treesame if needed.
+			 * Initialise the array with the comparison from our
+			 * first iteration.
+			 */
+			if (revs->treesame.name &&
+			    !revs->simplify_history &&
+			    !(commit->object.flags & UNINTERESTING)) {
+				ts = initialise_treesame(revs, commit);
+				if (!(irrelevant_change || relevant_change))
+					ts->treesame[0] = 1;
+			}
+		}
 		if (parse_commit(p) < 0)
 			die("cannot simplify commit %s (because of %s)",
 			    sha1_to_hex(commit->object.sha1),
 			    sha1_to_hex(p->object.sha1));
 		switch (rev_compare_tree(revs, p, commit)) {
 		case REV_TREE_SAME:
-			tree_same = 1;
-			if (!revs->simplify_history || (p->object.flags & UNINTERESTING)) {
+			if (!revs->simplify_history || !relevant_commit(p)) {
 				/* Even if a merge with an uninteresting
 				 * side branch brought the entire change
 				 * we are interested in, we do not want
 				 * to lose the other branches of this
 				 * merge, so we just keep going.
 				 */
-				pp = &parent->next;
+				if (ts)
+					ts->treesame[nth_parent] = 1;
 				continue;
 			}
 			parent->next = NULL;
@@ -510,15 +732,27 @@
 		/* fallthrough */
 		case REV_TREE_OLD:
 		case REV_TREE_DIFFERENT:
-			tree_changed = 1;
-			pp = &parent->next;
+			if (relevant_commit(p))
+				relevant_change = 1;
+			else
+				irrelevant_change = 1;
 			continue;
 		}
 		die("bad tree compare for commit %s", sha1_to_hex(commit->object.sha1));
 	}
-	if (tree_changed && !tree_same)
-		return;
-	commit->object.flags |= TREESAME;
+
+	/*
+	 * TREESAME is straightforward for single-parent commits. For merge
+	 * commits, it is most useful to define it so that "irrelevant"
+	 * parents cannot make us !TREESAME - if we have any relevant
+	 * parents, then we only consider TREESAMEness with respect to them,
+	 * allowing irrelevant merges from uninteresting branches to be
+	 * simplified away. Only if we have only irrelevant parents do we
+	 * base TREESAME on them. Note that this logic is replicated in
+	 * update_treesame, which should be kept in sync.
+	 */
+	if (relevant_parents ? !relevant_change : !irrelevant_change)
+		commit->object.flags |= TREESAME;
 }
 
 static void commit_list_insert_by_date_cached(struct commit *p, struct commit_list **head,
@@ -801,16 +1035,12 @@
  * to filter the result of "A..B" further to the ones that can actually
  * reach A.
  */
-static struct commit_list *collect_bottom_commits(struct rev_info *revs)
+static struct commit_list *collect_bottom_commits(struct commit_list *list)
 {
-	struct commit_list *bottom = NULL;
-	int i;
-	for (i = 0; i < revs->cmdline.nr; i++) {
-		struct rev_cmdline_entry *elem = &revs->cmdline.rev[i];
-		if ((elem->flags & UNINTERESTING) &&
-		    elem->item->type == OBJ_COMMIT)
-			commit_list_insert((struct commit *)elem->item, &bottom);
-	}
+	struct commit_list *elem, *bottom = NULL;
+	for (elem = list; elem; elem = elem->next)
+		if (elem->item->object.flags & BOTTOM)
+			commit_list_insert(elem->item, &bottom);
 	return bottom;
 }
 
@@ -841,7 +1071,7 @@
 	struct commit_list *bottom = NULL;
 
 	if (revs->ancestry_path) {
-		bottom = collect_bottom_commits(revs);
+		bottom = collect_bottom_commits(list);
 		if (!bottom)
 			die("--ancestry-path given but there are no bottom commits");
 	}
@@ -894,10 +1124,26 @@
 		free_commit_list(bottom);
 	}
 
+	/*
+	 * Check if any commits have become TREESAME by some of their parents
+	 * becoming UNINTERESTING.
+	 */
+	if (limiting_can_increase_treesame(revs))
+		for (list = newlist; list; list = list->next) {
+			struct commit *c = list->item;
+			if (c->object.flags & (UNINTERESTING | TREESAME))
+				continue;
+			update_treesame(revs, c);
+		}
+
 	revs->commits = newlist;
 	return 0;
 }
 
+/*
+ * Add an entry to refs->cmdline with the specified information.
+ * *name is copied.
+ */
 static void add_rev_cmdline(struct rev_info *revs,
 			    struct object *item,
 			    const char *name,
@@ -909,12 +1155,25 @@
 
 	ALLOC_GROW(info->rev, nr + 1, info->alloc);
 	info->rev[nr].item = item;
-	info->rev[nr].name = name;
+	info->rev[nr].name = xstrdup(name);
 	info->rev[nr].whence = whence;
 	info->rev[nr].flags = flags;
 	info->nr++;
 }
 
+static void add_rev_cmdline_list(struct rev_info *revs,
+				 struct commit_list *commit_list,
+				 int whence,
+				 unsigned flags)
+{
+	while (commit_list) {
+		struct object *object = &commit_list->item->object;
+		add_rev_cmdline(revs, object, sha1_to_hex(object->sha1),
+				whence, flags);
+		commit_list = commit_list->next;
+	}
+}
+
 struct all_refs_cb {
 	int all_flags;
 	int warned_bad_reflog;
@@ -1000,7 +1259,7 @@
 	const char *arg = arg_;
 
 	if (*arg == '^') {
-		flags ^= UNINTERESTING;
+		flags ^= UNINTERESTING | BOTTOM;
 		arg++;
 	}
 	if (get_sha1_committish(arg, sha1))
@@ -1038,7 +1297,7 @@
 	DIFF_OPT_SET(&revs->pruning, QUICK);
 	revs->pruning.add_remove = file_add_remove;
 	revs->pruning.change = file_change;
-	revs->lifo = 1;
+	revs->sort_order = REV_SORT_IN_GRAPH_ORDER;
 	revs->dense = 1;
 	revs->prefix = prefix;
 	revs->max_age = -1;
@@ -1092,14 +1351,15 @@
 	add_pending_object(revs, &head->object, "HEAD");
 	add_pending_object(revs, &other->object, "MERGE_HEAD");
 	bases = get_merge_bases(head, other, 1);
-	add_pending_commit_list(revs, bases, UNINTERESTING);
+	add_rev_cmdline_list(revs, bases, REV_CMD_MERGE_BASE, UNINTERESTING | BOTTOM);
+	add_pending_commit_list(revs, bases, UNINTERESTING | BOTTOM);
 	free_commit_list(bases);
 	head->object.flags |= SYMMETRIC_LEFT;
 
 	if (!active_nr)
 		read_cache();
 	for (i = 0; i < active_nr; i++) {
-		struct cache_entry *ce = active_cache[i];
+		const struct cache_entry *ce = active_cache[i];
 		if (!ce_stage(ce))
 			continue;
 		if (ce_path_match(ce, &revs->prune_data)) {
@@ -1128,13 +1388,15 @@
 	int cant_be_filename = revarg_opt & REVARG_CANNOT_BE_FILENAME;
 	unsigned get_sha1_flags = 0;
 
+	flags = flags & UNINTERESTING ? flags | BOTTOM : flags & ~BOTTOM;
+
 	dotdot = strstr(arg, "..");
 	if (dotdot) {
 		unsigned char from_sha1[20];
 		const char *next = dotdot + 2;
 		const char *this = arg;
 		int symmetric = *next == '.';
-		unsigned int flags_exclude = flags ^ UNINTERESTING;
+		unsigned int flags_exclude = flags ^ (UNINTERESTING | BOTTOM);
 		static const char head_by_default[] = "HEAD";
 		unsigned int a_flags;
 
@@ -1179,6 +1441,9 @@
 
 			if (symmetric) {
 				exclude = get_merge_bases(a, b, 1);
+				add_rev_cmdline_list(revs, exclude,
+						     REV_CMD_MERGE_BASE,
+						     flags_exclude);
 				add_pending_commit_list(revs, exclude,
 							flags_exclude);
 				free_commit_list(exclude);
@@ -1207,13 +1472,13 @@
 	dotdot = strstr(arg, "^!");
 	if (dotdot && !dotdot[2]) {
 		*dotdot = 0;
-		if (!add_parents_only(revs, arg, flags ^ UNINTERESTING))
+		if (!add_parents_only(revs, arg, flags ^ (UNINTERESTING | BOTTOM)))
 			*dotdot = '^';
 	}
 
 	local_flags = 0;
 	if (*arg == '^') {
-		local_flags = UNINTERESTING;
+		local_flags = UNINTERESTING | BOTTOM;
 		arg++;
 	}
 
@@ -1276,7 +1541,7 @@
 			}
 			die("options not supported in --stdin mode");
 		}
-		if (handle_revision_arg(xstrdup(sb.buf), revs, 0,
+		if (handle_revision_arg(sb.buf, revs, 0,
 					REVARG_CANNOT_BE_FILENAME))
 			die("bad revision '%s'", sb.buf);
 	}
@@ -1374,7 +1639,7 @@
 	} else if (!strcmp(arg, "--merge")) {
 		revs->show_merge = 1;
 	} else if (!strcmp(arg, "--topo-order")) {
-		revs->lifo = 1;
+		revs->sort_order = REV_SORT_IN_GRAPH_ORDER;
 		revs->topo_order = 1;
 	} else if (!strcmp(arg, "--simplify-merges")) {
 		revs->simplify_merges = 1;
@@ -1392,7 +1657,10 @@
 		revs->prune = 1;
 		load_ref_decorations(DECORATE_SHORT_REFS);
 	} else if (!strcmp(arg, "--date-order")) {
-		revs->lifo = 0;
+		revs->sort_order = REV_SORT_BY_COMMIT_DATE;
+		revs->topo_order = 1;
+	} else if (!strcmp(arg, "--author-date-order")) {
+		revs->sort_order = REV_SORT_BY_AUTHOR_DATE;
 		revs->topo_order = 1;
 	} else if (!prefixcmp(arg, "--early-output")) {
 		int count = 100;
@@ -1690,7 +1958,7 @@
 		handle_refs(submodule, revs, *flags, for_each_branch_ref_submodule);
 	} else if (!strcmp(arg, "--bisect")) {
 		handle_refs(submodule, revs, *flags, for_each_bad_bisect_ref);
-		handle_refs(submodule, revs, *flags ^ UNINTERESTING, for_each_good_bisect_ref);
+		handle_refs(submodule, revs, *flags ^ (UNINTERESTING | BOTTOM), for_each_good_bisect_ref);
 		revs->bisect = 1;
 	} else if (!strcmp(arg, "--tags")) {
 		handle_refs(submodule, revs, *flags, for_each_tag_ref_submodule);
@@ -1716,7 +1984,7 @@
 	} else if (!strcmp(arg, "--reflog")) {
 		handle_reflog(revs, *flags);
 	} else if (!strcmp(arg, "--not")) {
-		*flags ^= UNINTERESTING;
+		*flags ^= UNINTERESTING | BOTTOM;
 	} else if (!strcmp(arg, "--no-walk")) {
 		revs->no_walk = REVISION_WALK_NO_WALK_SORTED;
 	} else if (!prefixcmp(arg, "--no-walk=")) {
@@ -1897,6 +2165,12 @@
 	if (revs->combine_merges)
 		revs->ignore_merges = 0;
 	revs->diffopt.abbrev = revs->abbrev;
+
+	if (revs->line_level_traverse) {
+		revs->limited = 1;
+		revs->topo_order = 1;
+	}
+
 	diff_setup_done(&revs->diffopt);
 
 	grep_commit_pattern_type(GREP_PATTERN_TYPE_UNSPECIFIED,
@@ -1930,28 +2204,32 @@
 	l->next = add_decoration(&revs->children, &parent->object, l);
 }
 
-static int remove_duplicate_parents(struct commit *commit)
+static int remove_duplicate_parents(struct rev_info *revs, struct commit *commit)
 {
+	struct treesame_state *ts = lookup_decoration(&revs->treesame, &commit->object);
 	struct commit_list **pp, *p;
 	int surviving_parents;
 
 	/* Examine existing parents while marking ones we have seen... */
 	pp = &commit->parents;
+	surviving_parents = 0;
 	while ((p = *pp) != NULL) {
 		struct commit *parent = p->item;
 		if (parent->object.flags & TMP_MARK) {
 			*pp = p->next;
+			if (ts)
+				compact_treesame(revs, commit, surviving_parents);
 			continue;
 		}
 		parent->object.flags |= TMP_MARK;
+		surviving_parents++;
 		pp = &p->next;
 	}
-	/* count them while clearing the temporary mark */
-	surviving_parents = 0;
+	/* clear the temporary mark */
 	for (p = commit->parents; p; p = p->next) {
 		p->item->object.flags &= ~TMP_MARK;
-		surviving_parents++;
 	}
+	/* no update_treesame() - removing duplicates can't affect TREESAME */
 	return surviving_parents;
 }
 
@@ -1971,9 +2249,157 @@
 	return st;
 }
 
+static int mark_redundant_parents(struct rev_info *revs, struct commit *commit)
+{
+	struct commit_list *h = reduce_heads(commit->parents);
+	int i = 0, marked = 0;
+	struct commit_list *po, *pn;
+
+	/* Want these for sanity-checking only */
+	int orig_cnt = commit_list_count(commit->parents);
+	int cnt = commit_list_count(h);
+
+	/*
+	 * Not ready to remove items yet, just mark them for now, based
+	 * on the output of reduce_heads(). reduce_heads outputs the reduced
+	 * set in its original order, so this isn't too hard.
+	 */
+	po = commit->parents;
+	pn = h;
+	while (po) {
+		if (pn && po->item == pn->item) {
+			pn = pn->next;
+			i++;
+		} else {
+			po->item->object.flags |= TMP_MARK;
+			marked++;
+		}
+		po=po->next;
+	}
+
+	if (i != cnt || cnt+marked != orig_cnt)
+		die("mark_redundant_parents %d %d %d %d", orig_cnt, cnt, i, marked);
+
+	free_commit_list(h);
+
+	return marked;
+}
+
+static int mark_treesame_root_parents(struct rev_info *revs, struct commit *commit)
+{
+	struct commit_list *p;
+	int marked = 0;
+
+	for (p = commit->parents; p; p = p->next) {
+		struct commit *parent = p->item;
+		if (!parent->parents && (parent->object.flags & TREESAME)) {
+			parent->object.flags |= TMP_MARK;
+			marked++;
+		}
+	}
+
+	return marked;
+}
+
+/*
+ * Awkward naming - this means one parent we are TREESAME to.
+ * cf mark_treesame_root_parents: root parents that are TREESAME (to an
+ * empty tree). Better name suggestions?
+ */
+static int leave_one_treesame_to_parent(struct rev_info *revs, struct commit *commit)
+{
+	struct treesame_state *ts = lookup_decoration(&revs->treesame, &commit->object);
+	struct commit *unmarked = NULL, *marked = NULL;
+	struct commit_list *p;
+	unsigned n;
+
+	for (p = commit->parents, n = 0; p; p = p->next, n++) {
+		if (ts->treesame[n]) {
+			if (p->item->object.flags & TMP_MARK) {
+				if (!marked)
+					marked = p->item;
+			} else {
+				if (!unmarked) {
+					unmarked = p->item;
+					break;
+				}
+			}
+		}
+	}
+
+	/*
+	 * If we are TREESAME to a marked-for-deletion parent, but not to any
+	 * unmarked parents, unmark the first TREESAME parent. This is the
+	 * parent that the default simplify_history==1 scan would have followed,
+	 * and it doesn't make sense to omit that path when asking for a
+	 * simplified full history. Retaining it improves the chances of
+	 * understanding odd missed merges that took an old version of a file.
+	 *
+	 * Example:
+	 *
+	 *   I--------*X       A modified the file, but mainline merge X used
+	 *    \       /        "-s ours", so took the version from I. X is
+	 *     `-*A--'         TREESAME to I and !TREESAME to A.
+	 *
+	 * Default log from X would produce "I". Without this check,
+	 * --full-history --simplify-merges would produce "I-A-X", showing
+	 * the merge commit X and that it changed A, but not making clear that
+	 * it had just taken the I version. With this check, the topology above
+	 * is retained.
+	 *
+	 * Note that it is possible that the simplification chooses a different
+	 * TREESAME parent from the default, in which case this test doesn't
+	 * activate, and we _do_ drop the default parent. Example:
+	 *
+	 *   I------X         A modified the file, but it was reverted in B,
+	 *    \    /          meaning mainline merge X is TREESAME to both
+	 *    *A-*B           parents.
+	 *
+	 * Default log would produce "I" by following the first parent;
+	 * --full-history --simplify-merges will produce "I-A-B". But this is a
+	 * reasonable result - it presents a logical full history leading from
+	 * I to X, and X is not an important merge.
+	 */
+	if (!unmarked && marked) {
+		marked->object.flags &= ~TMP_MARK;
+		return 1;
+	}
+
+	return 0;
+}
+
+static int remove_marked_parents(struct rev_info *revs, struct commit *commit)
+{
+	struct commit_list **pp, *p;
+	int nth_parent, removed = 0;
+
+	pp = &commit->parents;
+	nth_parent = 0;
+	while ((p = *pp) != NULL) {
+		struct commit *parent = p->item;
+		if (parent->object.flags & TMP_MARK) {
+			parent->object.flags &= ~TMP_MARK;
+			*pp = p->next;
+			free(p);
+			removed++;
+			compact_treesame(revs, commit, nth_parent);
+			continue;
+		}
+		pp = &p->next;
+		nth_parent++;
+	}
+
+	/* Removing parents can only increase TREESAMEness */
+	if (removed && !(commit->object.flags & TREESAME))
+		update_treesame(revs, commit);
+
+	return nth_parent;
+}
+
 static struct commit_list **simplify_one(struct rev_info *revs, struct commit *commit, struct commit_list **tail)
 {
 	struct commit_list *p;
+	struct commit *parent;
 	struct merge_simplify_state *st, *pst;
 	int cnt;
 
@@ -2015,7 +2441,9 @@
 	}
 
 	/*
-	 * Rewrite our list of parents.
+	 * Rewrite our list of parents. Note that this cannot
+	 * affect our TREESAME flags in any way - a commit is
+	 * always TREESAME to its simplification.
 	 */
 	for (p = commit->parents; p; p = p->next) {
 		pst = locate_simplify_state(revs, p->item);
@@ -2027,43 +2455,53 @@
 	if (revs->first_parent_only)
 		cnt = 1;
 	else
-		cnt = remove_duplicate_parents(commit);
+		cnt = remove_duplicate_parents(revs, commit);
 
 	/*
 	 * It is possible that we are a merge and one side branch
 	 * does not have any commit that touches the given paths;
-	 * in such a case, the immediate parents will be rewritten
-	 * to different commits.
+	 * in such a case, the immediate parent from that branch
+	 * will be rewritten to be the merge base.
 	 *
 	 *      o----X		X: the commit we are looking at;
 	 *     /    /		o: a commit that touches the paths;
 	 * ---o----'
 	 *
-	 * Further reduce the parents by removing redundant parents.
+	 * Further, a merge of an independent branch that doesn't
+	 * touch the path will reduce to a treesame root parent:
+	 *
+	 *  ----o----X		X: the commit we are looking at;
+	 *          /		o: a commit that touches the paths;
+	 *         r		r: a root commit not touching the paths
+	 *
+	 * Detect and simplify both cases.
 	 */
 	if (1 < cnt) {
-		struct commit_list *h = reduce_heads(commit->parents);
-		cnt = commit_list_count(h);
-		free_commit_list(commit->parents);
-		commit->parents = h;
+		int marked = mark_redundant_parents(revs, commit);
+		marked += mark_treesame_root_parents(revs, commit);
+		if (marked)
+			marked -= leave_one_treesame_to_parent(revs, commit);
+		if (marked)
+			cnt = remove_marked_parents(revs, commit);
 	}
 
 	/*
 	 * A commit simplifies to itself if it is a root, if it is
 	 * UNINTERESTING, if it touches the given paths, or if it is a
-	 * merge and its parents simplifies to more than one commits
+	 * merge and its parents don't simplify to one relevant commit
 	 * (the first two cases are already handled at the beginning of
 	 * this function).
 	 *
-	 * Otherwise, it simplifies to what its sole parent simplifies to.
+	 * Otherwise, it simplifies to what its sole relevant parent
+	 * simplifies to.
 	 */
 	if (!cnt ||
 	    (commit->object.flags & UNINTERESTING) ||
 	    !(commit->object.flags & TREESAME) ||
-	    (1 < cnt))
+	    (parent = one_relevant_parent(revs, commit->parents)) == NULL)
 		st->simplified = commit;
 	else {
-		pst = locate_simplify_state(revs, commit->parents->item);
+		pst = locate_simplify_state(revs, parent);
 		st->simplified = pst->simplified;
 	}
 	return tail;
@@ -2159,6 +2597,11 @@
 	if (!revs->leak_pending)
 		free(list);
 
+	/* Signal whether we need per-parent treesame decoration */
+	if (revs->simplify_merges ||
+	    (revs->limited && limiting_can_increase_treesame(revs)))
+		revs->treesame.name = "treesame";
+
 	if (revs->no_walk != REVISION_WALK_NO_WALK_UNSORTED)
 		commit_list_sort_by_date(&revs->commits);
 	if (revs->no_walk)
@@ -2167,7 +2610,9 @@
 		if (limit_list(revs) < 0)
 			return -1;
 	if (revs->topo_order)
-		sort_in_topological_order(&revs->commits, revs->lifo);
+		sort_in_topological_order(&revs->commits, revs->sort_order);
+	if (revs->line_level_traverse)
+		line_log_filter(revs);
 	if (revs->simplify_merges)
 		simplify_merges(revs);
 	if (revs->children.name)
@@ -2175,12 +2620,6 @@
 	return 0;
 }
 
-enum rewrite_result {
-	rewrite_one_ok,
-	rewrite_one_noparents,
-	rewrite_one_error
-};
-
 static enum rewrite_result rewrite_one(struct rev_info *revs, struct commit **pp)
 {
 	struct commit_list *cache = NULL;
@@ -2190,24 +2629,25 @@
 		if (!revs->limited)
 			if (add_parents_to_list(revs, p, &revs->commits, &cache) < 0)
 				return rewrite_one_error;
-		if (p->parents && p->parents->next)
-			return rewrite_one_ok;
 		if (p->object.flags & UNINTERESTING)
 			return rewrite_one_ok;
 		if (!(p->object.flags & TREESAME))
 			return rewrite_one_ok;
 		if (!p->parents)
 			return rewrite_one_noparents;
-		*pp = p->parents->item;
+		if ((p = one_relevant_parent(revs, p->parents)) == NULL)
+			return rewrite_one_ok;
+		*pp = p;
 	}
 }
 
-static int rewrite_parents(struct rev_info *revs, struct commit *commit)
+int rewrite_parents(struct rev_info *revs, struct commit *commit,
+	rewrite_parent_fn_t rewrite_parent)
 {
 	struct commit_list **pp = &commit->parents;
 	while (*pp) {
 		struct commit_list *parent = *pp;
-		switch (rewrite_one(revs, &parent->item)) {
+		switch (rewrite_parent(revs, &parent->item)) {
 		case rewrite_one_ok:
 			break;
 		case rewrite_one_noparents:
@@ -2218,7 +2658,7 @@
 		}
 		pp = &parent->next;
 	}
-	remove_duplicate_parents(commit);
+	remove_duplicate_parents(revs, commit);
 	return 0;
 }
 
@@ -2324,7 +2764,7 @@
 	return retval;
 }
 
-static inline int want_ancestry(struct rev_info *revs)
+static inline int want_ancestry(const struct rev_info *revs)
 {
 	return (revs->rewrite_parents || revs->children.name);
 }
@@ -2342,10 +2782,7 @@
 	if (revs->min_age != -1 && (commit->date > revs->min_age))
 		return commit_ignore;
 	if (revs->min_parents || (revs->max_parents >= 0)) {
-		int n = 0;
-		struct commit_list *p;
-		for (p = commit->parents; p; p = p->next)
-			n++;
+		int n = commit_list_count(commit->parents);
 		if ((n < revs->min_parents) ||
 		    ((revs->max_parents >= 0) && (n > revs->max_parents)))
 			return commit_ignore;
@@ -2355,12 +2792,23 @@
 	if (revs->prune && revs->dense) {
 		/* Commit without changes? */
 		if (commit->object.flags & TREESAME) {
+			int n;
+			struct commit_list *p;
 			/* drop merges unless we want parenthood */
 			if (!want_ancestry(revs))
 				return commit_ignore;
-			/* non-merge - always ignore it */
-			if (!commit->parents || !commit->parents->next)
-				return commit_ignore;
+			/*
+			 * If we want ancestry, then need to keep any merges
+			 * between relevant commits to tie together topology.
+			 * For consistency with TREESAME and simplification
+			 * use "relevant" here rather than just INTERESTING,
+			 * to treat bottom commit(s) as part of the topology.
+			 */
+			for (n = 0, p = commit->parents; p; p = p->next)
+				if (relevant_commit(p->item))
+					if (++n >= 2)
+						return commit_show;
+			return commit_ignore;
 		}
 	}
 	return commit_show;
@@ -2373,7 +2821,15 @@
 	if (action == commit_show &&
 	    !revs->show_all &&
 	    revs->prune && revs->dense && want_ancestry(revs)) {
-		if (rewrite_parents(revs, commit) < 0)
+		/*
+		 * --full-diff on simplified parents is no good: it
+		 * will show spurious changes from the commits that
+		 * were elided.  So we save the parents on the side
+		 * when --full-diff is in effect.
+		 */
+		if (revs->full_diff)
+			save_parents(revs, commit);
+		if (rewrite_parents(revs, commit, rewrite_one) < 0)
 			return commit_error;
 	}
 	return action;
@@ -2392,6 +2848,7 @@
 		free(entry);
 
 		if (revs->reflog_info) {
+			save_parents(revs, commit);
 			fake_reflog_parent(revs->reflog_info, commit);
 			commit->object.flags &= ~(ADDED | SEEN | SHOWN);
 		}
@@ -2423,25 +2880,23 @@
 	return NULL;
 }
 
+/*
+ * Return true for entries that have not yet been shown.  (This is an
+ * object_array_each_func_t.)
+ */
+static int entry_unshown(struct object_array_entry *entry, void *cb_data_unused)
+{
+	return !(entry->item->flags & SHOWN);
+}
+
+/*
+ * If array is on the verge of a realloc, garbage-collect any entries
+ * that have already been shown to try to free up some space.
+ */
 static void gc_boundary(struct object_array *array)
 {
-	unsigned nr = array->nr;
-	unsigned alloc = array->alloc;
-	struct object_array_entry *objects = array->objects;
-
-	if (alloc <= nr) {
-		unsigned i, j;
-		for (i = j = 0; i < nr; i++) {
-			if (objects[i].item->flags & SHOWN)
-				continue;
-			if (i != j)
-				objects[j] = objects[i];
-			j++;
-		}
-		for (i = j; i < nr; i++)
-			objects[i].item = NULL;
-		array->nr = j;
-	}
+	if (array->nr == array->alloc)
+		object_array_filter(array, entry_unshown, NULL);
 }
 
 static void create_boundary_commit_list(struct rev_info *revs)
@@ -2482,7 +2937,7 @@
 	 * If revs->topo_order is set, sort the boundary commits
 	 * in topological order
 	 */
-	sort_in_topological_order(&revs->commits, revs->lifo);
+	sort_in_topological_order(&revs->commits, revs->sort_order);
 }
 
 static struct commit *get_revision_internal(struct rev_info *revs)
@@ -2593,6 +3048,8 @@
 	c = get_revision_internal(revs);
 	if (c && revs->graph)
 		graph_update(revs->graph, c);
+	if (!c)
+		free_saved_parents(revs);
 	return c;
 }
 
@@ -2624,3 +3081,54 @@
 	fputs(mark, stdout);
 	putchar(' ');
 }
+
+define_commit_slab(saved_parents, struct commit_list *);
+
+#define EMPTY_PARENT_LIST ((struct commit_list *)-1)
+
+void save_parents(struct rev_info *revs, struct commit *commit)
+{
+	struct commit_list **pp;
+
+	if (!revs->saved_parents_slab) {
+		revs->saved_parents_slab = xmalloc(sizeof(struct saved_parents));
+		init_saved_parents(revs->saved_parents_slab);
+	}
+
+	pp = saved_parents_at(revs->saved_parents_slab, commit);
+
+	/*
+	 * When walking with reflogs, we may visit the same commit
+	 * several times: once for each appearance in the reflog.
+	 *
+	 * In this case, save_parents() will be called multiple times.
+	 * We want to keep only the first set of parents.  We need to
+	 * store a sentinel value for an empty (i.e., NULL) parent
+	 * list to distinguish it from a not-yet-saved list, however.
+	 */
+	if (*pp)
+		return;
+	if (commit->parents)
+		*pp = copy_commit_list(commit->parents);
+	else
+		*pp = EMPTY_PARENT_LIST;
+}
+
+struct commit_list *get_saved_parents(struct rev_info *revs, const struct commit *commit)
+{
+	struct commit_list *parents;
+
+	if (!revs->saved_parents_slab)
+		return commit->parents;
+
+	parents = *saved_parents_at(revs->saved_parents_slab, commit);
+	if (parents == EMPTY_PARENT_LIST)
+		return NULL;
+	return parents;
+}
+
+void free_saved_parents(struct rev_info *revs)
+{
+	if (revs->saved_parents_slab)
+		clear_saved_parents(revs->saved_parents_slab);
+}
diff --git a/revision.h b/revision.h
index 01bd2b7..e7f1d21 100644
--- a/revision.h
+++ b/revision.h
@@ -4,6 +4,7 @@
 #include "parse-options.h"
 #include "grep.h"
 #include "notes.h"
+#include "commit.h"
 
 #define SEEN		(1u<<0)
 #define UNINTERESTING   (1u<<1)
@@ -15,7 +16,8 @@
 #define ADDED		(1u<<7)	/* Parents already parsed and added? */
 #define SYMMETRIC_LEFT	(1u<<8)
 #define PATCHSAME	(1u<<9)
-#define ALL_REV_FLAGS	((1u<<10)-1)
+#define BOTTOM		(1u<<10)
+#define ALL_REV_FLAGS	((1u<<11)-1)
 
 #define DECORATE_SHORT_REFS	1
 #define DECORATE_FULL_REFS	2
@@ -23,6 +25,7 @@
 struct rev_info;
 struct log_info;
 struct string_list;
+struct saved_parents;
 
 struct rev_cmdline_info {
 	unsigned int nr;
@@ -35,6 +38,7 @@
 			REV_CMD_PARENTS_ONLY,
 			REV_CMD_LEFT,
 			REV_CMD_RIGHT,
+			REV_CMD_MERGE_BASE,
 			REV_CMD_REV
 		} whence;
 		unsigned flags;
@@ -60,6 +64,10 @@
 	const char *prefix;
 	const char *def;
 	struct pathspec prune_data;
+
+	/* topo-sort */
+	enum rev_sort_order sort_order;
+
 	unsigned int	early_output:1,
 			ignore_missing:1;
 
@@ -70,7 +78,6 @@
 			show_all:1,
 			remove_empty_trees:1,
 			simplify_history:1,
-			lifo:1,
 			topo_order:1,
 			simplify_merges:1,
 			simplify_by_decoration:1,
@@ -96,7 +103,8 @@
 			cherry_mark:1,
 			bisect:1,
 			ancestry_path:1,
-			first_parent_only:1;
+			first_parent_only:1,
+			line_level_traverse:1;
 
 	/* Diff flags */
 	unsigned int	diff:1,
@@ -137,6 +145,7 @@
 	int		numbered_files;
 	int		reroll_count;
 	char		*message_id;
+	struct ident_split from_ident;
 	struct string_list *ref_message_ids;
 	int		add_signoff;
 	const char	*extra_headers;
@@ -167,6 +176,7 @@
 	struct reflog_walk_info *reflog_info;
 	struct decoration children;
 	struct decoration merge_simplification;
+	struct decoration treesame;
 
 	/* notes-specific options: which refs to show */
 	struct display_notes_opt notes_opt;
@@ -175,6 +185,12 @@
 	int count_left;
 	int count_right;
 	int count_same;
+
+	/* line level range that we are chasing */
+	struct decoration line_log_data;
+
+	/* copies of the parent lists, for --full-diff display */
+	struct saved_parents *saved_parents_slab;
 };
 
 #define REV_TREE_SAME		0
@@ -195,19 +211,23 @@
 };
 
 extern void init_revisions(struct rev_info *revs, const char *prefix);
-extern int setup_revisions(int argc, const char **argv, struct rev_info *revs, struct setup_revision_opt *);
+extern int setup_revisions(int argc, const char **argv, struct rev_info *revs,
+			   struct setup_revision_opt *);
 extern void parse_revision_opt(struct rev_info *revs, struct parse_opt_ctx_t *ctx,
-				 const struct option *options,
-				 const char * const usagestr[]);
+			       const struct option *options,
+			       const char * const usagestr[]);
 #define REVARG_CANNOT_BE_FILENAME 01
 #define REVARG_COMMITTISH 02
-extern int handle_revision_arg(const char *arg, struct rev_info *revs, int flags, unsigned revarg_opt);
+extern int handle_revision_arg(const char *arg, struct rev_info *revs,
+			       int flags, unsigned revarg_opt);
 
 extern void reset_revision_walk(void);
 extern int prepare_revision_walk(struct rev_info *revs);
 extern struct commit *get_revision(struct rev_info *revs);
-extern char *get_revision_mark(const struct rev_info *revs, const struct commit *commit);
-extern void put_revision_mark(const struct rev_info *revs, const struct commit *commit);
+extern char *get_revision_mark(const struct rev_info *revs,
+			       const struct commit *commit);
+extern void put_revision_mark(const struct rev_info *revs,
+			      const struct commit *commit);
 
 extern void mark_parents_uninteresting(struct commit *commit);
 extern void mark_tree_uninteresting(struct tree *tree);
@@ -220,15 +240,19 @@
 
 char *path_name(const struct name_path *path, const char *name);
 
-extern void show_object_with_name(FILE *, struct object *, const struct name_path *, const char *);
+extern void show_object_with_name(FILE *, struct object *,
+				  const struct name_path *, const char *);
 
 extern void add_object(struct object *obj,
 		       struct object_array *p,
 		       struct name_path *path,
 		       const char *name);
 
-extern void add_pending_object(struct rev_info *revs, struct object *obj, const char *name);
-extern void add_pending_sha1(struct rev_info *revs, const char *name, const unsigned char *sha1, unsigned int flags);
+extern void add_pending_object(struct rev_info *revs,
+			       struct object *obj, const char *name);
+extern void add_pending_sha1(struct rev_info *revs,
+			     const char *name, const unsigned char *sha1,
+			     unsigned int flags);
 
 extern void add_head_to_pending(struct rev_info *);
 
@@ -238,7 +262,35 @@
 	commit_error
 };
 
-extern enum commit_action get_commit_action(struct rev_info *revs, struct commit *commit);
-extern enum commit_action simplify_commit(struct rev_info *revs, struct commit *commit);
+extern enum commit_action get_commit_action(struct rev_info *revs,
+					    struct commit *commit);
+extern enum commit_action simplify_commit(struct rev_info *revs,
+					  struct commit *commit);
+
+enum rewrite_result {
+	rewrite_one_ok,
+	rewrite_one_noparents,
+	rewrite_one_error
+};
+
+typedef enum rewrite_result (*rewrite_parent_fn_t)(struct rev_info *revs, struct commit **pp);
+
+extern int rewrite_parents(struct rev_info *revs, struct commit *commit,
+	rewrite_parent_fn_t rewrite_parent);
+
+/*
+ * Save a copy of the parent list, and return the saved copy.  This is
+ * used by the log machinery to retrieve the original parents when
+ * commit->parents has been modified by history simpification.
+ *
+ * You may only call save_parents() once per commit (this is checked
+ * for non-root commits).
+ *
+ * get_saved_parents() will transparently return commit->parents if
+ * history simplification is off.
+ */
+extern void save_parents(struct rev_info *revs, struct commit *commit);
+extern struct commit_list *get_saved_parents(struct rev_info *revs, const struct commit *commit);
+extern void free_saved_parents(struct rev_info *revs);
 
 #endif
diff --git a/run-command.c b/run-command.c
index 1b32a12..1b7f88e 100644
--- a/run-command.c
+++ b/run-command.c
@@ -72,11 +72,14 @@
 	close(fd[1]);
 }
 
-#ifndef WIN32
+#ifndef GIT_WINDOWS_NATIVE
 static inline void dup_devnull(int to)
 {
 	int fd = open("/dev/null", O_RDWR);
-	dup2(fd, to);
+	if (fd < 0)
+		die_errno(_("open /dev/null failed"));
+	if (dup2(fd, to) < 0)
+		die_errno(_("dup2(%d,%d) failed"), fd, to);
 	close(fd);
 }
 #endif
@@ -159,7 +162,7 @@
 		die("BUG: shell command is empty");
 
 	if (strcspn(argv[0], "|&;<>()$`\\\"' \t\n*?[#~=%") != strlen(argv[0])) {
-#ifndef WIN32
+#ifndef GIT_WINDOWS_NATIVE
 		nargv[nargc++] = SHELL_PATH;
 #else
 		nargv[nargc++] = "sh";
@@ -182,7 +185,7 @@
 	return nargv;
 }
 
-#ifndef WIN32
+#ifndef GIT_WINDOWS_NATIVE
 static int execv_shell_cmd(const char **argv)
 {
 	const char **nargv = prepare_shell_cmd(argv);
@@ -193,7 +196,7 @@
 }
 #endif
 
-#ifndef WIN32
+#ifndef GIT_WINDOWS_NATIVE
 static int child_err = 2;
 static int child_notifier = -1;
 
@@ -334,7 +337,7 @@
 	trace_argv_printf(cmd->argv, "trace: run_command:");
 	fflush(NULL);
 
-#ifndef WIN32
+#ifndef GIT_WINDOWS_NATIVE
 {
 	int notify_pipe[2];
 	if (pipe(notify_pipe))
diff --git a/run-command.h b/run-command.h
index 221ce33..6b985af 100644
--- a/run-command.h
+++ b/run-command.h
@@ -46,6 +46,7 @@
 int run_command(struct child_process *);
 
 extern char *find_hook(const char *name);
+LAST_ARG_MUST_BE_NULL
 extern int run_hook(const char *index_file, const char *name, ...);
 
 #define RUN_COMMAND_NO_STDIN 1
diff --git a/sequencer.c b/sequencer.c
index cf8fbeb..351548f 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -270,15 +270,20 @@
 }
 
 static int fast_forward_to(const unsigned char *to, const unsigned char *from,
-			   int unborn)
+			int unborn, struct replay_opts *opts)
 {
 	struct ref_lock *ref_lock;
+	struct strbuf sb = STRBUF_INIT;
+	int ret;
 
 	read_cache();
 	if (checkout_fast_forward(from, to, 1))
 		exit(1); /* the callee should have complained already */
 	ref_lock = lock_any_ref_for_update("HEAD", unborn ? null_sha1 : from, 0);
-	return write_ref_sha1(ref_lock, to, "cherry-pick");
+	strbuf_addf(&sb, "%s: fast-forward", action_name(opts));
+	ret = write_ref_sha1(ref_lock, to, sb.buf);
+	strbuf_release(&sb);
+	return ret;
 }
 
 static int do_recursive_merge(struct commit *base, struct commit *next,
@@ -326,7 +331,7 @@
 		int i;
 		strbuf_addstr(msgbuf, "\nConflicts:\n");
 		for (i = 0; i < active_nr;) {
-			struct cache_entry *ce = active_cache[i++];
+			const struct cache_entry *ce = active_cache[i++];
 			if (ce_stage(ce)) {
 				strbuf_addch(msgbuf, '\t');
 				strbuf_addstr(msgbuf, ce->name);
@@ -366,8 +371,9 @@
 		active_cache_tree = cache_tree();
 
 	if (!cache_tree_fully_valid(active_cache_tree))
-		if (cache_tree_update(active_cache_tree, active_cache,
-				  active_nr, 0))
+		if (cache_tree_update(active_cache_tree,
+				      (const struct cache_entry * const *)active_cache,
+				      active_nr, 0))
 			return error(_("Unable to update cache tree\n"));
 
 	return !hashcmp(active_cache_tree->sha1, head_commit->tree->object.sha1);
@@ -474,7 +480,7 @@
 	struct commit_message msg = { NULL, NULL, NULL, NULL, NULL };
 	char *defmsg = NULL;
 	struct strbuf msgbuf = STRBUF_INIT;
-	int res, unborn = 0;
+	int res, unborn = 0, allow;
 
 	if (opts->no_commit) {
 		/*
@@ -523,7 +529,7 @@
 	if (opts->allow_ff &&
 	    ((parent && !hashcmp(parent->object.sha1, head)) ||
 	     (!parent && unborn)))
-	     return fast_forward_to(commit->object.sha1, head, unborn);
+		return fast_forward_to(commit->object.sha1, head, unborn, opts);
 
 	if (parent && parse_commit(parent) < 0)
 		/* TRANSLATORS: The first %s will be "revert" or
@@ -624,14 +630,18 @@
 		      msg.subject);
 		print_advice(res == 1, opts);
 		rerere(opts->allow_rerere_auto);
-	} else {
-		int allow = allow_empty(opts, commit);
-		if (allow < 0)
-			return allow;
-		if (!opts->no_commit)
-			res = run_git_commit(defmsg, opts, allow);
+		goto leave;
 	}
 
+	allow = allow_empty(opts, commit);
+	if (allow < 0) {
+		res = allow;
+		goto leave;
+	}
+	if (!opts->no_commit)
+		res = run_git_commit(defmsg, opts, allow);
+
+leave:
 	free_message(&msg);
 	free(defmsg);
 
@@ -1077,10 +1087,10 @@
 			continue;
 
 		if (!get_sha1(name, sha1)) {
-			enum object_type type = sha1_object_info(sha1, NULL);
-
-			if (type > 0 && type != OBJ_COMMIT)
+			if (!lookup_commit_reference_gently(sha1, 1)) {
+				enum object_type type = sha1_object_info(sha1, NULL);
 				die(_("%s: can't cherry-pick a %s"), name, typename(type));
+			}
 		} else
 			die(_("%s: bad revision"), name);
 	}
diff --git a/setup.c b/setup.c
index 94c1e61..5262319 100644
--- a/setup.c
+++ b/setup.c
@@ -360,6 +360,7 @@
 
 void setup_work_tree(void)
 {
+	struct strbuf sb = STRBUF_INIT;
 	const char *work_tree, *git_dir;
 	static int initialized = 0;
 
@@ -379,8 +380,10 @@
 	if (getenv(GIT_WORK_TREE_ENVIRONMENT))
 		setenv(GIT_WORK_TREE_ENVIRONMENT, ".", 1);
 
-	set_git_dir(relative_path(git_dir, work_tree));
+	set_git_dir(relative_path(git_dir, work_tree, &sb));
 	initialized = 1;
+
+	strbuf_release(&sb);
 }
 
 static int check_repository_format_gently(const char *gitdir, int *nongit_ok)
@@ -908,3 +911,15 @@
 		return suspect;
 	return read_gitfile(suspect);
 }
+
+/* if any standard file descriptor is missing open it to /dev/null */
+void sanitize_stdfds(void)
+{
+	int fd = open("/dev/null", O_RDWR, 0);
+	while (fd != -1 && fd < 2)
+		fd = dup(fd);
+	if (fd == -1)
+		die_errno("open /dev/null or dup failed");
+	if (fd > 2)
+		close(fd);
+}
diff --git a/sha1_file.c b/sha1_file.c
index 67e815b..8e27db1 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -36,6 +36,9 @@
 
 const unsigned char null_sha1[20];
 
+static const char *no_log_pack_access = "no_log_pack_access";
+static const char *log_pack_access;
+
 /*
  * This is meant to hold a *small* number of objects that you would
  * want read_sha1_file() to be able to return, but yet you do not want
@@ -1303,6 +1306,26 @@
 	}
 }
 
+static int stat_sha1_file(const unsigned char *sha1, struct stat *st)
+{
+	char *name = sha1_file_name(sha1);
+	struct alternate_object_database *alt;
+
+	if (!lstat(name, st))
+		return 0;
+
+	prepare_alt_odb();
+	errno = ENOENT;
+	for (alt = alt_odb_list; alt; alt = alt->next) {
+		name = alt->name;
+		fill_sha1_path(name, sha1);
+		if (!lstat(alt->base, st))
+			return 0;
+	}
+
+	return -1;
+}
+
 static int open_sha1_file(const unsigned char *sha1)
 {
 	int fd;
@@ -1690,46 +1713,21 @@
 	return type;
 }
 
-
 #define POI_STACK_PREALLOC 64
 
-static int packed_object_info(struct packed_git *p, off_t obj_offset,
-			      unsigned long *sizep, int *rtype)
+static enum object_type packed_to_object_type(struct packed_git *p,
+					      off_t obj_offset,
+					      enum object_type type,
+					      struct pack_window **w_curs,
+					      off_t curpos)
 {
-	struct pack_window *w_curs = NULL;
-	unsigned long size;
-	off_t curpos = obj_offset;
-	enum object_type type;
 	off_t small_poi_stack[POI_STACK_PREALLOC];
 	off_t *poi_stack = small_poi_stack;
 	int poi_stack_nr = 0, poi_stack_alloc = POI_STACK_PREALLOC;
 
-	type = unpack_object_header(p, &w_curs, &curpos, &size);
-
-	if (rtype)
-		*rtype = type; /* representation type */
-
-	if (sizep) {
-		if (type == OBJ_OFS_DELTA || type == OBJ_REF_DELTA) {
-			off_t tmp_pos = curpos;
-			off_t base_offset = get_delta_base(p, &w_curs, &tmp_pos,
-							   type, obj_offset);
-			if (!base_offset) {
-				type = OBJ_BAD;
-				goto out;
-			}
-			*sizep = get_size_from_delta(p, &w_curs, tmp_pos);
-			if (*sizep == 0) {
-				type = OBJ_BAD;
-				goto out;
-			}
-		} else {
-			*sizep = size;
-		}
-	}
-
 	while (type == OBJ_OFS_DELTA || type == OBJ_REF_DELTA) {
 		off_t base_offset;
+		unsigned long size;
 		/* Push the object we're going to leave behind */
 		if (poi_stack_nr >= poi_stack_alloc && poi_stack == small_poi_stack) {
 			poi_stack_alloc = alloc_nr(poi_stack_nr);
@@ -1740,11 +1738,11 @@
 		}
 		poi_stack[poi_stack_nr++] = obj_offset;
 		/* If parsing the base offset fails, just unwind */
-		base_offset = get_delta_base(p, &w_curs, &curpos, type, obj_offset);
+		base_offset = get_delta_base(p, w_curs, &curpos, type, obj_offset);
 		if (!base_offset)
 			goto unwind;
 		curpos = obj_offset = base_offset;
-		type = unpack_object_header(p, &w_curs, &curpos, &size);
+		type = unpack_object_header(p, w_curs, &curpos, &size);
 		if (type <= OBJ_NONE) {
 			/* If getting the base itself fails, we first
 			 * retry the base, otherwise unwind */
@@ -1771,7 +1769,6 @@
 out:
 	if (poi_stack != small_poi_stack)
 		free(poi_stack);
-	unuse_pack(&w_curs);
 	return type;
 
 unwind:
@@ -1785,6 +1782,57 @@
 	goto out;
 }
 
+static int packed_object_info(struct packed_git *p, off_t obj_offset,
+			      struct object_info *oi)
+{
+	struct pack_window *w_curs = NULL;
+	unsigned long size;
+	off_t curpos = obj_offset;
+	enum object_type type;
+
+	/*
+	 * We always get the representation type, but only convert it to
+	 * a "real" type later if the caller is interested.
+	 */
+	type = unpack_object_header(p, &w_curs, &curpos, &size);
+
+	if (oi->sizep) {
+		if (type == OBJ_OFS_DELTA || type == OBJ_REF_DELTA) {
+			off_t tmp_pos = curpos;
+			off_t base_offset = get_delta_base(p, &w_curs, &tmp_pos,
+							   type, obj_offset);
+			if (!base_offset) {
+				type = OBJ_BAD;
+				goto out;
+			}
+			*oi->sizep = get_size_from_delta(p, &w_curs, tmp_pos);
+			if (*oi->sizep == 0) {
+				type = OBJ_BAD;
+				goto out;
+			}
+		} else {
+			*oi->sizep = size;
+		}
+	}
+
+	if (oi->disk_sizep) {
+		struct revindex_entry *revidx = find_pack_revindex(p, obj_offset);
+		*oi->disk_sizep = revidx[1].offset - obj_offset;
+	}
+
+	if (oi->typep) {
+		*oi->typep = packed_to_object_type(p, obj_offset, type, &w_curs, curpos);
+		if (*oi->typep < 0) {
+			type = OBJ_BAD;
+			goto out;
+		}
+	}
+
+out:
+	unuse_pack(&w_curs);
+	return type;
+}
+
 static void *unpack_compressed_entry(struct packed_git *p,
 				    struct pack_window **w_curs,
 				    off_t curpos,
@@ -1956,12 +2004,19 @@
 {
 	static FILE *log_file;
 
+	if (!log_pack_access)
+		log_pack_access = getenv("GIT_TRACE_PACK_ACCESS");
+	if (!log_pack_access)
+		log_pack_access = no_log_pack_access;
+	if (log_pack_access == no_log_pack_access)
+		return;
+
 	if (!log_file) {
 		log_file = fopen(log_pack_access, "w");
 		if (!log_file) {
 			error("cannot open pack access log '%s' for writing: %s",
 			      log_pack_access, strerror(errno));
-			log_pack_access = NULL;
+			log_pack_access = no_log_pack_access;
 			return;
 		}
 	}
@@ -1992,7 +2047,7 @@
 	int delta_stack_nr = 0, delta_stack_alloc = UNPACK_ENTRY_STACK_PREALLOC;
 	int base_from_cache = 0;
 
-	if (log_pack_access)
+	if (log_pack_access != no_log_pack_access)
 		write_pack_access_log(p, obj_offset);
 
 	/* PHASE 1: drill down to the innermost base object */
@@ -2135,10 +2190,19 @@
 		data = patch_delta(base, base_size,
 				   delta_data, delta_size,
 				   &size);
-		if (!data)
-			die("failed to apply delta");
 
-		free (delta_data);
+		/*
+		 * We could not apply the delta; warn the user, but keep going.
+		 * Our failure will be noticed either in the next iteration of
+		 * the loop, or if this is the final delta, in the caller when
+		 * we return NULL. Those code paths will take care of making
+		 * a more explicit warning and retrying with another copy of
+		 * the object.
+		 */
+		if (!data)
+			error("failed to apply delta");
+
+		free(delta_data);
 	}
 
 	*final_type = type;
@@ -2338,7 +2402,8 @@
 
 }
 
-static int sha1_loose_object_info(const unsigned char *sha1, unsigned long *sizep)
+static int sha1_loose_object_info(const unsigned char *sha1,
+				  struct object_info *oi)
 {
 	int status;
 	unsigned long mapsize, size;
@@ -2346,19 +2411,37 @@
 	git_zstream stream;
 	char hdr[32];
 
+	/*
+	 * If we don't care about type or size, then we don't
+	 * need to look inside the object at all.
+	 */
+	if (!oi->typep && !oi->sizep) {
+		if (oi->disk_sizep) {
+			struct stat st;
+			if (stat_sha1_file(sha1, &st) < 0)
+				return -1;
+			*oi->disk_sizep = st.st_size;
+		}
+		return 0;
+	}
+
 	map = map_sha1_file(sha1, &mapsize);
 	if (!map)
-		return error("unable to find %s", sha1_to_hex(sha1));
+		return -1;
+	if (oi->disk_sizep)
+		*oi->disk_sizep = mapsize;
 	if (unpack_sha1_header(&stream, map, mapsize, hdr, sizeof(hdr)) < 0)
 		status = error("unable to unpack %s header",
 			       sha1_to_hex(sha1));
 	else if ((status = parse_sha1_header(hdr, &size)) < 0)
 		status = error("unable to parse %s header", sha1_to_hex(sha1));
-	else if (sizep)
-		*sizep = size;
+	else if (oi->sizep)
+		*oi->sizep = size;
 	git_inflate_end(&stream);
 	munmap(map, mapsize);
-	return status;
+	if (oi->typep)
+		*oi->typep = status;
+	return 0;
 }
 
 /* returns enum object_type or negative */
@@ -2366,34 +2449,37 @@
 {
 	struct cached_object *co;
 	struct pack_entry e;
-	int status, rtype;
+	int rtype;
 
 	co = find_cached_object(sha1);
 	if (co) {
+		if (oi->typep)
+			*(oi->typep) = co->type;
 		if (oi->sizep)
 			*(oi->sizep) = co->size;
+		if (oi->disk_sizep)
+			*(oi->disk_sizep) = 0;
 		oi->whence = OI_CACHED;
-		return co->type;
+		return 0;
 	}
 
 	if (!find_pack_entry(sha1, &e)) {
 		/* Most likely it's a loose object. */
-		status = sha1_loose_object_info(sha1, oi->sizep);
-		if (status >= 0) {
+		if (!sha1_loose_object_info(sha1, oi)) {
 			oi->whence = OI_LOOSE;
-			return status;
+			return 0;
 		}
 
 		/* Not a loose object; someone else may have just packed it. */
 		reprepare_packed_git();
 		if (!find_pack_entry(sha1, &e))
-			return status;
+			return -1;
 	}
 
-	status = packed_object_info(e.p, e.offset, oi->sizep, &rtype);
-	if (status < 0) {
+	rtype = packed_object_info(e.p, e.offset, oi);
+	if (rtype < 0) {
 		mark_bad_packed_object(e.p, sha1);
-		status = sha1_object_info_extended(sha1, oi);
+		return sha1_object_info_extended(sha1, oi);
 	} else if (in_delta_base_cache(e.p, e.offset)) {
 		oi->whence = OI_DBCACHED;
 	} else {
@@ -2404,15 +2490,19 @@
 					 rtype == OBJ_OFS_DELTA);
 	}
 
-	return status;
+	return 0;
 }
 
 int sha1_object_info(const unsigned char *sha1, unsigned long *sizep)
 {
-	struct object_info oi;
+	enum object_type type;
+	struct object_info oi = {NULL};
 
+	oi.typep = &type;
 	oi.sizep = sizep;
-	return sha1_object_info_extended(sha1, &oi);
+	if (sha1_object_info_extended(sha1, &oi) < 0)
+		return -1;
+	return type;
 }
 
 static void *read_packed_sha1(const unsigned char *sha1,
diff --git a/sha1_name.c b/sha1_name.c
index 3820f28..65ad066 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -52,7 +52,7 @@
 	}
 
 	if (!ds->candidate_ok) {
-		/* discard the candidate; we know it does not satisify fn */
+		/* discard the candidate; we know it does not satisfy fn */
 		hashcpy(ds->candidate, current);
 		ds->candidate_checked = 0;
 		return;
@@ -241,7 +241,7 @@
 		return 0;
 
 	/* We need to do this the hard way... */
-	obj = deref_tag(lookup_object(sha1), NULL, 0);
+	obj = deref_tag(parse_object(sha1), NULL, 0);
 	if (obj && obj->type == OBJ_COMMIT)
 		return 1;
 	return 0;
@@ -431,22 +431,51 @@
 }
 
 static int get_sha1_1(const char *name, int len, unsigned char *sha1, unsigned lookup_flags);
+static int interpret_nth_prior_checkout(const char *name, struct strbuf *buf);
 
 static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
 {
 	static const char *warn_msg = "refname '%.*s' is ambiguous.";
+	static const char *object_name_msg = N_(
+	"Git normally never creates a ref that ends with 40 hex characters\n"
+	"because it will be ignored when you just specify 40-hex. These refs\n"
+	"may be created by mistake. For example,\n"
+	"\n"
+	"  git checkout -b $br $(git rev-parse ...)\n"
+	"\n"
+	"where \"$br\" is somehow empty and a 40-hex ref is created. Please\n"
+	"examine these refs and maybe delete them. Turn this message off by\n"
+	"running \"git config advice.objectNameWarning false\"");
+	unsigned char tmp_sha1[20];
 	char *real_ref = NULL;
 	int refs_found = 0;
-	int at, reflog_len;
+	int at, reflog_len, nth_prior = 0;
 
-	if (len == 40 && !get_sha1_hex(str, sha1))
+	if (len == 40 && !get_sha1_hex(str, sha1)) {
+		if (warn_on_object_refname_ambiguity) {
+			refs_found = dwim_ref(str, len, tmp_sha1, &real_ref);
+			if (refs_found > 0 && warn_ambiguous_refs) {
+				warning(warn_msg, len, str);
+				if (advice_object_name_warning)
+					fprintf(stderr, "%s\n", _(object_name_msg));
+			}
+			free(real_ref);
+		}
 		return 0;
+	}
 
 	/* basic@{time or number or -number} format to query ref-log */
 	reflog_len = at = 0;
 	if (len && str[len-1] == '}') {
-		for (at = len-2; at >= 0; at--) {
+		for (at = len-4; at >= 0; at--) {
 			if (str[at] == '@' && str[at+1] == '{') {
+				if (str[at+2] == '-') {
+					if (at != 0)
+						/* @{-N} not at start */
+						return -1;
+					nth_prior = 1;
+					continue;
+				}
 				if (!upstream_mark(str + at, len - at)) {
 					reflog_len = (len-1) - (at+2);
 					len = at;
@@ -460,20 +489,22 @@
 	if (len && ambiguous_path(str, len))
 		return -1;
 
-	if (!len && reflog_len) {
+	if (nth_prior) {
 		struct strbuf buf = STRBUF_INIT;
-		int ret;
-		/* try the @{-N} syntax for n-th checkout */
-		ret = interpret_branch_name(str+at, &buf);
-		if (ret > 0) {
-			/* substitute this branch name and restart */
-			return get_sha1_1(buf.buf, buf.len, sha1, 0);
-		} else if (ret == 0) {
-			return -1;
+		int detached;
+
+		if (interpret_nth_prior_checkout(str, &buf) > 0) {
+			detached = (buf.len == 40 && !get_sha1_hex(buf.buf, sha1));
+			strbuf_release(&buf);
+			if (detached)
+				return 0;
 		}
+	}
+
+	if (!len && reflog_len)
 		/* allow "@{...}" to mean the current branch reflog */
 		refs_found = dwim_ref("HEAD", 4, sha1, &real_ref);
-	} else if (reflog_len)
+	else if (reflog_len)
 		refs_found = dwim_log(str, len, sha1, &real_ref);
 	else
 		refs_found = dwim_ref(str, len, sha1, &real_ref);
@@ -481,7 +512,9 @@
 	if (!refs_found)
 		return -1;
 
-	if (warn_ambiguous_refs && refs_found > 1)
+	if (warn_ambiguous_refs &&
+	    (refs_found > 1 ||
+	     !get_short_sha1(str, len, tmp_sha1, GET_SHA1_QUIETLY)))
 		warning(warn_msg, len, str);
 
 	if (reflog_len) {
@@ -490,10 +523,6 @@
 		unsigned long co_time;
 		int co_tz, co_cnt;
 
-		/* a @{-N} placed anywhere except the start is an error */
-		if (str[at+2] == '-')
-			return -1;
-
 		/* Is it asking for N-th entry, or approxidate? */
 		for (i = nth = 0; 0 <= nth && i < reflog_len; i++) {
 			char ch = str[at+2+i];
@@ -517,12 +546,21 @@
 		}
 		if (read_ref_at(real_ref, at_time, nth, sha1, NULL,
 				&co_time, &co_tz, &co_cnt)) {
+			if (!len) {
+				if (!prefixcmp(real_ref, "refs/heads/")) {
+					str = real_ref + 11;
+					len = strlen(real_ref + 11);
+				} else {
+					/* detached HEAD */
+					str = "HEAD";
+					len = 4;
+				}
+			}
 			if (at_time)
 				warning("Log for '%.*s' only goes "
 					"back to %s.", len, str,
 					show_date(co_time, co_tz, DATE_RFC2822));
 			else {
-				free(real_ref);
 				die("Log for '%.*s' only has %d entries.",
 				    len, str, co_cnt);
 			}
@@ -966,6 +1004,27 @@
 	return st;
 }
 
+static int reinterpret(const char *name, int namelen, int len, struct strbuf *buf)
+{
+	/* we have extra data, which might need further processing */
+	struct strbuf tmp = STRBUF_INIT;
+	int used = buf->len;
+	int ret;
+
+	strbuf_add(buf, name + len, namelen - len);
+	ret = interpret_branch_name(buf->buf, &tmp);
+	/* that data was not interpreted, remove our cruft */
+	if (ret < 0) {
+		strbuf_setlen(buf, used);
+		return len;
+	}
+	strbuf_reset(buf);
+	strbuf_addbuf(buf, &tmp);
+	strbuf_release(&tmp);
+	/* tweak for size of {-N} versus expanded ref name */
+	return ret - used + len;
+}
+
 /*
  * This reads short-hand syntax that not only evaluates to a commit
  * object name, but also can act as if the end user spelled the name
@@ -995,28 +1054,13 @@
 	int len = interpret_nth_prior_checkout(name, buf);
 	int tmp_len;
 
-	if (!len)
+	if (!len) {
 		return len; /* syntax Ok, not enough switches */
-	if (0 < len && len == namelen)
-		return len; /* consumed all */
-	else if (0 < len) {
-		/* we have extra data, which might need further processing */
-		struct strbuf tmp = STRBUF_INIT;
-		int used = buf->len;
-		int ret;
-
-		strbuf_add(buf, name + len, namelen - len);
-		ret = interpret_branch_name(buf->buf, &tmp);
-		/* that data was not interpreted, remove our cruft */
-		if (ret < 0) {
-			strbuf_setlen(buf, used);
-			return len;
-		}
-		strbuf_reset(buf);
-		strbuf_addbuf(buf, &tmp);
-		strbuf_release(&tmp);
-		/* tweak for size of {-N} versus expanded ref name */
-		return ret - used + len;
+	} else if (len > 0) {
+		if (len == namelen)
+			return len; /* consumed all */
+		else
+			return reinterpret(name, namelen, len, buf);
 	}
 
 	cp = strchr(name, '@');
@@ -1033,14 +1077,15 @@
 	 * points to something different than a branch.
 	 */
 	if (!upstream)
-		return error(_("HEAD does not point to a branch"));
+		die(_("HEAD does not point to a branch"));
 	if (!upstream->merge || !upstream->merge[0]->dst) {
 		if (!ref_exists(upstream->refname))
-			return error(_("No such branch: '%s'"), cp);
-		if (!upstream->merge)
-			return error(_("No upstream configured for branch '%s'"),
-				     upstream->name);
-		return error(
+			die(_("No such branch: '%s'"), cp);
+		if (!upstream->merge) {
+			die(_("No upstream configured for branch '%s'"),
+				upstream->name);
+		}
+		die(
 			_("Upstream branch '%s' not stored as a remote-tracking branch"),
 			upstream->merge[0]->src);
 	}
@@ -1055,9 +1100,13 @@
 int strbuf_branchname(struct strbuf *sb, const char *name)
 {
 	int len = strlen(name);
-	if (interpret_branch_name(name, sb) == len)
+	int used = interpret_branch_name(name, sb);
+
+	if (used == len)
 		return 0;
-	strbuf_add(sb, name, len);
+	if (used < 0)
+		used = 0;
+	strbuf_add(sb, name + used, len - used);
 	return len;
 }
 
@@ -1170,7 +1219,7 @@
 					const char *filename)
 {
 	struct stat st;
-	struct cache_entry *ce;
+	const struct cache_entry *ce;
 	int pos;
 	unsigned namelen = strlen(filename);
 	unsigned fullnamelen;
@@ -1264,7 +1313,7 @@
 	 */
 	if (name[0] == ':') {
 		int stage = 0;
-		struct cache_entry *ce;
+		const struct cache_entry *ce;
 		char *new_path = NULL;
 		int pos;
 		if (!only_to_die && namelen > 2 && name[1] == '/') {
diff --git a/shallow.c b/shallow.c
index 6be915f..8a9c96d 100644
--- a/shallow.c
+++ b/shallow.c
@@ -3,6 +3,16 @@
 #include "tag.h"
 
 static int is_shallow = -1;
+static struct stat shallow_stat;
+static char *alternate_shallow_file;
+
+void set_alternate_shallow_file(const char *path)
+{
+	if (is_shallow != -1)
+		die("BUG: is_repository_shallow must not be called before set_alternate_shallow_file");
+	free(alternate_shallow_file);
+	alternate_shallow_file = path ? xstrdup(path) : NULL;
+}
 
 int register_shallow(const unsigned char *sha1)
 {
@@ -21,12 +31,21 @@
 {
 	FILE *fp;
 	char buf[1024];
+	const char *path = alternate_shallow_file;
 
 	if (is_shallow >= 0)
 		return is_shallow;
 
-	fp = fopen(git_path("shallow"), "r");
-	if (!fp) {
+	if (!path)
+		path = git_path("shallow");
+	/*
+	 * fetch-pack sets '--shallow-file ""' as an indicator that no
+	 * shallow file should be used. We could just open it and it
+	 * will likely fail. But let's do an explicit check instead.
+	 */
+	if (!*path ||
+	    stat(path, &shallow_stat) ||
+	    (fp = fopen(path, "r")) == NULL) {
 		is_shallow = 0;
 		return is_shallow;
 	}
@@ -91,20 +110,34 @@
 					continue;
 				*pointer = cur_depth;
 			}
-			if (cur_depth < depth) {
-				if (p->next)
-					add_object_array(&p->item->object,
-							NULL, &stack);
-				else {
-					commit = p->item;
-					cur_depth = *(int *)commit->util;
-				}
-			} else {
-				commit_list_insert(p->item, &result);
-				p->item->object.flags |= shallow_flag;
+			if (p->next)
+				add_object_array(&p->item->object,
+						NULL, &stack);
+			else {
+				commit = p->item;
+				cur_depth = *(int *)commit->util;
 			}
 		}
 	}
 
 	return result;
 }
+
+void check_shallow_file_for_update(void)
+{
+	struct stat st;
+
+	if (!is_shallow)
+		return;
+	else if (is_shallow == -1)
+		die("BUG: shallow must be initialized by now");
+
+	if (stat(git_path("shallow"), &st))
+		die("shallow file was removed during fetch");
+	else if (st.st_mtime != shallow_stat.st_mtime
+#ifdef USE_NSEC
+		 || ST_MTIME_NSEC(st) != ST_MTIME_NSEC(shallow_stat)
+#endif
+		   )
+		die("shallow file was changed during fetch");
+}
diff --git a/shell.c b/shell.c
index 1429870..66350b2 100644
--- a/shell.c
+++ b/shell.c
@@ -147,7 +147,6 @@
 	char *prog;
 	const char **user_argv;
 	struct commands *cmd;
-	int devnull_fd;
 	int count;
 
 	git_setup_gettext();
@@ -156,15 +155,10 @@
 
 	/*
 	 * Always open file descriptors 0/1/2 to avoid clobbering files
-	 * in die().  It also avoids not messing up when the pipes are
-	 * dup'ed onto stdin/stdout/stderr in the child processes we spawn.
+	 * in die().  It also avoids messing up when the pipes are dup'ed
+	 * onto stdin/stdout/stderr in the child processes we spawn.
 	 */
-	devnull_fd = open("/dev/null", O_RDWR);
-	while (devnull_fd >= 0 && devnull_fd <= 2)
-		devnull_fd = dup(devnull_fd);
-	if (devnull_fd == -1)
-		die_errno("opening /dev/null failed");
-	close (devnull_fd);
+	sanitize_stdfds();
 
 	/*
 	 * Special hack to pretend to be a CVS server
diff --git a/streaming.c b/streaming.c
index cabcd9d..debe904 100644
--- a/streaming.c
+++ b/streaming.c
@@ -111,11 +111,11 @@
 	unsigned long size;
 	int status;
 
+	oi->typep = type;
 	oi->sizep = &size;
 	status = sha1_object_info_extended(sha1, oi);
 	if (status < 0)
 		return stream_error;
-	*type = status;
 
 	switch (oi->whence) {
 	case OI_LOOSE:
@@ -135,7 +135,7 @@
 				 struct stream_filter *filter)
 {
 	struct git_istream *st;
-	struct object_info oi;
+	struct object_info oi = {NULL};
 	const unsigned char *real = lookup_replace_object(sha1);
 	enum input_source src = istream_source(real, type, &oi);
 
@@ -149,7 +149,7 @@
 			return NULL;
 		}
 	}
-	if (st && filter) {
+	if (filter) {
 		/* Add "&& !is_null_stream_filter(filter)" for performance */
 		struct git_istream *nst = attach_stream_filter(st, filter);
 		if (!nst)
diff --git a/submodule.c b/submodule.c
index e728025..c0f93c2 100644
--- a/submodule.c
+++ b/submodule.c
@@ -134,6 +134,9 @@
 		return 0;
 
 	if (!strcmp(key, "path")) {
+		if (!value)
+			return config_error_nonbool(var);
+
 		config = unsorted_string_list_lookup(&config_name_for_path, value);
 		if (config)
 			free(config->util);
@@ -151,6 +154,9 @@
 	} else if (!strcmp(key, "ignore")) {
 		char *name_cstr;
 
+		if (!value)
+			return config_error_nonbool(var);
+
 		if (strcmp(value, "untracked") && strcmp(value, "dirty") &&
 		    strcmp(value, "all") && strcmp(value, "none")) {
 			warning("Invalid parameter \"%s\" for config option \"submodule.%s.ignore\"", value, var);
@@ -226,6 +232,7 @@
 	while ((commit = get_revision(rev))) {
 		struct pretty_print_context ctx = {0};
 		ctx.date_mode = rev->date_mode;
+		ctx.output_encoding = get_log_output_encoding();
 		strbuf_setlen(&sb, 0);
 		strbuf_addstr(&sb, line_prefix);
 		if (commit->object.flags & SYMMETRIC_LEFT) {
@@ -603,9 +610,8 @@
 	if (!work_tree)
 		goto out;
 
-	if (!the_index.initialized)
-		if (read_cache() < 0)
-			die("index file corrupt");
+	if (read_cache() < 0)
+		die("index file corrupt");
 
 	argv_array_push(&argv, "fetch");
 	for (i = 0; i < options->argc; i++)
@@ -624,7 +630,7 @@
 		struct strbuf submodule_path = STRBUF_INIT;
 		struct strbuf submodule_git_dir = STRBUF_INIT;
 		struct strbuf submodule_prefix = STRBUF_INIT;
-		struct cache_entry *ce = active_cache[i];
+		const struct cache_entry *ce = active_cache[i];
 		const char *git_dir, *name, *default_argv;
 
 		if (!S_ISGITLINK(ce->ce_mode))
@@ -846,7 +852,7 @@
 		struct commit *a, struct commit *b)
 {
 	int i, j;
-	struct object_array merges;
+	struct object_array merges = OBJECT_ARRAY_INIT;
 	struct commit *commit;
 	int contains_another;
 
@@ -856,7 +862,6 @@
 	struct rev_info revs;
 	struct setup_revision_opt rev_opts;
 
-	memset(&merges, 0, sizeof(merges));
 	memset(result, 0, sizeof(struct object_array));
 	memset(&rev_opts, 0, sizeof(rev_opts));
 
@@ -894,8 +899,7 @@
 		}
 
 		if (!contains_another)
-			add_object_array(merges.objects[i].item,
-					 merges.objects[i].name, result);
+			add_object_array(merges.objects[i].item, NULL, result);
 	}
 
 	free(merges.objects);
diff --git a/t/Makefile b/t/Makefile
index 44ca7d3..2373a04 100644
--- a/t/Makefile
+++ b/t/Makefile
@@ -15,9 +15,16 @@
 DEFAULT_TEST_TARGET ?= test
 TEST_LINT ?= test-lint-duplicates test-lint-executable
 
+ifdef TEST_OUTPUT_DIRECTORY
+TEST_RESULTS_DIRECTORY = $(TEST_OUTPUT_DIRECTORY)/test-results
+else
+TEST_RESULTS_DIRECTORY = test-results
+endif
+
 # Shell quote;
 SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH))
 PERL_PATH_SQ = $(subst ','\'',$(PERL_PATH))
+TEST_RESULTS_DIRECTORY_SQ = $(subst ','\'',$(TEST_RESULTS_DIRECTORY))
 
 T = $(sort $(wildcard t[0-9][0-9][0-9][0-9]-*.sh))
 TSVN = $(sort $(wildcard t91[0-9][0-9]-*.sh))
@@ -36,10 +43,10 @@
 	@echo "*** $@ ***"; GIT_CONFIG=.git/config '$(SHELL_PATH_SQ)' $@ $(GIT_TEST_OPTS)
 
 pre-clean:
-	$(RM) -r test-results
+	$(RM) -r '$(TEST_RESULTS_DIRECTORY_SQ)'
 
 clean-except-prove-cache:
-	$(RM) -r 'trash directory'.* test-results
+	$(RM) -r 'trash directory'.* '$(TEST_RESULTS_DIRECTORY_SQ)'
 	$(RM) -r valgrind/bin
 
 clean: clean-except-prove-cache
@@ -65,7 +72,7 @@
 	$(MAKE) clean
 
 aggregate-results:
-	for f in test-results/t*-*.counts; do \
+	for f in '$(TEST_RESULTS_DIRECTORY_SQ)'/t*-*.counts; do \
 		echo "$$f"; \
 	done | '$(SHELL_PATH_SQ)' ./aggregate-results.sh
 
diff --git a/t/README b/t/README
index e669bb3..2167125 100644
--- a/t/README
+++ b/t/README
@@ -76,6 +76,11 @@
 	command being run and their output if any are also
 	output.
 
+--verbose-only=<pattern>::
+	Like --verbose, but the effect is limited to tests with
+	numbers matching <pattern>.  The number matched against is
+	simply the running count of the test within the file.
+
 --debug::
 	This may help the person who is developing a new test.
 	It causes the command defined with test_debug to run.
@@ -121,6 +126,11 @@
 	the 't/valgrind/' directory and use the commands under
 	't/valgrind/bin/'.
 
+--valgrind-only=<pattern>::
+	Like --valgrind, but the effect is limited to tests with
+	numbers matching <pattern>.  The number matched against is
+	simply the running count of the test within the file.
+
 --tee::
 	In addition to printing the test output to the terminal,
 	write it to files named 't/test-results/$TEST_NAME.out'.
@@ -324,6 +334,9 @@
    use 'test_must_fail git cmd'.  This will signal a failure if git
    dies in an unexpected way (e.g. segfault).
 
+   On the other hand, don't use test_must_fail for running regular
+   platform commands; just use '! cmd'.
+
  - use perl without spelling it as "$PERL_PATH". This is to help our
    friends on Windows where the platform Perl often adds CR before
    the end of line, and they bundle Git with a version of Perl that
@@ -592,6 +605,20 @@
 		test_cmp expected actual
 	'
 
+ - test_ln_s_add <path1> <path2>
+
+   This function helps systems whose filesystem does not support symbolic
+   links. Use it to add a symbolic link entry to the index when it is not
+   important that the file system entry is a symbolic link, i.e., instead
+   of the sequence
+
+	ln -s foo bar &&
+	git add bar
+
+   Sometimes it is possible to split a test in a part that does not need
+   the symbolic link in the file system and a part that does; then only
+   the latter part need be protected by a SYMLINKS prerequisite (see below).
+
 Prerequisites
 -------------
 
diff --git a/t/annotate-tests.sh b/t/annotate-tests.sh
index c56a77d..d4e7f47 100644
--- a/t/annotate-tests.sh
+++ b/t/annotate-tests.sh
@@ -2,11 +2,21 @@
 # sourced from t8001-annotate.sh and t8002-blame.sh.
 
 check_count () {
-	head=
-	case "$1" in -h) head="$2"; shift; shift ;; esac
-	echo "$PROG file $head" >&4
-	$PROG file $head >.result || return 1
-	cat .result | perl -e '
+	head= &&
+	file='file' &&
+	options= &&
+	while :
+	do
+		case "$1" in
+		-h) head="$2"; shift; shift ;;
+		-f) file="$2"; shift; shift ;;
+		-*) options="$options $1"; shift ;;
+		*) break ;;
+		esac
+	done &&
+	echo "$PROG $options $file $head" >&4 &&
+	$PROG $options $file $head >actual &&
+	perl -e '
 		my %expect = (@ARGV);
 		my %count = map { $_ => 0 } keys %expect;
 		while (<STDIN>) {
@@ -31,107 +41,246 @@
 			print STDERR "Author $author (expected $value, attributed $count) $ok\n";
 		}
 		exit($bad);
-	' "$@"
+	' "$@" <actual
 }
 
-test_expect_success \
-    'prepare reference tree' \
-    'echo "1A quick brown fox jumps over the" >file &&
-     echo "lazy dog" >>file &&
-     git add file &&
-     GIT_AUTHOR_NAME="A" GIT_AUTHOR_EMAIL="A@test.git" git commit -a -m "Initial."'
+test_expect_success 'setup A lines' '
+	echo "1A quick brown fox jumps over the" >file &&
+	echo "lazy dog" >>file &&
+	git add file &&
+	GIT_AUTHOR_NAME="A" GIT_AUTHOR_EMAIL="A@test.git" \
+	git commit -a -m "Initial."
+'
 
-test_expect_success \
-    'check all lines blamed on A' \
-    'check_count A 2'
+test_expect_success 'blame 1 author' '
+	check_count A 2
+'
 
-test_expect_success \
-    'Setup new lines blamed on B' \
-    'echo "2A quick brown fox jumps over the" >>file &&
-     echo "lazy dog" >> file &&
-     GIT_AUTHOR_NAME="B" GIT_AUTHOR_EMAIL="B@test.git" git commit -a -m "Second."'
+test_expect_success 'setup B lines' '
+	echo "2A quick brown fox jumps over the" >>file &&
+	echo "lazy dog" >>file &&
+	GIT_AUTHOR_NAME="B" GIT_AUTHOR_EMAIL="B@test.git" \
+	git commit -a -m "Second."
+'
 
-test_expect_success \
-    'Two lines blamed on A, two on B' \
-    'check_count A 2 B 2'
+test_expect_success 'blame 2 authors' '
+	check_count A 2 B 2
+'
 
-test_expect_success \
-    'merge-setup part 1' \
-    'git checkout -b branch1 master &&
-     echo "3A slow green fox jumps into the" >> file &&
-     echo "well." >> file &&
-     GIT_AUTHOR_NAME="B1" GIT_AUTHOR_EMAIL="B1@test.git" git commit -a -m "Branch1-1"'
+test_expect_success 'setup B1 lines (branch1)' '
+	git checkout -b branch1 master &&
+	echo "3A slow green fox jumps into the" >>file &&
+	echo "well." >>file &&
+	GIT_AUTHOR_NAME="B1" GIT_AUTHOR_EMAIL="B1@test.git" \
+	git commit -a -m "Branch1-1"
+'
 
-test_expect_success \
-    'Two lines blamed on A, two on B, two on B1' \
-    'check_count A 2 B 2 B1 2'
+test_expect_success 'blame 2 authors + 1 branch1 author' '
+	check_count A 2 B 2 B1 2
+'
 
-test_expect_success \
-    'merge-setup part 2' \
-    'git checkout -b branch2 master &&
-     sed -e "s/2A quick brown/4A quick brown lazy dog/" < file > file.new &&
-     mv file.new file &&
-     GIT_AUTHOR_NAME="B2" GIT_AUTHOR_EMAIL="B2@test.git" git commit -a -m "Branch2-1"'
+test_expect_success 'setup B2 lines (branch2)' '
+	git checkout -b branch2 master &&
+	sed -e "s/2A quick brown/4A quick brown lazy dog/" <file >file.new &&
+	mv file.new file &&
+	GIT_AUTHOR_NAME="B2" GIT_AUTHOR_EMAIL="B2@test.git" \
+	git commit -a -m "Branch2-1"
+'
 
-test_expect_success \
-    'Two lines blamed on A, one on B, one on B2' \
-    'check_count A 2 B 1 B2 1'
+test_expect_success 'blame 2 authors + 1 branch2 author' '
+	check_count A 2 B 1 B2 1
+'
 
-test_expect_success \
-    'merge-setup part 3' \
-    'git pull . branch1'
+test_expect_success 'merge branch1 & branch2' '
+	git pull . branch1
+'
 
-test_expect_success \
-    'Two lines blamed on A, one on B, two on B1, one on B2' \
-    'check_count A 2 B 1 B1 2 B2 1'
+test_expect_success 'blame 2 authors + 2 merged-in authors' '
+	check_count A 2 B 1 B1 2 B2 1
+'
 
-test_expect_success \
-    'Annotating an old revision works' \
-    'check_count -h master A 2 B 2'
+test_expect_success 'blame ancestor' '
+	check_count -h master A 2 B 2
+'
 
-test_expect_success \
-    'Annotating an old revision works' \
-    'check_count -h master^ A 2'
+test_expect_success 'blame great-ancestor' '
+	check_count -h master^ A 2
+'
 
-test_expect_success \
-    'merge-setup part 4' \
-    'echo "evil merge." >>file &&
-     git commit -a --amend'
+test_expect_success 'setup evil merge' '
+	echo "evil merge." >>file &&
+	git commit -a --amend
+'
 
-test_expect_success \
-    'Two lines blamed on A, one on B, two on B1, one on B2, one on A U Thor' \
-    'check_count A 2 B 1 B1 2 B2 1 "A U Thor" 1'
+test_expect_success 'blame evil merge' '
+	check_count A 2 B 1 B1 2 B2 1 "A U Thor" 1
+'
 
-test_expect_success \
-    'an incomplete line added' \
-    'echo "incomplete" | tr -d "\\012" >>file &&
-    GIT_AUTHOR_NAME="C" GIT_AUTHOR_EMAIL="C@test.git" git commit -a -m "Incomplete"'
+test_expect_success 'setup incomplete line' '
+	echo "incomplete" | tr -d "\\012" >>file &&
+	GIT_AUTHOR_NAME="C" GIT_AUTHOR_EMAIL="C@test.git" \
+	git commit -a -m "Incomplete"
+'
 
-test_expect_success \
-    'With incomplete lines.' \
-    'check_count A 2 B 1 B1 2 B2 1 "A U Thor" 1 C 1'
+test_expect_success 'blame incomplete line' '
+	check_count A 2 B 1 B1 2 B2 1 "A U Thor" 1 C 1
+'
 
-test_expect_success \
-    'some edit' \
-    'mv file file.orig &&
-    {
-	cat file.orig &&
-	echo
-    } | sed -e "s/^3A/99/" -e "/^1A/d" -e "/^incomplete/d" > file &&
-    echo "incomplete" | tr -d "\\012" >>file &&
-    GIT_AUTHOR_NAME="D" GIT_AUTHOR_EMAIL="D@test.git" git commit -a -m "edit"'
+test_expect_success 'setup edits' '
+	mv file file.orig &&
+	{
+		cat file.orig &&
+		echo
+	} | sed -e "s/^3A/99/" -e "/^1A/d" -e "/^incomplete/d" >file &&
+	echo "incomplete" | tr -d "\\012" >>file &&
+	GIT_AUTHOR_NAME="D" GIT_AUTHOR_EMAIL="D@test.git" \
+	git commit -a -m "edit"
+'
 
-test_expect_success \
-    'some edit' \
-    'check_count A 1 B 1 B1 1 B2 1 "A U Thor" 1 C 1 D 1'
+test_expect_success 'blame edits' '
+	check_count A 1 B 1 B1 1 B2 1 "A U Thor" 1 C 1 D 1
+'
 
-test_expect_success \
-    'an obfuscated email added' \
-    'echo "No robots allowed" > file.new &&
-     cat file >> file.new &&
-     mv file.new file &&
-     GIT_AUTHOR_NAME="E" GIT_AUTHOR_EMAIL="E at test dot git" git commit -a -m "norobots"'
+test_expect_success 'setup obfuscated email' '
+	echo "No robots allowed" >file.new &&
+	cat file >>file.new &&
+	mv file.new file &&
+	GIT_AUTHOR_NAME="E" GIT_AUTHOR_EMAIL="E at test dot git" \
+	git commit -a -m "norobots"
+'
 
-test_expect_success \
-    'obfuscated email parsed' \
-    'check_count A 1 B 1 B1 1 B2 1 "A U Thor" 1 C 1 D 1 E 1'
+test_expect_success 'blame obfuscated email' '
+	check_count A 1 B 1 B1 1 B2 1 "A U Thor" 1 C 1 D 1 E 1
+'
+
+test_expect_success 'blame -L 1 (all)' '
+	check_count -L1 A 1 B 1 B1 1 B2 1 "A U Thor" 1 C 1 D 1 E 1
+'
+
+test_expect_success 'blame -L , (all)' '
+	check_count -L, A 1 B 1 B1 1 B2 1 "A U Thor" 1 C 1 D 1 E 1
+'
+
+test_expect_success 'blame -L X (X to end)' '
+	check_count -L5 B1 1 C 1 D 1 "A U Thor" 1
+'
+
+test_expect_success 'blame -L X, (X to end)' '
+	check_count -L5, B1 1 C 1 D 1 "A U Thor" 1
+'
+
+test_expect_success 'blame -L ,Y (up to Y)' '
+	check_count -L,3 A 1 B2 1 E 1
+'
+
+test_expect_success 'blame -L X,X' '
+	check_count -L3,3 B2 1
+'
+
+test_expect_success 'blame -L X,Y' '
+	check_count -L3,6 B 1 B1 1 B2 1 D 1
+'
+
+test_expect_success 'blame -L Y,X (undocumented)' '
+	check_count -L6,3 B 1 B1 1 B2 1 D 1
+'
+
+test_expect_success 'blame -L X,+1' '
+	check_count -L3,+1 B2 1
+'
+
+test_expect_success 'blame -L X,+N' '
+	check_count -L3,+4 B 1 B1 1 B2 1 D 1
+'
+
+test_expect_success 'blame -L X,-1' '
+	check_count -L3,-1 B2 1
+'
+
+test_expect_success 'blame -L X,-N' '
+	check_count -L6,-4 B 1 B1 1 B2 1 D 1
+'
+
+test_expect_success 'blame -L /RE/ (RE to end)' '
+	check_count -L/evil/ C 1 "A U Thor" 1
+'
+
+test_expect_success 'blame -L /RE/,/RE2/' '
+	check_count -L/robot/,/green/ A 1 B 1 B2 1 D 1 E 1
+'
+
+test_expect_success 'blame -L X,/RE/' '
+	check_count -L5,/evil/ B1 1 D 1 "A U Thor" 1
+'
+
+test_expect_success 'blame -L /RE/,Y' '
+	check_count -L/99/,7 B1 1 D 1 "A U Thor" 1
+'
+
+test_expect_success 'blame -L /RE/,+N' '
+	check_count -L/99/,+3 B1 1 D 1 "A U Thor" 1
+'
+
+test_expect_success 'blame -L /RE/,-N' '
+	check_count -L/99/,-3 B 1 B2 1 D 1
+'
+
+test_expect_success 'blame -L X (X > nlines)' '
+	test_must_fail $PROG -L12345 file
+'
+
+test_expect_success 'blame -L ,Y (Y > nlines)' '
+	test_must_fail $PROG -L,12345 file
+'
+
+test_expect_success 'setup -L :regex' '
+	tr Q "\\t" >hello.c <<-\EOF &&
+	int main(int argc, const char *argv[])
+	{
+	Qputs("hello");
+	}
+	EOF
+	git add hello.c &&
+	GIT_AUTHOR_NAME="F" GIT_AUTHOR_EMAIL="F@test.git" \
+	git commit -m "hello" &&
+
+	mv hello.c hello.orig &&
+	sed -e "/}/ {x; s/$/Qputs(\"goodbye\");/; G;}" <hello.orig |
+	tr Q "\\t" >hello.c &&
+	GIT_AUTHOR_NAME="G" GIT_AUTHOR_EMAIL="G@test.git" \
+	git commit -a -m "goodbye" &&
+
+	mv hello.c hello.orig &&
+	echo "#include <stdio.h>" >hello.c &&
+	cat hello.orig >>hello.c &&
+	tr Q "\\t" >>hello.c <<-\EOF
+	void mail()
+	{
+	Qputs("mail");
+	}
+	EOF
+	GIT_AUTHOR_NAME="H" GIT_AUTHOR_EMAIL="H@test.git" \
+	git commit -a -m "mail"
+'
+
+test_expect_success 'blame -L :literal' '
+	check_count -f hello.c -L:main F 4 G 1
+'
+
+test_expect_success 'blame -L :regex' '
+	check_count -f hello.c "-L:m[a-z][a-z]l" H 4
+'
+
+test_expect_success 'blame -L :nomatch' '
+	test_must_fail $PROG -L:nomatch hello.c
+'
+
+test_expect_success 'blame -L bogus' '
+	test_must_fail $PROG -L file &&
+	test_must_fail $PROG -L1,+ file &&
+	test_must_fail $PROG -L1,- file &&
+	test_must_fail $PROG -LX file &&
+	test_must_fail $PROG -L1,X file &&
+	test_must_fail $PROG -L1,+N file &&
+	test_must_fail $PROG -L1,-N file
+'
diff --git a/t/check-non-portable-shell.pl b/t/check-non-portable-shell.pl
index 8b5a71d..45971f4 100755
--- a/t/check-non-portable-shell.pl
+++ b/t/check-non-portable-shell.pl
@@ -21,6 +21,7 @@
 	/^\s*declare\s+/ and err 'arrays/declare not portable';
 	/^\s*[^#]\s*which\s/ and err 'which is not portable (please use type)';
 	/test\s+[^=]*==/ and err '"test a == b" is not portable (please use =)';
+	/^\s*export\s+[^=]*=/ and err '"export FOO=bar" is not portable (please use FOO=bar && export FOO)';
 	# this resets our $. for each file
 	close ARGV if eof;
 }
diff --git a/t/gitweb-lib.sh b/t/gitweb-lib.sh
index ae2dc46..9e381e0 100644
--- a/t/gitweb-lib.sh
+++ b/t/gitweb-lib.sh
@@ -36,7 +36,7 @@
 
 	# You can set the GITWEB_TEST_INSTALLED environment variable to
 	# the gitwebdir (the directory where gitweb is installed / deployed to)
-	# of an existing gitweb instalation to test that installation,
+	# of an existing gitweb installation to test that installation,
 	# or simply to pathname of installed gitweb script.
 	if test -n "$GITWEB_TEST_INSTALLED" ; then
 		if test -d $GITWEB_TEST_INSTALLED; then
diff --git a/t/lib-httpd/apache.conf b/t/lib-httpd/apache.conf
index b5bce45..dd17e3a 100644
--- a/t/lib-httpd/apache.conf
+++ b/t/lib-httpd/apache.conf
@@ -1,5 +1,4 @@
 ServerName dummy
-LockFile accept.lock
 PidFile httpd.pid
 DocumentRoot www
 LogFormat "%h %l %u %t \"%r\" %>s %b" common
@@ -24,6 +23,10 @@
 	LoadModule version_module modules/mod_version.so
 </IfModule>
 
+<IfVersion < 2.4>
+LockFile accept.lock
+</IfVersion>
+
 <IfVersion < 2.1>
 <IfModule !mod_auth.c>
 	LoadModule auth_module modules/mod_auth.so
@@ -45,6 +48,21 @@
 </IfModule>
 </IfVersion>
 
+<IfVersion >= 2.4>
+<IfModule !mod_authn_core.c>
+	LoadModule authn_core_module modules/mod_authn_core.so
+</IfModule>
+<IfModule !mod_authz_core.c>
+	LoadModule authz_core_module modules/mod_authz_core.so
+</IfModule>
+<IfModule !mod_access_compat.c>
+	LoadModule access_compat_module modules/mod_access_compat.so
+</IfModule>
+<IfModule !mod_mpm_prefork.c>
+	LoadModule mpm_prefork_module modules/mod_mpm_prefork.so
+</IfModule>
+</IfVersion>
+
 PassEnv GIT_VALGRIND
 PassEnv GIT_VALGRIND_OPTIONS
 
diff --git a/t/lib-rebase.sh b/t/lib-rebase.sh
index 6ccf797..8ff87fb 100644
--- a/t/lib-rebase.sh
+++ b/t/lib-rebase.sh
@@ -17,51 +17,98 @@
 #       ("squash", "fixup", "edit", or "reword") and the SHA1 taken
 #       from the specified line.
 #
+#   "exec_cmd_with_args" -- add an "exec cmd with args" line.
+#
 #   "#" -- Add a comment line.
 #
 #   ">" -- Add a blank line.
 
 set_fake_editor () {
-	echo "#!$SHELL_PATH" >fake-editor.sh
-	cat >> fake-editor.sh <<\EOF
-case "$1" in
-*/COMMIT_EDITMSG)
-	test -z "$EXPECT_HEADER_COUNT" ||
-		test "$EXPECT_HEADER_COUNT" = "$(sed -n '1s/^# This is a combination of \(.*\) commits\./\1/p' < "$1")" ||
+	write_script fake-editor.sh <<-\EOF
+	case "$1" in
+	*/COMMIT_EDITMSG)
+		test -z "$EXPECT_HEADER_COUNT" ||
+			test "$EXPECT_HEADER_COUNT" = "$(sed -n '1s/^# This is a combination of \(.*\) commits\./\1/p' < "$1")" ||
+			exit
+		test -z "$FAKE_COMMIT_MESSAGE" || echo "$FAKE_COMMIT_MESSAGE" > "$1"
+		test -z "$FAKE_COMMIT_AMEND" || echo "$FAKE_COMMIT_AMEND" >> "$1"
 		exit
-	test -z "$FAKE_COMMIT_MESSAGE" || echo "$FAKE_COMMIT_MESSAGE" > "$1"
-	test -z "$FAKE_COMMIT_AMEND" || echo "$FAKE_COMMIT_AMEND" >> "$1"
-	exit
-	;;
-esac
-test -z "$EXPECT_COUNT" ||
-	test "$EXPECT_COUNT" = $(sed -e '/^#/d' -e '/^$/d' < "$1" | wc -l) ||
-	exit
-test -z "$FAKE_LINES" && exit
-grep -v '^#' < "$1" > "$1".tmp
-rm -f "$1"
-echo 'rebase -i script before editing:'
-cat "$1".tmp
-action=pick
-for line in $FAKE_LINES; do
-	case $line in
-	squash|fixup|edit|reword)
-		action="$line";;
-	exec*)
-		echo "$line" | sed 's/_/ /g' >> "$1";;
-	"#")
-		echo '# comment' >> "$1";;
-	">")
-		echo >> "$1";;
-	*)
-		sed -n "${line}s/^pick/$action/p" < "$1".tmp >> "$1"
-		action=pick;;
+		;;
 	esac
-done
-echo 'rebase -i script after editing:'
-cat "$1"
-EOF
+	test -z "$EXPECT_COUNT" ||
+		test "$EXPECT_COUNT" = $(sed -e '/^#/d' -e '/^$/d' < "$1" | wc -l) ||
+		exit
+	test -z "$FAKE_LINES" && exit
+	grep -v '^#' < "$1" > "$1".tmp
+	rm -f "$1"
+	echo 'rebase -i script before editing:'
+	cat "$1".tmp
+	action=pick
+	for line in $FAKE_LINES; do
+		case $line in
+		squash|fixup|edit|reword)
+			action="$line";;
+		exec*)
+			echo "$line" | sed 's/_/ /g' >> "$1";;
+		"#")
+			echo '# comment' >> "$1";;
+		">")
+			echo >> "$1";;
+		*)
+			sed -n "${line}s/^pick/$action/p" < "$1".tmp >> "$1"
+			action=pick;;
+		esac
+	done
+	echo 'rebase -i script after editing:'
+	cat "$1"
+	EOF
 
 	test_set_editor "$(pwd)/fake-editor.sh"
-	chmod a+x fake-editor.sh
+}
+
+# After set_cat_todo_editor, rebase -i will write the todo list (ignoring
+# blank lines and comments) to stdout, and exit failure (so you should run
+# it with test_must_fail).  This can be used to verify the expected user
+# experience, for todo list changes that do not affect the outcome of
+# rebase; or as an extra check in addition to checking the outcome.
+
+set_cat_todo_editor () {
+	write_script fake-editor.sh <<-\EOF
+	grep "^[^#]" "$1"
+	exit 1
+	EOF
+	test_set_editor "$(pwd)/fake-editor.sh"
+}
+
+# checks that the revisions in "$2" represent a linear range with the
+# subjects in "$1"
+test_linear_range () {
+	revlist_merges=$(git rev-list --merges "$2") &&
+	test -z "$revlist_merges" &&
+	expected=$1
+	set -- $(git log --reverse --format=%s "$2")
+	test "$expected" = "$*"
+}
+
+reset_rebase () {
+	test_might_fail git rebase --abort &&
+	git reset --hard &&
+	git clean -f
+}
+
+cherry_pick () {
+	git cherry-pick -n "$2" &&
+	git commit -m "$1" &&
+	git tag "$1"
+}
+
+revert () {
+	git revert -n "$2" &&
+	git commit -m "$1" &&
+	git tag "$1"
+}
+
+make_empty () {
+	git commit --allow-empty -m "$1" &&
+	git tag "$1"
 }
diff --git a/t/lib-t6000.sh b/t/lib-t6000.sh
index ea25dd8..3f2d873 100644
--- a/t/lib-t6000.sh
+++ b/t/lib-t6000.sh
@@ -1,55 +1,50 @@
 : included from 6002 and others
 
-[ -d .git/refs/tags ] || mkdir -p .git/refs/tags
+mkdir -p .git/refs/tags
 
-:> sed.script
+>sed.script
 
-# Answer the sha1 has associated with the tag. The tag must exist in .git or .git/refs/tags
-tag()
-{
+# Answer the sha1 has associated with the tag. The tag must exist in .git/refs/tags
+tag () {
 	_tag=$1
-	[ -f .git/refs/tags/$_tag ] || error "tag: \"$_tag\" does not exist"
-	cat .git/refs/tags/$_tag
+	test -f ".git/refs/tags/$_tag" || error "tag: \"$_tag\" does not exist"
+	cat ".git/refs/tags/$_tag"
 }
 
 # Generate a commit using the text specified to make it unique and the tree
 # named by the tag specified.
-unique_commit()
-{
+unique_commit () {
 	_text=$1
-        _tree=$2
+	_tree=$2
 	shift 2
-	echo $_text | git commit-tree $(tag $_tree) "$@"
+	echo "$_text" | git commit-tree $(tag "$_tree") "$@"
 }
 
 # Save the output of a command into the tag specified. Prepend
 # a substitution script for the tag onto the front of sed.script
-save_tag()
-{
+save_tag () {
 	_tag=$1
-	[ -n "$_tag" ] || error "usage: save_tag tag commit-args ..."
+	test -n "$_tag" || error "usage: save_tag tag commit-args ..."
 	shift 1
-	"$@" >.git/refs/tags/$_tag
+	"$@" >".git/refs/tags/$_tag"
 
-        echo "s/$(tag $_tag)/$_tag/g" > sed.script.tmp
-	cat sed.script >> sed.script.tmp
+	echo "s/$(tag $_tag)/$_tag/g" >sed.script.tmp
+	cat sed.script >>sed.script.tmp
 	rm sed.script
 	mv sed.script.tmp sed.script
 }
 
-# Replace unhelpful sha1 hashses with their symbolic equivalents
-entag()
-{
+# Replace unhelpful sha1 hashes with their symbolic equivalents
+entag () {
 	sed -f sed.script
 }
 
 # Execute a command after first saving, then setting the GIT_AUTHOR_EMAIL
 # tag to a specified value. Restore the original value on return.
-as_author()
-{
+as_author () {
 	_author=$1
 	shift 1
-        _save=$GIT_AUTHOR_EMAIL
+	_save=$GIT_AUTHOR_EMAIL
 
 	GIT_AUTHOR_EMAIL="$_author"
 	export GIT_AUTHOR_EMAIL
@@ -63,45 +58,58 @@
 	fi
 }
 
-commit_date()
-{
-        _commit=$1
-	git cat-file commit $_commit | sed -n "s/^committer .*> \([0-9]*\) .*/\1/p"
+commit_date () {
+	_commit=$1
+	git cat-file commit $_commit |
+	sed -n "s/^committer .*> \([0-9]*\) .*/\1/p"
 }
 
-on_committer_date()
-{
-    _date=$1
-    shift 1
-    GIT_COMMITTER_DATE="$_date"
-    export GIT_COMMITTER_DATE
-    "$@"
-    unset GIT_COMMITTER_DATE
+# Assign the value of fake date to a variable, but
+# allow fairly common "1971-08-16 00:00" to be omittd
+assign_fake_date () {
+	case "$2" in
+	??:??:??)	eval "$1='1971-08-16 $2'" ;;
+	??:??)		eval "$1='1971-08-16 00:$2'" ;;
+	??)		eval "$1='1971-08-16 00:00:$2'" ;;
+	*)		eval "$1='$2'" ;;
+	esac
+}
+
+on_committer_date () {
+	assign_fake_date GIT_COMMITTER_DATE "$1"
+	export GIT_COMMITTER_DATE
+	shift 1
+	"$@"
+}
+
+on_dates () {
+	assign_fake_date GIT_COMMITTER_DATE "$1"
+	assign_fake_date GIT_AUTHOR_DATE "$2"
+	export GIT_COMMITTER_DATE GIT_AUTHOR_DATE
+	shift 2
+	"$@"
 }
 
 # Execute a command and suppress any error output.
-hide_error()
-{
+hide_error () {
 	"$@" 2>/dev/null
 }
 
-check_output()
-{
+check_output () {
 	_name=$1
 	shift 1
-	if eval "$*" | entag > $_name.actual
+	if eval "$*" | entag >"$_name.actual"
 	then
-		test_cmp $_name.expected $_name.actual
+		test_cmp "$_name.expected" "$_name.actual"
 	else
-		return 1;
+		return 1
 	fi
 }
 
 # Turn a reasonable test description into a reasonable test name.
 # All alphanums translated into -'s which are then compressed and stripped
 # from front and back.
-name_from_description()
-{
+name_from_description () {
 	perl -pe '
 		s/[^A-Za-z0-9.]/-/g;
 		s/-+/-/g;
@@ -119,9 +127,11 @@
 test_output_expect_success()
 {
 	_description=$1
-        _test=$2
-        [ $# -eq 2 ] || error "usage: test_output_expect_success description test <<EOF ... EOF"
-        _name=$(echo $_description | name_from_description)
-	cat > $_name.expected
+	_test=$2
+	test $# -eq 2 ||
+	error "usage: test_output_expect_success description test <<EOF ... EOF"
+
+	_name=$(echo $_description | name_from_description)
+	cat >"$_name.expected"
 	test_expect_success "$_description" "check_output $_name \"$_test\""
 }
diff --git a/t/perf/README b/t/perf/README
index c552f56..8848c14 100644
--- a/t/perf/README
+++ b/t/perf/README
@@ -66,7 +66,7 @@
     GIT_PERF_LARGE_REPO
 	Repositories to copy for the performance tests.  The normal
 	repo should be at least git.git size.  The large repo should
-	probably be about linux-2.6.git size for optimal results.
+	probably be about linux.git size for optimal results.
 	Both default to the git.git you are running from.
 
 You can also pass the options taken by ordinary git tests; the most
diff --git a/t/perf/p0002-read-cache.sh b/t/perf/p0002-read-cache.sh
new file mode 100755
index 0000000..9180ae9
--- /dev/null
+++ b/t/perf/p0002-read-cache.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+test_description="Tests performance of reading the index"
+
+. ./perf-lib.sh
+
+test_perf_default_repo
+
+count=1000
+test_perf "read_cache/discard_cache $count times" "
+	test-read-cache $count
+"
+
+test_done
diff --git a/t/perf/p4211-line-log.sh b/t/perf/p4211-line-log.sh
new file mode 100755
index 0000000..3d074b0
--- /dev/null
+++ b/t/perf/p4211-line-log.sh
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+test_description='Tests log -L performance'
+. ./perf-lib.sh
+
+test_perf_default_repo
+
+# Pick a file to log pseudo-randomly.  The sort key is the blob hash,
+# so it is stable.
+test_expect_success 'select a file' '
+	git ls-tree HEAD | grep ^100644 |
+	sort -k 3 | head -1 | cut -f 2 >filelist
+'
+
+file=$(cat filelist)
+export file
+
+test_perf 'git rev-list --topo-order (baseline)' '
+	git rev-list --topo-order HEAD >/dev/null
+'
+
+test_perf 'git log --follow (baseline for -M)' '
+	git log --oneline --follow -- "$file" >/dev/null
+'
+
+test_perf 'git log -L' '
+	git log -L 1:"$file" >/dev/null
+'
+
+test_perf 'git log -M -L' '
+	git log -M -L 1:"$file" >/dev/null
+'
+
+test_done
diff --git a/t/perf/perf-lib.sh b/t/perf/perf-lib.sh
index a816fbc..f4eecaa 100644
--- a/t/perf/perf-lib.sh
+++ b/t/perf/perf-lib.sh
@@ -150,6 +150,7 @@
 
 
 test_perf () {
+	test_start_
 	test "$#" = 3 && { test_prereq=$1; shift; } || test_prereq=
 	test "$#" = 2 ||
 	error "bug in the test script: not 2 or 3 parameters to test-expect-success"
@@ -160,7 +161,7 @@
 		echo "$test_count" >>"$perf_results_dir"/$base.subtests
 		echo "$1" >"$perf_results_dir"/$base.$test_count.descr
 		if test -z "$verbose"; then
-			echo -n "perf $test_count - $1:"
+			printf "%s" "perf $test_count - $1:"
 		else
 			echo "perf $test_count - $1:"
 		fi
@@ -169,7 +170,7 @@
 			if test_run_perf_ "$2"
 			then
 				if test -z "$verbose"; then
-					echo -n " $i"
+					printf " %s" "$i"
 				else
 					echo "* timing run $i/$GIT_PERF_REPEAT_COUNT:"
 				fi
@@ -187,7 +188,7 @@
 		base="$perf_results_dir"/"$perf_results_prefix$(basename "$0" .sh)"."$test_count"
 		"$TEST_DIRECTORY"/perf/min_time.perl test_time.* >"$base".times
 	fi
-	echo >&3 ""
+	test_finish_
 }
 
 # We extend test_done to print timings at the end (./run disables this
diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh
index cefe33d..10be52b 100755
--- a/t/t0000-basic.sh
+++ b/t/t0000-basic.sh
@@ -47,8 +47,14 @@
 
 run_sub_test_lib_test () {
 	name="$1" descr="$2" # stdin is the body of the test code
+	shift 2
 	mkdir "$name" &&
 	(
+		# Pretend we're a test harness.  This prevents
+		# test-lib from writing the counts to a file that will
+		# later be summarized, showing spurious "failed" tests
+		HARNESS_ACTIVE=t &&
+		export HARNESS_ACTIVE &&
 		cd "$name" &&
 		cat >"$name.sh" <<-EOF &&
 		#!$SHELL_PATH
@@ -65,7 +71,7 @@
 		cat >>"$name.sh" &&
 		chmod +x "$name.sh" &&
 		export TEST_DIRECTORY &&
-		./"$name.sh" >out 2>err
+		./"$name.sh" "$@" >out 2>err
 	)
 }
 
@@ -215,6 +221,60 @@
 	EOF
 "
 
+test_expect_success 'test --verbose' '
+	test_must_fail run_sub_test_lib_test \
+		test-verbose "test verbose" --verbose <<-\EOF &&
+	test_expect_success "passing test" true
+	test_expect_success "test with output" "echo foo"
+	test_expect_success "failing test" false
+	test_done
+	EOF
+	mv test-verbose/out test-verbose/out+
+	grep -v "^Initialized empty" test-verbose/out+ >test-verbose/out &&
+	check_sub_test_lib_test test-verbose <<-\EOF
+	> expecting success: true
+	> Z
+	> ok 1 - passing test
+	> Z
+	> expecting success: echo foo
+	> foo
+	> Z
+	> ok 2 - test with output
+	> Z
+	> expecting success: false
+	> Z
+	> not ok 3 - failing test
+	> #	false
+	> Z
+	> # failed 1 among 3 test(s)
+	> 1..3
+	EOF
+'
+
+test_expect_success 'test --verbose-only' '
+	test_must_fail run_sub_test_lib_test \
+		test-verbose-only-2 "test verbose-only=2" \
+		--verbose-only=2 <<-\EOF &&
+	test_expect_success "passing test" true
+	test_expect_success "test with output" "echo foo"
+	test_expect_success "failing test" false
+	test_done
+	EOF
+	check_sub_test_lib_test test-verbose-only-2 <<-\EOF
+	> ok 1 - passing test
+	> Z
+	> expecting success: echo foo
+	> foo
+	> Z
+	> ok 2 - test with output
+	> Z
+	> not ok 3 - failing test
+	> #	false
+	> # failed 1 among 3 test(s)
+	> 1..3
+	EOF
+'
+
 test_set_prereq HAVEIT
 haveit=no
 test_expect_success HAVEIT 'test runs if prerequisite is satisfied' '
@@ -367,22 +427,6 @@
 
 # Various types of objects
 
-# Some filesystems do not support symblic links; on such systems
-# some expected values are different
-if test_have_prereq SYMLINKS
-then
-	expectfilter=cat
-	expectedtree=087704a96baf1c2d1c869a8b084481e121c88b5b
-	expectedptree1=21ae8269cacbe57ae09138dcc3a2887f904d02b3
-	expectedptree2=3c5e5399f3a333eddecce7a9b9465b63f65f51e2
-else
-	expectfilter='grep -v sym'
-	expectedtree=8e18edf7d7edcf4371a3ac6ae5f07c2641db7c46
-	expectedptree1=cfb8591b2f65de8b8cc1020cd7d9e67e7793b325
-	expectedptree2=ce580448f0148b985a513b693fdf7d802cacb44f
-fi
-
-
 test_expect_success 'adding various types of objects with git update-index --add' '
 	mkdir path2 path3 path3/subp3 &&
 	paths="path0 path2/file2 path3/file3 path3/subp3/file3" &&
@@ -390,10 +434,7 @@
 		for p in $paths
 		do
 			echo "hello $p" >$p || exit 1
-			if test_have_prereq SYMLINKS
-			then
-				ln -s "hello $p" ${p}sym || exit 1
-			fi
+			test_ln_s_add "hello $p" ${p}sym || exit 1
 		done
 	) &&
 	find path* ! -type d -print | xargs git update-index --add
@@ -405,7 +446,7 @@
 '
 
 test_expect_success 'validate git ls-files output for a known tree' '
-	$expectfilter >expected <<-\EOF &&
+	cat >expected <<-\EOF &&
 	100644 f87290f8eb2cbbea7857214459a0739927eab154 0	path0
 	120000 15a98433ae33114b085f3eb3bb03b832b3180a01 0	path0sym
 	100644 3feff949ed00a62d9f7af97c15cd8a30595e7ac7 0	path2/file2
@@ -423,14 +464,14 @@
 '
 
 test_expect_success 'validate object ID for a known tree' '
-	test "$tree" = "$expectedtree"
+	test "$tree" = 087704a96baf1c2d1c869a8b084481e121c88b5b
 '
 
 test_expect_success 'showing tree with git ls-tree' '
     git ls-tree $tree >current
 '
 
-test_expect_success SYMLINKS 'git ls-tree output for a known tree' '
+test_expect_success 'git ls-tree output for a known tree' '
 	cat >expected <<-\EOF &&
 	100644 blob f87290f8eb2cbbea7857214459a0739927eab154	path0
 	120000 blob 15a98433ae33114b085f3eb3bb03b832b3180a01	path0sym
@@ -447,7 +488,7 @@
 '
 
 test_expect_success 'git ls-tree -r output for a known tree' '
-	$expectfilter >expected <<-\EOF &&
+	cat >expected <<-\EOF &&
 	100644 blob f87290f8eb2cbbea7857214459a0739927eab154	path0
 	120000 blob 15a98433ae33114b085f3eb3bb03b832b3180a01	path0sym
 	100644 blob 3feff949ed00a62d9f7af97c15cd8a30595e7ac7	path2/file2
@@ -465,7 +506,7 @@
 	git ls-tree -r -t $tree >current
 '
 
-test_expect_success SYMLINKS 'git ls-tree -r output for a known tree' '
+test_expect_success 'git ls-tree -r output for a known tree' '
 	cat >expected <<-\EOF &&
 	100644 blob f87290f8eb2cbbea7857214459a0739927eab154	path0
 	120000 blob 15a98433ae33114b085f3eb3bb03b832b3180a01	path0sym
@@ -487,7 +528,7 @@
 '
 
 test_expect_success 'validate object ID for a known tree' '
-	test "$ptree" = "$expectedptree1"
+	test "$ptree" = 21ae8269cacbe57ae09138dcc3a2887f904d02b3
 '
 
 test_expect_success 'writing partial tree out with git write-tree --prefix' '
@@ -495,7 +536,7 @@
 '
 
 test_expect_success 'validate object ID for a known tree' '
-	test "$ptree" = "$expectedptree2"
+	test "$ptree" = 3c5e5399f3a333eddecce7a9b9465b63f65f51e2
 '
 
 test_expect_success 'put invalid objects into the index' '
@@ -529,7 +570,7 @@
 '
 
 test_expect_success 'validate git diff-files output for a know cache/work tree state' '
-	$expectfilter >expected <<\EOF &&
+	cat >expected <<\EOF &&
 :100644 100644 f87290f8eb2cbbea7857214459a0739927eab154 0000000000000000000000000000000000000000 M	path0
 :120000 120000 15a98433ae33114b085f3eb3bb03b832b3180a01 0000000000000000000000000000000000000000 M	path0sym
 :100644 100644 3feff949ed00a62d9f7af97c15cd8a30595e7ac7 0000000000000000000000000000000000000000 M	path2/file2
@@ -553,7 +594,7 @@
 '
 
 ################################################################
-P=$expectedtree
+P=087704a96baf1c2d1c869a8b084481e121c88b5b
 
 test_expect_success 'git commit-tree records the correct tree in a commit' '
 	commit0=$(echo NO | git commit-tree $P) &&
diff --git a/t/t0005-signals.sh b/t/t0005-signals.sh
index 93e58c0..981437b 100755
--- a/t/t0005-signals.sh
+++ b/t/t0005-signals.sh
@@ -20,4 +20,11 @@
 	test_cmp expect actual
 '
 
+test_expect_success !MINGW 'signals are propagated using shell convention' '
+	# we use exec here to avoid any sub-shell interpretation
+	# of the exit code
+	git config alias.sigterm "!exec test-sigchain" &&
+	test_expect_code 143 git sigterm
+'
+
 test_done
diff --git a/t/t0008-ignores.sh b/t/t0008-ignores.sh
index 9c1bde1..c29342d 100755
--- a/t/t0008-ignores.sh
+++ b/t/t0008-ignores.sh
@@ -66,16 +66,23 @@
 
 	init_vars &&
 	rm -f "$HOME/stdout" "$HOME/stderr" "$HOME/cmd" &&
-	echo git $global_args check-ignore $quiet_opt $verbose_opt $args \
+	echo git $global_args check-ignore $quiet_opt $verbose_opt $non_matching_opt $args \
 		>"$HOME/cmd" &&
+	echo "$expect_code" >"$HOME/expected-exit-code" &&
 	test_expect_code "$expect_code" \
-		git $global_args check-ignore $quiet_opt $verbose_opt $args \
+		git $global_args check-ignore $quiet_opt $verbose_opt $non_matching_opt $args \
 		>"$HOME/stdout" 2>"$HOME/stderr" &&
 	test_cmp "$HOME/expected-stdout" "$HOME/stdout" &&
 	stderr_empty_on_success "$expect_code"
 }
 
-# Runs the same code with 3 different levels of output verbosity,
+# Runs the same code with 4 different levels of output verbosity:
+#
+#   1. with -q / --quiet
+#   2. with default verbosity
+#   3. with -v / --verbose
+#   4. with -v / --verbose, *and* -n / --non-matching
+#
 # expecting success each time.  Takes advantage of the fact that
 # check-ignore --verbose output is the same as normal output except
 # for the extra first column.
@@ -83,7 +90,9 @@
 # Arguments:
 #   - (optional) prereqs for this test, e.g. 'SYMLINKS'
 #   - test name
-#   - output to expect from -v / --verbose mode
+#   - output to expect from the fourth verbosity mode (the output
+#     from the other verbosity modes is automatically inferred
+#     from this value)
 #   - code to run (should invoke test_check_ignore)
 test_expect_success_multi () {
 	prereq=
@@ -92,8 +101,9 @@
 		prereq=$1
 		shift
 	fi
-	testname="$1" expect_verbose="$2" code="$3"
+	testname="$1" expect_all="$2" code="$3"
 
+	expect_verbose=$( echo "$expect_all" | grep -v '^::	' )
 	expect=$( echo "$expect_verbose" | sed -e 's/.*	//' )
 
 	test_expect_success $prereq "$testname" '
@@ -101,23 +111,40 @@
 		eval "$code"
 	'
 
-	for quiet_opt in '-q' '--quiet'
-	do
-		test_expect_success $prereq "$testname${quiet_opt:+ with $quiet_opt}" "
+	# --quiet is only valid when a single pattern is passed
+	if test $( echo "$expect_all" | wc -l ) = 1
+	then
+		for quiet_opt in '-q' '--quiet'
+		do
+			test_expect_success $prereq "$testname${quiet_opt:+ with $quiet_opt}" "
 			expect '' &&
 			$code
 		"
-	done
-	quiet_opt=
+		done
+		quiet_opt=
+	fi
 
 	for verbose_opt in '-v' '--verbose'
 	do
-		test_expect_success $prereq "$testname${verbose_opt:+ with $verbose_opt}" "
-			expect '$expect_verbose' &&
-			$code
-		"
+		for non_matching_opt in '' ' -n' ' --non-matching'
+		do
+			if test -n "$non_matching_opt"
+			then
+				my_expect="$expect_all"
+			else
+				my_expect="$expect_verbose"
+			fi
+
+			test_code="
+				expect '$my_expect' &&
+				$code
+			"
+			opts="$verbose_opt$non_matching_opt"
+			test_expect_success $prereq "$testname${opts:+ with $opts}" "$test_code"
+		done
 	done
 	verbose_opt=
+	non_matching_opt=
 }
 
 test_expect_success 'setup' '
@@ -178,7 +205,7 @@
 #
 # test invalid inputs
 
-test_expect_success_multi '. corner-case' '' '
+test_expect_success_multi '. corner-case' '::	.' '
 	test_check_ignore . 1
 '
 
@@ -189,11 +216,7 @@
 
 test_expect_success_multi '--stdin with empty STDIN' '' '
 	test_check_ignore "--stdin" 1 </dev/null &&
-	if test -n "$quiet_opt"; then
-		test_stderr ""
-	else
-		test_stderr "no pathspec given."
-	fi
+	test_stderr ""
 '
 
 test_expect_success '-q with multiple args' '
@@ -276,27 +299,39 @@
 		where="in subdir $subdir"
 	fi
 
-	test_expect_success_multi "non-existent file $where not ignored" '' "
-		test_check_ignore '${subdir}non-existent' 1
-	"
+	test_expect_success_multi "non-existent file $where not ignored" \
+		"::	${subdir}non-existent" \
+		"test_check_ignore '${subdir}non-existent' 1"
 
 	test_expect_success_multi "non-existent file $where ignored" \
-		".gitignore:1:one	${subdir}one" "
-		test_check_ignore '${subdir}one'
-	"
+		".gitignore:1:one	${subdir}one" \
+		"test_check_ignore '${subdir}one'"
 
-	test_expect_success_multi "existing untracked file $where not ignored" '' "
-		test_check_ignore '${subdir}not-ignored' 1
-	"
+	test_expect_success_multi "existing untracked file $where not ignored" \
+		"::	${subdir}not-ignored" \
+		"test_check_ignore '${subdir}not-ignored' 1"
 
-	test_expect_success_multi "existing tracked file $where not ignored" '' "
-		test_check_ignore '${subdir}ignored-but-in-index' 1
-	"
+	test_expect_success_multi "existing tracked file $where not ignored" \
+		"::	${subdir}ignored-but-in-index" \
+		"test_check_ignore '${subdir}ignored-but-in-index' 1"
 
 	test_expect_success_multi "existing untracked file $where ignored" \
-		".gitignore:2:ignored-*	${subdir}ignored-and-untracked" "
-		test_check_ignore '${subdir}ignored-and-untracked'
-	"
+		".gitignore:2:ignored-*	${subdir}ignored-and-untracked" \
+		"test_check_ignore '${subdir}ignored-and-untracked'"
+
+	test_expect_success_multi "mix of file types $where" \
+"::	${subdir}non-existent
+.gitignore:1:one	${subdir}one
+::	${subdir}not-ignored
+::	${subdir}ignored-but-in-index
+.gitignore:2:ignored-*	${subdir}ignored-and-untracked" \
+		"test_check_ignore '
+			${subdir}non-existent
+			${subdir}one
+			${subdir}not-ignored
+			${subdir}ignored-but-in-index
+			${subdir}ignored-and-untracked'
+		"
 done
 
 # Having established the above, from now on we mostly test against
@@ -391,7 +426,7 @@
 #
 # test handling of symlinks
 
-test_expect_success_multi SYMLINKS 'symlink' '' '
+test_expect_success_multi SYMLINKS 'symlink' '::	a/symlink' '
 	test_check_ignore "a/symlink" 1
 '
 
@@ -574,37 +609,34 @@
 	globaltwo
 	b/globaltwo
 	../b/globaltwo
+	c/not-ignored
 EOF
-cat <<-\EOF >expected-default
-	../one
-	one
-	b/on
-	b/one
-	b/one one
-	b/one two
-	"b/one\"three"
-	b/two
-	b/twooo
-	../globaltwo
-	globaltwo
-	b/globaltwo
-	../b/globaltwo
-EOF
-cat <<-EOF >expected-verbose
+# N.B. we deliberately end STDIN with a non-matching pattern in order
+# to test that the exit code indicates that one or more of the
+# provided paths is ignored - in other words, that it represents an
+# aggregation of all the results, not just the final result.
+
+cat <<-EOF >expected-all
 	.gitignore:1:one	../one
+	::	../not-ignored
 	.gitignore:1:one	one
+	::	not-ignored
 	a/b/.gitignore:8:!on*	b/on
 	a/b/.gitignore:8:!on*	b/one
 	a/b/.gitignore:8:!on*	b/one one
 	a/b/.gitignore:8:!on*	b/one two
 	a/b/.gitignore:8:!on*	"b/one\"three"
 	a/b/.gitignore:9:!two	b/two
+	::	b/not-ignored
 	a/.gitignore:1:two*	b/twooo
 	$global_excludes:2:!globaltwo	../globaltwo
 	$global_excludes:2:!globaltwo	globaltwo
 	$global_excludes:2:!globaltwo	b/globaltwo
 	$global_excludes:2:!globaltwo	../b/globaltwo
+	::	c/not-ignored
 EOF
+grep -v '^::	' expected-all >expected-verbose
+sed -e 's/.*	//' expected-verbose >expected-default
 
 sed -e 's/^"//' -e 's/\\//' -e 's/"$//' stdin | \
 	tr "\n" "\0" >stdin0
@@ -629,6 +661,14 @@
 	)
 '
 
+test_expect_success '--stdin from subdirectory with -v -n' '
+	expect_from_stdin <expected-all &&
+	(
+		cd a &&
+		test_check_ignore "--stdin -v -n" <../stdin
+	)
+'
+
 for opts in '--stdin -z' '-z --stdin'
 do
 	test_expect_success "$opts from subdirectory" '
@@ -648,5 +688,31 @@
 	'
 done
 
+test_expect_success PIPE 'streaming support for --stdin' '
+	mkfifo in out &&
+	(git check-ignore -n -v --stdin <in >out &) &&
+
+	# We cannot just "echo >in" because check-ignore would get EOF
+	# after echo exited; instead we open the descriptor in our
+	# shell, and then echo to the fd. We make sure to close it at
+	# the end, so that the subprocess does get EOF and dies
+	# properly.
+	#
+	# Similarly, we must keep "out" open so that check-ignore does
+	# not ever get SIGPIPE trying to write to us. Not only would that
+	# produce incorrect results, but then there would be no writer on the
+	# other end of the pipe, and we would potentially block forever trying
+	# to open it.
+	exec 9>in &&
+	exec 8<out &&
+	test_when_finished "exec 9>&-" &&
+	test_when_finished "exec 8<&-" &&
+	echo >&9 one &&
+	read response <&8 &&
+	echo "$response" | grep "^\.gitignore:1:one	one" &&
+	echo >&9 two &&
+	read response <&8 &&
+	echo "$response" | grep "^::	two"
+'
 
 test_done
diff --git a/t/t0009-prio-queue.sh b/t/t0009-prio-queue.sh
new file mode 100755
index 0000000..94045c3
--- /dev/null
+++ b/t/t0009-prio-queue.sh
@@ -0,0 +1,50 @@
+#!/bin/sh
+
+test_description='basic tests for priority queue implementation'
+. ./test-lib.sh
+
+cat >expect <<'EOF'
+1
+2
+3
+4
+5
+5
+6
+7
+8
+9
+10
+EOF
+test_expect_success 'basic ordering' '
+	test-prio-queue 2 6 3 10 9 5 7 4 5 8 1 dump >actual &&
+	test_cmp expect actual
+'
+
+cat >expect <<'EOF'
+2
+3
+4
+1
+5
+6
+EOF
+test_expect_success 'mixed put and get' '
+	test-prio-queue 6 2 4 get 5 3 get get 1 dump >actual &&
+	test_cmp expect actual
+'
+
+cat >expect <<'EOF'
+1
+2
+NULL
+1
+2
+NULL
+EOF
+test_expect_success 'notice empty queue' '
+	test-prio-queue 1 2 get get get 1 2 get get get >actual &&
+	test_cmp expect actual
+'
+
+test_done
diff --git a/t/t0020-crlf.sh b/t/t0020-crlf.sh
index 1a8f44c..e526184 100755
--- a/t/t0020-crlf.sh
+++ b/t/t0020-crlf.sh
@@ -81,6 +81,14 @@
 	test $(git add doublewarn 2>&1 | grep "CRLF will be replaced by LF" | wc -l) = 1
 '
 
+
+test_expect_success 'safecrlf: git diff demotes safecrlf=true to warn' '
+	git config core.autocrlf input &&
+	git config core.safecrlf true &&
+	git diff HEAD
+'
+
+
 test_expect_success 'switch off autocrlf, safecrlf, reset HEAD' '
 	git config core.autocrlf false &&
 	git config core.safecrlf false &&
diff --git a/t/t0021-conversion.sh b/t/t0021-conversion.sh
index e50f0f7..b92e6cb 100755
--- a/t/t0021-conversion.sh
+++ b/t/t0021-conversion.sh
@@ -190,4 +190,18 @@
 	test_must_fail git add test.fc
 '
 
+test -n "$GIT_TEST_LONG" && test_set_prereq EXPENSIVE
+
+test_expect_success EXPENSIVE 'filter large file' '
+	git config filter.largefile.smudge cat &&
+	git config filter.largefile.clean cat &&
+	for i in $(test_seq 1 2048); do printf "%1048576d" 1; done >2GB &&
+	echo "2GB filter=largefile" >.gitattributes &&
+	git add 2GB 2>err &&
+	! test -s err &&
+	rm -f 2GB &&
+	git checkout -- 2GB 2>err &&
+	! test -s err
+'
+
 test_done
diff --git a/t/t0040-parse-options.sh b/t/t0040-parse-options.sh
index 244a43c..65606df 100755
--- a/t/t0040-parse-options.sh
+++ b/t/t0040-parse-options.sh
@@ -50,7 +50,7 @@
 
 test_expect_success 'test help' '
 	test_must_fail test-parse-options -h > output 2> output.err &&
-	test ! -s output.err &&
+	test_must_be_empty output.err &&
 	test_i18ncmp expect output
 '
 
@@ -75,7 +75,7 @@
 	shift &&
 	sed "s/^$what .*/$what $expect/" <expect.template >expect &&
 	test-parse-options $* >output 2>output.err &&
-	test ! -s output.err &&
+	test_must_be_empty output.err &&
 	test_cmp expect output
 }
 
@@ -86,7 +86,7 @@
 	shift &&
 	sed "s/^$what .*/$what $expect/" <expect.template >expect &&
 	test-parse-options $* >output 2>output.err &&
-	test ! -s output.err &&
+	test_must_be_empty output.err &&
 	test_i18ncmp expect output
 }
 
@@ -99,7 +99,7 @@
 	esac &&
 	cat expect.err >>expect &&
 	test_must_fail test-parse-options $* >output 2>output.err &&
-	test ! -s output &&
+	test_must_be_empty output &&
 	test_cmp expect output.err
 }
 
@@ -112,7 +112,7 @@
 	esac &&
 	cat expect.err >>expect &&
 	test_must_fail test-parse-options $* >output 2>output.err &&
-	test ! -s output &&
+	test_must_be_empty output &&
 	test_i18ncmp expect output.err
 }
 
@@ -149,7 +149,7 @@
 	test-parse-options -s123 -b -i 1729 -b -vv -n -F my.file \
 	> output 2> output.err &&
 	test_cmp expect output &&
-	test ! -s output.err
+	test_must_be_empty output.err
 '
 
 cat > expect << EOF
@@ -168,7 +168,7 @@
 	test-parse-options --boolean --integer 1729 --boolean --string2=321 \
 		--verbose --verbose --no-dry-run --abbrev=10 --file fi.le\
 		--obsolete > output 2> output.err &&
-	test ! -s output.err &&
+	test_must_be_empty output.err &&
 	test_cmp expect output
 '
 
@@ -199,7 +199,7 @@
 test_expect_success 'intermingled arguments' '
 	test-parse-options a1 --string 123 b1 --boolean -j 13 -- --boolean \
 		> output 2> output.err &&
-	test ! -s output.err &&
+	test_must_be_empty output.err &&
 	test_cmp expect output
 '
 
@@ -217,13 +217,13 @@
 
 test_expect_success 'unambiguously abbreviated option' '
 	test-parse-options --int 2 --boolean --no-bo > output 2> output.err &&
-	test ! -s output.err &&
+	test_must_be_empty output.err &&
 	test_cmp expect output
 '
 
 test_expect_success 'unambiguously abbreviated option with "="' '
 	test-parse-options --int=2 > output 2> output.err &&
-	test ! -s output.err &&
+	test_must_be_empty output.err &&
 	test_cmp expect output
 '
 
@@ -246,7 +246,7 @@
 
 test_expect_success 'non ambiguous option (after two options it abbreviates)' '
 	test-parse-options --st 123 > output 2> output.err &&
-	test ! -s output.err &&
+	test_must_be_empty output.err &&
 	test_cmp expect output
 '
 
@@ -256,7 +256,7 @@
 
 test_expect_success 'detect possible typos' '
 	test_must_fail test-parse-options -boolean > output 2> output.err &&
-	test ! -s output &&
+	test_must_be_empty output &&
 	test_cmp typo.err output.err
 '
 
@@ -266,7 +266,7 @@
 
 test_expect_success 'detect possible typos' '
 	test_must_fail test-parse-options -ambiguous > output 2> output.err &&
-	test ! -s output &&
+	test_must_be_empty output &&
 	test_cmp typo.err output.err
 '
 
@@ -285,7 +285,7 @@
 
 test_expect_success 'keep some options as arguments' '
 	test-parse-options --quux > output 2> output.err &&
-        test ! -s output.err &&
+	test_must_be_empty output.err &&
         test_cmp expect output
 '
 
@@ -305,7 +305,7 @@
 test_expect_success 'OPT_DATE() and OPT_SET_PTR() work' '
 	test-parse-options -t "1970-01-01 00:00:01 +0000" --default-string \
 		foo -q > output 2> output.err &&
-	test ! -s output.err &&
+	test_must_be_empty output.err &&
 	test_cmp expect output
 '
 
@@ -324,7 +324,7 @@
 
 test_expect_success 'OPT_CALLBACK() and OPT_BIT() work' '
 	test-parse-options --length=four -b -4 > output 2> output.err &&
-	test ! -s output.err &&
+	test_must_be_empty output.err &&
 	test_cmp expect output
 '
 
@@ -352,13 +352,13 @@
 
 test_expect_success 'OPT_BIT() and OPT_SET_INT() work' '
 	test-parse-options --set23 -bbbbb --no-or4 > output 2> output.err &&
-	test ! -s output.err &&
+	test_must_be_empty output.err &&
 	test_cmp expect output
 '
 
 test_expect_success 'OPT_NEGBIT() and OPT_SET_INT() work' '
 	test-parse-options --set23 -bbbbb --neg-or4 > output 2> output.err &&
-	test ! -s output.err &&
+	test_must_be_empty output.err &&
 	test_cmp expect output
 '
 
@@ -376,19 +376,19 @@
 
 test_expect_success 'OPT_BIT() works' '
 	test-parse-options -bb --or4 > output 2> output.err &&
-	test ! -s output.err &&
+	test_must_be_empty output.err &&
 	test_cmp expect output
 '
 
 test_expect_success 'OPT_NEGBIT() works' '
 	test-parse-options -bb --no-neg-or4 > output 2> output.err &&
-	test ! -s output.err &&
+	test_must_be_empty output.err &&
 	test_cmp expect output
 '
 
 test_expect_success 'OPT_COUNTUP() with PARSE_OPT_NODASH works' '
 	test-parse-options + + + + + + > output 2> output.err &&
-	test ! -s output.err &&
+	test_must_be_empty output.err &&
 	test_cmp expect output
 '
 
@@ -406,7 +406,7 @@
 
 test_expect_success 'OPT_NUMBER_CALLBACK() works' '
 	test-parse-options -12345 > output 2> output.err &&
-	test ! -s output.err &&
+	test_must_be_empty output.err &&
 	test_cmp expect output
 '
 
@@ -424,7 +424,7 @@
 
 test_expect_success 'negation of OPT_NONEG flags is not ambiguous' '
 	test-parse-options --no-ambig >output 2>output.err &&
-	test ! -s output.err &&
+	test_must_be_empty output.err &&
 	test_cmp expect output
 '
 
diff --git a/t/t0060-path-utils.sh b/t/t0060-path-utils.sh
index 09a42a4..3a48de2 100755
--- a/t/t0060-path-utils.sh
+++ b/t/t0060-path-utils.sh
@@ -8,8 +8,15 @@
 . ./test-lib.sh
 
 norm_path() {
+	expected=$(test-path-utils mingw_path "$2")
 	test_expect_success $3 "normalize path: $1 => $2" \
-	"test \"\$(test-path-utils normalize_path_copy '$1')\" = '$2'"
+	"test \"\$(test-path-utils normalize_path_copy '$1')\" = '$expected'"
+}
+
+relative_path() {
+	expected=$(test-path-utils mingw_path "$3")
+	test_expect_success $4 "relative path: $1 $2 => $3" \
+	"test \"\$(test-path-utils relative_path '$1' '$2')\" = '$expected'"
 }
 
 # On Windows, we are using MSYS's bash, which mangles the paths.
@@ -34,8 +41,8 @@
 	 test \"\$actual\" = '$expected'"
 }
 
-# Absolute path tests must be skipped on Windows because due to path mangling
-# the test program never sees a POSIX-style absolute path
+# Some absolute path tests should be skipped on Windows due to path mangling
+# on POSIX-style absolute paths
 case $(uname -s) in
 *MINGW*)
 	;;
@@ -68,30 +75,30 @@
 norm_path d1/.../d2 d1/.../d2
 norm_path d1/..././../d2 d1/d2
 
-norm_path / / POSIX
+norm_path / /
 norm_path // / POSIX
 norm_path /// / POSIX
-norm_path /. / POSIX
+norm_path /. /
 norm_path /./ / POSIX
 norm_path /./.. ++failed++ POSIX
-norm_path /../. ++failed++ POSIX
+norm_path /../. ++failed++
 norm_path /./../.// ++failed++ POSIX
 norm_path /dir/.. / POSIX
 norm_path /dir/sub/../.. / POSIX
 norm_path /dir/sub/../../.. ++failed++ POSIX
-norm_path /dir /dir POSIX
-norm_path /dir// /dir/ POSIX
-norm_path /./dir /dir POSIX
-norm_path /dir/. /dir/ POSIX
-norm_path /dir///./ /dir/ POSIX
-norm_path /dir//sub/.. /dir/ POSIX
-norm_path /dir/sub/../ /dir/ POSIX
+norm_path /dir /dir
+norm_path /dir// /dir/
+norm_path /./dir /dir
+norm_path /dir/. /dir/
+norm_path /dir///./ /dir/
+norm_path /dir//sub/.. /dir/
+norm_path /dir/sub/../ /dir/
 norm_path //dir/sub/../. /dir/ POSIX
-norm_path /dir/s1/../s2/ /dir/s2/ POSIX
-norm_path /d1/s1///s2/..//../s3/ /d1/s3/ POSIX
-norm_path /d1/s1//../s2/../../d2 /d2 POSIX
-norm_path /d1/.../d2 /d1/.../d2 POSIX
-norm_path /d1/..././../d2 /d1/d2 POSIX
+norm_path /dir/s1/../s2/ /dir/s2/
+norm_path /d1/s1///s2/..//../s3/ /d1/s3/
+norm_path /d1/s1//../s2/../../d2 /d2
+norm_path /d1/.../d2 /d1/.../d2
+norm_path /d1/..././../d2 /d1/d2
 
 ancestor / / -1
 ancestor /foo / 0
@@ -183,4 +190,33 @@
 	test "$sym" = "$(test-path-utils real_path "$dir2/syml")"
 '
 
+relative_path /a/b/c/	/a/b/		c/
+relative_path /a/b/c/	/a/b		c/
+relative_path /a//b//c/	//a/b//		c/	POSIX
+relative_path /a/b	/a/b		./
+relative_path /a/b/	/a/b		./
+relative_path /a	/a/b		../
+relative_path /		/a/b/		../../
+relative_path /a/c	/a/b/		../c
+relative_path /a/c	/a/b		../c
+relative_path /x/y	/a/b/		../../x/y
+relative_path /a/b	"<empty>"	/a/b
+relative_path /a/b 	"<null>"	/a/b
+relative_path a/b/c/	a/b/		c/
+relative_path a/b/c/	a/b		c/
+relative_path a/b//c	a//b		c
+relative_path a/b/	a/b/		./
+relative_path a/b/	a/b		./
+relative_path a		a/b		../
+relative_path x/y	a/b		../../x/y
+relative_path a/c	a/b		../c
+relative_path a/b	"<empty>"	a/b
+relative_path a/b 	"<null>"	a/b
+relative_path "<empty>"	/a/b		./
+relative_path "<empty>"	"<empty>"	./
+relative_path "<empty>"	"<null>"	./
+relative_path "<null>"	"<empty>"	./
+relative_path "<null>"	"<null>"	./
+relative_path "<null>"	/a/b		./
+
 test_done
diff --git a/t/t0070-fundamental.sh b/t/t0070-fundamental.sh
index da2c504..986b2a8 100755
--- a/t/t0070-fundamental.sh
+++ b/t/t0070-fundamental.sh
@@ -17,7 +17,7 @@
 	grep "doesnotexist/test" err
 '
 
-test_expect_success POSIXPERM 'mktemp to unwritable directory prints filename' '
+test_expect_success POSIXPERM,SANITY 'mktemp to unwritable directory prints filename' '
 	mkdir cannotwrite &&
 	chmod -w cannotwrite &&
 	test_when_finished "chmod +w cannotwrite" &&
diff --git a/t/t0100-previous.sh b/t/t0100-previous.sh
index 315b9b3..e0a6940 100755
--- a/t/t0100-previous.sh
+++ b/t/t0100-previous.sh
@@ -27,6 +27,7 @@
 	test_commit B &&
 	git checkout A &&
 	test_commit C &&
+	test_commit D &&
 	git branch -f master B &&
 	git branch -f other &&
 	git checkout other &&
@@ -35,14 +36,24 @@
 	git cat-file commit HEAD | grep "Merge branch '\''other'\''"
 '
 
-test_expect_success 'merge @{-1} when there is not enough switches yet' '
+test_expect_success 'merge @{-1}~1' '
+	git checkout master &&
+	git reset --hard B &&
+	git checkout other &&
+	git checkout master &&
+	git merge @{-1}~1 &&
+	git cat-file commit HEAD >actual &&
+	grep "Merge branch '\''other'\''" actual
+'
+
+test_expect_success 'merge @{-100} before checking out that many branches yet' '
 	git reflog expire --expire=now &&
 	git checkout -f master &&
 	git reset --hard B &&
 	git branch -f other C &&
 	git checkout other &&
 	git checkout master &&
-	test_must_fail git merge @{-12}
+	test_must_fail git merge @{-100}
 '
 
 test_done
diff --git a/t/t1004-read-tree-m-u-wf.sh b/t/t1004-read-tree-m-u-wf.sh
index b3ae7d5..3e72aff 100755
--- a/t/t1004-read-tree-m-u-wf.sh
+++ b/t/t1004-read-tree-m-u-wf.sh
@@ -158,7 +158,7 @@
 
 '
 
-test_expect_success SYMLINKS 'funny symlink in work tree' '
+test_expect_success 'funny symlink in work tree' '
 
 	git reset --hard &&
 	git checkout -b sym-b side-b &&
@@ -170,15 +170,14 @@
 	rm -fr a &&
 	git checkout -b sym-a side-a &&
 	mkdir -p a &&
-	ln -s ../b a/b &&
-	git add a/b &&
+	test_ln_s_add ../b a/b &&
 	git commit -m "we add a/b" &&
 
 	read_tree_u_must_succeed -m -u sym-a sym-a sym-b
 
 '
 
-test_expect_success SYMLINKS,SANITY 'funny symlink in work tree, un-unlink-able' '
+test_expect_success SANITY 'funny symlink in work tree, un-unlink-able' '
 
 	rm -fr a b &&
 	git reset --hard &&
diff --git a/t/t1006-cat-file.sh b/t/t1006-cat-file.sh
index 9cc5c6b..4e911fb 100755
--- a/t/t1006-cat-file.sh
+++ b/t/t1006-cat-file.sh
@@ -36,66 +36,47 @@
     '
 
     test_expect_success "Type of $type is correct" '
-        test $type = "$(git cat-file -t $sha1)"
+	echo $type >expect &&
+	git cat-file -t $sha1 >actual &&
+	test_cmp expect actual
     '
 
     test_expect_success "Size of $type is correct" '
-        test $size = "$(git cat-file -s $sha1)"
+	echo $size >expect &&
+	git cat-file -s $sha1 >actual &&
+	test_cmp expect actual
     '
 
     test -z "$content" ||
     test_expect_success "Content of $type is correct" '
-	expect="$(maybe_remove_timestamp "$content" $no_ts)"
-	actual="$(maybe_remove_timestamp "$(git cat-file $type $sha1)" $no_ts)"
-
-        if test "z$expect" = "z$actual"
-	then
-		: happy
-	else
-		echo "Oops: expected $expect"
-		echo "but got $actual"
-		false
-        fi
+	maybe_remove_timestamp "$content" $no_ts >expect &&
+	maybe_remove_timestamp "$(git cat-file $type $sha1)" $no_ts >actual &&
+	test_cmp expect actual
     '
 
     test_expect_success "Pretty content of $type is correct" '
-	expect="$(maybe_remove_timestamp "$pretty_content" $no_ts)"
-	actual="$(maybe_remove_timestamp "$(git cat-file -p $sha1)" $no_ts)"
-        if test "z$expect" = "z$actual"
-	then
-		: happy
-	else
-		echo "Oops: expected $expect"
-		echo "but got $actual"
-		false
-        fi
+	maybe_remove_timestamp "$pretty_content" $no_ts >expect &&
+	maybe_remove_timestamp "$(git cat-file -p $sha1)" $no_ts >actual &&
+	test_cmp expect actual
     '
 
     test -z "$content" ||
     test_expect_success "--batch output of $type is correct" '
-	expect="$(maybe_remove_timestamp "$batch_output" $no_ts)"
-	actual="$(maybe_remove_timestamp "$(echo $sha1 | git cat-file --batch)" $no_ts)"
-        if test "z$expect" = "z$actual"
-	then
-		: happy
-	else
-		echo "Oops: expected $expect"
-		echo "but got $actual"
-		false
-        fi
+	maybe_remove_timestamp "$batch_output" $no_ts >expect &&
+	maybe_remove_timestamp "$(echo $sha1 | git cat-file --batch)" $no_ts >actual &&
+	test_cmp expect actual
     '
 
     test_expect_success "--batch-check output of $type is correct" '
-	expect="$sha1 $type $size"
-	actual="$(echo_without_newline $sha1 | git cat-file --batch-check)"
-        if test "z$expect" = "z$actual"
-	then
-		: happy
-	else
-		echo "Oops: expected $expect"
-		echo "but got $actual"
-		false
-        fi
+	echo "$sha1 $type $size" >expect &&
+	echo_without_newline $sha1 | git cat-file --batch-check >actual &&
+	test_cmp expect actual
+    '
+
+    test_expect_success "custom --batch-check format" '
+	echo "$type $sha1" >expect &&
+	echo $sha1 | git cat-file --batch-check="%(objecttype) %(objectname)" >actual &&
+	test_cmp expect actual
     '
 }
 
diff --git a/t/t1307-config-blob.sh b/t/t1307-config-blob.sh
new file mode 100755
index 0000000..fdc257e
--- /dev/null
+++ b/t/t1307-config-blob.sh
@@ -0,0 +1,70 @@
+#!/bin/sh
+
+test_description='support for reading config from a blob'
+. ./test-lib.sh
+
+test_expect_success 'create config blob' '
+	cat >config <<-\EOF &&
+	[some]
+		value = 1
+	EOF
+	git add config &&
+	git commit -m foo
+'
+
+test_expect_success 'list config blob contents' '
+	echo some.value=1 >expect &&
+	git config --blob=HEAD:config --list >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'fetch value from blob' '
+	echo true >expect &&
+	git config --blob=HEAD:config --bool some.value >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'reading non-existing value from blob is an error' '
+	test_must_fail git config --blob=HEAD:config non.existing
+'
+
+test_expect_success 'reading from blob and file is an error' '
+	test_must_fail git config --blob=HEAD:config --system --list
+'
+
+test_expect_success 'reading from missing ref is an error' '
+	test_must_fail git config --blob=HEAD:doesnotexist --list
+'
+
+test_expect_success 'reading from non-blob is an error' '
+	test_must_fail git config --blob=HEAD --list
+'
+
+test_expect_success 'setting a value in a blob is an error' '
+	test_must_fail git config --blob=HEAD:config some.value foo
+'
+
+test_expect_success 'deleting a value in a blob is an error' '
+	test_must_fail git config --blob=HEAD:config --unset some.value
+'
+
+test_expect_success 'editing a blob is an error' '
+	test_must_fail git config --blob=HEAD:config --edit
+'
+
+test_expect_success 'parse errors in blobs are properly attributed' '
+	cat >config <<-\EOF &&
+	[some]
+		value = "
+	EOF
+	git add config &&
+	git commit -m broken &&
+
+	test_must_fail git config --blob=HEAD:config some.value 2>err &&
+
+	# just grep for our token as the exact error message is likely to
+	# change or be internationalized
+	grep "HEAD:config" err
+'
+
+test_done
diff --git a/t/t1403-show-ref.sh b/t/t1403-show-ref.sh
new file mode 100755
index 0000000..3e500ed
--- /dev/null
+++ b/t/t1403-show-ref.sh
@@ -0,0 +1,167 @@
+#!/bin/sh
+
+test_description='show-ref'
+. ./test-lib.sh
+
+test_expect_success setup '
+	test_commit A &&
+	git tag -f -a -m "annotated A" A &&
+	git checkout -b side &&
+	test_commit B &&
+	git tag -f -a -m "annotated B" B &&
+	git checkout master &&
+	test_commit C &&
+	git branch B A^0
+'
+
+test_expect_success 'show-ref' '
+	echo $(git rev-parse refs/tags/A) refs/tags/A >expect &&
+
+	git show-ref A >actual &&
+	test_cmp expect actual &&
+
+	git show-ref tags/A >actual &&
+	test_cmp expect actual &&
+
+	git show-ref refs/tags/A >actual &&
+	test_cmp expect actual &&
+
+	>expect &&
+
+	test_must_fail git show-ref D >actual
+	test_cmp expect actual
+'
+
+test_expect_success 'show-ref -q' '
+	>expect &&
+
+	git show-ref -q A >actual &&
+	test_cmp expect actual &&
+
+	git show-ref -q tags/A >actual &&
+	test_cmp expect actual &&
+
+	git show-ref -q refs/tags/A >actual &&
+	test_cmp expect actual &&
+
+	test_must_fail git show-ref -q D >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'show-ref --verify' '
+	echo $(git rev-parse refs/tags/A) refs/tags/A >expect &&
+
+	git show-ref --verify refs/tags/A >actual &&
+	test_cmp expect actual &&
+
+	>expect &&
+
+	test_must_fail git show-ref --verify A >actual &&
+	test_cmp expect actual &&
+
+	test_must_fail git show-ref --verify tags/A >actual &&
+	test_cmp expect actual &&
+
+	test_must_fail git show-ref --verify D >actual
+	test_cmp expect actual
+'
+
+test_expect_success 'show-ref --verify -q' '
+	>expect &&
+
+	git show-ref --verify -q refs/tags/A >actual &&
+	test_cmp expect actual &&
+
+	test_must_fail git show-ref --verify -q A >actual &&
+	test_cmp expect actual &&
+
+	test_must_fail git show-ref --verify -q tags/A >actual &&
+	test_cmp expect actual &&
+
+	test_must_fail git show-ref --verify -q D >actual
+	test_cmp expect actual
+'
+
+test_expect_success 'show-ref -d' '
+	{
+		echo $(git rev-parse refs/tags/A) refs/tags/A &&
+		echo $(git rev-parse refs/tags/A^0) "refs/tags/A^{}"
+		echo $(git rev-parse refs/tags/C) refs/tags/C
+	} >expect &&
+	git show-ref -d A C >actual &&
+	test_cmp expect actual &&
+
+	git show-ref -d tags/A tags/C >actual &&
+	test_cmp expect actual &&
+
+	git show-ref -d refs/tags/A refs/tags/C >actual &&
+	test_cmp expect actual &&
+
+	echo $(git rev-parse refs/heads/master) refs/heads/master >expect &&
+	git show-ref -d master >actual &&
+	test_cmp expect actual &&
+
+	git show-ref -d heads/master >actual &&
+	test_cmp expect actual &&
+
+	git show-ref -d refs/heads/master >actual &&
+	test_cmp expect actual
+
+	git show-ref -d --verify refs/heads/master >actual &&
+	test_cmp expect actual
+
+	>expect &&
+
+	test_must_fail git show-ref -d --verify master >actual &&
+	test_cmp expect actual &&
+
+	test_must_fail git show-ref -d --verify heads/master >actual &&
+	test_cmp expect actual
+
+'
+
+test_expect_success 'show-ref --heads, --tags, --head, pattern' '
+	for branch in B master side
+	do
+		echo $(git rev-parse refs/heads/$branch) refs/heads/$branch
+	done >expect.heads &&
+	git show-ref --heads >actual &&
+	test_cmp expect.heads actual &&
+
+	for tag in A B C
+	do
+		echo $(git rev-parse refs/tags/$tag) refs/tags/$tag
+	done >expect.tags &&
+	git show-ref --tags >actual &&
+	test_cmp expect.tags actual &&
+
+	cat expect.heads expect.tags >expect &&
+	git show-ref --heads --tags >actual &&
+	test_cmp expect actual &&
+
+	{
+		echo $(git rev-parse HEAD) HEAD &&
+		cat expect.heads expect.tags
+	} >expect &&
+	git show-ref --heads --tags --head >actual &&
+	test_cmp expect actual &&
+
+	{
+		echo $(git rev-parse HEAD) HEAD &&
+		echo $(git rev-parse refs/heads/B) refs/heads/B
+		echo $(git rev-parse refs/tags/B) refs/tags/B
+	} >expect &&
+	git show-ref --head B >actual &&
+	test_cmp expect actual &&
+
+	{
+		echo $(git rev-parse HEAD) HEAD &&
+		echo $(git rev-parse refs/heads/B) refs/heads/B
+		echo $(git rev-parse refs/tags/B) refs/tags/B
+		echo $(git rev-parse refs/tags/B^0) "refs/tags/B^{}"
+	} >expect &&
+	git show-ref --head -d B >actual &&
+	test_cmp expect actual
+'
+
+test_done
diff --git a/t/t1411-reflog-show.sh b/t/t1411-reflog-show.sh
index 9a105fe..6f47c0d 100755
--- a/t/t1411-reflog-show.sh
+++ b/t/t1411-reflog-show.sh
@@ -144,4 +144,26 @@
 	test_cmp expect actual
 '
 
+# This guards against the alternative of showing the diffs vs. the
+# reflog ancestor.  The reflog used is designed to list the commits
+# more than once, so as to exercise the corresponding logic.
+test_expect_success 'git log -g -p shows diffs vs. parents' '
+	test_commit two &&
+	git branch flipflop &&
+	git update-ref refs/heads/flipflop -m flip1 HEAD^ &&
+	git update-ref refs/heads/flipflop -m flop1 HEAD &&
+	git update-ref refs/heads/flipflop -m flip2 HEAD^ &&
+	git log -g -p flipflop >reflog &&
+	grep -v ^Reflog reflog >actual &&
+	git log -1 -p HEAD^ >log.one &&
+	git log -1 -p HEAD >log.two &&
+	(
+		cat log.one; echo
+		cat log.two; echo
+		cat log.one; echo
+		cat log.two
+	) >expect &&
+	test_cmp expect actual
+'
+
 test_done
diff --git a/t/t1507-rev-parse-upstream.sh b/t/t1507-rev-parse-upstream.sh
index b27a720..2a19e79 100755
--- a/t/t1507-rev-parse-upstream.sh
+++ b/t/t1507-rev-parse-upstream.sh
@@ -129,8 +129,7 @@
 
 test_expect_success 'branch@{u} error message when no upstream' '
 	cat >expect <<-EOF &&
-	error: No upstream configured for branch ${sq}non-tracking${sq}
-	fatal: Needed a single revision
+	fatal: No upstream configured for branch ${sq}non-tracking${sq}
 	EOF
 	error_message non-tracking@{u} 2>actual &&
 	test_i18ncmp expect actual
@@ -138,8 +137,7 @@
 
 test_expect_success '@{u} error message when no upstream' '
 	cat >expect <<-EOF &&
-	error: No upstream configured for branch ${sq}master${sq}
-	fatal: Needed a single revision
+	fatal: No upstream configured for branch ${sq}master${sq}
 	EOF
 	test_must_fail git rev-parse --verify @{u} 2>actual &&
 	test_i18ncmp expect actual
@@ -147,8 +145,7 @@
 
 test_expect_success 'branch@{u} error message with misspelt branch' '
 	cat >expect <<-EOF &&
-	error: No such branch: ${sq}no-such-branch${sq}
-	fatal: Needed a single revision
+	fatal: No such branch: ${sq}no-such-branch${sq}
 	EOF
 	error_message no-such-branch@{u} 2>actual &&
 	test_i18ncmp expect actual
@@ -156,8 +153,7 @@
 
 test_expect_success '@{u} error message when not on a branch' '
 	cat >expect <<-EOF &&
-	error: HEAD does not point to a branch
-	fatal: Needed a single revision
+	fatal: HEAD does not point to a branch
 	EOF
 	git checkout HEAD^0 &&
 	test_must_fail git rev-parse --verify @{u} 2>actual &&
@@ -166,8 +162,7 @@
 
 test_expect_success 'branch@{u} error message if upstream branch not fetched' '
 	cat >expect <<-EOF &&
-	error: Upstream branch ${sq}refs/heads/side${sq} not stored as a remote-tracking branch
-	fatal: Needed a single revision
+	fatal: Upstream branch ${sq}refs/heads/side${sq} not stored as a remote-tracking branch
 	EOF
 	error_message bad-upstream@{u} 2>actual &&
 	test_i18ncmp expect actual
diff --git a/t/t1508-at-combinations.sh b/t/t1508-at-combinations.sh
index d5d6244..e5aea3b 100755
--- a/t/t1508-at-combinations.sh
+++ b/t/t1508-at-combinations.sh
@@ -4,17 +4,24 @@
 . ./test-lib.sh
 
 check() {
-test_expect_${3:-success} "$1 = $2" "
-	echo '$2' >expect &&
-	git log -1 --format=%s '$1' >actual &&
-	test_cmp expect actual
-"
+	test_expect_${4:-success} "$1 = $3" "
+		echo '$3' >expect &&
+		if test '$2' = 'commit'
+		then
+			git log -1 --format=%s '$1' >actual
+		else
+			git rev-parse --symbolic-full-name '$1' >actual
+		fi &&
+		test_cmp expect actual
+	"
 }
+
 nonsense() {
-test_expect_${2:-success} "$1 is nonsensical" "
-	test_must_fail git log -1 '$1'
-"
+	test_expect_${2:-success} "$1 is nonsensical" "
+		test_must_fail git rev-parse --verify '$1'
+	"
 }
+
 fail() {
 	"$@" failure
 }
@@ -31,21 +38,40 @@
 	git checkout -b new-branch &&
 	test_commit new-one &&
 	test_commit new-two &&
-	git config branch.old-branch.remote . &&
-	git config branch.old-branch.merge refs/heads/master &&
-	git config branch.new-branch.remote . &&
-	git config branch.new-branch.merge refs/heads/upstream-branch
+	git branch -u master old-branch &&
+	git branch -u upstream-branch new-branch
 '
 
-check HEAD new-two
-check "@{1}" new-one
-check "@{-1}" old-two
-check "@{-1}@{1}" old-one
-check "@{u}" upstream-two
-check "@{u}@{1}" upstream-one
-check "@{-1}@{u}" master-two
-check "@{-1}@{u}@{1}" master-one
+check HEAD ref refs/heads/new-branch
+check "@{1}" commit new-one
+check "HEAD@{1}" commit new-one
+check "@{now}" commit new-two
+check "HEAD@{now}" commit new-two
+check "@{-1}" ref refs/heads/old-branch
+check "@{-1}@{0}" commit old-two
+check "@{-1}@{1}" commit old-one
+check "@{u}" ref refs/heads/upstream-branch
+check "HEAD@{u}" ref refs/heads/upstream-branch
+check "@{u}@{1}" commit upstream-one
+check "@{-1}@{u}" ref refs/heads/master
+check "@{-1}@{u}@{1}" commit master-one
 nonsense "@{u}@{-1}"
+nonsense "@{0}@{0}"
 nonsense "@{1}@{u}"
+nonsense "HEAD@{-1}"
+nonsense "@{-1}@{-1}"
+
+# @{N} versus HEAD@{N}
+
+check "HEAD@{3}" commit old-two
+nonsense "@{3}"
+
+test_expect_success 'switch to old-branch' '
+	git checkout old-branch
+'
+
+check HEAD ref refs/heads/old-branch
+check "HEAD@{1}" commit new-two
+check "@{1}" commit old-one
 
 test_done
diff --git a/t/t1512-rev-parse-disambiguation.sh b/t/t1512-rev-parse-disambiguation.sh
index 6b3d797..4a155c8 100755
--- a/t/t1512-rev-parse-disambiguation.sh
+++ b/t/t1512-rev-parse-disambiguation.sh
@@ -77,6 +77,7 @@
 
 test_expect_success 'disambiguate tree' '
 	commit=$(echo "d7xm" | git commit-tree 000000000) &&
+	# this commit is fffff2e and not ambiguous with the 00000* objects
 	test $(git rev-parse $commit^{tree}) = $(git rev-parse 0000000000cdc)
 '
 
@@ -99,10 +100,14 @@
 
 test_expect_success 'disambiguate commit' '
 	commit=$(echo "hoaxj" | git commit-tree 0000000000cdc -p 000000000) &&
+	# this commit is ffffffd8 and not ambiguous with the 00000* objects
 	test $(git rev-parse $commit^) = $(git rev-parse 0000000000e4f)
 '
 
 test_expect_success 'log name1..name2 takes only commit-ishes on both ends' '
+	# These are underspecified from the prefix-length point of view
+	# to disambiguate the commit with other objects, but there is only
+	# one commit that has 00000* prefix at this point.
 	git log 000000000..000000000 &&
 	git log ..000000000 &&
 	git log 000000000.. &&
@@ -112,16 +117,19 @@
 '
 
 test_expect_success 'rev-parse name1..name2 takes only commit-ishes on both ends' '
+	# Likewise.
 	git rev-parse 000000000..000000000 &&
 	git rev-parse ..000000000 &&
 	git rev-parse 000000000..
 '
 
 test_expect_success 'git log takes only commit-ish' '
+	# Likewise.
 	git log 000000000
 '
 
 test_expect_success 'git reset takes only commit-ish' '
+	# Likewise.
 	git reset 000000000
 '
 
@@ -131,26 +139,30 @@
 '
 
 test_expect_failure 'two semi-ambiguous commit-ish' '
+	# At this point, we have a tag 0000000000f8f that points
+	# at a commit 0000000000e4f, and a tree and a blob that
+	# share 0000000000 prefix with these tag and commit.
+	#
 	# Once the parser becomes ultra-smart, it could notice that
-	# 110282 before ^{commit} name many different objects, but
+	# 0000000000 before ^{commit} name many different objects, but
 	# that only two (HEAD and v1.0.0 tag) can be peeled to commit,
 	# and that peeling them down to commit yield the same commit
 	# without ambiguity.
-	git rev-parse --verify 110282^{commit} &&
+	git rev-parse --verify 0000000000^{commit} &&
 
 	# likewise
-	git log 000000000..000000000 &&
-	git log ..000000000 &&
-	git log 000000000.. &&
-	git log 000000000...000000000 &&
-	git log ...000000000 &&
-	git log 000000000...
+	git log 0000000000..0000000000 &&
+	git log ..0000000000 &&
+	git log 0000000000.. &&
+	git log 0000000000...0000000000 &&
+	git log ...0000000000 &&
+	git log 0000000000...
 '
 
 test_expect_failure 'three semi-ambiguous tree-ish' '
 	# Likewise for tree-ish.  HEAD, v1.0.0 and HEAD^{tree} share
 	# the prefix but peeling them to tree yields the same thing
-	git rev-parse --verify 000000000^{tree}
+	git rev-parse --verify 0000000000^{tree}
 '
 
 test_expect_success 'parse describe name' '
@@ -241,7 +253,7 @@
 	# Now there are many commits that begin with the
 	# common prefix, none of these should pick one at
 	# random.  They all should result in ambiguity errors.
-	test_must_fail git rev-parse --verify 110282^{commit} &&
+	test_must_fail git rev-parse --verify 00000000^{commit} &&
 
 	# likewise
 	test_must_fail git log 000000000..000000000 &&
@@ -261,4 +273,22 @@
 	test "$(sed -e "s/^\(.........\).*/\1/" actual | sort -u)" = 000000000
 '
 
+test_expect_success 'ambiguous 40-hex ref' '
+	TREE=$(git mktree </dev/null) &&
+	REF=`git rev-parse HEAD` &&
+	VAL=$(git commit-tree $TREE </dev/null) &&
+	git update-ref refs/heads/$REF $VAL &&
+	test `git rev-parse $REF 2>err` = $REF &&
+	grep "refname.*${REF}.*ambiguous" err
+'
+
+test_expect_success 'ambiguous short sha1 ref' '
+	TREE=$(git mktree </dev/null) &&
+	REF=`git rev-parse --short HEAD` &&
+	VAL=$(git commit-tree $TREE </dev/null) &&
+	git update-ref refs/heads/$REF $VAL &&
+	test `git rev-parse $REF 2>err` = $VAL &&
+	grep "refname.*${REF}.*ambiguous" err
+'
+
 test_done
diff --git a/t/t1513-rev-parse-prefix.sh b/t/t1513-rev-parse-prefix.sh
new file mode 100755
index 0000000..87ec3ae
--- /dev/null
+++ b/t/t1513-rev-parse-prefix.sh
@@ -0,0 +1,96 @@
+#!/bin/sh
+
+test_description='Tests for rev-parse --prefix'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+	mkdir -p sub1/sub2 &&
+	echo top >top &&
+	echo file1 >sub1/file1 &&
+	echo file2 >sub1/sub2/file2 &&
+	git add top sub1/file1 sub1/sub2/file2 &&
+	git commit -m commit
+'
+
+test_expect_success 'empty prefix -- file' '
+	git rev-parse --prefix "" -- top sub1/file1 >actual &&
+	cat <<-\EOF >expected &&
+	--
+	top
+	sub1/file1
+	EOF
+	test_cmp expected actual
+'
+
+test_expect_success 'valid prefix -- file' '
+	git rev-parse --prefix sub1/ -- file1 sub2/file2 >actual &&
+	cat <<-\EOF >expected &&
+	--
+	sub1/file1
+	sub1/sub2/file2
+	EOF
+	test_cmp expected actual
+'
+
+test_expect_success 'valid prefix -- ../file' '
+	git rev-parse --prefix sub1/ -- ../top sub2/file2 >actual &&
+	cat <<-\EOF >expected &&
+	--
+	sub1/../top
+	sub1/sub2/file2
+	EOF
+	test_cmp expected actual
+'
+
+test_expect_success 'empty prefix HEAD:./path' '
+	git rev-parse --prefix "" HEAD:./top >actual &&
+	git rev-parse HEAD:top >expected &&
+	test_cmp expected actual
+'
+
+test_expect_success 'valid prefix HEAD:./path' '
+	git rev-parse --prefix sub1/ HEAD:./file1 >actual &&
+	git rev-parse HEAD:sub1/file1 >expected &&
+	test_cmp expected actual
+'
+
+test_expect_success 'valid prefix HEAD:../path' '
+	git rev-parse --prefix sub1/ HEAD:../top >actual &&
+	git rev-parse HEAD:top >expected &&
+	test_cmp expected actual
+'
+
+test_expect_success 'prefix ignored with HEAD:top' '
+	git rev-parse --prefix sub1/ HEAD:top >actual &&
+	git rev-parse HEAD:top >expected &&
+	test_cmp expected actual
+'
+
+test_expect_success 'disambiguate path with valid prefix' '
+	git rev-parse --prefix sub1/ file1 >actual &&
+	cat <<-\EOF >expected &&
+	sub1/file1
+	EOF
+	test_cmp expected actual
+'
+
+test_expect_success 'file and refs with prefix' '
+	git rev-parse --prefix sub1/ master file1 >actual &&
+	cat <<-EOF >expected &&
+	$(git rev-parse master)
+	sub1/file1
+	EOF
+	test_cmp expected actual
+'
+
+test_expect_success 'two-levels deep' '
+	git rev-parse --prefix sub1/sub2/ -- file2 >actual &&
+	cat <<-\EOF >expected &&
+	--
+	sub1/sub2/file2
+	EOF
+	test_cmp expected actual
+'
+
+test_done
diff --git a/t/t2001-checkout-cache-clash.sh b/t/t2001-checkout-cache-clash.sh
index 98aa73e..1fc8e63 100755
--- a/t/t2001-checkout-cache-clash.sh
+++ b/t/t2001-checkout-cache-clash.sh
@@ -59,10 +59,9 @@
     'git read-tree -m $tree1 && git checkout-index -f -a'
 test_debug 'show_files $tree1'
 
-test_expect_success SYMLINKS \
-    'git update-index --add a symlink.' \
-    'ln -s path0 path1 &&
-     git update-index --add path1'
+test_expect_success \
+    'add a symlink' \
+    'test_ln_s_add path0 path1'
 test_expect_success \
     'writing tree out with git write-tree' \
     'tree3=$(git write-tree)'
diff --git a/t/t2004-checkout-cache-temp.sh b/t/t2004-checkout-cache-temp.sh
index 0f4b289..f171a55 100755
--- a/t/t2004-checkout-cache-temp.sh
+++ b/t/t2004-checkout-cache-temp.sh
@@ -194,11 +194,10 @@
  test $(cat ../$s1) = tree1asubdir/path5)
 )'
 
-test_expect_success SYMLINKS \
+test_expect_success \
 'checkout --temp symlink' '
 rm -f path* .merge_* out .git/index &&
-ln -s b a &&
-git update-index --add a &&
+test_ln_s_add b a &&
 t4=$(git write-tree) &&
 rm -f .git/index &&
 git read-tree $t4 &&
diff --git a/t/t2007-checkout-symlink.sh b/t/t2007-checkout-symlink.sh
index e6f59f1..fc9aad5 100755
--- a/t/t2007-checkout-symlink.sh
+++ b/t/t2007-checkout-symlink.sh
@@ -6,7 +6,7 @@
 
 . ./test-lib.sh
 
-test_expect_success SYMLINKS setup '
+test_expect_success setup '
 
 	mkdir frotz &&
 	echo hello >frotz/filfre &&
@@ -25,25 +25,25 @@
 
 	git rm --cached frotz/filfre &&
 	mv frotz xyzzy &&
-	ln -s xyzzy frotz &&
-	git add xyzzy/filfre frotz &&
+	test_ln_s_add xyzzy frotz &&
+	git add xyzzy/filfre &&
 	test_tick &&
 	git commit -m "side moves frotz/ to xyzzy/ and adds frotz->xyzzy/"
 
 '
 
-test_expect_success SYMLINKS 'switch from symlink to dir' '
+test_expect_success 'switch from symlink to dir' '
 
 	git checkout master
 
 '
 
-test_expect_success SYMLINKS 'Remove temporary directories & switch to master' '
+test_expect_success 'Remove temporary directories & switch to master' '
 	rm -fr frotz xyzzy nitfol &&
 	git checkout -f master
 '
 
-test_expect_success SYMLINKS 'switch from dir to symlink' '
+test_expect_success 'switch from dir to symlink' '
 
 	git checkout side
 
diff --git a/t/t2012-checkout-last.sh b/t/t2012-checkout-last.sh
index b44de9d..e7ba8c5 100755
--- a/t/t2012-checkout-last.sh
+++ b/t/t2012-checkout-last.sh
@@ -116,4 +116,38 @@
 	test "z$(git rev-parse --verify HEAD)" = "z$(git rev-parse --verify master^)"
 '
 
+test_expect_success '"checkout -" works after a rebase A' '
+	git checkout master &&
+	git checkout other &&
+	git rebase master &&
+	git checkout - &&
+	test "z$(git symbolic-ref HEAD)" = "zrefs/heads/master"
+'
+
+test_expect_success '"checkout -" works after a rebase A B' '
+	git branch moodle master~1 &&
+	git checkout master &&
+	git checkout other &&
+	git rebase master moodle &&
+	git checkout - &&
+	test "z$(git symbolic-ref HEAD)" = "zrefs/heads/master"
+'
+
+test_expect_success '"checkout -" works after a rebase -i A' '
+	git checkout master &&
+	git checkout other &&
+	git rebase -i master &&
+	git checkout - &&
+	test "z$(git symbolic-ref HEAD)" = "zrefs/heads/master"
+'
+
+test_expect_success '"checkout -" works after a rebase -i A B' '
+	git branch foodle master~1 &&
+	git checkout master &&
+	git checkout other &&
+	git rebase master foodle &&
+	git checkout - &&
+	test "z$(git symbolic-ref HEAD)" = "zrefs/heads/master"
+'
+
 test_done
diff --git a/t/t2021-checkout-overwrite.sh b/t/t2021-checkout-overwrite.sh
index 5da63e9..c2ada7d 100755
--- a/t/t2021-checkout-overwrite.sh
+++ b/t/t2021-checkout-overwrite.sh
@@ -29,21 +29,25 @@
 	test -f a/b
 '
 
-test_expect_success SYMLINKS 'create a commit where dir a/b changed to symlink' '
+test_expect_success 'create a commit where dir a/b changed to symlink' '
 
 	rm -rf a/b &&	# cleanup if previous test failed
 	git checkout -f -b symlink start &&
 	rm -rf a/b &&
-	ln -s foo a/b &&
 	git add -A &&
+	test_ln_s_add foo a/b &&
 	git commit -m "dir to symlink"
 '
 
-test_expect_success SYMLINKS 'checkout commit with dir must not remove untracked a/b' '
+test_expect_success 'checkout commit with dir must not remove untracked a/b' '
 
 	git rm --cached a/b &&
 	git commit -m "un-track the symlink" &&
-	test_must_fail git checkout start &&
+	test_must_fail git checkout start
+'
+
+test_expect_success SYMLINKS 'the symlink remained' '
+
 	test -h a/b
 '
 
diff --git a/t/t2024-checkout-dwim.sh b/t/t2024-checkout-dwim.sh
new file mode 100755
index 0000000..dee55e4
--- /dev/null
+++ b/t/t2024-checkout-dwim.sh
@@ -0,0 +1,167 @@
+#!/bin/sh
+
+test_description='checkout <branch>
+
+Ensures that checkout on an unborn branch does what the user expects'
+
+. ./test-lib.sh
+
+# Is the current branch "refs/heads/$1"?
+test_branch () {
+	printf "%s\n" "refs/heads/$1" >expect.HEAD &&
+	git symbolic-ref HEAD >actual.HEAD &&
+	test_cmp expect.HEAD actual.HEAD
+}
+
+# Is branch "refs/heads/$1" set to pull from "$2/$3"?
+test_branch_upstream () {
+	printf "%s\n" "$2" "refs/heads/$3" >expect.upstream &&
+	{
+		git config "branch.$1.remote" &&
+		git config "branch.$1.merge"
+	} >actual.upstream &&
+	test_cmp expect.upstream actual.upstream
+}
+
+test_expect_success 'setup' '
+	test_commit my_master &&
+	git init repo_a &&
+	(
+		cd repo_a &&
+		test_commit a_master &&
+		git checkout -b foo &&
+		test_commit a_foo &&
+		git checkout -b bar &&
+		test_commit a_bar
+	) &&
+	git init repo_b &&
+	(
+		cd repo_b &&
+		test_commit b_master &&
+		git checkout -b foo &&
+		test_commit b_foo &&
+		git checkout -b baz &&
+		test_commit b_baz
+	) &&
+	git remote add repo_a repo_a &&
+	git remote add repo_b repo_b &&
+	git config remote.repo_b.fetch \
+		"+refs/heads/*:refs/remotes/other_b/*" &&
+	git fetch --all
+'
+
+test_expect_success 'checkout of non-existing branch fails' '
+	git checkout -B master &&
+	test_might_fail git branch -D xyzzy &&
+
+	test_must_fail git checkout xyzzy &&
+	test_must_fail git rev-parse --verify refs/heads/xyzzy &&
+	test_branch master
+'
+
+test_expect_success 'checkout of branch from multiple remotes fails #1' '
+	git checkout -B master &&
+	test_might_fail git branch -D foo &&
+
+	test_must_fail git checkout foo &&
+	test_must_fail git rev-parse --verify refs/heads/foo &&
+	test_branch master
+'
+
+test_expect_success 'checkout of branch from a single remote succeeds #1' '
+	git checkout -B master &&
+	test_might_fail git branch -D bar &&
+
+	git checkout bar &&
+	test_branch bar &&
+	test_cmp_rev remotes/repo_a/bar HEAD &&
+	test_branch_upstream bar repo_a bar
+'
+
+test_expect_success 'checkout of branch from a single remote succeeds #2' '
+	git checkout -B master &&
+	test_might_fail git branch -D baz &&
+
+	git checkout baz &&
+	test_branch baz &&
+	test_cmp_rev remotes/other_b/baz HEAD &&
+	test_branch_upstream baz repo_b baz
+'
+
+test_expect_success '--no-guess suppresses branch auto-vivification' '
+	git checkout -B master &&
+	test_might_fail git branch -D bar &&
+
+	test_must_fail git checkout --no-guess bar &&
+	test_must_fail git rev-parse --verify refs/heads/bar &&
+	test_branch master
+'
+
+test_expect_success 'setup more remotes with unconventional refspecs' '
+	git checkout -B master &&
+	git init repo_c &&
+	(
+		cd repo_c &&
+		test_commit c_master &&
+		git checkout -b bar &&
+		test_commit c_bar
+		git checkout -b spam &&
+		test_commit c_spam
+	) &&
+	git init repo_d &&
+	(
+		cd repo_d &&
+		test_commit d_master &&
+		git checkout -b baz &&
+		test_commit f_baz
+		git checkout -b eggs &&
+		test_commit c_eggs
+	) &&
+	git remote add repo_c repo_c &&
+	git config remote.repo_c.fetch \
+		"+refs/heads/*:refs/remotes/extra_dir/repo_c/extra_dir/*" &&
+	git remote add repo_d repo_d &&
+	git config remote.repo_d.fetch \
+		"+refs/heads/*:refs/repo_d/*" &&
+	git fetch --all
+'
+
+test_expect_success 'checkout of branch from multiple remotes fails #2' '
+	git checkout -B master &&
+	test_might_fail git branch -D bar &&
+
+	test_must_fail git checkout bar &&
+	test_must_fail git rev-parse --verify refs/heads/bar &&
+	test_branch master
+'
+
+test_expect_success 'checkout of branch from multiple remotes fails #3' '
+	git checkout -B master &&
+	test_might_fail git branch -D baz &&
+
+	test_must_fail git checkout baz &&
+	test_must_fail git rev-parse --verify refs/heads/baz &&
+	test_branch master
+'
+
+test_expect_success 'checkout of branch from a single remote succeeds #3' '
+	git checkout -B master &&
+	test_might_fail git branch -D spam &&
+
+	git checkout spam &&
+	test_branch spam &&
+	test_cmp_rev refs/remotes/extra_dir/repo_c/extra_dir/spam HEAD &&
+	test_branch_upstream spam repo_c spam
+'
+
+test_expect_success 'checkout of branch from a single remote succeeds #4' '
+	git checkout -B master &&
+	test_might_fail git branch -D eggs &&
+
+	git checkout eggs &&
+	test_branch eggs &&
+	test_cmp_rev refs/repo_d/eggs HEAD &&
+	test_branch_upstream eggs repo_d eggs
+'
+
+test_done
diff --git a/t/t2200-add-update.sh b/t/t2200-add-update.sh
index b2bd419..9bf2bdf 100755
--- a/t/t2200-add-update.sh
+++ b/t/t2200-add-update.sh
@@ -96,11 +96,10 @@
 	test_cmp expect actual
 '
 
-test_expect_success SYMLINKS 'replace a file with a symlink' '
+test_expect_success 'replace a file with a symlink' '
 
 	rm foo &&
-	ln -s top foo &&
-	git add -u -- foo
+	test_ln_s_add top foo
 
 '
 
diff --git a/t/t2202-add-addremove.sh b/t/t2202-add-addremove.sh
index 6a81510..fc8b59e 100755
--- a/t/t2202-add-addremove.sh
+++ b/t/t2202-add-addremove.sh
@@ -41,4 +41,14 @@
 	test_cmp expect actual
 '
 
+test_expect_success 'Just "git add" is a no-op' '
+	git reset --hard &&
+	echo >will-remove &&
+	>will-not-be-added &&
+	git add &&
+	git diff-index --name-status --cached HEAD >actual &&
+	>expect &&
+	test_cmp expect actual
+'
+
 test_done
diff --git a/t/t3001-ls-files-others-exclude.sh b/t/t3001-ls-files-others-exclude.sh
index 4e3735f..f0421c0 100755
--- a/t/t3001-ls-files-others-exclude.sh
+++ b/t/t3001-ls-files-others-exclude.sh
@@ -175,6 +175,24 @@
 	grep "^a.1" output
 '
 
+test_expect_success 'excluded directory overrides content patterns' '
+
+	git ls-files --others --exclude="one" --exclude="!one/a.1" >output &&
+	if grep "^one/a.1" output
+	then
+		false
+	fi
+'
+
+test_expect_success 'negated directory doesn'\''t affect content patterns' '
+
+	git ls-files --others --exclude="!one" --exclude="one/a.1" >output &&
+	if grep "^one/a.1" output
+	then
+		false
+	fi
+'
+
 test_expect_success 'subdirectory ignore (setup)' '
 	mkdir -p top/l1/l2 &&
 	(
diff --git a/t/t3010-ls-files-killed-modified.sh b/t/t3010-ls-files-killed-modified.sh
index 95671c2..f611d79 100755
--- a/t/t3010-ls-files-killed-modified.sh
+++ b/t/t3010-ls-files-killed-modified.sh
@@ -11,6 +11,8 @@
     path1       - a symlink
     path2/file2 - a file in a directory
     path3/file3 - a file in a directory
+    submod1/	- a submodule
+    submod2/	- another submodule
 
 and the following on the filesystem:
 
@@ -21,9 +23,11 @@
     path4	- a file
     path5	- a symlink
     path6/file6 - a file in a directory
+    submod1/	- a submodule (modified from the cache)
+    submod2/	- a submodule (matches the cache)
 
-git ls-files -k should report that existing filesystem
-objects except path4, path5 and path6/file6 to be killed.
+git ls-files -k should report that existing filesystem objects
+path0/*, path1/*, path2 and path3 to be killed.
 
 Also for modification test, the cache and working tree have:
 
@@ -33,75 +37,82 @@
     path10	- a non-empty file, cache dirtied.
 
 We should report path0, path1, path2/file2, path3/file3, path7 and path8
-modified without reporting path9 and path10.
+modified without reporting path9 and path10.  submod1 is also modified.
 '
 . ./test-lib.sh
 
-date >path0
-if test_have_prereq SYMLINKS
-then
-	ln -s xyzzy path1
-else
-	date > path1
-fi
-mkdir path2 path3
-date >path2/file2
-date >path3/file3
-: >path7
-date >path8
-: >path9
-date >path10
-test_expect_success \
-    'git update-index --add to add various paths.' \
-    "git update-index --add -- path0 path1 path?/file? path7 path8 path9 path10"
+test_expect_success 'git update-index --add to add various paths.' '
+	date >path0 &&
+	test_ln_s_add xyzzy path1 &&
+	mkdir path2 path3 &&
+	date >path2/file2 &&
+	date >path3/file3 &&
+	: >path7 &&
+	date >path8 &&
+	: >path9 &&
+	date >path10 &&
+	git update-index --add -- path0 path?/file? path7 path8 path9 path10 &&
+	for i in 1 2
+	do
+		git init submod$i &&
+		(
+			cd submod$i && git commit --allow-empty -m "empty $i"
+		) || break
+	done &&
+	git update-index --add submod[12]
+	(
+		cd submod1 &&
+		git commit --allow-empty -m "empty 1 (updated)"
+	) &&
+	rm -fr path?	# leave path10 alone
+'
 
-rm -fr path? ;# leave path10 alone
-date >path2
-if test_have_prereq SYMLINKS
-then
-	ln -s frotz path3
-	ln -s nitfol path5
-else
-	date > path3
-	date > path5
-fi
-mkdir path0 path1 path6
-date >path0/file0
-date >path1/file1
-date >path6/file6
-date >path7
-: >path8
-: >path9
-touch path10
+test_expect_success 'git ls-files -k to show killed files.' '
+	date >path2 &&
+	if test_have_prereq SYMLINKS
+	then
+		ln -s frotz path3 &&
+		ln -s nitfol path5
+	else
+		date >path3 &&
+		date >path5
+	fi &&
+	mkdir path0 path1 path6 &&
+	date >path0/file0 &&
+	date >path1/file1 &&
+	date >path6/file6 &&
+	date >path7 &&
+	: >path8 &&
+	: >path9 &&
+	touch path10 &&
+	git ls-files -k >.output
+'
 
-test_expect_success \
-    'git ls-files -k to show killed files.' \
-    'git ls-files -k >.output'
-cat >.expected <<EOF
-path0/file0
-path1/file1
-path2
-path3
-EOF
+test_expect_success 'validate git ls-files -k output.' '
+	cat >.expected <<-\EOF &&
+	path0/file0
+	path1/file1
+	path2
+	path3
+	EOF
+	test_cmp .expected .output
+'
 
-test_expect_success \
-    'validate git ls-files -k output.' \
-    'test_cmp .expected .output'
+test_expect_success 'git ls-files -m to show modified files.' '
+	git ls-files -m >.output
+'
 
-test_expect_success \
-    'git ls-files -m to show modified files.' \
-    'git ls-files -m >.output'
-cat >.expected <<EOF
-path0
-path1
-path2/file2
-path3/file3
-path7
-path8
-EOF
-
-test_expect_success \
-    'validate git ls-files -m output.' \
-    'test_cmp .expected .output'
+test_expect_success 'validate git ls-files -m output.' '
+	cat >.expected <<-\EOF &&
+	path0
+	path1
+	path2/file2
+	path3/file3
+	path7
+	path8
+	submod1
+	EOF
+	test_cmp .expected .output
+'
 
 test_done
diff --git a/t/t3030-merge-recursive.sh b/t/t3030-merge-recursive.sh
index a5e3da7..2f96100 100755
--- a/t/t3030-merge-recursive.sh
+++ b/t/t3030-merge-recursive.sh
@@ -25,10 +25,7 @@
 	git branch submod &&
 	git branch copy &&
 	git branch rename &&
-	if test_have_prereq SYMLINKS
-	then
-		git branch rename-ln
-	fi &&
+	git branch rename-ln &&
 
 	echo hello >>a &&
 	cp a d/e &&
@@ -260,16 +257,12 @@
 	git add e &&
 	test_tick &&
 	git commit -m "rename a->e" &&
-	if test_have_prereq SYMLINKS
-	then
-		git checkout rename-ln &&
-		git mv a e &&
-		ln -s e a &&
-		git add a e &&
-		test_tick &&
-		git commit -m "rename a->e, symlink a->e" &&
-		oln=`printf e | git hash-object --stdin`
-	fi
+	git checkout rename-ln &&
+	git mv a e &&
+	test_ln_s_add e a &&
+	test_tick &&
+	git commit -m "rename a->e, symlink a->e" &&
+	oln=`printf e | git hash-object --stdin`
 '
 
 test_expect_success 'setup 9' '
@@ -569,28 +562,25 @@
 	test_cmp expected actual
 '
 
-if test_have_prereq SYMLINKS
-then
-	test_expect_failure 'merge-recursive rename vs. rename/symlink' '
+test_expect_failure 'merge-recursive rename vs. rename/symlink' '
 
-		git checkout -f rename &&
-		git merge rename-ln &&
-		( git ls-tree -r HEAD ; git ls-files -s ) >actual &&
-		(
-			echo "120000 blob $oln	a"
-			echo "100644 blob $o0	b"
-			echo "100644 blob $o0	c"
-			echo "100644 blob $o0	d/e"
-			echo "100644 blob $o0	e"
-			echo "120000 $oln 0	a"
-			echo "100644 $o0 0	b"
-			echo "100644 $o0 0	c"
-			echo "100644 $o0 0	d/e"
-			echo "100644 $o0 0	e"
-		) >expected &&
-		test_cmp expected actual
-	'
-fi
+	git checkout -f rename &&
+	git merge rename-ln &&
+	( git ls-tree -r HEAD ; git ls-files -s ) >actual &&
+	(
+		echo "120000 blob $oln	a"
+		echo "100644 blob $o0	b"
+		echo "100644 blob $o0	c"
+		echo "100644 blob $o0	d/e"
+		echo "100644 blob $o0	e"
+		echo "120000 $oln 0	a"
+		echo "100644 $o0 0	b"
+		echo "100644 $o0 0	c"
+		echo "100644 $o0 0	d/e"
+		echo "100644 $o0 0	e"
+	) >expected &&
+	test_cmp expected actual
+'
 
 
 test_done
diff --git a/t/t3032-merge-recursive-options.sh b/t/t3032-merge-recursive-options.sh
index 2b17311..5fd7bbb 100755
--- a/t/t3032-merge-recursive-options.sh
+++ b/t/t3032-merge-recursive-options.sh
@@ -14,7 +14,7 @@
 . ./test-lib.sh
 
 test_have_prereq SED_STRIPS_CR && SED_OPTIONS=-b
-test_have_prereq MINGW && export GREP_OPTIONS=-U
+test_have_prereq GREP_STRIPS_CR && export GREP_OPTIONS=-U
 
 test_expect_success 'setup' '
 	conflict_hunks () {
diff --git a/t/t3070-wildmatch.sh b/t/t3070-wildmatch.sh
index 4c37057..38446a0 100755
--- a/t/t3070-wildmatch.sh
+++ b/t/t3070-wildmatch.sh
@@ -6,20 +6,20 @@
 
 match() {
     if [ $1 = 1 ]; then
-	test_expect_success "wildmatch:    match '$3' '$4'" "
+	test_expect_success "wildmatch:     match '$3' '$4'" "
 	    test-wildmatch wildmatch '$3' '$4'
 	"
     else
-	test_expect_success "wildmatch: no match '$3' '$4'" "
+	test_expect_success "wildmatch:  no match '$3' '$4'" "
 	    ! test-wildmatch wildmatch '$3' '$4'
 	"
     fi
     if [ $2 = 1 ]; then
-	test_expect_success "fnmatch:      match '$3' '$4'" "
+	test_expect_success "fnmatch:       match '$3' '$4'" "
 	    test-wildmatch fnmatch '$3' '$4'
 	"
     elif [ $2 = 0 ]; then
-	test_expect_success "fnmatch:   no match '$3' '$4'" "
+	test_expect_success "fnmatch:    no match '$3' '$4'" "
 	    ! test-wildmatch fnmatch '$3' '$4'
 	"
 #    else
@@ -29,13 +29,25 @@
     fi
 }
 
+imatch() {
+    if [ $1 = 1 ]; then
+	test_expect_success "iwildmatch:    match '$2' '$3'" "
+	    test-wildmatch iwildmatch '$2' '$3'
+	"
+    else
+	test_expect_success "iwildmatch: no match '$2' '$3'" "
+	    ! test-wildmatch iwildmatch '$2' '$3'
+	"
+    fi
+}
+
 pathmatch() {
     if [ $1 = 1 ]; then
-	test_expect_success "pathmatch:    match '$2' '$3'" "
+	test_expect_success "pathmatch:     match '$2' '$3'" "
 	    test-wildmatch pathmatch '$2' '$3'
 	"
     else
-	test_expect_success "pathmatch: no match '$2' '$3'" "
+	test_expect_success "pathmatch:  no match '$2' '$3'" "
 	    ! test-wildmatch pathmatch '$2' '$3'
 	"
     fi
@@ -235,4 +247,35 @@
 pathmatch 1 ab/cXd/efXg/hi '*/*X*/*/*i'
 pathmatch 1 ab/cXd/efXg/hi '*Xg*i'
 
+# Case-sensitivy features
+match 0 x 'a' '[A-Z]'
+match 1 x 'A' '[A-Z]'
+match 0 x 'A' '[a-z]'
+match 1 x 'a' '[a-z]'
+match 0 x 'a' '[[:upper:]]'
+match 1 x 'A' '[[:upper:]]'
+match 0 x 'A' '[[:lower:]]'
+match 1 x 'a' '[[:lower:]]'
+match 0 x 'A' '[B-Za]'
+match 1 x 'a' '[B-Za]'
+match 0 x 'A' '[B-a]'
+match 1 x 'a' '[B-a]'
+match 0 x 'z' '[Z-y]'
+match 1 x 'Z' '[Z-y]'
+
+imatch 1 'a' '[A-Z]'
+imatch 1 'A' '[A-Z]'
+imatch 1 'A' '[a-z]'
+imatch 1 'a' '[a-z]'
+imatch 1 'a' '[[:upper:]]'
+imatch 1 'A' '[[:upper:]]'
+imatch 1 'A' '[[:lower:]]'
+imatch 1 'a' '[[:lower:]]'
+imatch 1 'A' '[B-Za]'
+imatch 1 'a' '[B-Za]'
+imatch 1 'A' '[B-a]'
+imatch 1 'a' '[B-a]'
+imatch 1 'z' '[Z-y]'
+imatch 1 'Z' '[Z-y]'
+
 test_done
diff --git a/t/t3100-ls-tree-restrict.sh b/t/t3100-ls-tree-restrict.sh
index 81d90b6..eb73c06 100755
--- a/t/t3100-ls-tree-restrict.sh
+++ b/t/t3100-ls-tree-restrict.sh
@@ -22,20 +22,8 @@
     'setup' \
     'mkdir path2 path2/baz &&
      echo Hi >path0 &&
-     if test_have_prereq SYMLINKS
-     then
-	ln -s path0 path1 &&
-	ln -s ../path1 path2/bazbo
-	make_expected () {
-		cat >expected
-	}
-     else
-	printf path0 > path1 &&
-	printf ../path1 > path2/bazbo
-	make_expected () {
-		sed -e "s/120000 /100644 /" >expected
-	}
-     fi &&
+     test_ln_s_add path0 path1 &&
+     test_ln_s_add ../path1 path2/bazbo &&
      echo Lo >path2/foo &&
      echo Mi >path2/baz/b &&
      find path? \( -type f -o -type l \) -print |
@@ -51,7 +39,7 @@
 test_expect_success \
     'ls-tree plain' \
     'git ls-tree $tree >current &&
-     make_expected <<\EOF &&
+     cat >expected <<\EOF &&
 100644 blob X	path0
 120000 blob X	path1
 040000 tree X	path2
@@ -61,7 +49,7 @@
 test_expect_success \
     'ls-tree recursive' \
     'git ls-tree -r $tree >current &&
-     make_expected <<\EOF &&
+     cat >expected <<\EOF &&
 100644 blob X	path0
 120000 blob X	path1
 100644 blob X	path2/baz/b
@@ -73,7 +61,7 @@
 test_expect_success \
     'ls-tree recursive with -t' \
     'git ls-tree -r -t $tree >current &&
-     make_expected <<\EOF &&
+     cat >expected <<\EOF &&
 100644 blob X	path0
 120000 blob X	path1
 040000 tree X	path2
@@ -87,7 +75,7 @@
 test_expect_success \
     'ls-tree recursive with -d' \
     'git ls-tree -r -d $tree >current &&
-     make_expected <<\EOF &&
+     cat >expected <<\EOF &&
 040000 tree X	path2
 040000 tree X	path2/baz
 EOF
@@ -96,7 +84,7 @@
 test_expect_success \
     'ls-tree filtered with path' \
     'git ls-tree $tree path >current &&
-     make_expected <<\EOF &&
+     cat >expected <<\EOF &&
 EOF
      test_output'
 
@@ -106,7 +94,7 @@
 test_expect_success \
     'ls-tree filtered with path1 path0' \
     'git ls-tree $tree path1 path0 >current &&
-     make_expected <<\EOF &&
+     cat >expected <<\EOF &&
 100644 blob X	path0
 120000 blob X	path1
 EOF
@@ -115,7 +103,7 @@
 test_expect_success \
     'ls-tree filtered with path0/' \
     'git ls-tree $tree path0/ >current &&
-     make_expected <<\EOF &&
+     cat >expected <<\EOF &&
 EOF
      test_output'
 
@@ -124,7 +112,7 @@
 test_expect_success \
     'ls-tree filtered with path2' \
     'git ls-tree $tree path2 >current &&
-     make_expected <<\EOF &&
+     cat >expected <<\EOF &&
 040000 tree X	path2
 EOF
      test_output'
@@ -133,7 +121,7 @@
 test_expect_success \
     'ls-tree filtered with path2/' \
     'git ls-tree $tree path2/ >current &&
-     make_expected <<\EOF &&
+     cat >expected <<\EOF &&
 040000 tree X	path2/baz
 120000 blob X	path2/bazbo
 100644 blob X	path2/foo
@@ -145,7 +133,7 @@
 test_expect_success \
     'ls-tree filtered with path2/baz' \
     'git ls-tree $tree path2/baz >current &&
-     make_expected <<\EOF &&
+     cat >expected <<\EOF &&
 040000 tree X	path2/baz
 EOF
      test_output'
@@ -153,14 +141,14 @@
 test_expect_success \
     'ls-tree filtered with path2/bak' \
     'git ls-tree $tree path2/bak >current &&
-     make_expected <<\EOF &&
+     cat >expected <<\EOF &&
 EOF
      test_output'
 
 test_expect_success \
     'ls-tree -t filtered with path2/bak' \
     'git ls-tree -t $tree path2/bak >current &&
-     make_expected <<\EOF &&
+     cat >expected <<\EOF &&
 040000 tree X	path2
 EOF
      test_output'
@@ -168,7 +156,7 @@
 test_expect_success \
     'ls-tree with one path a prefix of the other' \
     'git ls-tree $tree path2/baz path2/bazbo >current &&
-     make_expected <<\EOF &&
+     cat >expected <<\EOF &&
 040000 tree X	path2/baz
 120000 blob X	path2/bazbo
 EOF
diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
index d969f0e..44ec6a4 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -317,13 +317,13 @@
 	test $(git config branch.my4.merge) = refs/heads/master
 '
 
-test_expect_success 'test tracking setup (non-wildcard, not matching)' '
+test_expect_success 'tracking setup fails on non-matching refspec' '
 	git config remote.local.url . &&
 	git config remote.local.fetch refs/heads/s:refs/remotes/local/s &&
 	(git show-ref -q refs/remotes/local/master || git fetch local) &&
-	git branch --track my5 local/master &&
-	! test "$(git config branch.my5.remote)" = local &&
-	! test "$(git config branch.my5.merge)" = refs/heads/master
+	test_must_fail git branch --track my5 local/master &&
+	test_must_fail git config branch.my5.remote &&
+	test_must_fail git config branch.my5.merge
 '
 
 test_expect_success 'test tracking setup via config' '
diff --git a/t/t3210-pack-refs.sh b/t/t3210-pack-refs.sh
index cd04361..1a2080e 100755
--- a/t/t3210-pack-refs.sh
+++ b/t/t3210-pack-refs.sh
@@ -118,4 +118,37 @@
 	test_cmp all-of-them again
 '
 
+test_expect_success 'explicit pack-refs with dangling packed reference' '
+	git commit --allow-empty -m "soon to be garbage-collected" &&
+	git pack-refs --all &&
+	git reset --hard HEAD^ &&
+	git reflog expire --expire=all --all &&
+	git prune --expire=all &&
+	git pack-refs --all 2>result &&
+	test_cmp /dev/null result
+'
+
+test_expect_success 'delete ref with dangling packed version' '
+	git checkout -b lamb &&
+	git commit --allow-empty -m "future garbage" &&
+	git pack-refs --all &&
+	git reset --hard HEAD^ &&
+	git checkout master &&
+	git reflog expire --expire=all --all &&
+	git prune --expire=all &&
+	git branch -d lamb 2>result &&
+	test_cmp /dev/null result
+'
+
+test_expect_success 'delete ref while another dangling packed ref' '
+	git branch lamb &&
+	git commit --allow-empty -m "future garbage" &&
+	git pack-refs --all &&
+	git reset --hard HEAD^ &&
+	git reflog expire --expire=all --all &&
+	git prune --expire=all &&
+	git branch -d lamb 2>result &&
+	test_cmp /dev/null result
+'
+
 test_done
diff --git a/t/t3211-peel-ref.sh b/t/t3211-peel-ref.sh
index d4d7792..3b7caca 100755
--- a/t/t3211-peel-ref.sh
+++ b/t/t3211-peel-ref.sh
@@ -61,4 +61,13 @@
 	test_cmp expect actual
 '
 
+test_expect_success 'peeled refs survive deletion of packed ref' '
+	git pack-refs --all &&
+	cp .git/packed-refs fully-peeled &&
+	git branch yadda &&
+	git pack-refs --all &&
+	git branch -d yadda &&
+	test_cmp fully-peeled .git/packed-refs
+'
+
 test_done
diff --git a/t/t3400-rebase.sh b/t/t3400-rebase.sh
index b58fa1a..ebf93b0 100755
--- a/t/t3400-rebase.sh
+++ b/t/t3400-rebase.sh
@@ -40,13 +40,6 @@
 	echo Side >>C &&
 	git add C &&
 	git commit -m "Add C" &&
-	git checkout -b nonlinear my-topic-branch &&
-	echo Edit >>B &&
-	git add B &&
-	git commit -m "Modify B" &&
-	git merge side &&
-	git checkout -b upstream-merged-nonlinear &&
-	git merge master &&
 	git checkout -f my-topic-branch &&
 	git tag topic
 '
@@ -66,26 +59,15 @@
 	git rebase master
 '
 
-test_expect_success 'rebase against master twice' '
-	git rebase master >out &&
-	test_i18ngrep "Current branch my-topic-branch is up to date" out
-'
-
-test_expect_success 'rebase against master twice with --force' '
-	git rebase --force-rebase master >out &&
-	test_i18ngrep "Current branch my-topic-branch is up to date, rebase forced" out
-'
-
-test_expect_success 'rebase against master twice from another branch' '
-	git checkout my-topic-branch^ &&
-	git rebase master my-topic-branch >out &&
-	test_i18ngrep "Current branch my-topic-branch is up to date" out
-'
-
-test_expect_success 'rebase fast-forward to master' '
-	git checkout my-topic-branch^ &&
-	git rebase my-topic-branch >out &&
-	test_i18ngrep "Fast-forwarded HEAD to my-topic-branch" out
+test_expect_success 'rebase, with <onto> and <upstream> specified as :/quuxery' '
+	test_when_finished "git branch -D torebase" &&
+	git checkout -b torebase my-topic-branch^ &&
+	upstream=$(git rev-parse ":/Add B") &&
+	onto=$(git rev-parse ":/Add A") &&
+	git rebase --onto $onto $upstream &&
+	git reset --hard my-topic-branch^ &&
+	git rebase --onto ":/Add A" ":/Add B" &&
+	git checkout my-topic-branch
 '
 
 test_expect_success 'the rebase operation should not have destroyed author information' '
@@ -106,31 +88,9 @@
 	git rebase master
 '
 
-test_expect_success 'rebase after merge master' '
-	git checkout --detach refs/tags/topic &&
-	git branch -D topic &&
-	git reset --hard topic &&
-	git merge master &&
-	git rebase master &&
-	! (git show | grep "^Merge:")
-'
-
-test_expect_success 'rebase of history with merges is linearized' '
-	git checkout nonlinear &&
-	test 4 = $(git rev-list master.. | wc -l) &&
-	git rebase master &&
-	test 3 = $(git rev-list master.. | wc -l)
-'
-
-test_expect_success 'rebase of history with merges after upstream merge is linearized' '
-	git checkout upstream-merged-nonlinear &&
-	test 5 = $(git rev-list master.. | wc -l) &&
-	git rebase master &&
-	test 3 = $(git rev-list master.. | wc -l)
-'
-
 test_expect_success 'rebase a single mode change' '
 	git checkout master &&
+	git branch -D topic &&
 	echo 1 >X &&
 	git add X &&
 	test_tick &&
@@ -185,7 +145,7 @@
 test_expect_success 'rebase -q is quiet' '
 	git checkout -b quiet topic &&
 	git rebase -q master >output.out 2>&1 &&
-	test ! -s output.out
+	test_must_be_empty output.out
 '
 
 test_expect_success 'Rebase a commit that sprinkles CRs in' '
diff --git a/t/t3401-rebase-partial.sh b/t/t3401-rebase-partial.sh
deleted file mode 100755
index 58f4823..0000000
--- a/t/t3401-rebase-partial.sh
+++ /dev/null
@@ -1,69 +0,0 @@
-#!/bin/sh
-#
-# Copyright (c) 2006 Yann Dirson, based on t3400 by Amos Waterland
-#
-
-test_description='git rebase should detect patches integrated upstream
-
-This test cherry-picks one local change of two into master branch, and
-checks that git rebase succeeds with only the second patch in the
-local branch.
-'
-. ./test-lib.sh
-
-test_expect_success 'prepare repository with topic branch' '
-	test_commit A &&
-	git checkout -b my-topic-branch &&
-	test_commit B &&
-	test_commit C &&
-	git checkout -f master &&
-	test_commit A2 A.t
-'
-
-test_expect_success 'pick top patch from topic branch into master' '
-	git cherry-pick C &&
-	git checkout -f my-topic-branch
-'
-
-test_debug '
-	git cherry master &&
-	git format-patch -k --stdout --full-index master >/dev/null &&
-	gitk --all & sleep 1
-'
-
-test_expect_success 'rebase topic branch against new master and check git am did not get halted' '
-	git rebase master &&
-	test_path_is_missing .git/rebase-apply
-'
-
-test_expect_success 'rebase --merge topic branch that was partially merged upstream' '
-	git reset --hard C &&
-	git rebase --merge master &&
-	test_path_is_missing .git/rebase-merge
-'
-
-test_expect_success 'rebase ignores empty commit' '
-	git reset --hard A &&
-	git commit --allow-empty -m empty &&
-	test_commit D &&
-	git rebase C &&
-	test "$(git log --format=%s C..)" = "D"
-'
-
-test_expect_success 'rebase --keep-empty' '
-	git reset --hard D &&
-	git rebase --keep-empty C &&
-	test "$(git log --format=%s C..)" = "D
-empty"
-'
-
-test_expect_success 'rebase --keep-empty keeps empty even if already in upstream' '
-	git reset --hard A &&
-	git commit --allow-empty -m also-empty &&
-	git rebase --keep-empty D &&
-	test "$(git log --format=%s A..)" = "also-empty
-D
-empty"
-'
-
-test_done
diff --git a/t/t3403-rebase-skip.sh b/t/t3403-rebase-skip.sh
index 826500b..3968020 100755
--- a/t/t3403-rebase-skip.sh
+++ b/t/t3403-rebase-skip.sh
@@ -64,10 +64,11 @@
 
 test_expect_success 'rebase --skip with --merge' '
 	git rebase --skip
-	'
+'
 
-test_expect_success 'merge and reference trees equal' \
-	'test -z "`git diff-tree skip-merge skip-reference`"'
+test_expect_success 'merge and reference trees equal' '
+	test -z "`git diff-tree skip-merge skip-reference`"
+'
 
 test_expect_success 'moved back to branch correctly' '
 	test refs/heads/skip-merge = $(git symbolic-ref HEAD)
diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index a58406d..4dbeddb 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -477,19 +477,11 @@
 	test $one = $(git rev-parse HEAD~2)
 '
 
-test_expect_success 'ignore patch if in upstream' '
-	HEAD=$(git rev-parse HEAD) &&
-	git checkout -b has-cherry-picked HEAD^ &&
+test_expect_success '--continue tries to commit, even for "edit"' '
 	echo unrelated > file7 &&
 	git add file7 &&
 	test_tick &&
 	git commit -m "unrelated change" &&
-	git cherry-pick $HEAD &&
-	EXPECT_COUNT=1 git rebase -i $HEAD &&
-	test $HEAD = $(git rev-parse HEAD^)
-'
-
-test_expect_success '--continue tries to commit, even for "edit"' '
 	parent=$(git rev-parse HEAD^) &&
 	test_tick &&
 	FAKE_LINES="edit 1" git rebase -i HEAD^ &&
@@ -692,7 +684,7 @@
 	test_commit n2 &&
 	test_commit n3 &&
 	git notes add -m"a note" n3 &&
-	git rebase --onto n1 n2 &&
+	git rebase -i --onto n1 n2 &&
 	test "a note" = "$(git notes show HEAD)"
 '
 
@@ -934,6 +926,21 @@
 	test L = $(git cat-file commit HEAD | sed -ne \$p)
 '
 
+test_expect_success 'rebase -i produces readable reflog' '
+	git reset --hard &&
+	git branch -f branch-reflog-test H &&
+	git rebase -i --onto I F branch-reflog-test &&
+	cat >expect <<-\EOF &&
+	rebase -i (start): checkout I
+	rebase -i (pick): G
+	rebase -i (pick): H
+	rebase -i (finish): returning to refs/heads/branch-reflog-test
+	EOF
+	tail -n 4 .git/logs/HEAD |
+	sed -e "s/.*	//" >actual &&
+	test_cmp expect actual
+'
+
 test_expect_success 'rebase -i respects core.commentchar' '
 	git reset --hard &&
 	git checkout E^0 &&
@@ -947,4 +954,39 @@
 	test B = $(git cat-file commit HEAD^ | sed -ne \$p)
 '
 
+test_expect_success 'rebase -i, with <onto> and <upstream> specified as :/quuxery' '
+	test_when_finished "git branch -D torebase" &&
+	git checkout -b torebase branch1 &&
+	upstream=$(git rev-parse ":/J") &&
+	onto=$(git rev-parse ":/A") &&
+	git rebase --onto $onto $upstream &&
+	git reset --hard branch1 &&
+	git rebase --onto ":/A" ":/J" &&
+	git checkout branch1
+'
+
+test_expect_success 'rebase -i with --strategy and -X' '
+	git checkout -b conflict-merge-use-theirs conflict-branch &&
+	git reset --hard HEAD^ &&
+	echo five >conflict &&
+	echo Z >file1 &&
+	git commit -a -m "one file conflict" &&
+	EDITOR=true git rebase -i --strategy=recursive -Xours conflict-branch &&
+	test $(git show conflict-branch:conflict) = $(cat conflict) &&
+	test $(cat file1) = Z
+'
+
+test_expect_success 'rebase -i error on commits with \ in message' '
+	current_head=$(git rev-parse HEAD)
+	test_when_finished "git rebase --abort; git reset --hard $current_head; rm -f error" &&
+	test_commit TO-REMOVE will-conflict old-content &&
+	test_commit "\temp" will-conflict new-content dummy &&
+	(
+	EDITOR=true &&
+	export EDITOR &&
+	test_must_fail git rebase -i HEAD^ --onto HEAD^^ 2>error
+	) &&
+	test_expect_code 1 grep  "	emp" error
+'
+
 test_done
diff --git a/t/t3406-rebase-message.sh b/t/t3406-rebase-message.sh
index e6a9a0d..0392e36 100755
--- a/t/t3406-rebase-message.sh
+++ b/t/t3406-rebase-message.sh
@@ -4,27 +4,17 @@
 
 . ./test-lib.sh
 
-quick_one () {
-	echo "$1" >"file$1" &&
-	git add "file$1" &&
-	test_tick &&
-	git commit -m "$1"
-}
+test_expect_success 'setup' '
+	test_commit O fileO &&
+	test_commit X fileX &&
+	test_commit A fileA &&
+	test_commit B fileB &&
+	test_commit Y fileY &&
 
-test_expect_success setup '
-	quick_one O &&
-	git branch topic &&
-	quick_one X &&
-	quick_one A &&
-	quick_one B &&
-	quick_one Y &&
-
-	git checkout topic &&
-	quick_one A &&
-	quick_one B &&
-	quick_one Z &&
+	git checkout -b topic O &&
+	git cherry-pick A B &&
+	test_commit Z fileZ &&
 	git tag start
-
 '
 
 cat >expect <<\EOF
@@ -34,12 +24,32 @@
 EOF
 
 test_expect_success 'rebase -m' '
-
 	git rebase -m master >report &&
 	sed -n -e "/^Already applied: /p" \
 		-e "/^Committed: /p" report >actual &&
 	test_cmp expect actual
+'
 
+test_expect_success 'rebase against master twice' '
+	git rebase master >out &&
+	test_i18ngrep "Current branch topic is up to date" out
+'
+
+test_expect_success 'rebase against master twice with --force' '
+	git rebase --force-rebase master >out &&
+	test_i18ngrep "Current branch topic is up to date, rebase forced" out
+'
+
+test_expect_success 'rebase against master twice from another branch' '
+	git checkout topic^ &&
+	git rebase master topic >out &&
+	test_i18ngrep "Current branch topic is up to date" out
+'
+
+test_expect_success 'rebase fast-forward to master' '
+	git checkout topic^ &&
+	git rebase topic >out &&
+	test_i18ngrep "Fast-forwarded HEAD to topic" out
 '
 
 test_expect_success 'rebase --stat' '
diff --git a/t/t3409-rebase-preserve-merges.sh b/t/t3409-rebase-preserve-merges.sh
index 6de4e22..2e0c364 100755
--- a/t/t3409-rebase-preserve-merges.sh
+++ b/t/t3409-rebase-preserve-merges.sh
@@ -11,14 +11,6 @@
 GIT_AUTHOR_EMAIL=bogus_email_address
 export GIT_AUTHOR_EMAIL
 
-# Clone 1 (trivial merge):
-#
-# A1--A2  <-- origin/master
-#  \   \
-#   B1--M  <-- topic
-#    \
-#     B2  <-- origin/topic
-#
 # Clone 2 (conflicting merge):
 #
 # A1--A2--B3   <-- origin/master
@@ -36,16 +28,6 @@
 #     \--A3    <-- topic2
 #      \
 #       B2     <-- origin/topic
-#
-# Clone 4 (merge using second parent as base):
-#
-# A1--A2--B3   <-- origin/master
-#  \
-#   B1--A3--M  <-- topic
-#    \     /
-#     \--A4    <-- topic2
-#      \
-#       B2     <-- origin/topic
 
 test_expect_success 'setup for merge-preserving rebase' \
 	'echo First > A &&
@@ -58,20 +40,6 @@
 	git checkout -f master &&
 	echo Third >> A &&
 	git commit -a -m "Modify A2" &&
-
-	git clone ./. clone1 &&
-	(cd clone1 &&
-	git checkout -b topic origin/topic &&
-	git merge origin/master
-	) &&
-
-	git clone ./. clone4 &&
-	(
-		cd clone4 &&
-		git checkout -b topic origin/topic &&
-		git merge origin/master
-	) &&
-
 	echo Fifth > B &&
 	git add B &&
 	git commit -m "Add different B" &&
@@ -101,16 +69,6 @@
 	git commit -a -m "Modify B2"
 '
 
-test_expect_success 'rebase -p fakes interactive rebase' '
-	(
-	cd clone1 &&
-	git fetch &&
-	git rebase -p origin/topic &&
-	test 1 = $(git rev-list --all --pretty=oneline | grep "Modify A" | wc -l) &&
-	test 1 = $(git rev-list --all --pretty=oneline | grep "Merge remote-tracking branch " | wc -l)
-	)
-'
-
 test_expect_success '--continue works after a conflict' '
 	(
 	cd clone2 &&
@@ -138,15 +96,4 @@
 	)
 '
 
-test_expect_success 'rebase -p works when base inside second parent' '
-	(
-	cd clone4 &&
-	git fetch &&
-	git rebase -p HEAD^2 &&
-	test 1 = $(git rev-list --all --pretty=oneline | grep "Modify A" | wc -l) &&
-	test 1 = $(git rev-list --all --pretty=oneline | grep "Modify B" | wc -l) &&
-	test 1 = $(git rev-list --all --pretty=oneline | grep "Merge remote-tracking branch " | wc -l)
-	)
-'
-
 test_done
diff --git a/t/t3415-rebase-autosquash.sh b/t/t3415-rebase-autosquash.sh
index a1e86c4..41370ab 100755
--- a/t/t3415-rebase-autosquash.sh
+++ b/t/t3415-rebase-autosquash.sh
@@ -4,6 +4,8 @@
 
 . ./test-lib.sh
 
+. "$TEST_DIRECTORY"/lib-rebase.sh
+
 test_expect_success setup '
 	echo 0 >file0 &&
 	git add . &&
@@ -193,4 +195,59 @@
 	test_auto_commit_flags squash 2
 '
 
+test_auto_fixup_fixup () {
+	git reset --hard base &&
+	echo 1 >file1 &&
+	git add -u &&
+	test_tick &&
+	git commit -m "$1! first" &&
+	echo 2 >file1 &&
+	git add -u &&
+	test_tick &&
+	git commit -m "$1! $2! first" &&
+	git tag "final-$1-$2" &&
+	test_tick &&
+	(
+		set_cat_todo_editor &&
+		test_must_fail git rebase --autosquash -i HEAD^^^^ >actual &&
+		cat >expected <<-EOF &&
+		pick $(git rev-parse --short HEAD^^^) first commit
+		$1 $(git rev-parse --short HEAD^) $1! first
+		$1 $(git rev-parse --short HEAD) $1! $2! first
+		pick $(git rev-parse --short HEAD^^) second commit
+		EOF
+		test_cmp expected actual
+	) &&
+	git rebase --autosquash -i HEAD^^^^ &&
+	git log --oneline >actual &&
+	test_line_count = 3 actual
+	git diff --exit-code "final-$1-$2" &&
+	test 2 = "$(git cat-file blob HEAD^:file1)" &&
+	if test "$1" = "fixup"
+	then
+		test 1 = $(git cat-file commit HEAD^ | grep first | wc -l)
+	elif test "$1" = "squash"
+	then
+		test 3 = $(git cat-file commit HEAD^ | grep first | wc -l)
+	else
+		false
+	fi
+}
+
+test_expect_success 'fixup! fixup!' '
+	test_auto_fixup_fixup fixup fixup
+'
+
+test_expect_success 'fixup! squash!' '
+	test_auto_fixup_fixup fixup squash
+'
+
+test_expect_success 'squash! squash!' '
+	test_auto_fixup_fixup squash squash
+'
+
+test_expect_success 'squash! fixup!' '
+	test_auto_fixup_fixup squash fixup
+'
+
 test_done
diff --git a/t/t3420-rebase-autostash.sh b/t/t3420-rebase-autostash.sh
new file mode 100755
index 0000000..90eb264
--- /dev/null
+++ b/t/t3420-rebase-autostash.sh
@@ -0,0 +1,170 @@
+#!/bin/sh
+#
+# Copyright (c) 2013 Ramkumar Ramachandra
+#
+
+test_description='git rebase --autostash tests'
+. ./test-lib.sh
+
+test_expect_success setup '
+	echo hello-world >file0 &&
+	git add . &&
+	test_tick &&
+	git commit -m "initial commit" &&
+	git checkout -b feature-branch &&
+	echo another-hello >file1 &&
+	echo goodbye >file2 &&
+	git add . &&
+	test_tick &&
+	git commit -m "second commit" &&
+	echo final-goodbye >file3 &&
+	git add . &&
+	test_tick &&
+	git commit -m "third commit" &&
+	git checkout -b unrelated-onto-branch master &&
+	echo unrelated >file4 &&
+	git add . &&
+	test_tick &&
+	git commit -m "unrelated commit" &&
+	git checkout -b related-onto-branch master &&
+	echo conflicting-change >file2 &&
+	git add . &&
+	test_tick &&
+	git commit -m "related commit"
+'
+
+testrebase() {
+	type=$1
+	dotest=$2
+
+	test_expect_success "rebase$type: dirty worktree, non-conflicting rebase" '
+		test_config rebase.autostash true &&
+		git reset --hard &&
+		git checkout -b rebased-feature-branch feature-branch &&
+		test_when_finished git branch -D rebased-feature-branch &&
+		echo dirty >>file3 &&
+		git rebase$type unrelated-onto-branch &&
+		grep unrelated file4 &&
+		grep dirty file3 &&
+		git checkout feature-branch
+	'
+
+	test_expect_success "rebase$type: dirty index, non-conflicting rebase" '
+		test_config rebase.autostash true &&
+		git reset --hard &&
+		git checkout -b rebased-feature-branch feature-branch &&
+		test_when_finished git branch -D rebased-feature-branch &&
+		echo dirty >>file3 &&
+		git add file3 &&
+		git rebase$type unrelated-onto-branch &&
+		grep unrelated file4 &&
+		grep dirty file3 &&
+		git checkout feature-branch
+	'
+
+	test_expect_success "rebase$type: conflicting rebase" '
+		test_config rebase.autostash true &&
+		git reset --hard &&
+		git checkout -b rebased-feature-branch feature-branch &&
+		test_when_finished git branch -D rebased-feature-branch &&
+		echo dirty >>file3 &&
+		test_must_fail git rebase$type related-onto-branch &&
+		test_path_is_file $dotest/autostash &&
+		! grep dirty file3 &&
+		rm -rf $dotest &&
+		git reset --hard &&
+		git checkout feature-branch
+	'
+
+	test_expect_success "rebase$type: --continue" '
+		test_config rebase.autostash true &&
+		git reset --hard &&
+		git checkout -b rebased-feature-branch feature-branch &&
+		test_when_finished git branch -D rebased-feature-branch &&
+		echo dirty >>file3 &&
+		test_must_fail git rebase$type related-onto-branch &&
+		test_path_is_file $dotest/autostash &&
+		! grep dirty file3 &&
+		echo "conflicting-plus-goodbye" >file2 &&
+		git add file2 &&
+		git rebase --continue &&
+		test_path_is_missing $dotest/autostash &&
+		grep dirty file3 &&
+		git checkout feature-branch
+	'
+
+	test_expect_success "rebase$type: --skip" '
+		test_config rebase.autostash true &&
+		git reset --hard &&
+		git checkout -b rebased-feature-branch feature-branch &&
+		test_when_finished git branch -D rebased-feature-branch &&
+		echo dirty >>file3 &&
+		test_must_fail git rebase$type related-onto-branch &&
+		test_path_is_file $dotest/autostash &&
+		! grep dirty file3 &&
+		git rebase --skip &&
+		test_path_is_missing $dotest/autostash &&
+		grep dirty file3 &&
+		git checkout feature-branch
+	'
+
+	test_expect_success "rebase$type: --abort" '
+		test_config rebase.autostash true &&
+		git reset --hard &&
+		git checkout -b rebased-feature-branch feature-branch &&
+		test_when_finished git branch -D rebased-feature-branch &&
+		echo dirty >>file3 &&
+		test_must_fail git rebase$type related-onto-branch &&
+		test_path_is_file $dotest/autostash &&
+		! grep dirty file3 &&
+		git rebase --abort &&
+		test_path_is_missing $dotest/autostash &&
+		grep dirty file3 &&
+		git checkout feature-branch
+	'
+
+	test_expect_success "rebase$type: non-conflicting rebase, conflicting stash" '
+		test_config rebase.autostash true &&
+		git reset --hard &&
+		git checkout -b rebased-feature-branch feature-branch &&
+		test_when_finished git branch -D rebased-feature-branch &&
+		echo dirty >file4 &&
+		git add file4 &&
+		git rebase$type unrelated-onto-branch &&
+		test_path_is_missing $dotest &&
+		git reset --hard &&
+		grep unrelated file4 &&
+		! grep dirty file4 &&
+		git checkout feature-branch &&
+		git stash pop &&
+		grep dirty file4
+	'
+}
+
+test_expect_success "rebase: fast-forward rebase" '
+	test_config rebase.autostash true &&
+	git reset --hard &&
+	git checkout -b behind-feature-branch feature-branch~1 &&
+	test_when_finished git branch -D behind-feature-branch &&
+	echo dirty >>file1 &&
+	git rebase feature-branch &&
+	grep dirty file1 &&
+	git checkout feature-branch
+'
+
+test_expect_success "rebase: noop rebase" '
+	test_config rebase.autostash true &&
+	git reset --hard &&
+	git checkout -b same-feature-branch feature-branch &&
+	test_when_finished git branch -D same-feature-branch &&
+	echo dirty >>file1 &&
+	git rebase feature-branch &&
+	grep dirty file1 &&
+	git checkout feature-branch
+'
+
+testrebase "" .git/rebase-apply
+testrebase " --merge" .git/rebase-merge
+testrebase " --interactive" .git/rebase-merge
+
+test_done
diff --git a/t/t3421-rebase-topology-linear.sh b/t/t3421-rebase-topology-linear.sh
new file mode 100755
index 0000000..9c55cba
--- /dev/null
+++ b/t/t3421-rebase-topology-linear.sh
@@ -0,0 +1,350 @@
+#!/bin/sh
+
+test_description='basic rebase topology tests'
+. ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-rebase.sh
+
+# a---b---c
+#      \
+#       d---e
+test_expect_success 'setup' '
+	test_commit a &&
+	test_commit b &&
+	test_commit c &&
+	git checkout b &&
+	test_commit d &&
+	test_commit e
+'
+
+test_run_rebase () {
+	result=$1
+	shift
+	test_expect_$result "simple rebase $*" "
+		reset_rebase &&
+		git rebase $* c e &&
+		test_cmp_rev c HEAD~2 &&
+		test_linear_range 'd e' c..
+	"
+}
+test_run_rebase success ''
+test_run_rebase success -m
+test_run_rebase success -i
+test_run_rebase success -p
+
+test_run_rebase () {
+	result=$1
+	shift
+	test_expect_$result "rebase $* is no-op if upstream is an ancestor" "
+		reset_rebase &&
+		git rebase $* b e &&
+		test_cmp_rev e HEAD
+	"
+}
+test_run_rebase success ''
+test_run_rebase success -m
+test_run_rebase success -i
+test_run_rebase success -p
+
+test_run_rebase () {
+	result=$1
+	shift
+	test_expect_$result "rebase $* -f rewrites even if upstream is an ancestor" "
+		reset_rebase &&
+		git rebase $* -f b e &&
+		! test_cmp_rev e HEAD &&
+		test_cmp_rev b HEAD~2 &&
+		test_linear_range 'd e' b..
+	"
+}
+test_run_rebase success ''
+test_run_rebase success -m
+test_run_rebase success -i
+test_run_rebase failure -p
+
+test_run_rebase () {
+	result=$1
+	shift
+	test_expect_$result "rebase $* fast-forwards from ancestor of upstream" "
+		reset_rebase &&
+		git rebase $* e b &&
+		test_cmp_rev e HEAD
+	"
+}
+test_run_rebase success ''
+test_run_rebase success -m
+test_run_rebase success -i
+test_run_rebase success -p
+
+#       f
+#      /
+# a---b---c---g---h
+#      \
+#       d---gp--i
+#
+# gp = cherry-picked g
+# h = reverted g
+#
+# Reverted patches are there for tests to be able to check if a commit
+# that introduced the same change as another commit is
+# dropped. Without reverted commits, we could get false positives
+# because applying the patch succeeds, but simply results in no
+# changes.
+test_expect_success 'setup of linear history for range selection tests' '
+	git checkout c &&
+	test_commit g &&
+	revert h g &&
+	git checkout d &&
+	cherry_pick gp g &&
+	test_commit i &&
+	git checkout b &&
+	test_commit f
+'
+
+test_run_rebase () {
+	result=$1
+	shift
+	test_expect_$result "rebase $* drops patches in upstream" "
+		reset_rebase &&
+		git rebase $* h i &&
+		test_cmp_rev h HEAD~2 &&
+		test_linear_range 'd i' h..
+	"
+}
+test_run_rebase success ''
+test_run_rebase failure -m
+test_run_rebase success -i
+test_run_rebase success -p
+
+test_run_rebase () {
+	result=$1
+	shift
+	test_expect_$result "rebase $* can drop last patch if in upstream" "
+		reset_rebase &&
+		git rebase $* h gp &&
+		test_cmp_rev h HEAD^ &&
+		test_linear_range 'd' h..
+	"
+}
+test_run_rebase success ''
+test_run_rebase failure -m
+test_run_rebase success -i
+test_run_rebase success -p
+
+test_run_rebase () {
+	result=$1
+	shift
+	test_expect_$result "rebase $* --onto drops patches in upstream" "
+		reset_rebase &&
+		git rebase $* --onto f h i &&
+		test_cmp_rev f HEAD~2 &&
+		test_linear_range 'd i' f..
+	"
+}
+test_run_rebase success ''
+test_run_rebase failure -m
+test_run_rebase success -i
+test_run_rebase success -p
+
+test_run_rebase () {
+	result=$1
+	shift
+	test_expect_$result "rebase $* --onto does not drop patches in onto" "
+		reset_rebase &&
+		git rebase $* --onto h f i &&
+		test_cmp_rev h HEAD~3 &&
+		test_linear_range 'd gp i' h..
+	"
+}
+test_run_rebase success ''
+test_run_rebase success -m
+test_run_rebase success -i
+test_run_rebase success -p
+
+# a---b---c---j!
+#      \
+#       d---k!--l
+#
+# ! = empty
+test_expect_success 'setup of linear history for empty commit tests' '
+	git checkout c &&
+	make_empty j &&
+	git checkout d &&
+	make_empty k &&
+	test_commit l
+'
+
+test_run_rebase () {
+	result=$1
+	shift
+	test_expect_$result "rebase $* drops empty commit" "
+		reset_rebase &&
+		git rebase $* c l &&
+		test_cmp_rev c HEAD~2 &&
+		test_linear_range 'd l' c..
+	"
+}
+test_run_rebase success ''
+test_run_rebase success -m
+test_run_rebase success -i
+test_run_rebase success -p
+
+test_run_rebase () {
+	result=$1
+	shift
+	test_expect_$result "rebase $* --keep-empty" "
+		reset_rebase &&
+		git rebase $* --keep-empty c l &&
+		test_cmp_rev c HEAD~3 &&
+		test_linear_range 'd k l' c..
+	"
+}
+test_run_rebase success ''
+test_run_rebase failure -m
+test_run_rebase success -i
+test_run_rebase failure -p
+
+test_run_rebase () {
+	result=$1
+	shift
+	test_expect_$result "rebase $* --keep-empty keeps empty even if already in upstream" "
+		reset_rebase &&
+		git rebase $* --keep-empty j l &&
+		test_cmp_rev j HEAD~3 &&
+		test_linear_range 'd k l' j..
+	"
+}
+test_run_rebase success ''
+test_run_rebase failure -m
+test_run_rebase failure -i
+test_run_rebase failure -p
+
+#       m
+#      /
+# a---b---c---g
+#
+# x---y---bp
+#
+# bp = cherry-picked b
+# m = reverted b
+#
+# Reverted patches are there for tests to be able to check if a commit
+# that introduced the same change as another commit is
+# dropped. Without reverted commits, we could get false positives
+# because applying the patch succeeds, but simply results in no
+# changes.
+test_expect_success 'setup of linear history for test involving root' '
+	git checkout b &&
+	revert m b &&
+	git checkout --orphan disjoint &&
+	git rm -rf . &&
+	test_commit x &&
+	test_commit y &&
+	cherry_pick bp b
+'
+
+test_run_rebase () {
+	result=$1
+	shift
+	test_expect_$result "rebase $* --onto --root" "
+		reset_rebase &&
+		git rebase $* --onto c --root y &&
+		test_cmp_rev c HEAD~2 &&
+		test_linear_range 'x y' c..
+	"
+}
+test_run_rebase success ''
+test_run_rebase failure -m
+test_run_rebase success -i
+test_run_rebase success -p
+
+test_run_rebase () {
+	result=$1
+	shift
+	test_expect_$result "rebase $* without --onto --root with disjoint history" "
+		reset_rebase &&
+		git rebase $* c y &&
+		test_cmp_rev c HEAD~2 &&
+		test_linear_range 'x y' c..
+	"
+}
+test_run_rebase success ''
+test_run_rebase failure -m
+test_run_rebase success -i
+test_run_rebase failure -p
+
+test_run_rebase () {
+	result=$1
+	shift
+	test_expect_$result "rebase $* --onto --root drops patch in onto" "
+		reset_rebase &&
+		git rebase $* --onto m --root bp &&
+		test_cmp_rev m HEAD~2 &&
+		test_linear_range 'x y' m..
+	"
+}
+test_run_rebase success ''
+test_run_rebase failure -m
+test_run_rebase success -i
+test_run_rebase success -p
+
+test_run_rebase () {
+	result=$1
+	shift
+	test_expect_$result "rebase $* --onto --root with merge-base does not go to root" "
+		reset_rebase &&
+		git rebase $* --onto m --root g &&
+		test_cmp_rev m HEAD~2 &&
+		test_linear_range 'c g' m..
+	"
+}
+
+test_run_rebase success ''
+test_run_rebase success -m
+test_run_rebase success -i
+test_run_rebase failure -p
+
+test_run_rebase () {
+	result=$1
+	shift
+	test_expect_$result "rebase $* without --onto --root with disjoint history drops patch in onto" "
+		reset_rebase &&
+		git rebase $* m bp &&
+		test_cmp_rev m HEAD~2 &&
+		test_linear_range 'x y' m..
+	"
+}
+test_run_rebase success ''
+test_run_rebase failure -m
+test_run_rebase success -i
+test_run_rebase failure -p
+
+test_run_rebase () {
+	result=$1
+	shift
+	test_expect_$result "rebase $* --root on linear history is a no-op" "
+		reset_rebase &&
+		git rebase $* --root c &&
+		test_cmp_rev c HEAD
+	"
+}
+test_run_rebase failure ''
+test_run_rebase failure -m
+test_run_rebase failure -i
+test_run_rebase failure -p
+
+test_run_rebase () {
+	result=$1
+	shift
+	test_expect_$result "rebase $* -f --root on linear history causes re-write" "
+		reset_rebase &&
+		git rebase $* -f --root c &&
+		! test_cmp_rev a HEAD~2 &&
+		test_linear_range 'a b c' HEAD
+	"
+}
+test_run_rebase success ''
+test_run_rebase success -m
+test_run_rebase success -i
+test_run_rebase success -p
+
+test_done
diff --git a/t/t3425-rebase-topology-merges.sh b/t/t3425-rebase-topology-merges.sh
new file mode 100755
index 0000000..1d195fb
--- /dev/null
+++ b/t/t3425-rebase-topology-merges.sh
@@ -0,0 +1,258 @@
+#!/bin/sh
+
+test_description='rebase topology tests with merges'
+. ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-rebase.sh
+
+test_revision_subjects () {
+	expected="$1"
+	shift
+	set -- $(git log --format=%s --no-walk=unsorted "$@")
+	test "$expected" = "$*"
+}
+
+# a---b-----------c
+#      \           \
+#       d-------e   \
+#        \       \   \
+#         n---o---w---v
+#              \
+#               z
+test_expect_success 'setup of non-linear-history' '
+	test_commit a &&
+	test_commit b &&
+	test_commit c &&
+	git checkout b &&
+	test_commit d &&
+	test_commit e
+
+	git checkout c &&
+	test_commit g &&
+	revert h g &&
+	git checkout d &&
+	cherry_pick gp g &&
+	test_commit i &&
+	git checkout b &&
+	test_commit f
+
+	git checkout d &&
+	test_commit n &&
+	test_commit o &&
+	test_merge w e &&
+	test_merge v c &&
+	git checkout o &&
+	test_commit z
+'
+
+test_run_rebase () {
+	result=$1
+	shift
+	test_expect_$result "rebase $* after merge from upstream" "
+		reset_rebase &&
+		git rebase $* e w &&
+		test_cmp_rev e HEAD~2 &&
+		test_linear_range 'n o' e..
+	"
+}
+test_run_rebase success ''
+test_run_rebase success -m
+test_run_rebase success -i
+
+test_run_rebase () {
+	result=$1
+	shift
+	expected=$1
+	shift
+	test_expect_$result "rebase $* of non-linear history is linearized in place" "
+		reset_rebase &&
+		git rebase $* d w &&
+		test_cmp_rev d HEAD~3 &&
+		test_linear_range "\'"$expected"\'" d..
+	"
+}
+#TODO: make order consistent across all flavors of rebase
+test_run_rebase success 'e n o' ''
+test_run_rebase success 'e n o' -m
+test_run_rebase success 'n o e' -i
+
+test_run_rebase () {
+	result=$1
+	shift
+	expected=$1
+	shift
+	test_expect_$result "rebase $* of non-linear history is linearized upstream" "
+		reset_rebase &&
+		git rebase $* c w &&
+		test_cmp_rev c HEAD~4 &&
+		test_linear_range "\'"$expected"\'" c..
+	"
+}
+#TODO: make order consistent across all flavors of rebase
+test_run_rebase success 'd e n o' ''
+test_run_rebase success 'd e n o' -m
+test_run_rebase success 'd n o e' -i
+
+test_run_rebase () {
+	result=$1
+	shift
+	expected=$1
+	shift
+	test_expect_$result "rebase $* of non-linear history with merges after upstream merge is linearized" "
+		reset_rebase &&
+		git rebase $* c v &&
+		test_cmp_rev c HEAD~4 &&
+		test_linear_range "\'"$expected"\'" c..
+	"
+}
+#TODO: make order consistent across all flavors of rebase
+test_run_rebase success 'd e n o' ''
+test_run_rebase success 'd e n o' -m
+test_run_rebase success 'd n o e' -i
+
+test_expect_success "rebase -p is no-op in non-linear history" "
+	reset_rebase &&
+	git rebase -p d w &&
+	test_cmp_rev w HEAD
+"
+
+test_expect_success "rebase -p is no-op when base inside second parent" "
+	reset_rebase &&
+	git rebase -p e w &&
+	test_cmp_rev w HEAD
+"
+
+test_expect_failure "rebase -p --root on non-linear history is a no-op" "
+	reset_rebase &&
+	git rebase -p --root w &&
+	test_cmp_rev w HEAD
+"
+
+test_expect_success "rebase -p re-creates merge from side branch" "
+	reset_rebase &&
+	git rebase -p z w &&
+	test_cmp_rev z HEAD^ &&
+	test_cmp_rev w^2 HEAD^2
+"
+
+test_expect_success "rebase -p re-creates internal merge" "
+	reset_rebase &&
+	git rebase -p c w &&
+	test_cmp_rev c HEAD~4 &&
+	test_cmp_rev HEAD^2^ HEAD~3 &&
+	test_revision_subjects 'd n e o w' HEAD~3 HEAD~2 HEAD^2 HEAD^ HEAD
+"
+
+test_expect_success "rebase -p can re-create two branches on onto" "
+	reset_rebase &&
+	git rebase -p --onto c d w &&
+	test_cmp_rev c HEAD~3 &&
+	test_cmp_rev c HEAD^2^ &&
+	test_revision_subjects 'n e o w' HEAD~2 HEAD^2 HEAD^ HEAD
+"
+
+#       f
+#      /
+# a---b---c---g---h
+#      \
+#       d---gp--i
+#        \       \
+#         e-------u
+#
+# gp = cherry-picked g
+# h = reverted g
+test_expect_success 'setup of non-linear-history for patch-equivalence tests' '
+	git checkout e &&
+	test_merge u i
+'
+
+test_expect_success "rebase -p re-creates history around dropped commit matching upstream" "
+	reset_rebase &&
+	git rebase -p h u &&
+	test_cmp_rev h HEAD~3 &&
+	test_cmp_rev HEAD^2^ HEAD~2 &&
+	test_revision_subjects 'd i e u' HEAD~2 HEAD^2 HEAD^ HEAD
+"
+
+test_expect_success "rebase -p --onto in merged history drops patches in upstream" "
+	reset_rebase &&
+	git rebase -p --onto f h u &&
+	test_cmp_rev f HEAD~3 &&
+	test_cmp_rev HEAD^2^ HEAD~2 &&
+	test_revision_subjects 'd i e u' HEAD~2 HEAD^2 HEAD^ HEAD
+"
+
+test_expect_success "rebase -p --onto in merged history does not drop patches in onto" "
+	reset_rebase &&
+	git rebase -p --onto h f u &&
+	test_cmp_rev h HEAD~3 &&
+	test_cmp_rev HEAD^2~2 HEAD~2 &&
+	test_revision_subjects 'd gp i e u' HEAD~2 HEAD^2^ HEAD^2 HEAD^ HEAD
+"
+
+# a---b---c---g---h
+#      \
+#       d---gp--s
+#        \   \ /
+#         \   X
+#          \ / \
+#           e---t
+#
+# gp = cherry-picked g
+# h = reverted g
+test_expect_success 'setup of non-linear-history for dropping whole side' '
+	git checkout gp &&
+	test_merge s e &&
+	git checkout e &&
+	test_merge t gp
+'
+
+test_expect_failure "rebase -p drops merge commit when entire first-parent side is dropped" "
+	reset_rebase &&
+	git rebase -p h s &&
+	test_cmp_rev h HEAD~2 &&
+	test_linear_range 'd e' h..
+"
+
+test_expect_success "rebase -p drops merge commit when entire second-parent side is dropped" "
+	reset_rebase &&
+	git rebase -p h t &&
+	test_cmp_rev h HEAD~2 &&
+	test_linear_range 'd e' h..
+"
+
+# a---b---c
+#      \
+#       d---e
+#        \   \
+#         n---r
+#          \
+#           o
+#
+# r = tree-same with n
+test_expect_success 'setup of non-linear-history for empty commits' '
+	git checkout n &&
+	git merge --no-commit e &&
+	git reset n . &&
+	git commit -m r &&
+	git reset --hard &&
+	git clean -f &&
+	git tag r
+'
+
+test_expect_success "rebase -p re-creates empty internal merge commit" "
+	reset_rebase &&
+	git rebase -p c r &&
+	test_cmp_rev c HEAD~3 &&
+	test_cmp_rev HEAD^2^ HEAD~2 &&
+	test_revision_subjects 'd e n r' HEAD~2 HEAD^2 HEAD^ HEAD
+"
+
+test_expect_success "rebase -p re-creates empty merge commit" "
+	reset_rebase &&
+	git rebase -p o r &&
+	test_cmp_rev e HEAD^2 &&
+	test_cmp_rev o HEAD^ &&
+	test_revision_subjects 'r' HEAD
+"
+
+test_done
diff --git a/t/t3505-cherry-pick-empty.sh b/t/t3505-cherry-pick-empty.sh
index a0c6e30..fbdc47c 100755
--- a/t/t3505-cherry-pick-empty.sh
+++ b/t/t3505-cherry-pick-empty.sh
@@ -28,29 +28,21 @@
 '
 
 test_expect_success 'cherry-pick an empty commit' '
-	git checkout master && {
-		git cherry-pick empty-branch^
-		test "$?" = 1
-	}
+	git checkout master &&
+	test_expect_code 1 git cherry-pick empty-branch^
 '
 
 test_expect_success 'index lockfile was removed' '
-
 	test ! -f .git/index.lock
-
 '
 
 test_expect_success 'cherry-pick a commit with an empty message' '
-	git checkout master && {
-		git cherry-pick empty-branch
-		test "$?" = 1
-	}
+	git checkout master &&
+	test_expect_code 1 git cherry-pick empty-branch
 '
 
 test_expect_success 'index lockfile was removed' '
-
 	test ! -f .git/index.lock
-
 '
 
 test_expect_success 'cherry-pick a commit with an empty message with --allow-empty-message' '
@@ -101,7 +93,7 @@
 	git reset --hard &&
 	git checkout fork^0 &&
 	git cherry-pick --keep-redundant-commits master &&
-	git show -s --format='%s' >actual &&
+	git show -s --format=%s >actual &&
 	echo "add file2 on master" >expect &&
 	test_cmp expect actual
 '
diff --git a/t/t3509-cherry-pick-merge-df.sh b/t/t3509-cherry-pick-merge-df.sh
index df921d1..a5b6a5f 100755
--- a/t/t3509-cherry-pick-merge-df.sh
+++ b/t/t3509-cherry-pick-merge-df.sh
@@ -10,17 +10,15 @@
 	git commit -m a
 '
 
-test_expect_success SYMLINKS 'Setup rename across paths each below D/F conflicts' '
+test_expect_success 'Setup rename across paths each below D/F conflicts' '
 	mkdir b &&
-	ln -s ../a b/a &&
-	git add b &&
+	test_ln_s_add ../a b/a &&
 	git commit -m b &&
 
 	git checkout -b branch &&
 	rm b/a &&
-	mv a b/a &&
-	ln -s b/a a &&
-	git add . &&
+	git mv a b/a &&
+	test_ln_s_add b/a a &&
 	git commit -m swap &&
 
 	>f1 &&
@@ -28,7 +26,7 @@
 	git commit -m f1
 '
 
-test_expect_success SYMLINKS 'Cherry-pick succeeds with rename across D/F conflicts' '
+test_expect_success 'Cherry-pick succeeds with rename across D/F conflicts' '
 	git reset --hard &&
 	git checkout master^0 &&
 	git cherry-pick branch
diff --git a/t/t3600-rm.sh b/t/t3600-rm.sh
index 0c44e9f..5c87b55 100755
--- a/t/t3600-rm.sh
+++ b/t/t3600-rm.sh
@@ -687,4 +687,100 @@
 	test_path_is_file e/f
 '
 
+test_expect_success 'setup for testing rm messages' '
+	>bar.txt &&
+	>foo.txt &&
+	git add bar.txt foo.txt
+'
+
+test_expect_success 'rm files with different staged content' '
+	cat >expect <<-\EOF &&
+	error: the following files have staged content different from both the
+	file and the HEAD:
+	    bar.txt
+	    foo.txt
+	(use -f to force removal)
+	EOF
+	echo content1 >foo.txt &&
+	echo content1 >bar.txt &&
+	test_must_fail git rm foo.txt bar.txt 2>actual &&
+	test_i18ncmp expect actual
+'
+
+test_expect_success 'rm files with different staged content without hints' '
+	cat >expect <<-\EOF &&
+	error: the following files have staged content different from both the
+	file and the HEAD:
+	    bar.txt
+	    foo.txt
+	EOF
+	echo content2 >foo.txt &&
+	echo content2 >bar.txt &&
+	test_must_fail git -c advice.rmhints=false rm foo.txt bar.txt 2>actual &&
+	test_i18ncmp expect actual
+'
+
+test_expect_success 'rm file with local modification' '
+	cat >expect <<-\EOF &&
+	error: the following file has local modifications:
+	    foo.txt
+	(use --cached to keep the file, or -f to force removal)
+	EOF
+	git commit -m "testing rm 3" &&
+	echo content3 >foo.txt &&
+	test_must_fail git rm foo.txt 2>actual &&
+	test_i18ncmp expect actual
+'
+
+test_expect_success 'rm file with local modification without hints' '
+	cat >expect <<-\EOF &&
+	error: the following file has local modifications:
+	    bar.txt
+	EOF
+	echo content4 >bar.txt &&
+	test_must_fail git -c advice.rmhints=false rm bar.txt 2>actual &&
+	test_i18ncmp expect actual
+'
+
+test_expect_success 'rm file with changes in the index' '
+	cat >expect <<-\EOF &&
+	error: the following file has changes staged in the index:
+	    foo.txt
+	(use --cached to keep the file, or -f to force removal)
+	EOF
+	git reset --hard &&
+	echo content5 >foo.txt &&
+	git add foo.txt &&
+	test_must_fail git rm foo.txt 2>actual &&
+	test_i18ncmp expect actual
+'
+
+test_expect_success 'rm file with changes in the index without hints' '
+	cat >expect <<-\EOF &&
+	error: the following file has changes staged in the index:
+	    foo.txt
+	EOF
+	test_must_fail git -c advice.rmhints=false rm foo.txt 2>actual &&
+	test_i18ncmp expect actual
+'
+
+test_expect_success 'rm files with two different errors' '
+	cat >expect <<-\EOF &&
+	error: the following file has staged content different from both the
+	file and the HEAD:
+	    foo1.txt
+	(use -f to force removal)
+	error: the following file has changes staged in the index:
+	    bar1.txt
+	(use --cached to keep the file, or -f to force removal)
+	EOF
+	echo content >foo1.txt &&
+	git add foo1.txt &&
+	echo content6 >foo1.txt &&
+	echo content6 >bar1.txt &&
+	git add bar1.txt &&
+	test_must_fail git rm bar1.txt foo1.txt 2>actual &&
+	test_i18ncmp expect actual
+'
+
 test_done
diff --git a/t/t3700-add.sh b/t/t3700-add.sh
index 874b3a6..aab86e8 100755
--- a/t/t3700-add.sh
+++ b/t/t3700-add.sh
@@ -30,10 +30,9 @@
 	 *) echo fail; git ls-files --stage xfoo1; (exit 1);;
 	 esac'
 
-test_expect_success SYMLINKS 'git add: filemode=0 should not get confused by symlink' '
+test_expect_success 'git add: filemode=0 should not get confused by symlink' '
 	rm -f xfoo1 &&
-	ln -s foo xfoo1 &&
-	git add xfoo1 &&
+	test_ln_s_add foo xfoo1 &&
 	case "`git ls-files --stage xfoo1`" in
 	120000" "*xfoo1) echo pass;;
 	*) echo fail; git ls-files --stage xfoo1; (exit 1);;
@@ -51,21 +50,19 @@
 	 *) echo fail; git ls-files --stage xfoo2; (exit 1);;
 	 esac'
 
-test_expect_success SYMLINKS 'git add: filemode=0 should not get confused by symlink' '
+test_expect_success 'git add: filemode=0 should not get confused by symlink' '
 	rm -f xfoo2 &&
-	ln -s foo xfoo2 &&
-	git update-index --add xfoo2 &&
+	test_ln_s_add foo xfoo2 &&
 	case "`git ls-files --stage xfoo2`" in
 	120000" "*xfoo2) echo pass;;
 	*) echo fail; git ls-files --stage xfoo2; (exit 1);;
 	esac
 '
 
-test_expect_success SYMLINKS \
+test_expect_success \
 	'git update-index --add: Test that executable bit is not used...' \
 	'git config core.filemode 0 &&
-	 ln -s xfoo2 xfoo3 &&
-	 git update-index --add xfoo3 &&
+	 test_ln_s_add xfoo2 xfoo3 &&	# runs git update-index --add
 	 case "`git ls-files --stage xfoo3`" in
 	 120000" "*xfoo3) echo pass;;
 	 *) echo fail; git ls-files --stage xfoo3; (exit 1);;
diff --git a/t/t3900-i18n-commit.sh b/t/t3900-i18n-commit.sh
index 37ddabb..4bf1dbe 100755
--- a/t/t3900-i18n-commit.sh
+++ b/t/t3900-i18n-commit.sh
@@ -34,11 +34,47 @@
 	test z = "z$E"
 '
 
-test_expect_failure 'UTF-16 refused because of NULs' '
+test_expect_success 'UTF-16 refused because of NULs' '
 	echo UTF-16 >F &&
-	git commit -a -F "$TEST_DIRECTORY"/t3900/UTF-16.txt
+	test_must_fail git commit -a -F "$TEST_DIRECTORY"/t3900/UTF-16.txt
 '
 
+test_expect_success 'UTF-8 invalid characters refused' '
+	test_when_finished "rm -f $HOME/stderr $HOME/invalid" &&
+	echo "UTF-8 characters" >F &&
+	printf "Commit message\n\nInvalid surrogate:\355\240\200\n" \
+		>"$HOME/invalid" &&
+	git commit -a -F "$HOME/invalid" 2>"$HOME"/stderr &&
+	grep "did not conform" "$HOME"/stderr
+'
+
+test_expect_success 'UTF-8 overlong sequences rejected' '
+	test_when_finished "rm -f $HOME/stderr $HOME/invalid" &&
+	rm -f "$HOME/stderr" "$HOME/invalid" &&
+	echo "UTF-8 overlong" >F &&
+	printf "\340\202\251ommit message\n\nThis is not a space:\300\240\n" \
+		>"$HOME/invalid" &&
+	git commit -a -F "$HOME/invalid" 2>"$HOME"/stderr &&
+	grep "did not conform" "$HOME"/stderr
+'
+
+test_expect_success 'UTF-8 non-characters refused' '
+	test_when_finished "rm -f $HOME/stderr $HOME/invalid" &&
+	echo "UTF-8 non-character 1" >F &&
+	printf "Commit message\n\nNon-character:\364\217\277\276\n" \
+		>"$HOME/invalid" &&
+	git commit -a -F "$HOME/invalid" 2>"$HOME"/stderr &&
+	grep "did not conform" "$HOME"/stderr
+'
+
+test_expect_success 'UTF-8 non-characters refused' '
+	test_when_finished "rm -f $HOME/stderr $HOME/invalid" &&
+	echo "UTF-8 non-character 2." >F &&
+	printf "Commit message\n\nNon-character:\357\267\220\n" \
+		>"$HOME/invalid" &&
+	git commit -a -F "$HOME/invalid" 2>"$HOME"/stderr &&
+	grep "did not conform" "$HOME"/stderr
+'
 
 for H in ISO8859-1 eucJP ISO-2022-JP
 do
diff --git a/t/t3900/UTF-16.txt b/t/t3900/UTF-16.txt
new file mode 100644
index 0000000..2257f05
--- /dev/null
+++ b/t/t3900/UTF-16.txt
Binary files differ
diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh
index 5dfbda7..debda7a 100755
--- a/t/t3903-stash.sh
+++ b/t/t3903-stash.sh
@@ -200,17 +200,17 @@
 	echo foo > file &&
 	git stash &&
 	git stash apply -q > output.out 2>&1 &&
-	test ! -s output.out
+	test_must_be_empty output.out
 '
 
 test_expect_success 'save -q is quiet' '
 	git stash save --quiet > output.out 2>&1 &&
-	test ! -s output.out
+	test_must_be_empty output.out
 '
 
 test_expect_success 'pop -q is quiet' '
 	git stash pop -q > output.out 2>&1 &&
-	test ! -s output.out
+	test_must_be_empty output.out
 '
 
 test_expect_success 'pop -q --index works and is quiet' '
@@ -219,13 +219,13 @@
 	git stash save --quiet &&
 	git stash pop -q --index > output.out 2>&1 &&
 	test foo = "$(git show :file)" &&
-	test ! -s output.out
+	test_must_be_empty output.out
 '
 
 test_expect_success 'drop -q is quiet' '
 	git stash &&
 	git stash drop -q > output.out 2>&1 &&
-	test ! -s output.out
+	test_must_be_empty output.out
 '
 
 test_expect_success 'stash -k' '
@@ -336,41 +336,58 @@
 
 # This test creates a commit with a symlink used for the following tests
 
-test_expect_success SYMLINKS 'stash symlink to file' '
+test_expect_success 'stash symlink to file' '
 	git reset --hard &&
-	ln -s file filelink &&
-	git add filelink &&
+	test_ln_s_add file filelink &&
 	git commit -m "Add symlink" &&
 	rm filelink &&
 	cp file filelink &&
-	git stash save "symlink to file" &&
+	git stash save "symlink to file"
+'
+
+test_expect_success SYMLINKS 'this must have re-created the symlink' '
 	test -h filelink &&
-	case "$(ls -l filelink)" in *" filelink -> file") :;; *) false;; esac &&
+	case "$(ls -l filelink)" in *" filelink -> file") :;; *) false;; esac
+'
+
+test_expect_success 'unstash must re-create the file' '
 	git stash apply &&
 	! test -h filelink &&
 	test bar = "$(cat file)"
 '
 
-test_expect_success SYMLINKS 'stash symlink to file (stage rm)' '
+test_expect_success 'stash symlink to file (stage rm)' '
 	git reset --hard &&
 	git rm filelink &&
 	cp file filelink &&
-	git stash save "symlink to file (stage rm)" &&
+	git stash save "symlink to file (stage rm)"
+'
+
+test_expect_success SYMLINKS 'this must have re-created the symlink' '
 	test -h filelink &&
-	case "$(ls -l filelink)" in *" filelink -> file") :;; *) false;; esac &&
+	case "$(ls -l filelink)" in *" filelink -> file") :;; *) false;; esac
+'
+
+test_expect_success 'unstash must re-create the file' '
 	git stash apply &&
 	! test -h filelink &&
 	test bar = "$(cat file)"
 '
 
-test_expect_success SYMLINKS 'stash symlink to file (full stage)' '
+test_expect_success 'stash symlink to file (full stage)' '
 	git reset --hard &&
 	rm filelink &&
 	cp file filelink &&
 	git add filelink &&
-	git stash save "symlink to file (full stage)" &&
+	git stash save "symlink to file (full stage)"
+'
+
+test_expect_success SYMLINKS 'this must have re-created the symlink' '
 	test -h filelink &&
-	case "$(ls -l filelink)" in *" filelink -> file") :;; *) false;; esac &&
+	case "$(ls -l filelink)" in *" filelink -> file") :;; *) false;; esac
+'
+
+test_expect_success 'unstash must re-create the file' '
 	git stash apply &&
 	! test -h filelink &&
 	test bar = "$(cat file)"
@@ -637,4 +654,23 @@
 	test_cmp output expect
 '
 
+test_expect_success 'store called with invalid commit' '
+	test_must_fail git stash store foo
+'
+
+test_expect_success 'store updates stash ref and reflog' '
+	git stash clear &&
+	git reset --hard &&
+	echo quux >bazzy &&
+	git add bazzy &&
+	STASH_ID=$(git stash create) &&
+	git reset --hard &&
+	! grep quux bazzy &&
+	git stash store -m quuxery $STASH_ID &&
+	test $(cat .git/refs/stash) = $STASH_ID &&
+	grep $STASH_ID .git/logs/refs/stash &&
+	git stash pop &&
+	grep quux bazzy
+'
+
 test_done
diff --git a/t/t4000-diff-format.sh b/t/t4000-diff-format.sh
index 6ddd469..8de36b7 100755
--- a/t/t4000-diff-format.sh
+++ b/t/t4000-diff-format.sh
@@ -15,17 +15,17 @@
 cat path0 >path1
 chmod +x path1
 
-test_expect_success \
-    'update-index --add two files with and without +x.' \
-    'git update-index --add path0 path1'
+test_expect_success 'update-index --add two files with and without +x.' '
+	git update-index --add path0 path1
+'
 
 mv path0 path0-
 sed -e 's/line/Line/' <path0- >path0
 chmod +x path0
 rm -f path1
-test_expect_success \
-    'git diff-files -p after editing work tree.' \
-    'git diff-files -p >current'
+test_expect_success 'git diff-files -p after editing work tree.' '
+	git diff-files -p >actual
+'
 
 # that's as far as it comes
 if [ "$(git config --get core.filemode)" = false ]
@@ -55,8 +55,38 @@
 -line 3
 EOF
 
-test_expect_success \
-    'validate git diff-files -p output.' \
-    'compare_diff_patch current expected'
+test_expect_success 'validate git diff-files -p output.' '
+	compare_diff_patch expected actual
+'
+
+test_expect_success 'git diff-files -s after editing work tree' '
+	git diff-files -s >actual 2>err &&
+	test_must_be_empty actual &&
+	test_must_be_empty err
+'
+
+test_expect_success 'git diff-files --no-patch as synonym for -s' '
+	git diff-files --no-patch >actual 2>err &&
+	test_must_be_empty actual &&
+	test_must_be_empty err
+'
+
+test_expect_success 'git diff-files --no-patch --patch shows the patch' '
+	git diff-files --no-patch --patch >actual &&
+	compare_diff_patch expected actual
+'
+
+test_expect_success 'git diff-files --no-patch --patch-with-raw shows the patch and raw data' '
+	git diff-files --no-patch --patch-with-raw >actual &&
+	grep -q "^:100644 100755 .* 0000000000000000000000000000000000000000 M	path0\$" actual &&
+	tail -n +4 actual >actual-patch &&
+	compare_diff_patch expected actual-patch
+'
+
+test_expect_success 'git diff-files --patch --no-patch does not show the patch' '
+	git diff-files --patch --no-patch >actual 2>err &&
+	test_must_be_empty actual &&
+	test_must_be_empty err
+'
 
 test_done
diff --git a/t/t4008-diff-break-rewrite.sh b/t/t4008-diff-break-rewrite.sh
index 73b4a24..27e98a8 100755
--- a/t/t4008-diff-break-rewrite.sh
+++ b/t/t4008-diff-break-rewrite.sh
@@ -99,11 +99,11 @@
     'validate result of -B -M (#4)' \
     'compare_diff_raw expected current'
 
-test_expect_success SYMLINKS \
+test_expect_success \
     'make file0 into something completely different' \
     'rm -f file0 &&
-     ln -s frotz file0 &&
-     git update-index file0 file1'
+     test_ln_s_add frotz file0 &&
+     git update-index file1'
 
 test_expect_success \
     'run diff with -B' \
@@ -114,7 +114,7 @@
 :100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 f5deac7be59e7eeab8657fd9ae706fd6a57daed2 M100	file1
 EOF
 
-test_expect_success SYMLINKS \
+test_expect_success \
     'validate result of -B (#5)' \
     'compare_diff_raw expected current'
 
@@ -129,7 +129,7 @@
 :100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 f5deac7be59e7eeab8657fd9ae706fd6a57daed2 R	file0	file1
 EOF
 
-test_expect_success SYMLINKS \
+test_expect_success \
     'validate result of -B -M (#6)' \
     'compare_diff_raw expected current'
 
@@ -144,7 +144,7 @@
 :100644 100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 f5deac7be59e7eeab8657fd9ae706fd6a57daed2 M	file1
 EOF
 
-test_expect_success SYMLINKS \
+test_expect_success \
     'validate result of -M (#7)' \
     'compare_diff_raw expected current'
 
diff --git a/t/t4011-diff-symlink.sh b/t/t4011-diff-symlink.sh
index f0d5041..13e7f62 100755
--- a/t/t4011-diff-symlink.sh
+++ b/t/t4011-diff-symlink.sh
@@ -9,7 +9,7 @@
 . ./test-lib.sh
 . "$TEST_DIRECTORY"/diff-lib.sh
 
-test_expect_success SYMLINKS 'diff new symlink and file' '
+test_expect_success 'diff new symlink and file' '
 	cat >expected <<-\EOF &&
 	diff --git a/frotz b/frotz
 	new file mode 120000
@@ -27,22 +27,25 @@
 	@@ -0,0 +1 @@
 	+xyzzy
 	EOF
-	ln -s xyzzy frotz &&
-	echo xyzzy >nitfol &&
+
+	# the empty tree
 	git update-index &&
 	tree=$(git write-tree) &&
-	git update-index --add frotz nitfol &&
+
+	test_ln_s_add xyzzy frotz &&
+	echo xyzzy >nitfol &&
+	git update-index --add nitfol &&
 	GIT_DIFF_OPTS=--unified=0 git diff-index -M -p $tree >current &&
 	compare_diff_patch expected current
 '
 
-test_expect_success SYMLINKS 'diff unchanged symlink and file'  '
+test_expect_success 'diff unchanged symlink and file'  '
 	tree=$(git write-tree) &&
 	git update-index frotz nitfol &&
 	test -z "$(git diff-index --name-only $tree)"
 '
 
-test_expect_success SYMLINKS 'diff removed symlink and file' '
+test_expect_success 'diff removed symlink and file' '
 	cat >expected <<-\EOF &&
 	diff --git a/frotz b/frotz
 	deleted file mode 120000
@@ -66,12 +69,18 @@
 	compare_diff_patch expected current
 '
 
-test_expect_success SYMLINKS 'diff identical, but newly created symlink and file' '
+test_expect_success 'diff identical, but newly created symlink and file' '
 	>expected &&
 	rm -f frotz nitfol &&
 	echo xyzzy >nitfol &&
 	test-chmtime +10 nitfol &&
-	ln -s xyzzy frotz &&
+	if test_have_prereq SYMLINKS
+	then
+		ln -s xyzzy frotz
+	else
+		printf xyzzy >frotz
+		# the symlink property propagates from the index
+	fi &&
 	git diff-index -M -p $tree >current &&
 	compare_diff_patch expected current &&
 
@@ -80,7 +89,7 @@
 	compare_diff_patch expected current
 '
 
-test_expect_success SYMLINKS 'diff different symlink and file' '
+test_expect_success 'diff different symlink and file' '
 	cat >expected <<-\EOF &&
 	diff --git a/frotz b/frotz
 	index 7c465af..df1db54 120000
@@ -100,7 +109,13 @@
 	+yxyyz
 	EOF
 	rm -f frotz &&
-	ln -s yxyyz frotz &&
+	if test_have_prereq SYMLINKS
+	then
+		ln -s yxyyz frotz
+	else
+		printf yxyyz >frotz
+		# the symlink property propagates from the index
+	fi &&
 	echo yxyyz >nitfol &&
 	git diff-index -M -p $tree >current &&
 	compare_diff_patch expected current
diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh
index 58d4180..668933b 100755
--- a/t/t4014-format-patch.sh
+++ b/t/t4014-format-patch.sh
@@ -972,6 +972,49 @@
 	test_cmp expect actual
 '
 
+test_expect_success '--from=ident notices bogus ident' '
+	test_must_fail git format-patch -1 --stdout --from=foo >patch
+'
+
+test_expect_success '--from=ident replaces author' '
+	git format-patch -1 --stdout --from="Me <me@example.com>" >patch &&
+	cat >expect <<-\EOF &&
+	From: Me <me@example.com>
+
+	From: A U Thor <author@example.com>
+
+	EOF
+	sed -ne "/^From:/p; /^$/p; /^---$/q" <patch >patch.head &&
+	test_cmp expect patch.head
+'
+
+test_expect_success '--from uses committer ident' '
+	git format-patch -1 --stdout --from >patch &&
+	cat >expect <<-\EOF &&
+	From: C O Mitter <committer@example.com>
+
+	From: A U Thor <author@example.com>
+
+	EOF
+	sed -ne "/^From:/p; /^$/p; /^---$/q" <patch >patch.head &&
+	test_cmp expect patch.head
+'
+
+test_expect_success 'in-body headers trigger content encoding' '
+	GIT_AUTHOR_NAME="éxötìc" test_commit exotic &&
+	test_when_finished "git reset --hard HEAD^" &&
+	git format-patch -1 --stdout --from >patch &&
+	cat >expect <<-\EOF &&
+	From: C O Mitter <committer@example.com>
+	Content-Type: text/plain; charset=UTF-8
+
+	From: éxötìc <author@example.com>
+
+	EOF
+	sed -ne "/^From:/p; /^$/p; /^Content-Type/p; /^---$/q" <patch >patch.head &&
+	test_cmp expect patch.head
+'
+
 append_signoff()
 {
 	C=$(git commit-tree HEAD^^{tree} -p HEAD) &&
diff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh
index cc3db13..3fb4b97 100755
--- a/t/t4015-diff-whitespace.sh
+++ b/t/t4015-diff-whitespace.sh
@@ -142,6 +142,351 @@
 git diff --ignore-space-at-eol > out
 test_expect_success 'another test, with --ignore-space-at-eol' 'test_cmp expect out'
 
+test_expect_success 'ignore-blank-lines: only new lines' '
+	test_seq 5 >x &&
+	git update-index x &&
+	test_seq 5 | sed "/3/i \\
+" >x &&
+	git diff --ignore-blank-lines >out &&
+	>expect &&
+	test_cmp out expect
+'
+
+test_expect_success 'ignore-blank-lines: only new lines with space' '
+	test_seq 5 >x &&
+	git update-index x &&
+	test_seq 5 | sed "/3/i \ " >x &&
+	git diff -w --ignore-blank-lines >out &&
+	>expect &&
+	test_cmp out expect
+'
+
+test_expect_success 'ignore-blank-lines: after change' '
+	cat <<-\EOF >x &&
+	1
+	2
+
+	3
+	4
+	5
+
+	6
+	7
+	EOF
+	git update-index x &&
+	cat <<-\EOF >x &&
+	change
+
+	1
+	2
+	3
+	4
+	5
+	6
+
+	7
+	EOF
+	git diff --inter-hunk-context=100 --ignore-blank-lines >out.tmp &&
+	cat <<-\EOF >expected &&
+	diff --git a/x b/x
+	--- a/x
+	+++ b/x
+	@@ -1,6 +1,7 @@
+	+change
+	+
+	 1
+	 2
+	-
+	 3
+	 4
+	 5
+	EOF
+	compare_diff_patch expected out.tmp
+'
+
+test_expect_success 'ignore-blank-lines: before change' '
+	cat <<-\EOF >x &&
+	1
+	2
+
+	3
+	4
+	5
+	6
+	7
+	EOF
+	git update-index x &&
+	cat <<-\EOF >x &&
+
+	1
+	2
+	3
+	4
+	5
+
+	6
+	7
+	change
+	EOF
+	git diff --inter-hunk-context=100 --ignore-blank-lines >out.tmp &&
+	cat <<-\EOF >expected &&
+	diff --git a/x b/x
+	--- a/x
+	+++ b/x
+	@@ -4,5 +4,7 @@
+	 3
+	 4
+	 5
+	+
+	 6
+	 7
+	+change
+	EOF
+	compare_diff_patch expected out.tmp
+'
+
+test_expect_success 'ignore-blank-lines: between changes' '
+	cat <<-\EOF >x &&
+	1
+	2
+	3
+	4
+	5
+
+
+	6
+	7
+	8
+	9
+	10
+	EOF
+	git update-index x &&
+	cat <<-\EOF >x &&
+	change
+	1
+	2
+
+	3
+	4
+	5
+	6
+	7
+	8
+
+	9
+	10
+	change
+	EOF
+	git diff --ignore-blank-lines >out.tmp &&
+	cat <<-\EOF >expected &&
+	diff --git a/x b/x
+	--- a/x
+	+++ b/x
+	@@ -1,5 +1,7 @@
+	+change
+	 1
+	 2
+	+
+	 3
+	 4
+	 5
+	@@ -8,5 +8,7 @@
+	 6
+	 7
+	 8
+	+
+	 9
+	 10
+	+change
+	EOF
+	compare_diff_patch expected out.tmp
+'
+
+test_expect_success 'ignore-blank-lines: between changes (with interhunkctx)' '
+	test_seq 10 >x &&
+	git update-index x &&
+	cat <<-\EOF >x &&
+	change
+	1
+	2
+
+	3
+	4
+	5
+
+	6
+	7
+	8
+	9
+
+	10
+	change
+	EOF
+	git diff --inter-hunk-context=2 --ignore-blank-lines >out.tmp &&
+	cat <<-\EOF >expected &&
+	diff --git a/x b/x
+	--- a/x
+	+++ b/x
+	@@ -1,10 +1,15 @@
+	+change
+	 1
+	 2
+	+
+	 3
+	 4
+	 5
+	+
+	 6
+	 7
+	 8
+	 9
+	+
+	 10
+	+change
+	EOF
+	compare_diff_patch expected out.tmp
+'
+
+test_expect_success 'ignore-blank-lines: scattered spaces' '
+	test_seq 10 >x &&
+	git update-index x &&
+	cat <<-\EOF >x &&
+	change
+	1
+	2
+	3
+
+	4
+
+	5
+
+	6
+
+
+	7
+
+	8
+	9
+	10
+	change
+	EOF
+	git diff --inter-hunk-context=4 --ignore-blank-lines >out.tmp &&
+	cat <<-\EOF >expected &&
+	diff --git a/x b/x
+	--- a/x
+	+++ b/x
+	@@ -1,3 +1,4 @@
+	+change
+	 1
+	 2
+	 3
+	@@ -8,3 +15,4 @@
+	 8
+	 9
+	 10
+	+change
+	EOF
+	compare_diff_patch expected out.tmp
+'
+
+test_expect_success 'ignore-blank-lines: spaces coalesce' '
+	test_seq 6 >x &&
+	git update-index x &&
+	cat <<-\EOF >x &&
+	change
+	1
+	2
+	3
+
+	4
+
+	5
+
+	6
+	change
+	EOF
+	git diff --inter-hunk-context=4 --ignore-blank-lines >out.tmp &&
+	cat <<-\EOF >expected &&
+	diff --git a/x b/x
+	--- a/x
+	+++ b/x
+	@@ -1,6 +1,11 @@
+	+change
+	 1
+	 2
+	 3
+	+
+	 4
+	+
+	 5
+	+
+	 6
+	+change
+	EOF
+	compare_diff_patch expected out.tmp
+'
+
+test_expect_success 'ignore-blank-lines: mix changes and blank lines' '
+	test_seq 16 >x &&
+	git update-index x &&
+	cat <<-\EOF >x &&
+	change
+	1
+	2
+
+	3
+	4
+	5
+	change
+	6
+	7
+	8
+
+	9
+	10
+	11
+	change
+	12
+	13
+	14
+
+	15
+	16
+	change
+	EOF
+	git diff --ignore-blank-lines >out.tmp &&
+	cat <<-\EOF >expected &&
+	diff --git a/x b/x
+	--- a/x
+	+++ b/x
+	@@ -1,8 +1,11 @@
+	+change
+	 1
+	 2
+	+
+	 3
+	 4
+	 5
+	+change
+	 6
+	 7
+	 8
+	@@ -9,8 +13,11 @@
+	 9
+	 10
+	 11
+	+change
+	 12
+	 13
+	 14
+	+
+	 15
+	 16
+	+change
+	EOF
+	compare_diff_patch expected out.tmp
+'
+
 test_expect_success 'check mixed spaces and tabs in indent' '
 
 	# This is indented with SP HT SP.
diff --git a/t/t4023-diff-rename-typechange.sh b/t/t4023-diff-rename-typechange.sh
index 5d20acf..55d549f 100755
--- a/t/t4023-diff-rename-typechange.sh
+++ b/t/t4023-diff-rename-typechange.sh
@@ -4,44 +4,44 @@
 
 . ./test-lib.sh
 
-test_expect_success SYMLINKS setup '
+test_expect_success setup '
 
 	rm -f foo bar &&
 	cat "$TEST_DIRECTORY"/../COPYING >foo &&
-	ln -s linklink bar &&
-	git add foo bar &&
+	test_ln_s_add linklink bar &&
+	git add foo &&
 	git commit -a -m Initial &&
 	git tag one &&
 
-	rm -f foo bar &&
+	git rm -f foo bar &&
 	cat "$TEST_DIRECTORY"/../COPYING >bar &&
-	ln -s linklink foo &&
-	git add foo bar &&
+	test_ln_s_add linklink foo &&
+	git add bar &&
 	git commit -a -m Second &&
 	git tag two &&
 
-	rm -f foo bar &&
+	git rm -f foo bar &&
 	cat "$TEST_DIRECTORY"/../COPYING >foo &&
 	git add foo &&
 	git commit -a -m Third &&
 	git tag three &&
 
 	mv foo bar &&
-	ln -s linklink foo &&
-	git add foo bar &&
+	test_ln_s_add linklink foo &&
+	git add bar &&
 	git commit -a -m Fourth &&
 	git tag four &&
 
 	# This is purely for sanity check
 
-	rm -f foo bar &&
+	git rm -f foo bar &&
 	cat "$TEST_DIRECTORY"/../COPYING >foo &&
 	cat "$TEST_DIRECTORY"/../Makefile >bar &&
 	git add foo bar &&
 	git commit -a -m Fifth &&
 	git tag five &&
 
-	rm -f foo bar &&
+	git rm -f foo bar &&
 	cat "$TEST_DIRECTORY"/../Makefile >foo &&
 	cat "$TEST_DIRECTORY"/../COPYING >bar &&
 	git add foo bar &&
@@ -50,7 +50,7 @@
 
 '
 
-test_expect_success SYMLINKS 'cross renames to be detected for regular files' '
+test_expect_success 'cross renames to be detected for regular files' '
 
 	git diff-tree five six -r --name-status -B -M | sort >actual &&
 	{
@@ -61,7 +61,7 @@
 
 '
 
-test_expect_success SYMLINKS 'cross renames to be detected for typechange' '
+test_expect_success 'cross renames to be detected for typechange' '
 
 	git diff-tree one two -r --name-status -B -M | sort >actual &&
 	{
@@ -72,7 +72,7 @@
 
 '
 
-test_expect_success SYMLINKS 'moves and renames' '
+test_expect_success 'moves and renames' '
 
 	git diff-tree three four -r --name-status -B -M | sort >actual &&
 	{
diff --git a/t/t4030-diff-textconv.sh b/t/t4030-diff-textconv.sh
index 53ec330..f75f46f 100755
--- a/t/t4030-diff-textconv.sh
+++ b/t/t4030-diff-textconv.sh
@@ -139,12 +139,10 @@
 +frotz
 \ No newline at end of file
 EOF
-# make a symlink the hard way that works on symlink-challenged file systems
+
 test_expect_success 'textconv does not act on symlinks' '
-	printf frotz > file &&
-	git add file &&
-	git ls-files -s | sed -e s/100644/120000/ |
-		git update-index --index-info &&
+	rm -f file &&
+	test_ln_s_add frotz file &&
 	git commit -m typechange &&
 	git show >diff &&
 	find_diff <diff >actual &&
diff --git a/t/t4038-diff-combined.sh b/t/t4038-diff-combined.sh
index 1261dbb..1019d7b 100755
--- a/t/t4038-diff-combined.sh
+++ b/t/t4038-diff-combined.sh
@@ -353,4 +353,52 @@
 	compare_diff_patch expected actual
 '
 
+# Test for a bug reported at
+# http://thread.gmane.org/gmane.comp.version-control.git/224410
+# where a delete lines were missing from combined diff output when they
+# occurred exactly before the context lines of a later change.
+test_expect_success 'combine diff missing delete bug' '
+	git commit -m initial --allow-empty &&
+	cat <<-\EOF >test &&
+	1
+	2
+	3
+	4
+	EOF
+	git add test &&
+	git commit -a -m side1 &&
+	git checkout -B side1 &&
+	git checkout HEAD^ &&
+	cat <<-\EOF >test &&
+	0
+	1
+	2
+	3
+	4modified
+	EOF
+	git add test &&
+	git commit -m side2 &&
+	git branch -f side2 &&
+	test_must_fail git merge --no-commit side1 &&
+	cat <<-\EOF >test &&
+	1
+	2
+	3
+	4modified
+	EOF
+	git add test &&
+	git commit -a -m merge &&
+	git diff-tree -c -p HEAD >actual.tmp &&
+	sed -e "1,/^@@@/d" < actual.tmp >actual &&
+	tr -d Q <<-\EOF >expected &&
+	- 0
+	  1
+	  2
+	  3
+	 -4
+	 +4modified
+	EOF
+	compare_diff_patch expected actual
+'
+
 test_done
diff --git a/t/t4041-diff-submodule-option.sh b/t/t4041-diff-submodule-option.sh
index 32d4a60..1751c83 100755
--- a/t/t4041-diff-submodule-option.sh
+++ b/t/t4041-diff-submodule-option.sh
@@ -1,6 +1,7 @@
 #!/bin/sh
 #
 # Copyright (c) 2009 Jens Lehmann, based on t7401 by Ping Yin
+# Copyright (c) 2011 Alexey Shumkin (+ non-UTF-8 commit encoding tests)
 #
 
 test_description='Support for verbose submodule differences in git diff
@@ -10,6 +11,9 @@
 
 . ./test-lib.sh
 
+# String "added" in German (translated with Google Translate), encoded in UTF-8,
+# used in sample commit log messages in add_file() function below.
+added=$(printf "hinzugef\303\274gt")
 add_file () {
 	(
 		cd "$1" &&
@@ -19,7 +23,8 @@
 			echo "$name" >"$name" &&
 			git add "$name" &&
 			test_tick &&
-			git commit -m "Add $name" || exit
+			msg_added_iso88591=$(echo "Add $name ($added $name)" | iconv -f utf-8 -t iso8859-1) &&
+			git -c 'i18n.commitEncoding=iso8859-1' commit -m "$msg_added_iso88591"
 		done >/dev/null &&
 		git rev-parse --short --verify HEAD
 	)
@@ -93,7 +98,7 @@
 	git diff-index -p --submodule=log HEAD >actual &&
 	cat >expected <<-EOF &&
 	Submodule sm1 $head1..$head2:
-	  > Add foo3
+	  > Add foo3 ($added foo3)
 	EOF
 	test_cmp expected actual
 '
@@ -102,7 +107,7 @@
 	git diff --submodule=log >actual &&
 	cat >expected <<-EOF &&
 	Submodule sm1 $head1..$head2:
-	  > Add foo3
+	  > Add foo3 ($added foo3)
 	EOF
 	test_cmp expected actual
 '
@@ -111,7 +116,7 @@
 	git diff --submodule >actual &&
 	cat >expected <<-EOF &&
 	Submodule sm1 $head1..$head2:
-	  > Add foo3
+	  > Add foo3 ($added foo3)
 	EOF
 	test_cmp expected actual
 '
@@ -142,8 +147,8 @@
 	git diff-index -p --submodule=log HEAD >actual &&
 	cat >expected <<-EOF &&
 	Submodule sm1 $head2..$head3 (rewind):
-	  < Add foo3
-	  < Add foo2
+	  < Add foo3 ($added foo3)
+	  < Add foo2 ($added foo2)
 	EOF
 	test_cmp expected actual
 '
@@ -153,10 +158,10 @@
 	git diff-index -p --submodule=log HEAD >actual &&
 	cat >expected <<-EOF &&
 	Submodule sm1 $head2...$head4:
-	  > Add foo5
-	  > Add foo4
-	  < Add foo3
-	  < Add foo2
+	  > Add foo5 ($added foo5)
+	  > Add foo4 ($added foo4)
+	  < Add foo3 ($added foo3)
+	  < Add foo2 ($added foo2)
 	EOF
 	test_cmp expected actual
 '
diff --git a/t/t4111-apply-subdir.sh b/t/t4111-apply-subdir.sh
index 7c39843..1618a6d 100755
--- a/t/t4111-apply-subdir.sh
+++ b/t/t4111-apply-subdir.sh
@@ -86,6 +86,20 @@
 	test_cmp expected sub/dir/file
 '
 
+test_expect_success 'apply half-broken patch from subdir of toplevel' '
+	(
+		cd sub/dir &&
+		test_must_fail git apply <<-EOF
+		--- sub/dir/file
+		+++ sub/dir/file
+		@@ -1,0 +1,0 @@
+		--- file_in_root
+		+++ file_in_root
+		@@ -1,0 +1,0 @@
+		EOF
+	)
+'
+
 test_expect_success 'apply from .git dir' '
 	cp postimage expected &&
 	cp preimage .git/file &&
diff --git a/t/t4114-apply-typechange.sh b/t/t4114-apply-typechange.sh
index f12826f..ebadbc3 100755
--- a/t/t4114-apply-typechange.sh
+++ b/t/t4114-apply-typechange.sh
@@ -9,20 +9,19 @@
 
 . ./test-lib.sh
 
-test_expect_success SYMLINKS 'setup repository and commits' '
+test_expect_success 'setup repository and commits' '
 	echo "hello world" > foo &&
 	echo "hi planet" > bar &&
 	git update-index --add foo bar &&
 	git commit -m initial &&
 	git branch initial &&
 	rm -f foo &&
-	ln -s bar foo &&
-	git update-index foo &&
+	test_ln_s_add bar foo &&
 	git commit -m "foo symlinked to bar" &&
 	git branch foo-symlinked-to-bar &&
-	rm -f foo &&
+	git rm -f foo &&
 	echo "how far is the sun?" > foo &&
-	git update-index foo &&
+	git update-index --add foo &&
 	git commit -m "foo back to file" &&
 	git branch foo-back-to-file &&
 	printf "\0" > foo &&
@@ -42,7 +41,7 @@
 	git branch foo-baz-renamed-from-foo
 	'
 
-test_expect_success SYMLINKS 'file renamed from foo to foo/baz' '
+test_expect_success 'file renamed from foo to foo/baz' '
 	git checkout -f initial &&
 	git diff-tree -M -p HEAD foo-baz-renamed-from-foo > patch &&
 	git apply --index < patch
@@ -50,7 +49,7 @@
 test_debug 'cat patch'
 
 
-test_expect_success SYMLINKS 'file renamed from foo/baz to foo' '
+test_expect_success 'file renamed from foo/baz to foo' '
 	git checkout -f foo-baz-renamed-from-foo &&
 	git diff-tree -M -p HEAD initial > patch &&
 	git apply --index < patch
@@ -58,7 +57,7 @@
 test_debug 'cat patch'
 
 
-test_expect_success SYMLINKS 'directory becomes file' '
+test_expect_success 'directory becomes file' '
 	git checkout -f foo-becomes-a-directory &&
 	git diff-tree -p HEAD initial > patch &&
 	git apply --index < patch
@@ -66,7 +65,7 @@
 test_debug 'cat patch'
 
 
-test_expect_success SYMLINKS 'file becomes directory' '
+test_expect_success 'file becomes directory' '
 	git checkout -f initial &&
 	git diff-tree -p HEAD foo-becomes-a-directory > patch &&
 	git apply --index < patch
@@ -74,7 +73,7 @@
 test_debug 'cat patch'
 
 
-test_expect_success SYMLINKS 'file becomes symlink' '
+test_expect_success 'file becomes symlink' '
 	git checkout -f initial &&
 	git diff-tree -p HEAD foo-symlinked-to-bar > patch &&
 	git apply --index < patch
@@ -82,21 +81,21 @@
 test_debug 'cat patch'
 
 
-test_expect_success SYMLINKS 'symlink becomes file' '
+test_expect_success 'symlink becomes file' '
 	git checkout -f foo-symlinked-to-bar &&
 	git diff-tree -p HEAD foo-back-to-file > patch &&
 	git apply --index < patch
 	'
 test_debug 'cat patch'
 
-test_expect_success SYMLINKS 'binary file becomes symlink' '
+test_expect_success 'binary file becomes symlink' '
 	git checkout -f foo-becomes-binary &&
 	git diff-tree -p --binary HEAD foo-symlinked-to-bar > patch &&
 	git apply --index < patch
 	'
 test_debug 'cat patch'
 
-test_expect_success SYMLINKS 'symlink becomes binary file' '
+test_expect_success 'symlink becomes binary file' '
 	git checkout -f foo-symlinked-to-bar &&
 	git diff-tree -p --binary HEAD foo-becomes-binary > patch &&
 	git apply --index < patch
@@ -104,7 +103,7 @@
 test_debug 'cat patch'
 
 
-test_expect_success SYMLINKS 'symlink becomes directory' '
+test_expect_success 'symlink becomes directory' '
 	git checkout -f foo-symlinked-to-bar &&
 	git diff-tree -p HEAD foo-becomes-a-directory > patch &&
 	git apply --index < patch
@@ -112,7 +111,7 @@
 test_debug 'cat patch'
 
 
-test_expect_success SYMLINKS 'directory becomes symlink' '
+test_expect_success 'directory becomes symlink' '
 	git checkout -f foo-becomes-a-directory &&
 	git diff-tree -p HEAD foo-symlinked-to-bar > patch &&
 	git apply --index < patch
diff --git a/t/t4115-apply-symlink.sh b/t/t4115-apply-symlink.sh
index 7674dd2..872fcda 100755
--- a/t/t4115-apply-symlink.sh
+++ b/t/t4115-apply-symlink.sh
@@ -9,18 +9,16 @@
 
 . ./test-lib.sh
 
-test_expect_success SYMLINKS setup '
+test_expect_success setup '
 
-	ln -s path1/path2/path3/path4/path5 link1 &&
-	git add link? &&
+	test_ln_s_add path1/path2/path3/path4/path5 link1 &&
 	git commit -m initial &&
 
 	git branch side &&
 
 	rm -f link? &&
 
-	ln -s htap6 link1 &&
-	git update-index link? &&
+	test_ln_s_add htap6 link1 &&
 	git commit -m second &&
 
 	git diff-tree -p HEAD^ HEAD >patch  &&
@@ -37,7 +35,7 @@
 
 '
 
-test_expect_success SYMLINKS 'apply --index symlink patch' '
+test_expect_success 'apply --index symlink patch' '
 
 	git checkout -f side &&
 	git apply --index patch &&
diff --git a/t/t4122-apply-symlink-inside.sh b/t/t4122-apply-symlink-inside.sh
index 3940737..70b3a06 100755
--- a/t/t4122-apply-symlink-inside.sh
+++ b/t/t4122-apply-symlink-inside.sh
@@ -10,11 +10,11 @@
 	done
 }
 
-test_expect_success SYMLINKS setup '
+test_expect_success setup '
 
 	mkdir -p arch/i386/boot arch/x86_64 &&
 	lecho 1 2 3 4 5 >arch/i386/boot/Makefile &&
-	ln -s ../i386/boot arch/x86_64/boot &&
+	test_ln_s_add ../i386/boot arch/x86_64/boot &&
 	git add . &&
 	test_tick &&
 	git commit -m initial &&
@@ -31,7 +31,7 @@
 
 '
 
-test_expect_success SYMLINKS apply '
+test_expect_success apply '
 
 	git checkout test &&
 	git diff --exit-code test &&
@@ -40,7 +40,7 @@
 
 '
 
-test_expect_success SYMLINKS 'check result' '
+test_expect_success 'check result' '
 
 	git diff --exit-code master &&
 	git diff --exit-code --cached master &&
diff --git a/t/t4150-am.sh b/t/t4150-am.sh
index 12f6b02..5edb79a 100755
--- a/t/t4150-am.sh
+++ b/t/t4150-am.sh
@@ -147,7 +147,7 @@
 	git checkout first &&
 	test_tick &&
 	git am <patch1 &&
-	! test -d .git/rebase-apply &&
+	test_path_is_missing .git/rebase-apply &&
 	git diff --exit-code second &&
 	test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
 	test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
@@ -158,7 +158,7 @@
 	git reset --hard &&
 	git checkout first &&
 	git am patch1.eml &&
-	! test -d .git/rebase-apply &&
+	test_path_is_missing .git/rebase-apply &&
 	git diff --exit-code second &&
 	test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
 	test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
@@ -169,7 +169,7 @@
 	git reset --hard &&
 	git checkout first &&
 	git am patch1-crlf.eml &&
-	! test -d .git/rebase-apply &&
+	test_path_is_missing .git/rebase-apply &&
 	git diff --exit-code second &&
 	test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
 	test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
@@ -180,7 +180,7 @@
 	git reset --hard &&
 	git checkout first &&
 	git am patch1-ws.eml &&
-	! test -d .git/rebase-apply &&
+	test_path_is_missing .git/rebase-apply &&
 	git diff --exit-code second &&
 	test "$(git rev-parse second)" = "$(git rev-parse HEAD)" &&
 	test "$(git rev-parse second^)" = "$(git rev-parse HEAD^)"
@@ -206,7 +206,7 @@
 	git reset --hard &&
 	git checkout first &&
 	git am patch2 &&
-	! test -d .git/rebase-apply &&
+	test_path_is_missing .git/rebase-apply &&
 	test "$(git rev-parse master^^)" = "$(git rev-parse HEAD^^)" &&
 	git diff --exit-code master..HEAD &&
 	git diff --exit-code master^..HEAD^ &&
@@ -258,7 +258,7 @@
 	git reset --hard &&
 	git checkout HEAD^ &&
 	git am --keep patch4 &&
-	! test -d .git/rebase-apply &&
+	test_path_is_missing .git/rebase-apply &&
 	git cat-file commit HEAD >actual &&
 	grep "Re: Re: Re: \[PATCH 1/5 v2\] \[foo\] third" actual
 '
@@ -268,7 +268,7 @@
 	git reset --hard &&
 	git checkout HEAD^ &&
 	git am --keep-non-patch patch4 &&
-	! test -d .git/rebase-apply &&
+	test_path_is_missing .git/rebase-apply &&
 	git cat-file commit HEAD >actual &&
 	grep "^\[foo\] third" actual
 '
@@ -283,7 +283,7 @@
 	test_tick &&
 	git commit -m "copied stuff" &&
 	git am -3 lorem-move.patch &&
-	! test -d .git/rebase-apply &&
+	test_path_is_missing .git/rebase-apply &&
 	git diff --exit-code lorem
 '
 
@@ -297,7 +297,7 @@
 	test_tick &&
 	git commit -m "copied stuff" &&
 	git am -3 -p0 lorem-zero.patch &&
-	! test -d .git/rebase-apply &&
+	test_path_is_missing .git/rebase-apply &&
 	git diff --exit-code lorem
 '
 
@@ -307,7 +307,7 @@
 	git reset --hard &&
 	git checkout lorem^0 &&
 	git am rename.patch &&
-	! test -d .git/rebase-apply &&
+	test_path_is_missing .git/rebase-apply &&
 	git update-index --refresh &&
 	git diff --exit-code rename
 '
@@ -318,7 +318,7 @@
 	git reset --hard &&
 	git checkout lorem^0 &&
 	git am -3 rename.patch &&
-	! test -d .git/rebase-apply &&
+	test_path_is_missing .git/rebase-apply &&
 	git update-index --refresh &&
 	git diff --exit-code rename
 '
@@ -329,7 +329,7 @@
 	git reset --hard &&
 	git checkout lorem^0 &&
 	git am -3 rename-add.patch &&
-	! test -d .git/rebase-apply &&
+	test_path_is_missing .git/rebase-apply &&
 	git update-index --refresh &&
 	git diff --exit-code rename
 '
@@ -358,11 +358,17 @@
 test_expect_success 'am --skip works' '
 	echo goodbye >expected &&
 	git am --skip &&
-	! test -d .git/rebase-apply &&
+	test_path_is_missing .git/rebase-apply &&
 	git diff --exit-code lorem2^^ -- file &&
 	test_cmp expected another
 '
 
+test_expect_success 'am --abort removes a stray directory' '
+	mkdir .git/rebase-apply &&
+	git am --abort &&
+	test_path_is_missing .git/rebase-apply
+'
+
 test_expect_success 'am --resolved works' '
 	echo goodbye >expected &&
 	rm -fr .git/rebase-apply &&
@@ -373,7 +379,7 @@
 	echo resolved >>file &&
 	git add file &&
 	git am --resolved &&
-	! test -d .git/rebase-apply &&
+	test_path_is_missing .git/rebase-apply &&
 	test_cmp expected another
 '
 
@@ -382,7 +388,7 @@
 	git reset --hard &&
 	git checkout first &&
 	cat pine patch1 | git am &&
-	! test -d .git/rebase-apply &&
+	test_path_is_missing .git/rebase-apply &&
 	git diff --exit-code master^..HEAD
 '
 
@@ -391,7 +397,7 @@
 	git reset --hard &&
 	test_must_fail git am <failmail &&
 	git am --abort &&
-	! test -d .git/rebase-apply
+	test_path_is_missing .git/rebase-apply
 '
 
 test_expect_success 'am fails on empty patch' '
@@ -400,7 +406,7 @@
 	echo "---" >>failmail &&
 	test_must_fail git am <failmail &&
 	git am --skip &&
-	! test -d .git/rebase-apply
+	test_path_is_missing .git/rebase-apply
 '
 
 test_expect_success 'am works from stdin in subdirectory' '
diff --git a/t/t4202-log.sh b/t/t4202-log.sh
index 9243a97..cb03d28 100755
--- a/t/t4202-log.sh
+++ b/t/t4202-log.sh
@@ -530,6 +530,20 @@
 	)
 '
 
+test_expect_success 'git log -c --follow' '
+	test_create_repo follow-c &&
+	(
+		cd follow-c &&
+		test_commit initial file original &&
+		git rm file &&
+		test_commit rename file2 original &&
+		git reset --hard initial &&
+		test_commit modify file foo &&
+		git merge -m merge rename &&
+		git log -c --follow file2
+	)
+'
+
 cat >expect <<\EOF
 *   commit COMMIT_OBJECT_NAME
 |\  Merge: MERGE_PARENTS
diff --git a/t/t4203-mailmap.sh b/t/t4203-mailmap.sh
index 842b754..ce3eace 100755
--- a/t/t4203-mailmap.sh
+++ b/t/t4203-mailmap.sh
@@ -13,6 +13,11 @@
 }
 
 test_expect_success setup '
+	cat >contacts <<-\EOF &&
+	A U Thor <author@example.com>
+	nick1 <bugs@company.xx>
+	EOF
+
 	echo one >one &&
 	git add one &&
 	test_tick &&
@@ -23,6 +28,44 @@
 	git commit --author "nick1 <bugs@company.xx>" -m second
 '
 
+test_expect_success 'check-mailmap no arguments' '
+	test_must_fail git check-mailmap
+'
+
+test_expect_success 'check-mailmap arguments' '
+	cat >expect <<-\EOF &&
+	A U Thor <author@example.com>
+	nick1 <bugs@company.xx>
+	EOF
+	git check-mailmap \
+		"A U Thor <author@example.com>" \
+		"nick1 <bugs@company.xx>" >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'check-mailmap --stdin' '
+	cat >expect <<-\EOF &&
+	A U Thor <author@example.com>
+	nick1 <bugs@company.xx>
+	EOF
+	git check-mailmap --stdin <contacts >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'check-mailmap --stdin arguments' '
+	cat >expect <<-\EOF &&
+	Internal Guy <bugs@company.xy>
+	EOF
+	cat <contacts >>expect &&
+	git check-mailmap --stdin "Internal Guy <bugs@company.xy>" \
+		<contacts >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'check-mailmap bogus contact' '
+	test_must_fail git check-mailmap bogus
+'
+
 cat >expect <<\EOF
 A U Thor (1):
       initial
@@ -159,7 +202,8 @@
 	Blob Guy <author@example.com>
 	Blob Guy <bugs@company.xx>
 	EOF
-	git add just-bugs both &&
+	printf "Tricky Guy <author@example.com>" >no-newline &&
+	git add just-bugs both no-newline &&
 	git commit -m "my mailmaps" &&
 	echo "Repo Guy <author@example.com>" >.mailmap &&
 	echo "Internal Guy <author@example.com>" >internal.map
@@ -243,10 +287,41 @@
 	)
 '
 
+test_expect_success 'mailmap.blob can handle blobs without trailing newline' '
+	cat >expect <<-\EOF &&
+	Tricky Guy (1):
+	      initial
+
+	nick1 (1):
+	      second
+
+	EOF
+	git -c mailmap.blob=map:no-newline shortlog HEAD >actual &&
+	test_cmp expect actual
+'
+
 test_expect_success 'cleanup after mailmap.blob tests' '
 	rm -f .mailmap
 '
 
+test_expect_success 'single-character name' '
+	echo "     1	A <author@example.com>" >expect &&
+	echo "     1	nick1 <bugs@company.xx>" >>expect &&
+	echo "A <author@example.com>" >.mailmap &&
+	test_when_finished "rm .mailmap" &&
+	git shortlog -es HEAD >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'preserve canonical email case' '
+	echo "     1	A U Thor <AUTHOR@example.com>" >expect &&
+	echo "     1	nick1 <bugs@company.xx>" >>expect &&
+	echo "<AUTHOR@example.com> <author@example.com>" >.mailmap &&
+	test_when_finished "rm .mailmap" &&
+	git shortlog -es HEAD >actual &&
+	test_cmp expect actual
+'
+
 # Extended mailmap configurations should give us the following output for shortlog
 cat >expect <<\EOF
 A U Thor <author@example.com> (1):
diff --git a/t/t4205-log-pretty-formats.sh b/t/t4205-log-pretty-formats.sh
index 26fbfde..fb00041 100755
--- a/t/t4205-log-pretty-formats.sh
+++ b/t/t4205-log-pretty-formats.sh
@@ -1,20 +1,38 @@
 #!/bin/sh
 #
 # Copyright (c) 2010, Will Palmer
+# Copyright (c) 2011, Alexey Shumkin (+ non-UTF-8 commit encoding tests)
 #
 
 test_description='Test pretty formats'
 . ./test-lib.sh
 
+sample_utf8_part=$(printf "f\303\244ng")
+
+commit_msg () {
+	# String "initial. initial" partly in German
+	# (translated with Google Translate),
+	# encoded in UTF-8, used as a commit log message below.
+	msg="initial. an${sample_utf8_part}lich\n"
+	if test -n "$1"
+	then
+		printf "$msg" | iconv -f utf-8 -t "$1"
+	else
+		printf "$msg"
+	fi
+}
+
 test_expect_success 'set up basic repos' '
 	>foo &&
 	>bar &&
 	git add foo &&
 	test_tick &&
-	git commit -m initial &&
+	git config i18n.commitEncoding iso8859-1 &&
+	git commit -m "$(commit_msg iso8859-1)" &&
 	git add bar &&
 	test_tick &&
-	git commit -m "add bar"
+	git commit -m "add bar" &&
+	git config --unset i18n.commitEncoding
 '
 
 test_expect_success 'alias builtin format' '
@@ -38,6 +56,20 @@
 	test_cmp expected actual
 '
 
+test_expect_success 'alias user-defined tformat with %s (iso8859-1 encoding)' '
+	git config i18n.logOutputEncoding iso8859-1 &&
+	git log --oneline >expected-s &&
+	git log --pretty="tformat:%h %s" >actual-s &&
+	git config --unset i18n.logOutputEncoding &&
+	test_cmp expected-s actual-s
+'
+
+test_expect_success 'alias user-defined tformat with %s (utf-8 encoding)' '
+	git log --oneline >expected-s &&
+	git log --pretty="tformat:%h %s" >actual-s &&
+	test_cmp expected-s actual-s
+'
+
 test_expect_success 'alias user-defined tformat' '
 	git log --pretty="tformat:%h" >expected &&
 	git config pretty.test-alias "tformat:%h" &&
@@ -72,13 +104,13 @@
 '
 
 test_expect_success 'NUL separation' '
-	printf "add bar\0initial" >expected &&
+	printf "add bar\0$(commit_msg)" >expected &&
 	git log -z --pretty="format:%s" >actual &&
 	test_cmp expected actual
 '
 
 test_expect_success 'NUL termination' '
-	printf "add bar\0initial\0" >expected &&
+	printf "add bar\0$(commit_msg)\0" >expected &&
 	git log -z --pretty="tformat:%s" >actual &&
 	test_cmp expected actual
 '
@@ -86,7 +118,7 @@
 test_expect_success 'NUL separation with --stat' '
 	stat0_part=$(git diff --stat HEAD^ HEAD) &&
 	stat1_part=$(git diff-tree --no-commit-id --stat --root HEAD^) &&
-	printf "add bar\n$stat0_part\n\0initial\n$stat1_part\n" >expected &&
+	printf "add bar\n$stat0_part\n\0$(commit_msg)\n$stat1_part\n" >expected &&
 	git log -z --stat --pretty="format:%s" >actual &&
 	test_i18ncmp expected actual
 '
@@ -94,25 +126,29 @@
 test_expect_failure 'NUL termination with --stat' '
 	stat0_part=$(git diff --stat HEAD^ HEAD) &&
 	stat1_part=$(git diff-tree --no-commit-id --stat --root HEAD^) &&
-	printf "add bar\n$stat0_part\n\0initial\n$stat1_part\n\0" >expected &&
+	printf "add bar\n$stat0_part\n\0$(commit_msg)\n$stat1_part\n0" >expected &&
 	git log -z --stat --pretty="tformat:%s" >actual &&
 	test_i18ncmp expected actual
 '
 
 test_expect_success 'setup more commits' '
 	test_commit "message one" one one message-one &&
-	test_commit "message two" two two message-two
+	test_commit "message two" two two message-two &&
+	head1=$(git rev-parse --verify --short HEAD~0) &&
+	head2=$(git rev-parse --verify --short HEAD~1) &&
+	head3=$(git rev-parse --verify --short HEAD~2) &&
+	head4=$(git rev-parse --verify --short HEAD~3)
 '
 
 test_expect_success 'left alignment formatting' '
 	git log --pretty="format:%<(40)%s" >actual &&
 	# complete the incomplete line at the end
 	echo >>actual &&
-	qz_to_tab_space <<\EOF >expected &&
+	qz_to_tab_space <<EOF >expected &&
 message two                            Z
 message one                            Z
 add bar                                Z
-initial                                Z
+$(commit_msg)                    Z
 EOF
 	test_cmp expected actual
 '
@@ -121,11 +157,11 @@
 	git log --pretty="format:%h %<|(40)%s" >actual &&
 	# complete the incomplete line at the end
 	echo >>actual &&
-	qz_to_tab_space <<\EOF >expected &&
-fa33ab1 message two                    Z
-7cd6c63 message one                    Z
-1711bf9 add bar                        Z
-af20c06 initial                        Z
+	qz_to_tab_space <<EOF >expected &&
+$head1 message two                    Z
+$head2 message one                    Z
+$head3 add bar                        Z
+$head4 $(commit_msg)            Z
 EOF
 	test_cmp expected actual
 '
@@ -134,11 +170,11 @@
 	git log --pretty="format:%<(1)%s" >actual &&
 	# complete the incomplete line at the end
 	echo >>actual &&
-	cat <<\EOF >expected &&
+	cat <<EOF >expected &&
 message two
 message one
 add bar
-initial
+$(commit_msg)
 EOF
 	test_cmp expected actual
 '
@@ -147,11 +183,11 @@
 	git log --pretty="format:%<(10,trunc)%s" >actual &&
 	# complete the incomplete line at the end
 	echo >>actual &&
-	qz_to_tab_space <<\EOF >expected &&
+	qz_to_tab_space <<EOF >expected &&
 message ..
 message ..
 add bar  Z
-initial  Z
+initial...
 EOF
 	test_cmp expected actual
 '
@@ -160,11 +196,11 @@
 	git log --pretty="format:%<(10,ltrunc)%s" >actual &&
 	# complete the incomplete line at the end
 	echo >>actual &&
-	qz_to_tab_space <<\EOF >expected &&
+	qz_to_tab_space <<EOF >expected &&
 ..sage two
 ..sage one
 add bar  Z
-initial  Z
+..${sample_utf8_part}lich
 EOF
 	test_cmp expected actual
 '
@@ -173,11 +209,11 @@
 	git log --pretty="format:%<(10,mtrunc)%s" >actual &&
 	# complete the incomplete line at the end
 	echo >>actual &&
-	qz_to_tab_space <<\EOF >expected &&
+	qz_to_tab_space <<EOF >expected &&
 mess.. two
 mess.. one
 add bar  Z
-initial  Z
+init..lich
 EOF
 	test_cmp expected actual
 '
@@ -186,11 +222,11 @@
 	git log --pretty="format:%>(40)%s" >actual &&
 	# complete the incomplete line at the end
 	echo >>actual &&
-	qz_to_tab_space <<\EOF >expected &&
+	qz_to_tab_space <<EOF >expected &&
 Z                            message two
 Z                            message one
 Z                                add bar
-Z                                initial
+Z                    $(commit_msg)
 EOF
 	test_cmp expected actual
 '
@@ -199,11 +235,11 @@
 	git log --pretty="format:%h %>|(40)%s" >actual &&
 	# complete the incomplete line at the end
 	echo >>actual &&
-	qz_to_tab_space <<\EOF >expected &&
-fa33ab1                      message two
-7cd6c63                      message one
-1711bf9                          add bar
-af20c06                          initial
+	qz_to_tab_space <<EOF >expected &&
+$head1                      message two
+$head2                      message one
+$head3                          add bar
+$head4              $(commit_msg)
 EOF
 	test_cmp expected actual
 '
@@ -212,11 +248,11 @@
 	git log --pretty="format:%>(1)%s" >actual &&
 	# complete the incomplete line at the end
 	echo >>actual &&
-	cat <<\EOF >expected &&
+	cat <<EOF >expected &&
 message two
 message one
 add bar
-initial
+$(commit_msg)
 EOF
 	test_cmp expected actual
 '
@@ -225,11 +261,11 @@
 	git log --pretty="format:%><(40)%s" >actual &&
 	# complete the incomplete line at the end
 	echo >>actual &&
-	qz_to_tab_space <<\EOF >expected &&
+	qz_to_tab_space <<EOF >expected &&
 Z             message two              Z
 Z             message one              Z
 Z               add bar                Z
-Z               initial                Z
+Z         $(commit_msg)          Z
 EOF
 	test_cmp expected actual
 '
@@ -238,11 +274,11 @@
 	git log --pretty="format:%h %><|(40)%s" >actual &&
 	# complete the incomplete line at the end
 	echo >>actual &&
-	qz_to_tab_space <<\EOF >expected &&
-fa33ab1           message two          Z
-7cd6c63           message one          Z
-1711bf9             add bar            Z
-af20c06             initial            Z
+	qz_to_tab_space <<EOF >expected &&
+$head1           message two          Z
+$head2           message one          Z
+$head3             add bar            Z
+$head4       $(commit_msg)      Z
 EOF
 	test_cmp expected actual
 '
@@ -251,11 +287,11 @@
 	git log --pretty="format:%><(1)%s" >actual &&
 	# complete the incomplete line at the end
 	echo >>actual &&
-	cat <<\EOF >expected &&
+	cat <<EOF >expected &&
 message two
 message one
 add bar
-initial
+$(commit_msg)
 EOF
 	test_cmp expected actual
 '
@@ -265,11 +301,11 @@
 	git log --pretty="format:%<(10,trunc)%s%>>(10,ltrunc)% an" >actual &&
 	# complete the incomplete line at the end
 	echo >>actual &&
-	cat <<\EOF >expected &&
+	cat <<EOF >expected &&
 short long  long long
 message ..   A U Thor
 add bar      A U Thor
-initial      A U Thor
+initial...   A U Thor
 EOF
 	test_cmp expected actual
 '
diff --git a/t/t4211-line-log.sh b/t/t4211-line-log.sh
new file mode 100755
index 0000000..7665d67
--- /dev/null
+++ b/t/t4211-line-log.sh
@@ -0,0 +1,80 @@
+#!/bin/sh
+
+test_description='test log -L'
+. ./test-lib.sh
+
+test_expect_success 'setup (import history)' '
+	git fast-import < "$TEST_DIRECTORY"/t4211/history.export &&
+	git reset --hard
+'
+
+canned_test_1 () {
+	test_expect_$1 "$2" "
+		git log $2 >actual &&
+		test_cmp \"\$TEST_DIRECTORY\"/t4211/expect.$3 actual
+	"
+}
+
+canned_test () {
+	canned_test_1 success "$@"
+}
+canned_test_failure () {
+	canned_test_1 failure "$@"
+}
+
+test_bad_opts () {
+	test_expect_success "invalid args: $1" "
+		test_must_fail git log $1 2>errors &&
+		grep '$2' errors
+	"
+}
+
+canned_test "-L 4,12:a.c simple" simple-f
+canned_test "-L 4,+9:a.c simple" simple-f
+canned_test "-L '/long f/,/^}/:a.c' simple" simple-f
+canned_test "-L :f:a.c simple" simple-f-to-main
+
+canned_test "-L '/main/,/^}/:a.c' simple" simple-main
+canned_test "-L :main:a.c simple" simple-main-to-end
+
+canned_test "-L 1,+4:a.c simple" beginning-of-file
+
+canned_test "-L 20:a.c simple" end-of-file
+
+canned_test "-L '/long f/',/^}/:a.c -L /main/,/^}/:a.c simple" two-ranges
+canned_test "-L 24,+1:a.c simple" vanishes-early
+
+canned_test "-M -L '/long f/,/^}/:b.c' move-support" move-support-f
+canned_test "-M -L ':f:b.c' parallel-change" parallel-change-f-to-main
+
+canned_test "-L 4,12:a.c -L :main:a.c simple" multiple
+canned_test "-L 4,18:a.c -L :main:a.c simple" multiple-overlapping
+canned_test "-L :main:a.c -L 4,18:a.c simple" multiple-overlapping
+canned_test "-L 4:a.c -L 8,12:a.c simple" multiple-superset
+canned_test "-L 8,12:a.c -L 4:a.c simple" multiple-superset
+
+test_bad_opts "-L" "switch.*requires a value"
+test_bad_opts "-L b.c" "argument.*not of the form"
+test_bad_opts "-L 1:" "argument.*not of the form"
+test_bad_opts "-L 1:nonexistent" "There is no path"
+test_bad_opts "-L 1:simple" "There is no path"
+test_bad_opts "-L '/foo:b.c'" "argument.*not of the form"
+test_bad_opts "-L 1000:b.c" "has only.*lines"
+test_bad_opts "-L 1,1000:b.c" "has only.*lines"
+test_bad_opts "-L :b.c" "argument.*not of the form"
+test_bad_opts "-L :foo:b.c" "no match"
+
+# There is a separate bug when an empty -L range is the first -L encountered,
+# thus to demonstrate this particular bug, the empty -L range must follow a
+# non-empty -L range.
+test_expect_success '-L {empty-range} (any -L)' '
+	n=$(expr $(wc -l <b.c) + 1) &&
+	git log -L1,1:b.c -L$n:b.c
+'
+
+test_expect_success '-L {empty-range} (first -L)' '
+	n=$(expr $(wc -l <b.c) + 1) &&
+	git log -L$n:b.c
+'
+
+test_done
diff --git a/t/t4211/expect.beginning-of-file b/t/t4211/expect.beginning-of-file
new file mode 100644
index 0000000..91b4054
--- /dev/null
+++ b/t/t4211/expect.beginning-of-file
@@ -0,0 +1,43 @@
+commit 4a23ae5c98d59a58c6da036156959f2dc9f472ad
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:47:40 2013 +0100
+
+    change at very beginning
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -1,3 +1,4 @@
++#include <unistd.h>
+ #include <stdio.h>
+ 
+ long f(long x)
+
+commit a6eb82647d5d67f893da442f8f9375fd89a3b1e2
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:45:16 2013 +0100
+
+    touch both functions
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -1,3 +1,3 @@
+ #include <stdio.h>
+ 
+-int f(int x)
++long f(long x)
+
+commit de4c48ae814792c02a49c4c3c0c757ae69c55f6a
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:44:48 2013 +0100
+
+    initial
+
+diff --git a/a.c b/a.c
+--- /dev/null
++++ b/a.c
+@@ -0,0 +1,3 @@
++#include <stdio.h>
++
++int f(int x)
diff --git a/t/t4211/expect.end-of-file b/t/t4211/expect.end-of-file
new file mode 100644
index 0000000..bd25bb2
--- /dev/null
+++ b/t/t4211/expect.end-of-file
@@ -0,0 +1,62 @@
+commit 4659538844daa2849b1a9e7d6fadb96fcd26fc83
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:48:43 2013 +0100
+
+    change back to complete line
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -20,3 +20,5 @@
+ 	printf("%ld\n", f(15));
+ 	return 0;
+-}
+\ No newline at end of file
++}
++
++/* incomplete lines are bad! */
+
+commit 100b61a6f2f720f812620a9d10afb3a960ccb73c
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:48:10 2013 +0100
+
+    change to an incomplete line at end
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -20,3 +20,3 @@
+ 	printf("%ld\n", f(15));
+ 	return 0;
+-}
++}
+\ No newline at end of file
+
+commit a6eb82647d5d67f893da442f8f9375fd89a3b1e2
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:45:16 2013 +0100
+
+    touch both functions
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -19,3 +19,3 @@
+-	printf("%d\n", f(15));
++	printf("%ld\n", f(15));
+ 	return 0;
+ }
+
+commit de4c48ae814792c02a49c4c3c0c757ae69c55f6a
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:44:48 2013 +0100
+
+    initial
+
+diff --git a/a.c b/a.c
+--- /dev/null
++++ b/a.c
+@@ -0,0 +18,3 @@
++	printf("%d\n", f(15));
++	return 0;
++}
diff --git a/t/t4211/expect.move-support-f b/t/t4211/expect.move-support-f
new file mode 100644
index 0000000..c905e01
--- /dev/null
+++ b/t/t4211/expect.move-support-f
@@ -0,0 +1,80 @@
+commit 6ce3c4ff690136099bb17e1a8766b75764726ea7
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:49:50 2013 +0100
+
+    another simple change
+
+diff --git a/b.c b/b.c
+--- a/b.c
++++ b/b.c
+@@ -4,9 +4,9 @@
+ long f(long x)
+ {
+ 	int s = 0;
+ 	while (x) {
+-		x >>= 1;
++		x /= 2;
+ 		s++;
+ 	}
+ 	return s;
+ }
+
+commit a6eb82647d5d67f893da442f8f9375fd89a3b1e2
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:45:16 2013 +0100
+
+    touch both functions
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -3,9 +3,9 @@
+-int f(int x)
++long f(long x)
+ {
+ 	int s = 0;
+ 	while (x) {
+ 		x >>= 1;
+ 		s++;
+ 	}
+ 	return s;
+ }
+
+commit f04fb20f2c77850996cba739709acc6faecc58f7
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:44:55 2013 +0100
+
+    change f()
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -3,8 +3,9 @@
+ int f(int x)
+ {
+ 	int s = 0;
+ 	while (x) {
+ 		x >>= 1;
+ 		s++;
+ 	}
++	return s;
+ }
+
+commit de4c48ae814792c02a49c4c3c0c757ae69c55f6a
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:44:48 2013 +0100
+
+    initial
+
+diff --git a/a.c b/a.c
+--- /dev/null
++++ b/a.c
+@@ -0,0 +3,8 @@
++int f(int x)
++{
++	int s = 0;
++	while (x) {
++		x >>= 1;
++		s++;
++	}
++}
diff --git a/t/t4211/expect.multiple b/t/t4211/expect.multiple
new file mode 100644
index 0000000..76ad5b5
--- /dev/null
+++ b/t/t4211/expect.multiple
@@ -0,0 +1,104 @@
+commit 4659538844daa2849b1a9e7d6fadb96fcd26fc83
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:48:43 2013 +0100
+
+    change back to complete line
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -18,5 +18,7 @@
+ int main ()
+ {
+ 	printf("%ld\n", f(15));
+ 	return 0;
+-}
+\ No newline at end of file
++}
++
++/* incomplete lines are bad! */
+
+commit 100b61a6f2f720f812620a9d10afb3a960ccb73c
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:48:10 2013 +0100
+
+    change to an incomplete line at end
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -18,5 +18,5 @@
+ int main ()
+ {
+ 	printf("%ld\n", f(15));
+ 	return 0;
+-}
++}
+\ No newline at end of file
+
+commit a6eb82647d5d67f893da442f8f9375fd89a3b1e2
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:45:16 2013 +0100
+
+    touch both functions
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -3,9 +3,9 @@
+-int f(int x)
++long f(long x)
+ {
+ 	int s = 0;
+ 	while (x) {
+ 		x >>= 1;
+ 		s++;
+ 	}
+ 	return s;
+ }
+@@ -17,5 +17,5 @@
+ int main ()
+ {
+-	printf("%d\n", f(15));
++	printf("%ld\n", f(15));
+ 	return 0;
+ }
+
+commit f04fb20f2c77850996cba739709acc6faecc58f7
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:44:55 2013 +0100
+
+    change f()
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -3,8 +3,9 @@
+ int f(int x)
+ {
+ 	int s = 0;
+ 	while (x) {
+ 		x >>= 1;
+ 		s++;
+ 	}
++	return s;
+ }
+
+commit de4c48ae814792c02a49c4c3c0c757ae69c55f6a
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:44:48 2013 +0100
+
+    initial
+
+diff --git a/a.c b/a.c
+--- /dev/null
++++ b/a.c
+@@ -0,0 +3,8 @@
++int f(int x)
++{
++	int s = 0;
++	while (x) {
++		x >>= 1;
++		s++;
++	}
++}
diff --git a/t/t4211/expect.multiple-overlapping b/t/t4211/expect.multiple-overlapping
new file mode 100644
index 0000000..d930b6e
--- /dev/null
+++ b/t/t4211/expect.multiple-overlapping
@@ -0,0 +1,187 @@
+commit 4659538844daa2849b1a9e7d6fadb96fcd26fc83
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:48:43 2013 +0100
+
+    change back to complete line
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -4,19 +4,21 @@
+ long f(long x)
+ {
+ 	int s = 0;
+ 	while (x) {
+ 		x >>= 1;
+ 		s++;
+ 	}
+ 	return s;
+ }
+ 
+ /*
+  * This is only an example!
+  */
+ 
+ int main ()
+ {
+ 	printf("%ld\n", f(15));
+ 	return 0;
+-}
+\ No newline at end of file
++}
++
++/* incomplete lines are bad! */
+
+commit 100b61a6f2f720f812620a9d10afb3a960ccb73c
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:48:10 2013 +0100
+
+    change to an incomplete line at end
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -4,19 +4,19 @@
+ long f(long x)
+ {
+ 	int s = 0;
+ 	while (x) {
+ 		x >>= 1;
+ 		s++;
+ 	}
+ 	return s;
+ }
+ 
+ /*
+  * This is only an example!
+  */
+ 
+ int main ()
+ {
+ 	printf("%ld\n", f(15));
+ 	return 0;
+-}
++}
+\ No newline at end of file
+
+commit 39b6eb2d5b706d3322184a169f666f25ed3fbd00
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:45:41 2013 +0100
+
+    touch comment
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -3,19 +3,19 @@
+ long f(long x)
+ {
+ 	int s = 0;
+ 	while (x) {
+ 		x >>= 1;
+ 		s++;
+ 	}
+ 	return s;
+ }
+ 
+ /*
+- * A comment.
++ * This is only an example!
+  */
+ 
+ int main ()
+ {
+ 	printf("%ld\n", f(15));
+ 	return 0;
+ }
+
+commit a6eb82647d5d67f893da442f8f9375fd89a3b1e2
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:45:16 2013 +0100
+
+    touch both functions
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -3,19 +3,19 @@
+-int f(int x)
++long f(long x)
+ {
+ 	int s = 0;
+ 	while (x) {
+ 		x >>= 1;
+ 		s++;
+ 	}
+ 	return s;
+ }
+ 
+ /*
+  * A comment.
+  */
+ 
+ int main ()
+ {
+-	printf("%d\n", f(15));
++	printf("%ld\n", f(15));
+ 	return 0;
+ }
+
+commit f04fb20f2c77850996cba739709acc6faecc58f7
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:44:55 2013 +0100
+
+    change f()
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -3,18 +3,19 @@
+ int f(int x)
+ {
+ 	int s = 0;
+ 	while (x) {
+ 		x >>= 1;
+ 		s++;
+ 	}
++	return s;
+ }
+ 
+ /*
+  * A comment.
+  */
+ 
+ int main ()
+ {
+ 	printf("%d\n", f(15));
+ 	return 0;
+ }
+
+commit de4c48ae814792c02a49c4c3c0c757ae69c55f6a
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:44:48 2013 +0100
+
+    initial
+
+diff --git a/a.c b/a.c
+--- /dev/null
++++ b/a.c
+@@ -0,0 +3,18 @@
++int f(int x)
++{
++	int s = 0;
++	while (x) {
++		x >>= 1;
++		s++;
++	}
++}
++
++/*
++ * A comment.
++ */
++
++int main ()
++{
++	printf("%d\n", f(15));
++	return 0;
++}
diff --git a/t/t4211/expect.multiple-superset b/t/t4211/expect.multiple-superset
new file mode 100644
index 0000000..d930b6e
--- /dev/null
+++ b/t/t4211/expect.multiple-superset
@@ -0,0 +1,187 @@
+commit 4659538844daa2849b1a9e7d6fadb96fcd26fc83
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:48:43 2013 +0100
+
+    change back to complete line
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -4,19 +4,21 @@
+ long f(long x)
+ {
+ 	int s = 0;
+ 	while (x) {
+ 		x >>= 1;
+ 		s++;
+ 	}
+ 	return s;
+ }
+ 
+ /*
+  * This is only an example!
+  */
+ 
+ int main ()
+ {
+ 	printf("%ld\n", f(15));
+ 	return 0;
+-}
+\ No newline at end of file
++}
++
++/* incomplete lines are bad! */
+
+commit 100b61a6f2f720f812620a9d10afb3a960ccb73c
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:48:10 2013 +0100
+
+    change to an incomplete line at end
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -4,19 +4,19 @@
+ long f(long x)
+ {
+ 	int s = 0;
+ 	while (x) {
+ 		x >>= 1;
+ 		s++;
+ 	}
+ 	return s;
+ }
+ 
+ /*
+  * This is only an example!
+  */
+ 
+ int main ()
+ {
+ 	printf("%ld\n", f(15));
+ 	return 0;
+-}
++}
+\ No newline at end of file
+
+commit 39b6eb2d5b706d3322184a169f666f25ed3fbd00
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:45:41 2013 +0100
+
+    touch comment
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -3,19 +3,19 @@
+ long f(long x)
+ {
+ 	int s = 0;
+ 	while (x) {
+ 		x >>= 1;
+ 		s++;
+ 	}
+ 	return s;
+ }
+ 
+ /*
+- * A comment.
++ * This is only an example!
+  */
+ 
+ int main ()
+ {
+ 	printf("%ld\n", f(15));
+ 	return 0;
+ }
+
+commit a6eb82647d5d67f893da442f8f9375fd89a3b1e2
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:45:16 2013 +0100
+
+    touch both functions
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -3,19 +3,19 @@
+-int f(int x)
++long f(long x)
+ {
+ 	int s = 0;
+ 	while (x) {
+ 		x >>= 1;
+ 		s++;
+ 	}
+ 	return s;
+ }
+ 
+ /*
+  * A comment.
+  */
+ 
+ int main ()
+ {
+-	printf("%d\n", f(15));
++	printf("%ld\n", f(15));
+ 	return 0;
+ }
+
+commit f04fb20f2c77850996cba739709acc6faecc58f7
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:44:55 2013 +0100
+
+    change f()
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -3,18 +3,19 @@
+ int f(int x)
+ {
+ 	int s = 0;
+ 	while (x) {
+ 		x >>= 1;
+ 		s++;
+ 	}
++	return s;
+ }
+ 
+ /*
+  * A comment.
+  */
+ 
+ int main ()
+ {
+ 	printf("%d\n", f(15));
+ 	return 0;
+ }
+
+commit de4c48ae814792c02a49c4c3c0c757ae69c55f6a
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:44:48 2013 +0100
+
+    initial
+
+diff --git a/a.c b/a.c
+--- /dev/null
++++ b/a.c
+@@ -0,0 +3,18 @@
++int f(int x)
++{
++	int s = 0;
++	while (x) {
++		x >>= 1;
++		s++;
++	}
++}
++
++/*
++ * A comment.
++ */
++
++int main ()
++{
++	printf("%d\n", f(15));
++	return 0;
++}
diff --git a/t/t4211/expect.parallel-change-f-to-main b/t/t4211/expect.parallel-change-f-to-main
new file mode 100644
index 0000000..052def8
--- /dev/null
+++ b/t/t4211/expect.parallel-change-f-to-main
@@ -0,0 +1,160 @@
+commit 0469c60bc4837d52d97b1f081dec5f98dea20fed
+Merge: ba227c6 6ce3c4f
+Author: Thomas Rast <trast@inf.ethz.ch>
+Date:   Fri Apr 12 16:16:24 2013 +0200
+
+    Merge across the rename
+
+
+commit 6ce3c4ff690136099bb17e1a8766b75764726ea7
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:49:50 2013 +0100
+
+    another simple change
+
+diff --git a/b.c b/b.c
+--- a/b.c
++++ b/b.c
+@@ -4,14 +4,14 @@
+ long f(long x)
+ {
+ 	int s = 0;
+ 	while (x) {
+-		x >>= 1;
++		x /= 2;
+ 		s++;
+ 	}
+ 	return s;
+ }
+ 
+ /*
+  * This is only an example!
+  */
+ 
+
+commit ba227c6632349700fbb957dec2b50f5e2358be3f
+Author: Thomas Rast <trast@inf.ethz.ch>
+Date:   Fri Apr 12 16:15:57 2013 +0200
+
+    change on another line of history while rename happens
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -4,14 +4,14 @@
+ long f(long x)
+ {
+ 	int s = 0;
+ 	while (x) {
+ 		x >>= 1;
+ 		s++;
+ 	}
+ 	return s;
+ }
+ 
+ /*
+- * This is only an example!
++ * This is only a short example!
+  */
+ 
+
+commit 39b6eb2d5b706d3322184a169f666f25ed3fbd00
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:45:41 2013 +0100
+
+    touch comment
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -3,14 +3,14 @@
+ long f(long x)
+ {
+ 	int s = 0;
+ 	while (x) {
+ 		x >>= 1;
+ 		s++;
+ 	}
+ 	return s;
+ }
+ 
+ /*
+- * A comment.
++ * This is only an example!
+  */
+ 
+
+commit a6eb82647d5d67f893da442f8f9375fd89a3b1e2
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:45:16 2013 +0100
+
+    touch both functions
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -3,14 +3,14 @@
+-int f(int x)
++long f(long x)
+ {
+ 	int s = 0;
+ 	while (x) {
+ 		x >>= 1;
+ 		s++;
+ 	}
+ 	return s;
+ }
+ 
+ /*
+  * A comment.
+  */
+ 
+
+commit f04fb20f2c77850996cba739709acc6faecc58f7
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:44:55 2013 +0100
+
+    change f()
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -3,13 +3,14 @@
+ int f(int x)
+ {
+ 	int s = 0;
+ 	while (x) {
+ 		x >>= 1;
+ 		s++;
+ 	}
++	return s;
+ }
+ 
+ /*
+  * A comment.
+  */
+ 
+
+commit de4c48ae814792c02a49c4c3c0c757ae69c55f6a
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:44:48 2013 +0100
+
+    initial
+
+diff --git a/a.c b/a.c
+--- /dev/null
++++ b/a.c
+@@ -0,0 +3,13 @@
++int f(int x)
++{
++	int s = 0;
++	while (x) {
++		x >>= 1;
++		s++;
++	}
++}
++
++/*
++ * A comment.
++ */
++
diff --git a/t/t4211/expect.simple-f b/t/t4211/expect.simple-f
new file mode 100644
index 0000000..a1f5bc4
--- /dev/null
+++ b/t/t4211/expect.simple-f
@@ -0,0 +1,59 @@
+commit a6eb82647d5d67f893da442f8f9375fd89a3b1e2
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:45:16 2013 +0100
+
+    touch both functions
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -3,9 +3,9 @@
+-int f(int x)
++long f(long x)
+ {
+ 	int s = 0;
+ 	while (x) {
+ 		x >>= 1;
+ 		s++;
+ 	}
+ 	return s;
+ }
+
+commit f04fb20f2c77850996cba739709acc6faecc58f7
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:44:55 2013 +0100
+
+    change f()
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -3,8 +3,9 @@
+ int f(int x)
+ {
+ 	int s = 0;
+ 	while (x) {
+ 		x >>= 1;
+ 		s++;
+ 	}
++	return s;
+ }
+
+commit de4c48ae814792c02a49c4c3c0c757ae69c55f6a
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:44:48 2013 +0100
+
+    initial
+
+diff --git a/a.c b/a.c
+--- /dev/null
++++ b/a.c
+@@ -0,0 +3,8 @@
++int f(int x)
++{
++	int s = 0;
++	while (x) {
++		x >>= 1;
++		s++;
++	}
++}
diff --git a/t/t4211/expect.simple-f-to-main b/t/t4211/expect.simple-f-to-main
new file mode 100644
index 0000000..a475768
--- /dev/null
+++ b/t/t4211/expect.simple-f-to-main
@@ -0,0 +1,100 @@
+commit 39b6eb2d5b706d3322184a169f666f25ed3fbd00
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:45:41 2013 +0100
+
+    touch comment
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -3,14 +3,14 @@
+ long f(long x)
+ {
+ 	int s = 0;
+ 	while (x) {
+ 		x >>= 1;
+ 		s++;
+ 	}
+ 	return s;
+ }
+ 
+ /*
+- * A comment.
++ * This is only an example!
+  */
+ 
+
+commit a6eb82647d5d67f893da442f8f9375fd89a3b1e2
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:45:16 2013 +0100
+
+    touch both functions
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -3,14 +3,14 @@
+-int f(int x)
++long f(long x)
+ {
+ 	int s = 0;
+ 	while (x) {
+ 		x >>= 1;
+ 		s++;
+ 	}
+ 	return s;
+ }
+ 
+ /*
+  * A comment.
+  */
+ 
+
+commit f04fb20f2c77850996cba739709acc6faecc58f7
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:44:55 2013 +0100
+
+    change f()
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -3,13 +3,14 @@
+ int f(int x)
+ {
+ 	int s = 0;
+ 	while (x) {
+ 		x >>= 1;
+ 		s++;
+ 	}
++	return s;
+ }
+ 
+ /*
+  * A comment.
+  */
+ 
+
+commit de4c48ae814792c02a49c4c3c0c757ae69c55f6a
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:44:48 2013 +0100
+
+    initial
+
+diff --git a/a.c b/a.c
+--- /dev/null
++++ b/a.c
+@@ -0,0 +3,13 @@
++int f(int x)
++{
++	int s = 0;
++	while (x) {
++		x >>= 1;
++		s++;
++	}
++}
++
++/*
++ * A comment.
++ */
++
diff --git a/t/t4211/expect.simple-main b/t/t4211/expect.simple-main
new file mode 100644
index 0000000..39ce39b
--- /dev/null
+++ b/t/t4211/expect.simple-main
@@ -0,0 +1,68 @@
+commit 4659538844daa2849b1a9e7d6fadb96fcd26fc83
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:48:43 2013 +0100
+
+    change back to complete line
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -18,5 +18,5 @@
+ int main ()
+ {
+ 	printf("%ld\n", f(15));
+ 	return 0;
+-}
+\ No newline at end of file
++}
+
+commit 100b61a6f2f720f812620a9d10afb3a960ccb73c
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:48:10 2013 +0100
+
+    change to an incomplete line at end
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -18,5 +18,5 @@
+ int main ()
+ {
+ 	printf("%ld\n", f(15));
+ 	return 0;
+-}
++}
+\ No newline at end of file
+
+commit a6eb82647d5d67f893da442f8f9375fd89a3b1e2
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:45:16 2013 +0100
+
+    touch both functions
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -17,5 +17,5 @@
+ int main ()
+ {
+-	printf("%d\n", f(15));
++	printf("%ld\n", f(15));
+ 	return 0;
+ }
+
+commit de4c48ae814792c02a49c4c3c0c757ae69c55f6a
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:44:48 2013 +0100
+
+    initial
+
+diff --git a/a.c b/a.c
+--- /dev/null
++++ b/a.c
+@@ -0,0 +16,5 @@
++int main ()
++{
++	printf("%d\n", f(15));
++	return 0;
++}
diff --git a/t/t4211/expect.simple-main-to-end b/t/t4211/expect.simple-main-to-end
new file mode 100644
index 0000000..8480bd9
--- /dev/null
+++ b/t/t4211/expect.simple-main-to-end
@@ -0,0 +1,70 @@
+commit 4659538844daa2849b1a9e7d6fadb96fcd26fc83
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:48:43 2013 +0100
+
+    change back to complete line
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -18,5 +18,7 @@
+ int main ()
+ {
+ 	printf("%ld\n", f(15));
+ 	return 0;
+-}
+\ No newline at end of file
++}
++
++/* incomplete lines are bad! */
+
+commit 100b61a6f2f720f812620a9d10afb3a960ccb73c
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:48:10 2013 +0100
+
+    change to an incomplete line at end
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -18,5 +18,5 @@
+ int main ()
+ {
+ 	printf("%ld\n", f(15));
+ 	return 0;
+-}
++}
+\ No newline at end of file
+
+commit a6eb82647d5d67f893da442f8f9375fd89a3b1e2
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:45:16 2013 +0100
+
+    touch both functions
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -17,5 +17,5 @@
+ int main ()
+ {
+-	printf("%d\n", f(15));
++	printf("%ld\n", f(15));
+ 	return 0;
+ }
+
+commit de4c48ae814792c02a49c4c3c0c757ae69c55f6a
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:44:48 2013 +0100
+
+    initial
+
+diff --git a/a.c b/a.c
+--- /dev/null
++++ b/a.c
+@@ -0,0 +16,5 @@
++int main ()
++{
++	printf("%d\n", f(15));
++	return 0;
++}
diff --git a/t/t4211/expect.two-ranges b/t/t4211/expect.two-ranges
new file mode 100644
index 0000000..6109aa0
--- /dev/null
+++ b/t/t4211/expect.two-ranges
@@ -0,0 +1,102 @@
+commit 4659538844daa2849b1a9e7d6fadb96fcd26fc83
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:48:43 2013 +0100
+
+    change back to complete line
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -18,5 +18,5 @@
+ int main ()
+ {
+ 	printf("%ld\n", f(15));
+ 	return 0;
+-}
+\ No newline at end of file
++}
+
+commit 100b61a6f2f720f812620a9d10afb3a960ccb73c
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:48:10 2013 +0100
+
+    change to an incomplete line at end
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -18,5 +18,5 @@
+ int main ()
+ {
+ 	printf("%ld\n", f(15));
+ 	return 0;
+-}
++}
+\ No newline at end of file
+
+commit a6eb82647d5d67f893da442f8f9375fd89a3b1e2
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:45:16 2013 +0100
+
+    touch both functions
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -3,9 +3,9 @@
+-int f(int x)
++long f(long x)
+ {
+ 	int s = 0;
+ 	while (x) {
+ 		x >>= 1;
+ 		s++;
+ 	}
+ 	return s;
+ }
+@@ -17,5 +17,5 @@
+ int main ()
+ {
+-	printf("%d\n", f(15));
++	printf("%ld\n", f(15));
+ 	return 0;
+ }
+
+commit f04fb20f2c77850996cba739709acc6faecc58f7
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:44:55 2013 +0100
+
+    change f()
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -3,8 +3,9 @@
+ int f(int x)
+ {
+ 	int s = 0;
+ 	while (x) {
+ 		x >>= 1;
+ 		s++;
+ 	}
++	return s;
+ }
+
+commit de4c48ae814792c02a49c4c3c0c757ae69c55f6a
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:44:48 2013 +0100
+
+    initial
+
+diff --git a/a.c b/a.c
+--- /dev/null
++++ b/a.c
+@@ -0,0 +3,8 @@
++int f(int x)
++{
++	int s = 0;
++	while (x) {
++		x >>= 1;
++		s++;
++	}
++}
diff --git a/t/t4211/expect.vanishes-early b/t/t4211/expect.vanishes-early
new file mode 100644
index 0000000..1f7cd06
--- /dev/null
+++ b/t/t4211/expect.vanishes-early
@@ -0,0 +1,39 @@
+commit 4659538844daa2849b1a9e7d6fadb96fcd26fc83
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:48:43 2013 +0100
+
+    change back to complete line
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -22,1 +24,1 @@
+-}
+\ No newline at end of file
++/* incomplete lines are bad! */
+
+commit 100b61a6f2f720f812620a9d10afb3a960ccb73c
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:48:10 2013 +0100
+
+    change to an incomplete line at end
+
+diff --git a/a.c b/a.c
+--- a/a.c
++++ b/a.c
+@@ -22,1 +22,1 @@
+-}
++}
+\ No newline at end of file
+
+commit de4c48ae814792c02a49c4c3c0c757ae69c55f6a
+Author: Thomas Rast <trast@student.ethz.ch>
+Date:   Thu Feb 28 10:44:48 2013 +0100
+
+    initial
+
+diff --git a/a.c b/a.c
+--- /dev/null
++++ b/a.c
+@@ -0,0 +20,1 @@
++}
diff --git a/t/t4211/history.export b/t/t4211/history.export
new file mode 100644
index 0000000..f9f41e2
--- /dev/null
+++ b/t/t4211/history.export
@@ -0,0 +1,406 @@
+blob
+mark :1
+data 157
+#include <stdio.h>
+
+int f(int x)
+{
+	int s = 0;
+	while (x) {
+		x >>= 1;
+		s++;
+	}
+}
+
+/*
+ * A comment.
+ */
+
+int main ()
+{
+	printf("%d\n", f(15));
+	return 0;
+}
+
+reset refs/tags/simple
+commit refs/tags/simple
+mark :2
+author Thomas Rast <trast@student.ethz.ch> 1362044688 +0100
+committer Thomas Rast <trast@student.ethz.ch> 1362044688 +0100
+data 8
+initial
+M 100644 :1 a.c
+
+blob
+mark :3
+data 168
+#include <stdio.h>
+
+int f(int x)
+{
+	int s = 0;
+	while (x) {
+		x >>= 1;
+		s++;
+	}
+	return s;
+}
+
+/*
+ * A comment.
+ */
+
+int main ()
+{
+	printf("%d\n", f(15));
+	return 0;
+}
+
+commit refs/tags/simple
+mark :4
+author Thomas Rast <trast@student.ethz.ch> 1362044695 +0100
+committer Thomas Rast <trast@student.ethz.ch> 1362044695 +0100
+data 11
+change f()
+from :2
+M 100644 :3 a.c
+
+blob
+mark :5
+data 171
+#include <stdio.h>
+
+long f(long x)
+{
+	int s = 0;
+	while (x) {
+		x >>= 1;
+		s++;
+	}
+	return s;
+}
+
+/*
+ * A comment.
+ */
+
+int main ()
+{
+	printf("%ld\n", f(15));
+	return 0;
+}
+
+commit refs/tags/simple
+mark :6
+author Thomas Rast <trast@student.ethz.ch> 1362044716 +0100
+committer Thomas Rast <trast@student.ethz.ch> 1362044716 +0100
+data 21
+touch both functions
+from :4
+M 100644 :5 a.c
+
+blob
+mark :7
+data 185
+#include <stdio.h>
+
+long f(long x)
+{
+	int s = 0;
+	while (x) {
+		x >>= 1;
+		s++;
+	}
+	return s;
+}
+
+/*
+ * This is only an example!
+ */
+
+int main ()
+{
+	printf("%ld\n", f(15));
+	return 0;
+}
+
+commit refs/tags/simple
+mark :8
+author Thomas Rast <trast@student.ethz.ch> 1362044741 +0100
+committer Thomas Rast <trast@student.ethz.ch> 1362044741 +0100
+data 14
+touch comment
+from :6
+M 100644 :7 a.c
+
+blob
+mark :9
+data 205
+#include <unistd.h>
+#include <stdio.h>
+
+long f(long x)
+{
+	int s = 0;
+	while (x) {
+		x >>= 1;
+		s++;
+	}
+	return s;
+}
+
+/*
+ * This is only an example!
+ */
+
+int main ()
+{
+	printf("%ld\n", f(15));
+	return 0;
+}
+
+commit refs/tags/simple
+mark :10
+author Thomas Rast <trast@student.ethz.ch> 1362044860 +0100
+committer Thomas Rast <trast@student.ethz.ch> 1362044860 +0100
+data 25
+change at very beginning
+from :8
+M 100644 :9 a.c
+
+blob
+mark :11
+data 204
+#include <unistd.h>
+#include <stdio.h>
+
+long f(long x)
+{
+	int s = 0;
+	while (x) {
+		x >>= 1;
+		s++;
+	}
+	return s;
+}
+
+/*
+ * This is only an example!
+ */
+
+int main ()
+{
+	printf("%ld\n", f(15));
+	return 0;
+}
+commit refs/tags/simple
+mark :12
+author Thomas Rast <trast@student.ethz.ch> 1362044890 +0100
+committer Thomas Rast <trast@student.ethz.ch> 1362044890 +0100
+data 36
+change to an incomplete line at end
+from :10
+M 100644 :11 a.c
+
+blob
+mark :13
+data 238
+#include <unistd.h>
+#include <stdio.h>
+
+long f(long x)
+{
+	int s = 0;
+	while (x) {
+		x >>= 1;
+		s++;
+	}
+	return s;
+}
+
+/*
+ * This is only an example!
+ */
+
+int main ()
+{
+	printf("%ld\n", f(15));
+	return 0;
+}
+
+/* incomplete lines are bad! */
+
+commit refs/tags/simple
+mark :14
+author Thomas Rast <trast@student.ethz.ch> 1362044923 +0100
+committer Thomas Rast <trast@student.ethz.ch> 1362044923 +0100
+data 29
+change back to complete line
+from :12
+M 100644 :13 a.c
+
+commit refs/tags/move-support
+mark :15
+author Thomas Rast <trast@student.ethz.ch> 1362044968 +0100
+committer Thomas Rast <trast@student.ethz.ch> 1362044968 +0100
+data 10
+move file
+from :14
+D a.c
+M 100644 :13 b.c
+
+blob
+mark :16
+data 237
+#include <unistd.h>
+#include <stdio.h>
+
+long f(long x)
+{
+	int s = 0;
+	while (x) {
+		x /= 2;
+		s++;
+	}
+	return s;
+}
+
+/*
+ * This is only an example!
+ */
+
+int main ()
+{
+	printf("%ld\n", f(15));
+	return 0;
+}
+
+/* incomplete lines are bad! */
+
+commit refs/tags/move-support
+mark :17
+author Thomas Rast <trast@student.ethz.ch> 1362044990 +0100
+committer Thomas Rast <trast@student.ethz.ch> 1362044990 +0100
+data 22
+another simple change
+from :15
+M 100644 :16 b.c
+
+blob
+mark :18
+data 254
+#include <unistd.h>
+#include <stdio.h>
+
+long f(long x);
+
+/*
+ * This is only an example!
+ */
+
+int main ()
+{
+	printf("%ld\n", f(15));
+	return 0;
+}
+
+/* incomplete lines are bad! */
+
+long f(long x)
+{
+	int s = 0;
+	while (x) {
+		x /= 2;
+		s++;
+	}
+	return s;
+}
+
+commit refs/heads/master
+mark :19
+author Thomas Rast <trast@student.ethz.ch> 1362045024 +0100
+committer Thomas Rast <trast@student.ethz.ch> 1362045024 +0100
+data 21
+move within the file
+from :17
+M 100644 :18 b.c
+
+blob
+mark :20
+data 243
+#include <unistd.h>
+#include <stdio.h>
+
+long f(long x)
+{
+	int s = 0;
+	while (x) {
+		x >>= 1;
+		s++;
+	}
+	return s;
+}
+
+/*
+ * This is only a short example!
+ */
+
+int main ()
+{
+	printf("%ld\n", f(15));
+	return 0;
+}
+
+/* incomplete lines are bad! */
+
+commit refs/heads/parallel-change
+mark :21
+author Thomas Rast <trast@inf.ethz.ch> 1365776157 +0200
+committer Thomas Rast <trast@inf.ethz.ch> 1365776157 +0200
+data 55
+change on another line of history while rename happens
+from :14
+M 100644 :20 a.c
+
+blob
+mark :22
+data 242
+#include <unistd.h>
+#include <stdio.h>
+
+long f(long x)
+{
+	int s = 0;
+	while (x) {
+		x /= 2;
+		s++;
+	}
+	return s;
+}
+
+/*
+ * This is only a short example!
+ */
+
+int main ()
+{
+	printf("%ld\n", f(15));
+	return 0;
+}
+
+/* incomplete lines are bad! */
+
+commit refs/heads/parallel-change
+mark :23
+author Thomas Rast <trast@inf.ethz.ch> 1365776184 +0200
+committer Thomas Rast <trast@inf.ethz.ch> 1365776191 +0200
+data 24
+Merge across the rename
+from :21
+merge :17
+D a.c
+M 100644 :22 b.c
+
+reset refs/heads/parallel-change
+from :23
+
diff --git a/t/t4300-merge-tree.sh b/t/t4300-merge-tree.sh
index 2defb42..9015e47 100755
--- a/t/t4300-merge-tree.sh
+++ b/t/t4300-merge-tree.sh
@@ -259,6 +259,57 @@
 	test_cmp expected actual
 '
 
+test_expect_success 'tree add A, B (same)' '
+	cat >expect <<-\EOF &&
+	EOF
+	git reset --hard initial &&
+	mkdir sub &&
+	test_commit "add sub/file" "sub/file" "file" add-tree-A &&
+	git merge-tree initial add-tree-A add-tree-A >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'tree add A, B (different)' '
+	cat >expect <<-\EOF &&
+	added in both
+	  our    100644 43d5a8ed6ef6c00ff775008633f95787d088285d sub/file
+	  their  100644 ba629238ca89489f2b350e196ca445e09d8bb834 sub/file
+	@@ -1 +1,5 @@
+	+<<<<<<< .our
+	 AAA
+	+=======
+	+BBB
+	+>>>>>>> .their
+	EOF
+	git reset --hard initial &&
+	mkdir sub &&
+	test_commit "add sub/file" "sub/file" "AAA" add-tree-a-b-A &&
+	git reset --hard initial &&
+	mkdir sub &&
+	test_commit "add sub/file" "sub/file" "BBB" add-tree-a-b-B &&
+	git merge-tree initial add-tree-a-b-A add-tree-a-b-B >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'tree unchanged A, removed B' '
+	cat >expect <<-\EOF &&
+	removed in remote
+	  base   100644 43d5a8ed6ef6c00ff775008633f95787d088285d sub/file
+	  our    100644 43d5a8ed6ef6c00ff775008633f95787d088285d sub/file
+	@@ -1 +0,0 @@
+	-AAA
+	EOF
+	git reset --hard initial &&
+	mkdir sub &&
+	test_commit "add sub/file" "sub/file" "AAA" tree-remove-b-initial &&
+	git rm sub/file &&
+	test_tick &&
+	git commit -m "remove sub/file" &&
+	git tag tree-remove-b-B &&
+	git merge-tree tree-remove-b-initial tree-remove-b-initial tree-remove-b-B >actual &&
+	test_cmp expect actual
+'
+
 test_expect_success 'turn file to tree' '
 	git reset --hard initial &&
 	rm initial-file &&
diff --git a/t/t5000-tar-tree.sh b/t/t5000-tar-tree.sh
index 3fbd366..c2023b1 100755
--- a/t/t5000-tar-tree.sh
+++ b/t/t5000-tar-tree.sh
@@ -30,10 +30,76 @@
 
 SUBSTFORMAT=%H%n
 
+test_lazy_prereq TAR_NEEDS_PAX_FALLBACK '
+	(
+		mkdir pax &&
+		cd pax &&
+		"$TAR" xf "$TEST_DIRECTORY"/t5000/pax.tar &&
+		test -f PaxHeaders.1791/file
+	)
+'
+
+get_pax_header() {
+	file=$1
+	header=$2=
+
+	while read len rest
+	do
+		if test "$len" = $(echo "$len $rest" | wc -c)
+		then
+			case "$rest" in
+			$header*)
+				echo "${rest#$header}"
+				;;
+			esac
+		fi
+	done <"$file"
+}
+
+check_tar() {
+	tarfile=$1.tar
+	listfile=$1.lst
+	dir=$1
+	dir_with_prefix=$dir/$2
+
+	test_expect_success ' extract tar archive' '
+		(mkdir $dir && cd $dir && "$TAR" xf -) <$tarfile
+	'
+
+	test_expect_success TAR_NEEDS_PAX_FALLBACK ' interpret pax headers' '
+		(
+			cd $dir &&
+			for header in *.paxheader
+			do
+				data=${header%.paxheader}.data &&
+				if test -h $data -o -e $data
+				then
+					path=$(get_pax_header $header path) &&
+					if test -n "$path"
+					then
+						mv "$data" "$path"
+					fi
+				fi
+			done
+		)
+	'
+
+	test_expect_success ' validate filenames' '
+		(cd ${dir_with_prefix}a && find .) | sort >$listfile &&
+		test_cmp a.lst $listfile
+	'
+
+	test_expect_success ' validate file contents' '
+		diff -r a ${dir_with_prefix}a
+	'
+}
+
 test_expect_success \
     'populate workdir' \
-    'mkdir a b c &&
+    'mkdir a &&
      echo simple textfile >a/a &&
+     ten=0123456789 && hundred=$ten$ten$ten$ten$ten$ten$ten$ten$ten$ten &&
+     echo long filename >a/four$hundred &&
      mkdir a/bin &&
      cp /bin/sh a/bin &&
      printf "A\$Format:%s\$O" "$SUBSTFORMAT" >a/substfile1 &&
@@ -62,6 +128,12 @@
      git update-ref HEAD $(TZ=GMT GIT_COMMITTER_DATE="2005-05-27 22:00:00" \
      git commit-tree $treeid </dev/null)'
 
+test_expect_success 'setup export-subst' '
+	echo "substfile?" export-subst >>.git/info/attributes &&
+	git log --max-count=1 "--pretty=format:A${SUBSTFORMAT}O" HEAD \
+		>a/substfile1
+'
+
 test_expect_success \
     'create bare clone' \
     'git clone --bare . bare.git &&
@@ -75,13 +147,19 @@
     'git archive' \
     'git archive HEAD >b.tar'
 
-test_expect_success \
-    'git tar-tree' \
-    'git tar-tree HEAD >b2.tar'
+check_tar b
 
-test_expect_success \
-    'git archive vs. git tar-tree' \
-    'test_cmp b.tar b2.tar'
+test_expect_success 'git archive --prefix=prefix/' '
+	git archive --prefix=prefix/ HEAD >with_prefix.tar
+'
+
+check_tar with_prefix prefix/
+
+test_expect_success 'git-archive --prefix=olde-' '
+	git archive --prefix=olde- HEAD >with_olde-prefix.tar
+'
+
+check_tar with_olde-prefix olde-
 
 test_expect_success 'git archive on large files' '
     test_config core.bigfilethreshold 1 &&
@@ -118,66 +196,14 @@
     'git get-tar-commit-id <b.tar >b.commitid &&
      test_cmp .git/$(git symbolic-ref HEAD) b.commitid'
 
-test_expect_success \
-    'extract tar archive' \
-    '(cd b && "$TAR" xf -) <b.tar'
-
-test_expect_success \
-    'validate filenames' \
-    '(cd b/a && find .) | sort >b.lst &&
-     test_cmp a.lst b.lst'
-
-test_expect_success \
-    'validate file contents' \
-    'diff -r a b/a'
-
-test_expect_success \
-    'git tar-tree with prefix' \
-    'git tar-tree HEAD prefix >c.tar'
-
-test_expect_success \
-    'extract tar archive with prefix' \
-    '(cd c && "$TAR" xf -) <c.tar'
-
-test_expect_success \
-    'validate filenames with prefix' \
-    '(cd c/prefix/a && find .) | sort >c.lst &&
-     test_cmp a.lst c.lst'
-
-test_expect_success \
-    'validate file contents with prefix' \
-    'diff -r a c/prefix/a'
-
-test_expect_success \
-    'create archives with substfiles' \
-    'cp .git/info/attributes .git/info/attributes.before &&
-     echo "substfile?" export-subst >>.git/info/attributes &&
-     git archive HEAD >f.tar &&
-     git archive --prefix=prefix/ HEAD >g.tar &&
-     mv .git/info/attributes.before .git/info/attributes'
-
-test_expect_success \
-    'extract substfiles' \
-    '(mkdir f && cd f && "$TAR" xf -) <f.tar'
-
-test_expect_success \
-     'validate substfile contents' \
-     'git log --max-count=1 "--pretty=format:A${SUBSTFORMAT}O" HEAD \
-      >f/a/substfile1.expected &&
-      test_cmp f/a/substfile1.expected f/a/substfile1 &&
-      test_cmp a/substfile2 f/a/substfile2
+test_expect_success 'git tar-tree' '
+	git tar-tree HEAD >tar-tree.tar &&
+	test_cmp b.tar tar-tree.tar
 '
 
-test_expect_success \
-    'extract substfiles from archive with prefix' \
-    '(mkdir g && cd g && "$TAR" xf -) <g.tar'
-
-test_expect_success \
-     'validate substfile contents from archive with prefix' \
-     'git log --max-count=1 "--pretty=format:A${SUBSTFORMAT}O" HEAD \
-      >g/prefix/a/substfile1.expected &&
-      test_cmp g/prefix/a/substfile1.expected g/prefix/a/substfile1 &&
-      test_cmp a/substfile2 g/prefix/a/substfile2
+test_expect_success 'git tar-tree with prefix' '
+	git tar-tree HEAD prefix >tar-tree_with_prefix.tar &&
+	test_cmp with_prefix.tar tar-tree_with_prefix.tar
 '
 
 test_expect_success 'git archive with --output, override inferred format' '
@@ -197,18 +223,6 @@
 	test_must_fail git archive --remote=. $sha1 >remote.tar
 '
 
-test_expect_success 'git-archive --prefix=olde-' '
-	git archive --prefix=olde- >h.tar HEAD &&
-	(
-		mkdir h &&
-		cd h &&
-		"$TAR" xf - <../h.tar
-	) &&
-	test -d h/olde-a &&
-	test -d h/olde-a/bin &&
-	test -f h/olde-a/bin/sh
-'
-
 test_expect_success 'setup tar filters' '
 	git config tar.tar.foo.command "tr ab ba" &&
 	git config tar.bar.command "tr ab ba" &&
diff --git a/t/t5000/pax.tar b/t/t5000/pax.tar
new file mode 100644
index 0000000..d911737
--- /dev/null
+++ b/t/t5000/pax.tar
Binary files differ
diff --git a/t/t5003-archive-zip.sh b/t/t5003-archive-zip.sh
index 4e7b05d..c72f71e 100755
--- a/t/t5003-archive-zip.sh
+++ b/t/t5003-archive-zip.sh
@@ -37,7 +37,7 @@
 
 test_expect_success \
     'populate workdir' \
-    'mkdir a b c &&
+    'mkdir a &&
      echo simple textfile >a/a &&
      mkdir a/bin &&
      cp /bin/sh a/bin &&
diff --git a/t/t5004-archive-corner-cases.sh b/t/t5004-archive-corner-cases.sh
index bfdb56a..67f3b54 100755
--- a/t/t5004-archive-corner-cases.sh
+++ b/t/t5004-archive-corner-cases.sh
@@ -23,15 +23,29 @@
 			echo "$dir/$i"
 		done
 	} | sort >expect &&
-	find "$dir" -print | sort >actual &&
+	find "$dir" ! -name pax_global_header -print | sort >actual &&
 	test_cmp expect actual
 }
 
+
+# bsdtar/libarchive versions before 3.1.3 consider a tar file with a
+# global pax header that is not followed by a file record as corrupt.
+if "$TAR" tf "$TEST_DIRECTORY"/t5004/empty-with-pax-header.tar >/dev/null 2>&1
+then
+	test_set_prereq HEADER_ONLY_TAR_OK
+fi
+
+test_expect_success HEADER_ONLY_TAR_OK 'tar archive of commit with empty tree' '
+	git archive --format=tar HEAD >empty-with-pax-header.tar &&
+	make_dir extract &&
+	"$TAR" xf empty-with-pax-header.tar -C extract &&
+	check_dir extract
+'
+
 test_expect_success 'tar archive of empty tree is empty' '
 	git archive --format=tar HEAD: >empty.tar &&
-	make_dir extract &&
-	"$TAR" xf empty.tar -C extract &&
-	check_dir extract
+	perl -e "print \"\\0\" x 10240" >10knuls.tar &&
+	test_cmp 10knuls.tar empty.tar
 '
 
 test_expect_success 'tar archive of empty tree with prefix' '
diff --git a/t/t5004/empty-with-pax-header.tar b/t/t5004/empty-with-pax-header.tar
new file mode 100644
index 0000000..da9e39e
--- /dev/null
+++ b/t/t5004/empty-with-pax-header.tar
Binary files differ
diff --git a/t/t5150-request-pull.sh b/t/t5150-request-pull.sh
index 432f98c..1afa0d5 100755
--- a/t/t5150-request-pull.sh
+++ b/t/t5150-request-pull.sh
@@ -80,12 +80,12 @@
 
 	cat <<-EOT >fuzz.sed
 	#!/bin/sed -nf
+	s/$downstream_url_for_sed/URL/g
 	s/$_x40/OBJECT_NAME/g
 	s/A U Thor/AUTHOR/g
 	s/[-0-9]\{10\} [:0-9]\{8\} [-+][0-9]\{4\}/DATE/g
 	s/        [^ ].*/        SUBJECT/g
 	s/  [^ ].* (DATE)/  SUBJECT (DATE)/g
-	s/$downstream_url_for_sed/URL/g
 	s/for-upstream/BRANCH/g
 	s/mnemonic.txt/FILENAME/g
 	s/^version [0-9]/VERSION/
diff --git a/t/t5303-pack-corruption-resilience.sh b/t/t5303-pack-corruption-resilience.sh
index 5b1250f..35926de 100755
--- a/t/t5303-pack-corruption-resilience.sh
+++ b/t/t5303-pack-corruption-resilience.sh
@@ -51,7 +51,7 @@
     ofs=`git show-index < ${pack}.idx | grep $1 | cut -f1 -d" "` &&
     ofs=$(($ofs + $2)) &&
     chmod +w ${pack}.pack &&
-    dd of=${pack}.pack count=1 bs=1 conv=notrunc seek=$ofs &&
+    dd of=${pack}.pack bs=1 conv=notrunc seek=$ofs &&
     test_must_fail git verify-pack ${pack}.pack
 }
 
@@ -276,6 +276,33 @@
      git cat-file blob $blob_3 > /dev/null'
 
 test_expect_success \
+    'corruption of delta base reference pointing to wrong object' \
+    'create_new_pack --delta-base-offset &&
+     git prune-packed &&
+     printf "\220\033" | do_corrupt_object $blob_3 2 &&
+     git cat-file blob $blob_1 >/dev/null &&
+     git cat-file blob $blob_2 >/dev/null &&
+     test_must_fail git cat-file blob $blob_3 >/dev/null'
+
+test_expect_success \
+    '... but having a loose copy allows for full recovery' \
+    'mv ${pack}.idx tmp &&
+     git hash-object -t blob -w file_3 &&
+     mv tmp ${pack}.idx &&
+     git cat-file blob $blob_1 > /dev/null &&
+     git cat-file blob $blob_2 > /dev/null &&
+     git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
+    '... and then a repack "clears" the corruption' \
+    'do_repack --delta-base-offset --no-reuse-delta &&
+     git prune-packed &&
+     git verify-pack ${pack}.pack &&
+     git cat-file blob $blob_1 > /dev/null &&
+     git cat-file blob $blob_2 > /dev/null &&
+     git cat-file blob $blob_3 > /dev/null'
+
+test_expect_success \
     'corrupting header to have too small output buffer fails unpack' \
     'create_new_pack &&
      git prune-packed &&
diff --git a/t/t5407-post-rewrite-hook.sh b/t/t5407-post-rewrite-hook.sh
index baa670c..ea2e0d4 100755
--- a/t/t5407-post-rewrite-hook.sh
+++ b/t/t5407-post-rewrite-hook.sh
@@ -31,8 +31,8 @@
 }
 
 verify_hook_input () {
-	test_cmp "$TRASH_DIRECTORY"/post-rewrite.args expected.args &&
-	test_cmp "$TRASH_DIRECTORY"/post-rewrite.data expected.data
+	test_cmp expected.args "$TRASH_DIRECTORY"/post-rewrite.args &&
+	test_cmp expected.data "$TRASH_DIRECTORY"/post-rewrite.data
 }
 
 test_expect_success 'git commit --amend' '
diff --git a/t/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh
index d574085..a80584e 100755
--- a/t/t5500-fetch-pack.sh
+++ b/t/t5500-fetch-pack.sh
@@ -135,6 +135,13 @@
 	test "`git --git-dir=shallow0/.git rev-list --count HEAD`" = 1
 '
 
+test_expect_success 'clone shallow depth 1 with fsck' '
+	git config --global fetch.fsckobjects true &&
+	git clone --no-single-branch --depth 1 "file://$(pwd)/." shallow0fsck &&
+	test "`git --git-dir=shallow0fsck/.git rev-list --count HEAD`" = 1 &&
+	git config --global --unset fetch.fsckobjects
+'
+
 test_expect_success 'clone shallow' '
 	git clone --no-single-branch --depth 2 "file://$(pwd)/." shallow
 '
@@ -373,6 +380,20 @@
 	test_cmp count8.expected count8.actual
 '
 
+test_expect_success 'fetch in shallow repo unreachable shallow objects' '
+	(
+		git clone --bare --branch B --single-branch "file://$(pwd)/." no-reflog &&
+		git clone --depth 1 "file://$(pwd)/no-reflog" shallow9 &&
+		cd no-reflog &&
+		git tag -d TAGB1 TAGB2 &&
+		git update-ref refs/heads/B B~~ &&
+		git gc --prune=now &&
+		cd ../shallow9 &&
+		git fetch origin &&
+		git fsck --no-dangling
+	)
+'
+
 test_expect_success 'setup tests for the --stdin parameter' '
 	for head in C D E F
 	do
@@ -484,4 +505,20 @@
 	) >out-adt 2>error-adt
 '
 
+test_expect_success 'shallow fetch with tags does not break the repository' '
+	mkdir repo1 &&
+	(
+		cd repo1 &&
+		git init &&
+		test_commit 1 &&
+		test_commit 2 &&
+		test_commit 3 &&
+		mkdir repo2 &&
+		cd repo2 &&
+		git init &&
+		git fetch --depth=2 ../.git master:branch &&
+		git fsck
+	)
+'
+
 test_done
diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh
index dd10ff0..8f6e392 100755
--- a/t/t5505-remote.sh
+++ b/t/t5505-remote.sh
@@ -42,107 +42,104 @@
 }
 
 test_expect_success setup '
-
 	setup_repository one &&
 	setup_repository two &&
 	(
-		cd two && git branch another
+		cd two &&
+		git branch another
 	) &&
 	git clone one test
-
 '
 
 test_expect_success C_LOCALE_OUTPUT 'remote information for the origin' '
-(
-	cd test &&
-	tokens_match origin "$(git remote)" &&
-	check_remote_track origin master side &&
-	check_tracking_branch origin HEAD master side
-)
+	(
+		cd test &&
+		tokens_match origin "$(git remote)" &&
+		check_remote_track origin master side &&
+		check_tracking_branch origin HEAD master side
+	)
 '
 
 test_expect_success 'add another remote' '
-(
-	cd test &&
-	git remote add -f second ../two &&
-	tokens_match "origin second" "$(git remote)" &&
-	check_tracking_branch second master side another &&
-	git for-each-ref "--format=%(refname)" refs/remotes |
-	sed -e "/^refs\/remotes\/origin\//d" \
-	    -e "/^refs\/remotes\/second\//d" >actual &&
-	>expect &&
-	test_cmp expect actual
-)
+	(
+		cd test &&
+		git remote add -f second ../two &&
+		tokens_match "origin second" "$(git remote)" &&
+		check_tracking_branch second master side another &&
+		git for-each-ref "--format=%(refname)" refs/remotes |
+		sed -e "/^refs\/remotes\/origin\//d" \
+		    -e "/^refs\/remotes\/second\//d" >actual &&
+		>expect &&
+		test_cmp expect actual
+	)
 '
 
-test_expect_success C_LOCALE_OUTPUT 'check remote tracking' '
-(
-	cd test &&
-	check_remote_track origin master side &&
-	check_remote_track second master side another
-)
+test_expect_success C_LOCALE_OUTPUT 'check remote-tracking' '
+	(
+		cd test &&
+		check_remote_track origin master side &&
+		check_remote_track second master side another
+	)
 '
 
 test_expect_success 'remote forces tracking branches' '
-(
-	cd test &&
-	case `git config remote.second.fetch` in
-	+*) true ;;
-	 *) false ;;
-	esac
-)
+	(
+		cd test &&
+		case `git config remote.second.fetch` in
+		+*) true ;;
+		 *) false ;;
+		esac
+	)
 '
 
 test_expect_success 'remove remote' '
-(
-	cd test &&
-	git symbolic-ref refs/remotes/second/HEAD refs/remotes/second/master &&
-	git remote rm second
-)
+	(
+		cd test &&
+		git symbolic-ref refs/remotes/second/HEAD refs/remotes/second/master &&
+		git remote rm second
+	)
 '
 
 test_expect_success C_LOCALE_OUTPUT 'remove remote' '
-(
-	cd test &&
-	tokens_match origin "$(git remote)" &&
-	check_remote_track origin master side &&
-	git for-each-ref "--format=%(refname)" refs/remotes |
-	sed -e "/^refs\/remotes\/origin\//d" >actual &&
-	>expect &&
-	test_cmp expect actual
-)
+	(
+		cd test &&
+		tokens_match origin "$(git remote)" &&
+		check_remote_track origin master side &&
+		git for-each-ref "--format=%(refname)" refs/remotes |
+		sed -e "/^refs\/remotes\/origin\//d" >actual &&
+		>expect &&
+		test_cmp expect actual
+	)
 '
 
 test_expect_success 'remove remote protects local branches' '
-(
-	cd test &&
-	{ cat >expect1 <<EOF
-Note: A branch outside the refs/remotes/ hierarchy was not removed;
-to delete it, use:
-  git branch -d master
-EOF
-	} &&
-	{ cat >expect2 <<EOF
-Note: Some branches outside the refs/remotes/ hierarchy were not removed;
-to delete them, use:
-  git branch -d foobranch
-  git branch -d master
-EOF
-	} &&
-	git tag footag &&
-	git config --add remote.oops.fetch "+refs/*:refs/*" &&
-	git remote remove oops 2>actual1 &&
-	git branch foobranch &&
-	git config --add remote.oops.fetch "+refs/*:refs/*" &&
-	git remote rm oops 2>actual2 &&
-	git branch -d foobranch &&
-	git tag -d footag &&
-	test_i18ncmp expect1 actual1 &&
-	test_i18ncmp expect2 actual2
-)
+	(
+		cd test &&
+		cat >expect1 <<-\EOF &&
+		Note: A branch outside the refs/remotes/ hierarchy was not removed;
+		to delete it, use:
+		  git branch -d master
+		EOF
+		cat >expect2 <<-\EOF &&
+		Note: Some branches outside the refs/remotes/ hierarchy were not removed;
+		to delete them, use:
+		  git branch -d foobranch
+		  git branch -d master
+		EOF
+		git tag footag &&
+		git config --add remote.oops.fetch "+refs/*:refs/*" &&
+		git remote remove oops 2>actual1 &&
+		git branch foobranch &&
+		git config --add remote.oops.fetch "+refs/*:refs/*" &&
+		git remote rm oops 2>actual2 &&
+		git branch -d foobranch &&
+		git tag -d footag &&
+		test_i18ncmp expect1 actual1 &&
+		test_i18ncmp expect2 actual2
+	)
 '
 
-cat > test/expect << EOF
+cat >test/expect <<EOF
 * remote origin
   Fetch URL: $(pwd)/one
   Push  URL: $(pwd)/one
@@ -172,36 +169,40 @@
 EOF
 
 test_expect_success 'show' '
-	(cd test &&
-	 git config --add remote.origin.fetch refs/heads/master:refs/heads/upstream &&
-	 git fetch &&
-	 git checkout -b ahead origin/master &&
-	 echo 1 >> file &&
-	 test_tick &&
-	 git commit -m update file &&
-	 git checkout master &&
-	 git branch --track octopus origin/master &&
-	 git branch --track rebase origin/master &&
-	 git branch -d -r origin/master &&
-	 git config --add remote.two.url ../two &&
-	 git config --add remote.two.pushurl ../three &&
-	 git config branch.rebase.rebase true &&
-	 git config branch.octopus.merge "topic-a topic-b topic-c" &&
-	 (cd ../one &&
-	  echo 1 > file &&
-	  test_tick &&
-	  git commit -m update file) &&
-	 git config --add remote.origin.push : &&
-	 git config --add remote.origin.push refs/heads/master:refs/heads/upstream &&
-	 git config --add remote.origin.push +refs/tags/lastbackup &&
-	 git config --add remote.two.push +refs/heads/ahead:refs/heads/master &&
-	 git config --add remote.two.push refs/heads/master:refs/heads/another &&
-	 git remote show origin two > output &&
-	 git branch -d rebase octopus &&
-	 test_i18ncmp expect output)
+	(
+		cd test &&
+		git config --add remote.origin.fetch refs/heads/master:refs/heads/upstream &&
+		git fetch &&
+		git checkout -b ahead origin/master &&
+		echo 1 >>file &&
+		test_tick &&
+		git commit -m update file &&
+		git checkout master &&
+		git branch --track octopus origin/master &&
+		git branch --track rebase origin/master &&
+		git branch -d -r origin/master &&
+		git config --add remote.two.url ../two &&
+		git config --add remote.two.pushurl ../three &&
+		git config branch.rebase.rebase true &&
+		git config branch.octopus.merge "topic-a topic-b topic-c" &&
+		(
+			cd ../one &&
+			echo 1 >file &&
+			test_tick &&
+			git commit -m update file
+		) &&
+		git config --add remote.origin.push : &&
+		git config --add remote.origin.push refs/heads/master:refs/heads/upstream &&
+		git config --add remote.origin.push +refs/tags/lastbackup &&
+		git config --add remote.two.push +refs/heads/ahead:refs/heads/master &&
+		git config --add remote.two.push refs/heads/master:refs/heads/another &&
+		git remote show origin two >output &&
+		git branch -d rebase octopus &&
+		test_i18ncmp expect output
+	)
 '
 
-cat > test/expect << EOF
+cat >test/expect <<EOF
 * remote origin
   Fetch URL: $(pwd)/one
   Push  URL: $(pwd)/one
@@ -219,152 +220,187 @@
 EOF
 
 test_expect_success 'show -n' '
-	(mv one one.unreachable &&
-	 cd test &&
-	 git remote show -n origin > output &&
-	 mv ../one.unreachable ../one &&
-	 test_i18ncmp expect output)
-'
-
-test_expect_success 'prune' '
-	(cd one &&
-	 git branch -m side side2) &&
-	(cd test &&
-	 git fetch origin &&
-	 git remote prune origin &&
-	 git rev-parse refs/remotes/origin/side2 &&
-	 test_must_fail git rev-parse refs/remotes/origin/side)
-'
-
-test_expect_success 'set-head --delete' '
-	(cd test &&
-	 git symbolic-ref refs/remotes/origin/HEAD &&
-	 git remote set-head --delete origin &&
-	 test_must_fail git symbolic-ref refs/remotes/origin/HEAD)
-'
-
-test_expect_success 'set-head --auto' '
-	(cd test &&
-	 git remote set-head --auto origin &&
-	 echo refs/remotes/origin/master >expect &&
-	 git symbolic-ref refs/remotes/origin/HEAD >output &&
-	 test_cmp expect output
+	mv one one.unreachable &&
+	(
+		cd test &&
+		git remote show -n origin >output &&
+		mv ../one.unreachable ../one &&
+		test_i18ncmp expect output
 	)
 '
 
-cat >test/expect <<EOF
+test_expect_success 'prune' '
+	(
+		cd one &&
+		git branch -m side side2
+	) &&
+	(
+		cd test &&
+		git fetch origin &&
+		git remote prune origin &&
+		git rev-parse refs/remotes/origin/side2 &&
+		test_must_fail git rev-parse refs/remotes/origin/side
+	)
+'
+
+test_expect_success 'set-head --delete' '
+	(
+		cd test &&
+		git symbolic-ref refs/remotes/origin/HEAD &&
+		git remote set-head --delete origin &&
+		test_must_fail git symbolic-ref refs/remotes/origin/HEAD
+	)
+'
+
+test_expect_success 'set-head --auto' '
+	(
+		cd test &&
+		git remote set-head --auto origin &&
+		echo refs/remotes/origin/master >expect &&
+		git symbolic-ref refs/remotes/origin/HEAD >output &&
+		test_cmp expect output
+	)
+'
+
+cat >test/expect <<\EOF
 error: Multiple remote HEAD branches. Please choose one explicitly with:
   git remote set-head two another
   git remote set-head two master
 EOF
 
 test_expect_success 'set-head --auto fails w/multiple HEADs' '
-	(cd test &&
-	 test_must_fail git remote set-head --auto two >output 2>&1 &&
-	test_i18ncmp expect output)
+	(
+		cd test &&
+		test_must_fail git remote set-head --auto two >output 2>&1 &&
+		test_i18ncmp expect output
+	)
 '
 
-cat >test/expect <<EOF
+cat >test/expect <<\EOF
 refs/remotes/origin/side2
 EOF
 
 test_expect_success 'set-head explicit' '
-	(cd test &&
-	 git remote set-head origin side2 &&
-	 git symbolic-ref refs/remotes/origin/HEAD >output &&
-	 git remote set-head origin master &&
-	 test_cmp expect output)
+	(
+		cd test &&
+		git remote set-head origin side2 &&
+		git symbolic-ref refs/remotes/origin/HEAD >output &&
+		git remote set-head origin master &&
+		test_cmp expect output
+	)
 '
 
-cat > test/expect << EOF
+cat >test/expect <<EOF
 Pruning origin
 URL: $(pwd)/one
  * [would prune] origin/side2
 EOF
 
 test_expect_success 'prune --dry-run' '
-	(cd one &&
-	 git branch -m side2 side) &&
-	(cd test &&
-	 git remote prune --dry-run origin > output &&
-	 git rev-parse refs/remotes/origin/side2 &&
-	 test_must_fail git rev-parse refs/remotes/origin/side &&
-	(cd ../one &&
-	 git branch -m side side2) &&
-	 test_i18ncmp expect output)
+	(
+		cd one &&
+		git branch -m side2 side) &&
+	(
+		cd test &&
+		git remote prune --dry-run origin >output &&
+		git rev-parse refs/remotes/origin/side2 &&
+		test_must_fail git rev-parse refs/remotes/origin/side &&
+	(
+		cd ../one &&
+		git branch -m side side2) &&
+		test_i18ncmp expect output
+	)
 '
 
 test_expect_success 'add --mirror && prune' '
-	(mkdir mirror &&
-	 cd mirror &&
-	 git init --bare &&
-	 git remote add --mirror -f origin ../one) &&
-	(cd one &&
-	 git branch -m side2 side) &&
-	(cd mirror &&
-	 git rev-parse --verify refs/heads/side2 &&
-	 test_must_fail git rev-parse --verify refs/heads/side &&
-	 git fetch origin &&
-	 git remote prune origin &&
-	 test_must_fail git rev-parse --verify refs/heads/side2 &&
-	 git rev-parse --verify refs/heads/side)
+	mkdir mirror &&
+	(
+		cd mirror &&
+		git init --bare &&
+		git remote add --mirror -f origin ../one
+	) &&
+	(
+		cd one &&
+		git branch -m side2 side
+	) &&
+	(
+		cd mirror &&
+		git rev-parse --verify refs/heads/side2 &&
+		test_must_fail git rev-parse --verify refs/heads/side &&
+		git fetch origin &&
+		git remote prune origin &&
+		test_must_fail git rev-parse --verify refs/heads/side2 &&
+		git rev-parse --verify refs/heads/side
+	)
 '
 
 test_expect_success 'add --mirror=fetch' '
 	mkdir mirror-fetch &&
 	git init mirror-fetch/parent &&
-	(cd mirror-fetch/parent &&
-	 test_commit one) &&
+	(
+		cd mirror-fetch/parent &&
+		test_commit one
+	) &&
 	git init --bare mirror-fetch/child &&
-	(cd mirror-fetch/child &&
-	 git remote add --mirror=fetch -f parent ../parent)
+	(
+		cd mirror-fetch/child &&
+		git remote add --mirror=fetch -f parent ../parent
+	)
 '
 
 test_expect_success 'fetch mirrors act as mirrors during fetch' '
-	(cd mirror-fetch/parent &&
-	 git branch new &&
-	 git branch -m master renamed
+	(
+		cd mirror-fetch/parent &&
+		git branch new &&
+		git branch -m master renamed
 	) &&
-	(cd mirror-fetch/child &&
-	 git fetch parent &&
-	 git rev-parse --verify refs/heads/new &&
-	 git rev-parse --verify refs/heads/renamed
+	(
+		cd mirror-fetch/child &&
+		git fetch parent &&
+		git rev-parse --verify refs/heads/new &&
+		git rev-parse --verify refs/heads/renamed
 	)
 '
 
 test_expect_success 'fetch mirrors can prune' '
-	(cd mirror-fetch/child &&
-	 git remote prune parent &&
-	 test_must_fail git rev-parse --verify refs/heads/master
+	(
+		cd mirror-fetch/child &&
+		git remote prune parent &&
+		test_must_fail git rev-parse --verify refs/heads/master
 	)
 '
 
 test_expect_success 'fetch mirrors do not act as mirrors during push' '
-	(cd mirror-fetch/parent &&
-	 git checkout HEAD^0
+	(
+		cd mirror-fetch/parent &&
+		git checkout HEAD^0
 	) &&
-	(cd mirror-fetch/child &&
-	 git branch -m renamed renamed2 &&
-	 git push parent :
+	(
+		cd mirror-fetch/child &&
+		git branch -m renamed renamed2 &&
+		git push parent :
 	) &&
-	(cd mirror-fetch/parent &&
-	 git rev-parse --verify renamed &&
-	 test_must_fail git rev-parse --verify refs/heads/renamed2
+	(
+		cd mirror-fetch/parent &&
+		git rev-parse --verify renamed &&
+		test_must_fail git rev-parse --verify refs/heads/renamed2
 	)
 '
 
 test_expect_success 'add fetch mirror with specific branches' '
 	git init --bare mirror-fetch/track &&
-	(cd mirror-fetch/track &&
-	 git remote add --mirror=fetch -t heads/new parent ../parent
+	(
+		cd mirror-fetch/track &&
+		git remote add --mirror=fetch -t heads/new parent ../parent
 	)
 '
 
 test_expect_success 'fetch mirror respects specific branches' '
-	(cd mirror-fetch/track &&
-	 git fetch parent &&
-	 git rev-parse --verify refs/heads/new &&
-	 test_must_fail git rev-parse --verify refs/heads/renamed
+	(
+		cd mirror-fetch/track &&
+		git fetch parent &&
+		git rev-parse --verify refs/heads/new &&
+		test_must_fail git rev-parse --verify refs/heads/renamed
 	)
 '
 
@@ -372,60 +408,72 @@
 	mkdir mirror-push &&
 	git init --bare mirror-push/public &&
 	git init mirror-push/private &&
-	(cd mirror-push/private &&
-	 test_commit one &&
-	 git remote add --mirror=push public ../public
+	(
+		cd mirror-push/private &&
+		test_commit one &&
+		git remote add --mirror=push public ../public
 	)
 '
 
 test_expect_success 'push mirrors act as mirrors during push' '
-	(cd mirror-push/private &&
-	 git branch new &&
-	 git branch -m master renamed &&
-	 git push public
+	(
+		cd mirror-push/private &&
+		git branch new &&
+		git branch -m master renamed &&
+		git push public
 	) &&
-	(cd mirror-push/private &&
-	 git rev-parse --verify refs/heads/new &&
-	 git rev-parse --verify refs/heads/renamed &&
-	 test_must_fail git rev-parse --verify refs/heads/master
+	(
+		cd mirror-push/private &&
+		git rev-parse --verify refs/heads/new &&
+		git rev-parse --verify refs/heads/renamed &&
+		test_must_fail git rev-parse --verify refs/heads/master
 	)
 '
 
 test_expect_success 'push mirrors do not act as mirrors during fetch' '
-	(cd mirror-push/public &&
-	 git branch -m renamed renamed2 &&
-	 git symbolic-ref HEAD refs/heads/renamed2
+	(
+		cd mirror-push/public &&
+		git branch -m renamed renamed2 &&
+		git symbolic-ref HEAD refs/heads/renamed2
 	) &&
-	(cd mirror-push/private &&
-	 git fetch public &&
-	 git rev-parse --verify refs/heads/renamed &&
-	 test_must_fail git rev-parse --verify refs/heads/renamed2
+	(
+		cd mirror-push/private &&
+		git fetch public &&
+		git rev-parse --verify refs/heads/renamed &&
+		test_must_fail git rev-parse --verify refs/heads/renamed2
 	)
 '
 
 test_expect_success 'push mirrors do not allow you to specify refs' '
 	git init mirror-push/track &&
-	(cd mirror-push/track &&
-	 test_must_fail git remote add --mirror=push -t new public ../public
+	(
+		cd mirror-push/track &&
+		test_must_fail git remote add --mirror=push -t new public ../public
 	)
 '
 
 test_expect_success 'add alt && prune' '
-	(mkdir alttst &&
-	 cd alttst &&
-	 git init &&
-	 git remote add -f origin ../one &&
-	 git config remote.alt.url ../one &&
-	 git config remote.alt.fetch "+refs/heads/*:refs/remotes/origin/*") &&
-	(cd one &&
-	 git branch -m side side2) &&
-	(cd alttst &&
-	 git rev-parse --verify refs/remotes/origin/side &&
-	 test_must_fail git rev-parse --verify refs/remotes/origin/side2 &&
-	 git fetch alt &&
-	 git remote prune alt &&
-	 test_must_fail git rev-parse --verify refs/remotes/origin/side &&
-	 git rev-parse --verify refs/remotes/origin/side2)
+	mkdir alttst &&
+	(
+		cd alttst &&
+		git init &&
+		git remote add -f origin ../one &&
+		git config remote.alt.url ../one &&
+		git config remote.alt.fetch "+refs/heads/*:refs/remotes/origin/*"
+	) &&
+	(
+		cd one &&
+		git branch -m side side2
+	) &&
+	(
+		cd alttst &&
+		git rev-parse --verify refs/remotes/origin/side &&
+		test_must_fail git rev-parse --verify refs/remotes/origin/side2 &&
+		git fetch alt &&
+		git remote prune alt &&
+		test_must_fail git rev-parse --verify refs/remotes/origin/side &&
+		git rev-parse --verify refs/remotes/origin/side2
+	)
 '
 
 cat >test/expect <<\EOF
@@ -433,20 +481,24 @@
 EOF
 
 test_expect_success 'add with reachable tags (default)' '
-	(cd one &&
-	 >foobar &&
-	 git add foobar &&
-	 git commit -m "Foobar" &&
-	 git tag -a -m "Foobar tag" foobar-tag &&
-	 git reset --hard HEAD~1 &&
-	 git tag -a -m "Some tag" some-tag) &&
-	(mkdir add-tags &&
-	 cd add-tags &&
-	 git init &&
-	 git remote add -f origin ../one &&
-	 git tag -l some-tag >../test/output &&
-	 git tag -l foobar-tag >>../test/output &&
-	 test_must_fail git config remote.origin.tagopt) &&
+	(
+		cd one &&
+		>foobar &&
+		git add foobar &&
+		git commit -m "Foobar" &&
+		git tag -a -m "Foobar tag" foobar-tag &&
+		git reset --hard HEAD~1 &&
+		git tag -a -m "Some tag" some-tag
+	) &&
+	mkdir add-tags &&
+	(
+		cd add-tags &&
+		git init &&
+		git remote add -f origin ../one &&
+		git tag -l some-tag >../test/output &&
+		git tag -l foobar-tag >>../test/output &&
+		test_must_fail git config remote.origin.tagopt
+	) &&
 	test_cmp test/expect test/output
 '
 
@@ -457,14 +509,16 @@
 EOF
 
 test_expect_success 'add --tags' '
-	(rm -rf add-tags &&
-	 mkdir add-tags &&
-	 cd add-tags &&
-	 git init &&
-	 git remote add -f --tags origin ../one &&
-	 git tag -l some-tag >../test/output &&
-	 git tag -l foobar-tag >>../test/output &&
-	 git config remote.origin.tagopt >>../test/output) &&
+	rm -rf add-tags &&
+	(
+		mkdir add-tags &&
+		cd add-tags &&
+		git init &&
+		git remote add -f --tags origin ../one &&
+		git tag -l some-tag >../test/output &&
+		git tag -l foobar-tag >>../test/output &&
+		git config remote.origin.tagopt >>../test/output
+	) &&
 	test_cmp test/expect test/output
 '
 
@@ -473,25 +527,31 @@
 EOF
 
 test_expect_success 'add --no-tags' '
-	(rm -rf add-tags &&
-	 mkdir add-no-tags &&
-	 cd add-no-tags &&
-	 git init &&
-	 git remote add -f --no-tags origin ../one &&
-	 git tag -l some-tag >../test/output &&
-	 git tag -l foobar-tag >../test/output &&
-	 git config remote.origin.tagopt >>../test/output) &&
-	(cd one &&
-	 git tag -d some-tag foobar-tag) &&
+	rm -rf add-tags &&
+	(
+		mkdir add-no-tags &&
+		cd add-no-tags &&
+		git init &&
+		git remote add -f --no-tags origin ../one &&
+		git tag -l some-tag >../test/output &&
+		git tag -l foobar-tag >../test/output &&
+		git config remote.origin.tagopt >>../test/output
+	) &&
+	(
+		cd one &&
+		git tag -d some-tag foobar-tag
+	) &&
 	test_cmp test/expect test/output
 '
 
 test_expect_success 'reject --no-no-tags' '
-	(cd add-no-tags &&
-	 test_must_fail git remote add -f --no-no-tags neworigin ../one)
+	(
+		cd add-no-tags &&
+		test_must_fail git remote add -f --no-no-tags neworigin ../one
+	)
 '
 
-cat > one/expect << EOF
+cat >one/expect <<\EOF
   apis/master
   apis/side
   drosophila/another
@@ -500,17 +560,17 @@
 EOF
 
 test_expect_success 'update' '
-
-	(cd one &&
-	 git remote add drosophila ../two &&
-	 git remote add apis ../mirror &&
-	 git remote update &&
-	 git branch -r > output &&
-	 test_cmp expect output)
-
+	(
+		cd one &&
+		git remote add drosophila ../two &&
+		git remote add apis ../mirror &&
+		git remote update &&
+		git branch -r >output &&
+		test_cmp expect output
+	)
 '
 
-cat > one/expect << EOF
+cat >one/expect <<\EOF
   drosophila/another
   drosophila/master
   drosophila/side
@@ -521,34 +581,40 @@
 EOF
 
 test_expect_success 'update with arguments' '
-
-	(cd one &&
-	 for b in $(git branch -r)
-	 do
+	(
+		cd one &&
+		for b in $(git branch -r)
+		do
 		git branch -r -d $b || break
-	 done &&
-	 git remote add manduca ../mirror &&
-	 git remote add megaloprepus ../mirror &&
-	 git config remotes.phobaeticus "drosophila megaloprepus" &&
-	 git config remotes.titanus manduca &&
-	 git remote update phobaeticus titanus &&
-	 git branch -r > output &&
-	 test_cmp expect output)
-
+		done &&
+		git remote add manduca ../mirror &&
+		git remote add megaloprepus ../mirror &&
+		git config remotes.phobaeticus "drosophila megaloprepus" &&
+		git config remotes.titanus manduca &&
+		git remote update phobaeticus titanus &&
+		git branch -r >output &&
+		test_cmp expect output
+	)
 '
 
 test_expect_success 'update --prune' '
-
-	(cd one &&
-	 git branch -m side2 side3) &&
-	(cd test &&
-	 git remote update --prune &&
-	 (cd ../one && git branch -m side3 side2) &&
-	 git rev-parse refs/remotes/origin/side3 &&
-	 test_must_fail git rev-parse refs/remotes/origin/side2)
+	(
+		cd one &&
+		git branch -m side2 side3
+	) &&
+	(
+		cd test &&
+		git remote update --prune &&
+		(
+			cd ../one &&
+			git branch -m side3 side2
+		) &&
+		git rev-parse refs/remotes/origin/side3 &&
+		test_must_fail git rev-parse refs/remotes/origin/side2
+	)
 '
 
-cat > one/expect << EOF
+cat >one/expect <<-\EOF
   apis/master
   apis/side
   manduca/master
@@ -558,176 +624,204 @@
 EOF
 
 test_expect_success 'update default' '
-
-	(cd one &&
-	 for b in $(git branch -r)
-	 do
+	(
+		cd one &&
+		for b in $(git branch -r)
+		do
 		git branch -r -d $b || break
-	 done &&
-	 git config remote.drosophila.skipDefaultUpdate true &&
-	 git remote update default &&
-	 git branch -r > output &&
-	 test_cmp expect output)
-
+		done &&
+		git config remote.drosophila.skipDefaultUpdate true &&
+		git remote update default &&
+		git branch -r >output &&
+		test_cmp expect output
+	)
 '
 
-cat > one/expect << EOF
+cat >one/expect <<\EOF
   drosophila/another
   drosophila/master
   drosophila/side
 EOF
 
 test_expect_success 'update default (overridden, with funny whitespace)' '
-
-	(cd one &&
-	 for b in $(git branch -r)
-	 do
+	(
+		cd one &&
+		for b in $(git branch -r)
+		do
 		git branch -r -d $b || break
-	 done &&
-	 git config remotes.default "$(printf "\t drosophila  \n")" &&
-	 git remote update default &&
-	 git branch -r > output &&
-	 test_cmp expect output)
-
+		done &&
+		git config remotes.default "$(printf "\t drosophila  \n")" &&
+		git remote update default &&
+		git branch -r >output &&
+		test_cmp expect output
+	)
 '
 
 test_expect_success 'update (with remotes.default defined)' '
-
-	(cd one &&
-	 for b in $(git branch -r)
-	 do
+	(
+		cd one &&
+		for b in $(git branch -r)
+		do
 		git branch -r -d $b || break
-	 done &&
-	 git config remotes.default "drosophila" &&
-	 git remote update &&
-	 git branch -r > output &&
-	 test_cmp expect output)
-
+		done &&
+		git config remotes.default "drosophila" &&
+		git remote update &&
+		git branch -r >output &&
+		test_cmp expect output
+	)
 '
 
 test_expect_success '"remote show" does not show symbolic refs' '
-
 	git clone one three &&
-	(cd three &&
-	 git remote show origin > output &&
-	 ! grep "^ *HEAD$" < output &&
-	 ! grep -i stale < output)
-
+	(
+		cd three &&
+		git remote show origin >output &&
+		! grep "^ *HEAD$" < output &&
+		! grep -i stale < output
+	)
 '
 
 test_expect_success 'reject adding remote with an invalid name' '
-
 	test_must_fail git remote add some:url desired-name
-
 '
 
 # The first three test if the tracking branches are properly renamed,
 # the last two ones check if the config is updated.
 
 test_expect_success 'rename a remote' '
-
 	git clone one four &&
-	(cd four &&
-	 git remote rename origin upstream &&
-	 rmdir .git/refs/remotes/origin &&
-	 test "$(git symbolic-ref refs/remotes/upstream/HEAD)" = "refs/remotes/upstream/master" &&
-	 test "$(git rev-parse upstream/master)" = "$(git rev-parse master)" &&
-	 test "$(git config remote.upstream.fetch)" = "+refs/heads/*:refs/remotes/upstream/*" &&
-	 test "$(git config branch.master.remote)" = "upstream")
-
+	(
+		cd four &&
+		git remote rename origin upstream &&
+		rmdir .git/refs/remotes/origin &&
+		test "$(git symbolic-ref refs/remotes/upstream/HEAD)" = "refs/remotes/upstream/master" &&
+		test "$(git rev-parse upstream/master)" = "$(git rev-parse master)" &&
+		test "$(git config remote.upstream.fetch)" = "+refs/heads/*:refs/remotes/upstream/*" &&
+		test "$(git config branch.master.remote)" = "upstream"
+	)
 '
 
 test_expect_success 'rename does not update a non-default fetch refspec' '
-
 	git clone one four.one &&
-	(cd four.one &&
-	 git config remote.origin.fetch +refs/heads/*:refs/heads/origin/* &&
-	 git remote rename origin upstream &&
-	 test "$(git config remote.upstream.fetch)" = "+refs/heads/*:refs/heads/origin/*" &&
-	 git rev-parse -q origin/master)
-
+	(
+		cd four.one &&
+		git config remote.origin.fetch +refs/heads/*:refs/heads/origin/* &&
+		git remote rename origin upstream &&
+		test "$(git config remote.upstream.fetch)" = "+refs/heads/*:refs/heads/origin/*" &&
+		git rev-parse -q origin/master
+	)
 '
 
 test_expect_success 'rename a remote with name part of fetch spec' '
-
 	git clone one four.two &&
-	(cd four.two &&
-	 git remote rename origin remote &&
-	 git remote rename remote upstream &&
-	 test "$(git config remote.upstream.fetch)" = "+refs/heads/*:refs/remotes/upstream/*")
-
+	(
+		cd four.two &&
+		git remote rename origin remote &&
+		git remote rename remote upstream &&
+		test "$(git config remote.upstream.fetch)" = "+refs/heads/*:refs/remotes/upstream/*"
+	)
 '
 
 test_expect_success 'rename a remote with name prefix of other remote' '
-
 	git clone one four.three &&
-	(cd four.three &&
-	 git remote add o git://example.com/repo.git &&
-	 git remote rename o upstream &&
-	 test "$(git rev-parse origin/master)" = "$(git rev-parse master)")
-
+	(
+		cd four.three &&
+		git remote add o git://example.com/repo.git &&
+		git remote rename o upstream &&
+		test "$(git rev-parse origin/master)" = "$(git rev-parse master)"
+	)
 '
 
-cat > remotes_origin << EOF
+cat >remotes_origin <<EOF
 URL: $(pwd)/one
 Push: refs/heads/master:refs/heads/upstream
+Push: refs/heads/next:refs/heads/upstream2
 Pull: refs/heads/master:refs/heads/origin
+Pull: refs/heads/next:refs/heads/origin2
 EOF
 
 test_expect_success 'migrate a remote from named file in $GIT_DIR/remotes' '
 	git clone one five &&
 	origin_url=$(pwd)/one &&
-	(cd five &&
-	 git remote remove origin &&
-	 mkdir -p .git/remotes &&
-	 cat ../remotes_origin > .git/remotes/origin &&
-	 git remote rename origin origin &&
-	 ! test -f .git/remotes/origin &&
-	 test "$(git config remote.origin.url)" = "$origin_url" &&
-	 test "$(git config remote.origin.push)" = "refs/heads/master:refs/heads/upstream" &&
-	 test "$(git config remote.origin.fetch)" = "refs/heads/master:refs/heads/origin")
+	(
+		cd five &&
+		git remote remove origin &&
+		mkdir -p .git/remotes &&
+		cat ../remotes_origin >.git/remotes/origin &&
+		git remote rename origin origin &&
+		test_path_is_missing .git/remotes/origin &&
+		test "$(git config remote.origin.url)" = "$origin_url" &&
+		cat >push_expected <<-\EOF &&
+		refs/heads/master:refs/heads/upstream
+		refs/heads/next:refs/heads/upstream2
+		EOF
+		cat >fetch_expected <<-\EOF &&
+		refs/heads/master:refs/heads/origin
+		refs/heads/next:refs/heads/origin2
+		EOF
+		git config --get-all remote.origin.push >push_actual &&
+		git config --get-all remote.origin.fetch >fetch_actual &&
+		test_cmp push_expected push_actual &&
+		test_cmp fetch_expected fetch_actual
+	)
 '
 
 test_expect_success 'migrate a remote from named file in $GIT_DIR/branches' '
 	git clone one six &&
 	origin_url=$(pwd)/one &&
-	(cd six &&
-	 git remote rm origin &&
-	 echo "$origin_url" > .git/branches/origin &&
-	 git remote rename origin origin &&
-	 ! test -f .git/branches/origin &&
-	 test "$(git config remote.origin.url)" = "$origin_url" &&
-	 test "$(git config remote.origin.fetch)" = "refs/heads/master:refs/heads/origin")
+	(
+		cd six &&
+		git remote rm origin &&
+		echo "$origin_url" >.git/branches/origin &&
+		git remote rename origin origin &&
+		test_path_is_missing .git/branches/origin &&
+		test "$(git config remote.origin.url)" = "$origin_url" &&
+		test "$(git config remote.origin.fetch)" = "refs/heads/master:refs/heads/origin" &&
+		test "$(git config remote.origin.push)" = "HEAD:refs/heads/master"
+	)
+'
+
+test_expect_success 'migrate a remote from named file in $GIT_DIR/branches (2)' '
+	git clone one seven &&
+	(
+		cd seven &&
+		git remote rm origin &&
+		echo "quux#foom" > .git/branches/origin &&
+		git remote rename origin origin &&
+		test_path_is_missing .git/branches/origin &&
+		test "$(git config remote.origin.url)" = "quux" &&
+		test "$(git config remote.origin.fetch)" = "refs/heads/foom:refs/heads/origin"
+		test "$(git config remote.origin.push)" = "HEAD:refs/heads/foom"
+	)
 '
 
 test_expect_success 'remote prune to cause a dangling symref' '
-	git clone one seven &&
+	git clone one eight &&
 	(
 		cd one &&
 		git checkout side2 &&
 		git branch -D master
 	) &&
 	(
-		cd seven &&
+		cd eight &&
 		git remote prune origin
 	) >err 2>&1 &&
 	test_i18ngrep "has become dangling" err &&
 
 	: And the dangling symref will not cause other annoying errors &&
 	(
-		cd seven &&
+		cd eight &&
 		git branch -a
 	) 2>err &&
 	! grep "points nowhere" err &&
 	(
-		cd seven &&
+		cd eight &&
 		test_must_fail git branch nomore origin
 	) 2>err &&
 	grep "dangling symref" err
 '
 
 test_expect_success 'show empty remote' '
-
 	test_create_repo empty &&
 	git clone empty empty-clone &&
 	(
diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh
index d7a19a1..fde6891 100755
--- a/t/t5510-fetch.sh
+++ b/t/t5510-fetch.sh
@@ -370,30 +370,39 @@
 
 '
 
-test_expect_success 'explicit fetch should not update tracking' '
+test_expect_success 'mark initial state of origin/master' '
+	(
+		cd three &&
+		git tag base-origin-master refs/remotes/origin/master
+	)
+'
+
+test_expect_success 'explicit fetch should update tracking' '
 
 	cd "$D" &&
 	git branch -f side &&
 	(
 		cd three &&
+		git update-ref refs/remotes/origin/master base-origin-master &&
 		o=$(git rev-parse --verify refs/remotes/origin/master) &&
 		git fetch origin master &&
 		n=$(git rev-parse --verify refs/remotes/origin/master) &&
-		test "$o" = "$n" &&
+		test "$o" != "$n" &&
 		test_must_fail git rev-parse --verify refs/remotes/origin/side
 	)
 '
 
-test_expect_success 'explicit pull should not update tracking' '
+test_expect_success 'explicit pull should update tracking' '
 
 	cd "$D" &&
 	git branch -f side &&
 	(
 		cd three &&
+		git update-ref refs/remotes/origin/master base-origin-master &&
 		o=$(git rev-parse --verify refs/remotes/origin/master) &&
 		git pull origin master &&
 		n=$(git rev-parse --verify refs/remotes/origin/master) &&
-		test "$o" = "$n" &&
+		test "$o" != "$n" &&
 		test_must_fail git rev-parse --verify refs/remotes/origin/side
 	)
 '
@@ -404,6 +413,7 @@
 	git branch -f side &&
 	(
 		cd three &&
+		git update-ref refs/remotes/origin/master base-origin-master &&
 		o=$(git rev-parse --verify refs/remotes/origin/master) &&
 		git fetch origin &&
 		n=$(git rev-parse --verify refs/remotes/origin/master) &&
@@ -412,6 +422,22 @@
 	)
 '
 
+test_expect_success 'non-matching refspecs do not confuse tracking update' '
+	cd "$D" &&
+	git update-ref refs/odd/location HEAD &&
+	(
+		cd three &&
+		git update-ref refs/remotes/origin/master base-origin-master &&
+		git config --add remote.origin.fetch \
+			refs/odd/location:refs/remotes/origin/odd &&
+		o=$(git rev-parse --verify refs/remotes/origin/master) &&
+		git fetch origin master &&
+		n=$(git rev-parse --verify refs/remotes/origin/master) &&
+		test "$o" != "$n" &&
+		test_must_fail git rev-parse --verify refs/remotes/origin/odd
+	)
+'
+
 test_expect_success 'pushing nonexistent branch by mistake should not segv' '
 
 	cd "$D" &&
diff --git a/t/t5520-pull.sh b/t/t5520-pull.sh
index 6af6c63..ed4d9c8 100755
--- a/t/t5520-pull.sh
+++ b/t/t5520-pull.sh
@@ -57,6 +57,35 @@
 	)
 '
 
+test_expect_success 'pulling into void does not overwrite staged files' '
+	git init cloned-staged-colliding &&
+	(
+		cd cloned-staged-colliding &&
+		echo "alternate content" >file &&
+		git add file &&
+		test_must_fail git pull .. master &&
+		echo "alternate content" >expect &&
+		test_cmp expect file &&
+		git cat-file blob :file >file.index &&
+		test_cmp expect file.index
+	)
+'
+
+
+test_expect_success 'pulling into void does not remove new staged files' '
+	git init cloned-staged-new &&
+	(
+		cd cloned-staged-new &&
+		echo "new tracked file" >newfile &&
+		git add newfile &&
+		git pull .. master &&
+		echo "new tracked file" >expect &&
+		test_cmp expect newfile &&
+		git cat-file blob :newfile >newfile.index &&
+		test_cmp expect newfile.index
+	)
+'
+
 test_expect_success 'test . as a remote' '
 
 	git branch copy master &&
diff --git a/t/t5521-pull-options.sh b/t/t5521-pull-options.sh
index aa31abe..453aba5 100755
--- a/t/t5521-pull-options.sh
+++ b/t/t5521-pull-options.sh
@@ -15,19 +15,19 @@
 	mkdir clonedq &&
 	(cd clonedq && git init &&
 	git pull -q "../parent" >out 2>err &&
-	test ! -s err &&
-	test ! -s out)
+	test_must_be_empty err &&
+	test_must_be_empty out)
 '
 
 test_expect_success 'git pull -q --rebase' '
 	mkdir clonedqrb &&
 	(cd clonedqrb && git init &&
 	git pull -q --rebase "../parent" >out 2>err &&
-	test ! -s err &&
-	test ! -s out &&
+	test_must_be_empty err &&
+	test_must_be_empty out &&
 	git pull -q --rebase "../parent" >out 2>err &&
-	test ! -s err &&
-	test ! -s out)
+	test_must_be_empty err &&
+	test_must_be_empty out)
 '
 
 test_expect_success 'git pull' '
@@ -35,7 +35,7 @@
 	(cd cloned && git init &&
 	git pull "../parent" >out 2>err &&
 	test -s err &&
-	test ! -s out)
+	test_must_be_empty out)
 '
 
 test_expect_success 'git pull --rebase' '
@@ -43,7 +43,7 @@
 	(cd clonedrb && git init &&
 	git pull --rebase "../parent" >out 2>err &&
 	test -s err &&
-	test ! -s out)
+	test_must_be_empty out)
 '
 
 test_expect_success 'git pull -v' '
@@ -51,7 +51,7 @@
 	(cd clonedv && git init &&
 	git pull -v "../parent" >out 2>err &&
 	test -s err &&
-	test ! -s out)
+	test_must_be_empty out)
 '
 
 test_expect_success 'git pull -v --rebase' '
@@ -59,22 +59,22 @@
 	(cd clonedvrb && git init &&
 	git pull -v --rebase "../parent" >out 2>err &&
 	test -s err &&
-	test ! -s out)
+	test_must_be_empty out)
 '
 
 test_expect_success 'git pull -v -q' '
 	mkdir clonedvq &&
 	(cd clonedvq && git init &&
 	git pull -v -q "../parent" >out 2>err &&
-	test ! -s out &&
-	test ! -s err)
+	test_must_be_empty out &&
+	test_must_be_empty err)
 '
 
 test_expect_success 'git pull -q -v' '
 	mkdir clonedqv &&
 	(cd clonedqv && git init &&
 	git pull -q -v "../parent" >out 2>err &&
-	test ! -s out &&
+	test_must_be_empty out &&
 	test -s err)
 '
 
diff --git a/t/t5528-push-default.sh b/t/t5528-push-default.sh
index 4736da8..6a5ac3a 100755
--- a/t/t5528-push-default.sh
+++ b/t/t5528-push-default.sh
@@ -15,17 +15,19 @@
 
 # $1 = local revision
 # $2 = remote revision (tested to be equal to the local one)
+# $3 = [optional] repo to check for actual output (repo1 by default)
 check_pushed_commit () {
 	git log -1 --format='%h %s' "$1" >expect &&
-	git --git-dir=repo1 log -1 --format='%h %s' "$2" >actual &&
+	git --git-dir="${3:-repo1}" log -1 --format='%h %s' "$2" >actual &&
 	test_cmp expect actual
 }
 
 # $1 = push.default value
 # $2 = expected target branch for the push
+# $3 = [optional] repo to check for actual output (repo1 by default)
 test_push_success () {
 	git -c push.default="$1" push &&
-	check_pushed_commit HEAD "$2"
+	check_pushed_commit HEAD "$2" "$3"
 }
 
 # $1 = push.default value
@@ -37,6 +39,26 @@
 	test_cmp expect actual
 }
 
+# $1 = success or failure
+# $2 = push.default value
+# $3 = branch to check for actual output (master or foo)
+# $4 = [optional] switch to triangular workflow
+test_pushdefault_workflow () {
+	workflow=central
+	pushdefault=parent1
+	if test -n "${4-}"; then
+		workflow=triangular
+		pushdefault=parent2
+	fi
+	test_expect_success "push.default = $2 $1 in $workflow workflows" "
+		test_config branch.master.remote parent1 &&
+		test_config branch.master.merge refs/heads/foo &&
+		test_config remote.pushdefault $pushdefault &&
+		test_commit commit-for-$2${4+-triangular} &&
+		test_push_$1 $2 $3 ${4+repo2}
+	"
+}
+
 test_expect_success '"upstream" pushes to configured upstream' '
 	git checkout master &&
 	test_config branch.master.remote parent1 &&
@@ -48,7 +70,6 @@
 test_expect_success '"upstream" does not push on unconfigured remote' '
 	git checkout master &&
 	test_unconfig branch.master.remote &&
-	test_config push.default upstream &&
 	test_commit three &&
 	test_push_failure upstream
 '
@@ -57,7 +78,6 @@
 	git checkout master &&
 	test_config branch.master.remote parent1 &&
 	test_unconfig branch.master.merge &&
-	test_config push.default upstream
 	test_commit four &&
 	test_push_failure upstream
 '
@@ -115,4 +135,41 @@
 	test_cmp expect-other-name actual-other-name
 '
 
+# We are on 'master', which integrates with 'foo' from parent1
+# remote (set in test_pushdefault_workflow helper).  Push to
+# parent1 in centralized, and push to parent2 in triangular workflow.
+# The parent1 repository has 'master' and 'foo' branches, while
+# the parent2 repository has only 'master' branch.
+#
+# test_pushdefault_workflow() arguments:
+# $1 = success or failure
+# $2 = push.default value
+# $3 = branch to check for actual output (master or foo)
+# $4 = [optional] switch to triangular workflow
+
+# update parent1's master (which is not our upstream)
+test_pushdefault_workflow success current master
+
+# update parent1's foo (which is our upstream)
+test_pushdefault_workflow success upstream foo
+
+# upsream is foo which is not the name of the current branch
+test_pushdefault_workflow failure simple master
+
+# master and foo are updated
+test_pushdefault_workflow success matching master
+
+# master is updated
+test_pushdefault_workflow success current master triangular
+
+# upstream mode cannot be used in triangular
+test_pushdefault_workflow failure upstream foo triangular
+
+# in triangular, 'simple' works as 'current' and update the branch
+# with the same name.
+test_pushdefault_workflow success simple master triangular
+
+# master is updated (parent2 does not have foo)
+test_pushdefault_workflow success matching master triangular
+
 test_done
diff --git a/t/t5551-http-fetch.sh b/t/t5551-http-fetch.sh
index b23efbb..55a866a 100755
--- a/t/t5551-http-fetch.sh
+++ b/t/t5551-http-fetch.sh
@@ -209,13 +209,17 @@
 
 	# now assign tags to all the dangling commits we created above
 	tag=$("$PERL_PATH" -e "print \"bla\" x 30") &&
-	sed -e "s/^:\(.\+\) \(.\+\)$/\2 refs\/tags\/$tag-\1/" <marks >>packed-refs
+	sed -e "s|^:\([^ ]*\) \(.*\)$|\2 refs/tags/$tag-\1|" <marks >>packed-refs
 	)
 '
 
 test_expect_success EXPENSIVE 'clone the 50,000 tag repo to check OS command line overflow' '
 	git clone $HTTPD_URL/smart/repo.git too-many-refs 2>err &&
-	test_line_count = 0 err
+	test_line_count = 0 err &&
+	(
+		cd too-many-refs &&
+		test $(git for-each-ref refs/tags | wc -l) = 50000
+	)
 '
 
 stop_httpd
diff --git a/t/t5560-http-backend-noserver.sh b/t/t5560-http-backend-noserver.sh
index ef98d95..9be9ae3 100755
--- a/t/t5560-http-backend-noserver.sh
+++ b/t/t5560-http-backend-noserver.sh
@@ -5,7 +5,7 @@
 
 HTTPD_DOCUMENT_ROOT_PATH="$TRASH_DIRECTORY"
 
-test_have_prereq MINGW && export GREP_OPTIONS=-U
+test_have_prereq GREP_STRIPS_CR && export GREP_OPTIONS=-U
 
 run_backend() {
 	echo "$2" |
diff --git a/t/t5601-clone.sh b/t/t5601-clone.sh
index 67869b4..0629149 100755
--- a/t/t5601-clone.sh
+++ b/t/t5601-clone.sh
@@ -280,4 +280,9 @@
 	test_cmp fetch.expected fetch.actual
 '
 
+test_expect_success NOT_MINGW,NOT_CYGWIN 'clone local path foo:bar' '
+	cp -R src "foo:bar" &&
+	git clone "./foo:bar" foobar
+'
+
 test_done
diff --git a/t/t5702-clone-options.sh b/t/t5702-clone-options.sh
index 02cb024..85cadfa 100755
--- a/t/t5702-clone-options.sh
+++ b/t/t5702-clone-options.sh
@@ -22,7 +22,7 @@
 test_expect_success 'redirected clone' '
 
 	git clone "file://$(pwd)/parent" clone-redirected >out 2>err &&
-	test ! -s err
+	test_must_be_empty err
 
 '
 test_expect_success 'redirected clone -v' '
diff --git a/t/t5710-info-alternate.sh b/t/t5710-info-alternate.sh
index 8956c21..5a6e49d 100755
--- a/t/t5710-info-alternate.sh
+++ b/t/t5710-info-alternate.sh
@@ -58,7 +58,13 @@
 git clone -l -s D E &&
 git clone -l -s E F &&
 git clone -l -s F G &&
-test_must_fail git clone --bare -l -s G H'
+git clone --bare -l -s G H'
+
+test_expect_success 'invalidity of deepest repository' \
+'cd H && {
+	test_valid_repo
+	test $? -ne 0
+}'
 
 cd "$base_dir"
 
diff --git a/t/t5801-remote-helpers.sh b/t/t5801-remote-helpers.sh
index 69212cd..8c4c539 100755
--- a/t/t5801-remote-helpers.sh
+++ b/t/t5801-remote-helpers.sh
@@ -8,11 +8,6 @@
 . ./test-lib.sh
 . "$TEST_DIRECTORY"/lib-gpg.sh
 
-if ! type "${BASH-bash}" >/dev/null 2>&1; then
-	skip_all='skipping remote-testgit tests, bash not available'
-	test_done
-fi
-
 compare_refs() {
 	git --git-dir="$1/.git" rev-parse --verify $2 >expect &&
 	git --git-dir="$3/.git" rev-parse --verify $4 >actual &&
@@ -101,39 +96,28 @@
 
 test_expect_success 'cloning without refspec' '
 	GIT_REMOTE_TESTGIT_REFSPEC="" \
-	git clone "testgit::${PWD}/server" local2 &&
+	git clone "testgit::${PWD}/server" local2 2>error &&
+	grep "This remote helper should implement refspec capability" error &&
 	compare_refs local2 HEAD server HEAD
 '
 
 test_expect_success 'pulling without refspecs' '
 	(cd local2 &&
 	git reset --hard &&
-	GIT_REMOTE_TESTGIT_REFSPEC="" git pull) &&
+	GIT_REMOTE_TESTGIT_REFSPEC="" git pull 2>../error) &&
+	grep "This remote helper should implement refspec capability" error &&
 	compare_refs local2 HEAD server HEAD
 '
 
-test_expect_failure 'pushing without refspecs' '
+test_expect_success 'pushing without refspecs' '
 	test_when_finished "(cd local2 && git reset --hard origin)" &&
 	(cd local2 &&
 	echo content >>file &&
 	git commit -a -m ten &&
-	GIT_REMOTE_TESTGIT_REFSPEC="" git push) &&
-	compare_refs local2 HEAD server HEAD
-'
-
-test_expect_success 'pulling with straight refspec' '
-	(cd local2 &&
-	GIT_REMOTE_TESTGIT_REFSPEC="*:*" git pull) &&
-	compare_refs local2 HEAD server HEAD
-'
-
-test_expect_failure 'pushing with straight refspec' '
-	test_when_finished "(cd local2 && git reset --hard origin)" &&
-	(cd local2 &&
-	echo content >>file &&
-	git commit -a -m eleven &&
-	GIT_REMOTE_TESTGIT_REFSPEC="*:*" git push) &&
-	compare_refs local2 HEAD server HEAD
+	GIT_REMOTE_TESTGIT_REFSPEC="" &&
+	export GIT_REMOTE_TESTGIT_REFSPEC &&
+	test_must_fail git push 2>../error) &&
+	grep "remote-helper doesn.t support push; refspec needed" error
 '
 
 test_expect_success 'pulling without marks' '
@@ -186,4 +170,62 @@
 	compare_refs local signed-tag-2 server signed-tag-2
 '
 
+test_expect_success 'push update refs' '
+	(cd local &&
+	git checkout -b update master &&
+	echo update >>file &&
+	git commit -a -m update &&
+	git push origin update &&
+	git rev-parse --verify remotes/origin/update >expect &&
+	git rev-parse --verify testgit/origin/heads/update >actual &&
+	test_cmp expect actual
+	)
+'
+
+test_expect_success 'push update refs failure' '
+	(cd local &&
+	git checkout update &&
+	echo "update fail" >>file &&
+	git commit -a -m "update fail" &&
+	git rev-parse --verify testgit/origin/heads/update >expect &&
+	GIT_REMOTE_TESTGIT_PUSH_ERROR="non-fast forward" &&
+	export GIT_REMOTE_TESTGIT_PUSH_ERROR &&
+	test_expect_code 1 git push origin update &&
+	git rev-parse --verify testgit/origin/heads/update >actual &&
+	test_cmp expect actual
+	)
+'
+
+test_expect_success 'proper failure checks for fetching' '
+	(GIT_REMOTE_TESTGIT_FAILURE=1 &&
+	export GIT_REMOTE_TESTGIT_FAILURE &&
+	cd local &&
+	test_must_fail git fetch 2> error &&
+	cat error &&
+	grep -q "Error while running fast-import" error
+	)
+'
+
+test_expect_success 'proper failure checks for pushing' '
+	(GIT_REMOTE_TESTGIT_FAILURE=1 &&
+	export GIT_REMOTE_TESTGIT_FAILURE &&
+	cd local &&
+	test_must_fail git push --all
+	)
+'
+
+test_expect_success 'push messages' '
+	(cd local &&
+	git checkout -b new_branch master &&
+	echo new >>file &&
+	git commit -a -m new &&
+	git push origin new_branch &&
+	git fetch origin &&
+	echo new >>file &&
+	git commit -a -m new &&
+	git push origin new_branch 2> msg &&
+	! grep "\[new branch\]" msg
+	)
+'
+
 test_done
diff --git a/t/t5802-connect-helper.sh b/t/t5802-connect-helper.sh
new file mode 100755
index 0000000..878faf2
--- /dev/null
+++ b/t/t5802-connect-helper.sh
@@ -0,0 +1,72 @@
+#!/bin/sh
+
+test_description='ext::cmd remote "connect" helper'
+. ./test-lib.sh
+
+test_expect_success setup '
+	test_tick &&
+	git commit --allow-empty -m initial &&
+	test_tick &&
+	git commit --allow-empty -m second &&
+	test_tick &&
+	git commit --allow-empty -m third &&
+	test_tick &&
+	git tag -a -m "tip three" three &&
+
+	test_tick &&
+	git commit --allow-empty -m fourth
+'
+
+test_expect_success clone '
+	cmd=$(echo "echo >&2 ext::sh invoked && %S .." | sed -e "s/ /% /g") &&
+	git clone "ext::sh -c %S% ." dst &&
+	git for-each-ref refs/heads/ refs/tags/ >expect &&
+	(
+		cd dst &&
+		git config remote.origin.url "ext::sh -c $cmd" &&
+		git for-each-ref refs/heads/ refs/tags/
+	) >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'update following tag' '
+	test_tick &&
+	git commit --allow-empty -m fifth &&
+	test_tick &&
+	git tag -a -m "tip five" five &&
+	git for-each-ref refs/heads/ refs/tags/ >expect &&
+	(
+		cd dst &&
+		git pull &&
+		git for-each-ref refs/heads/ refs/tags/ >../actual
+	) &&
+	test_cmp expect actual
+'
+
+test_expect_success 'update backfilled tag' '
+	test_tick &&
+	git commit --allow-empty -m sixth &&
+	test_tick &&
+	git tag -a -m "tip two" two three^1 &&
+	git for-each-ref refs/heads/ refs/tags/ >expect &&
+	(
+		cd dst &&
+		git pull &&
+		git for-each-ref refs/heads/ refs/tags/ >../actual
+	) &&
+	test_cmp expect actual
+'
+
+test_expect_success 'update backfilled tag without primary transfer' '
+	test_tick &&
+	git tag -a -m "tip one " one two^1 &&
+	git for-each-ref refs/heads/ refs/tags/ >expect &&
+	(
+		cd dst &&
+		git pull &&
+		git for-each-ref refs/heads/ refs/tags/ >../actual
+	) &&
+	test_cmp expect actual
+'
+
+test_done
diff --git a/t/t6002-rev-list-bisect.sh b/t/t6002-rev-list-bisect.sh
index fb07536..43ad772 100755
--- a/t/t6002-rev-list-bisect.sh
+++ b/t/t6002-rev-list-bisect.sh
@@ -39,25 +39,25 @@
 date >path0
 git update-index --add path0
 save_tag tree git write-tree
-on_committer_date "1971-08-16 00:00:00" hide_error save_tag root unique_commit root tree
-on_committer_date "1971-08-16 00:00:01" save_tag l0 unique_commit l0 tree -p root
-on_committer_date "1971-08-16 00:00:02" save_tag l1 unique_commit l1 tree -p l0
-on_committer_date "1971-08-16 00:00:03" save_tag l2 unique_commit l2 tree -p l1
-on_committer_date "1971-08-16 00:00:04" save_tag a0 unique_commit a0 tree -p l2
-on_committer_date "1971-08-16 00:00:05" save_tag a1 unique_commit a1 tree -p a0
-on_committer_date "1971-08-16 00:00:06" save_tag b1 unique_commit b1 tree -p a0
-on_committer_date "1971-08-16 00:00:07" save_tag c1 unique_commit c1 tree -p b1
-on_committer_date "1971-08-16 00:00:08" save_tag b2 unique_commit b2 tree -p b1
-on_committer_date "1971-08-16 00:00:09" save_tag b3 unique_commit b2 tree -p b2
-on_committer_date "1971-08-16 00:00:10" save_tag c2 unique_commit c2 tree -p c1 -p b2
-on_committer_date "1971-08-16 00:00:11" save_tag c3 unique_commit c3 tree -p c2
-on_committer_date "1971-08-16 00:00:12" save_tag a2 unique_commit a2 tree -p a1
-on_committer_date "1971-08-16 00:00:13" save_tag a3 unique_commit a3 tree -p a2
-on_committer_date "1971-08-16 00:00:14" save_tag b4 unique_commit b4 tree -p b3 -p a3
-on_committer_date "1971-08-16 00:00:15" save_tag a4 unique_commit a4 tree -p a3 -p b4 -p c3
-on_committer_date "1971-08-16 00:00:16" save_tag l3 unique_commit l3 tree -p a4
-on_committer_date "1971-08-16 00:00:17" save_tag l4 unique_commit l4 tree -p l3
-on_committer_date "1971-08-16 00:00:18" save_tag l5 unique_commit l5 tree -p l4
+on_committer_date "00:00" hide_error save_tag root unique_commit root tree
+on_committer_date "00:01" save_tag l0 unique_commit l0 tree -p root
+on_committer_date "00:02" save_tag l1 unique_commit l1 tree -p l0
+on_committer_date "00:03" save_tag l2 unique_commit l2 tree -p l1
+on_committer_date "00:04" save_tag a0 unique_commit a0 tree -p l2
+on_committer_date "00:05" save_tag a1 unique_commit a1 tree -p a0
+on_committer_date "00:06" save_tag b1 unique_commit b1 tree -p a0
+on_committer_date "00:07" save_tag c1 unique_commit c1 tree -p b1
+on_committer_date "00:08" save_tag b2 unique_commit b2 tree -p b1
+on_committer_date "00:09" save_tag b3 unique_commit b2 tree -p b2
+on_committer_date "00:10" save_tag c2 unique_commit c2 tree -p c1 -p b2
+on_committer_date "00:11" save_tag c3 unique_commit c3 tree -p c2
+on_committer_date "00:12" save_tag a2 unique_commit a2 tree -p a1
+on_committer_date "00:13" save_tag a3 unique_commit a3 tree -p a2
+on_committer_date "00:14" save_tag b4 unique_commit b4 tree -p b3 -p a3
+on_committer_date "00:15" save_tag a4 unique_commit a4 tree -p a3 -p b4 -p c3
+on_committer_date "00:16" save_tag l3 unique_commit l3 tree -p a4
+on_committer_date "00:17" save_tag l4 unique_commit l4 tree -p l3
+on_committer_date "00:18" save_tag l5 unique_commit l5 tree -p l4
 git update-ref HEAD $(tag l5)
 
 
@@ -90,29 +90,29 @@
 #     F
 
 
-on_committer_date "1971-08-16 00:00:00" hide_error save_tag F unique_commit F tree
-on_committer_date "1971-08-16 00:00:01" save_tag e8 unique_commit e8 tree -p F
-on_committer_date "1971-08-16 00:00:02" save_tag e7 unique_commit e7 tree -p e8
-on_committer_date "1971-08-16 00:00:03" save_tag e6 unique_commit e6 tree -p e7
-on_committer_date "1971-08-16 00:00:04" save_tag e5 unique_commit e5 tree -p e6
-on_committer_date "1971-08-16 00:00:05" save_tag f4 unique_commit f4 tree -p F
-on_committer_date "1971-08-16 00:00:06" save_tag f3 unique_commit f3 tree -p f4
-on_committer_date "1971-08-16 00:00:07" save_tag f2 unique_commit f2 tree -p f3
-on_committer_date "1971-08-16 00:00:08" save_tag f1 unique_commit f1 tree -p f2
-on_committer_date "1971-08-16 00:00:09" save_tag e4 unique_commit e4 tree -p e5
-on_committer_date "1971-08-16 00:00:10" save_tag e3 unique_commit e3 tree -p e4
-on_committer_date "1971-08-16 00:00:11" save_tag e2 unique_commit e2 tree -p e3
-on_committer_date "1971-08-16 00:00:12" save_tag e1 unique_commit e1 tree -p e2
-on_committer_date "1971-08-16 00:00:13" save_tag E unique_commit E tree -p e1 -p f1
+on_committer_date "00:00" hide_error save_tag F unique_commit F tree
+on_committer_date "00:01" save_tag e8 unique_commit e8 tree -p F
+on_committer_date "00:02" save_tag e7 unique_commit e7 tree -p e8
+on_committer_date "00:03" save_tag e6 unique_commit e6 tree -p e7
+on_committer_date "00:04" save_tag e5 unique_commit e5 tree -p e6
+on_committer_date "00:05" save_tag f4 unique_commit f4 tree -p F
+on_committer_date "00:06" save_tag f3 unique_commit f3 tree -p f4
+on_committer_date "00:07" save_tag f2 unique_commit f2 tree -p f3
+on_committer_date "00:08" save_tag f1 unique_commit f1 tree -p f2
+on_committer_date "00:09" save_tag e4 unique_commit e4 tree -p e5
+on_committer_date "00:10" save_tag e3 unique_commit e3 tree -p e4
+on_committer_date "00:11" save_tag e2 unique_commit e2 tree -p e3
+on_committer_date "00:12" save_tag e1 unique_commit e1 tree -p e2
+on_committer_date "00:13" save_tag E unique_commit E tree -p e1 -p f1
 
-on_committer_date "1971-08-16 00:00:00" hide_error save_tag U unique_commit U tree
-on_committer_date "1971-08-16 00:00:01" save_tag u0 unique_commit u0 tree -p U
-on_committer_date "1971-08-16 00:00:01" save_tag u1 unique_commit u1 tree -p u0
-on_committer_date "1971-08-16 00:00:02" save_tag u2 unique_commit u2 tree -p u0
-on_committer_date "1971-08-16 00:00:03" save_tag u3 unique_commit u3 tree -p u0
-on_committer_date "1971-08-16 00:00:04" save_tag u4 unique_commit u4 tree -p u0
-on_committer_date "1971-08-16 00:00:05" save_tag u5 unique_commit u5 tree -p u0
-on_committer_date "1971-08-16 00:00:06" save_tag V unique_commit V tree -p u1 -p u2 -p u3 -p u4 -p u5
+on_committer_date "00:00" hide_error save_tag U unique_commit U tree
+on_committer_date "00:01" save_tag u0 unique_commit u0 tree -p U
+on_committer_date "00:01" save_tag u1 unique_commit u1 tree -p u0
+on_committer_date "00:02" save_tag u2 unique_commit u2 tree -p u0
+on_committer_date "00:03" save_tag u3 unique_commit u3 tree -p u0
+on_committer_date "00:04" save_tag u4 unique_commit u4 tree -p u0
+on_committer_date "00:05" save_tag u5 unique_commit u5 tree -p u0
+on_committer_date "00:06" save_tag V unique_commit V tree -p u1 -p u2 -p u3 -p u4 -p u5
 
 test_sequence()
 {
diff --git a/t/t6003-rev-list-topo-order.sh b/t/t6003-rev-list-topo-order.sh
index e4c52b0..24d1836 100755
--- a/t/t6003-rev-list-topo-order.sh
+++ b/t/t6003-rev-list-topo-order.sh
@@ -16,39 +16,34 @@
 date >path0
 git update-index --add path0
 save_tag tree git write-tree
-on_committer_date "1971-08-16 00:00:00" hide_error save_tag root unique_commit root tree
-on_committer_date "1971-08-16 00:00:01" save_tag l0 unique_commit l0 tree -p root
-on_committer_date "1971-08-16 00:00:02" save_tag l1 unique_commit l1 tree -p l0
-on_committer_date "1971-08-16 00:00:03" save_tag l2 unique_commit l2 tree -p l1
-on_committer_date "1971-08-16 00:00:04" save_tag a0 unique_commit a0 tree -p l2
-on_committer_date "1971-08-16 00:00:05" save_tag a1 unique_commit a1 tree -p a0
-on_committer_date "1971-08-16 00:00:06" save_tag b1 unique_commit b1 tree -p a0
-on_committer_date "1971-08-16 00:00:07" save_tag c1 unique_commit c1 tree -p b1
-on_committer_date "1971-08-16 00:00:08" as_author foobar@example.com save_tag b2 unique_commit b2 tree -p b1
-on_committer_date "1971-08-16 00:00:09" save_tag b3 unique_commit b3 tree -p b2
-on_committer_date "1971-08-16 00:00:10" save_tag c2 unique_commit c2 tree -p c1 -p b2
-on_committer_date "1971-08-16 00:00:11" save_tag c3 unique_commit c3 tree -p c2
-on_committer_date "1971-08-16 00:00:12" save_tag a2 unique_commit a2 tree -p a1
-on_committer_date "1971-08-16 00:00:13" save_tag a3 unique_commit a3 tree -p a2
-on_committer_date "1971-08-16 00:00:14" save_tag b4 unique_commit b4 tree -p b3 -p a3
-on_committer_date "1971-08-16 00:00:15" save_tag a4 unique_commit a4 tree -p a3 -p b4 -p c3
-on_committer_date "1971-08-16 00:00:16" save_tag l3 unique_commit l3 tree -p a4
-on_committer_date "1971-08-16 00:00:17" save_tag l4 unique_commit l4 tree -p l3
-on_committer_date "1971-08-16 00:00:18" save_tag l5 unique_commit l5 tree -p l4
-on_committer_date "1971-08-16 00:00:19" save_tag m1 unique_commit m1 tree -p a4 -p c3
-on_committer_date "1971-08-16 00:00:20" save_tag m2 unique_commit m2 tree -p c3 -p a4
-on_committer_date "1971-08-16 00:00:21" hide_error save_tag alt_root unique_commit alt_root tree
-on_committer_date "1971-08-16 00:00:22" save_tag r0 unique_commit r0 tree -p alt_root
-on_committer_date "1971-08-16 00:00:23" save_tag r1 unique_commit r1 tree -p r0
-on_committer_date "1971-08-16 00:00:24" save_tag l5r1 unique_commit l5r1 tree -p l5 -p r1
-on_committer_date "1971-08-16 00:00:25" save_tag r1l5 unique_commit r1l5 tree -p r1 -p l5
+on_dates "00:00" "00:00" hide_error save_tag root unique_commit root tree
+on_dates "00:01" "00:01" save_tag l0 unique_commit l0 tree -p root
+on_dates "00:02" "00:02" save_tag l1 unique_commit l1 tree -p l0
+on_dates "00:03" "00:03" save_tag l2 unique_commit l2 tree -p l1
+on_dates "00:04" "00:04" save_tag a0 unique_commit a0 tree -p l2
+on_dates "00:05" "00:05" save_tag a1 unique_commit a1 tree -p a0
+on_dates "00:06" "00:06" save_tag b1 unique_commit b1 tree -p a0
+on_dates "00:07" "00:07" save_tag c1 unique_commit c1 tree -p b1
+on_dates "00:08" "00:08" as_author foobar@example.com save_tag b2 unique_commit b2 tree -p b1
+on_dates "00:09" "00:09" save_tag b3 unique_commit b3 tree -p b2
+on_dates "00:10" "00:10" save_tag c2 unique_commit c2 tree -p c1 -p b2
+on_dates "00:11" "00:11" save_tag c3 unique_commit c3 tree -p c2
+on_dates "00:12" "00:00" save_tag a2 unique_commit a2 tree -p a1
+on_dates "00:13" "00:01" save_tag a3 unique_commit a3 tree -p a2
+on_dates "00:14" "00:14" save_tag b4 unique_commit b4 tree -p b3 -p a3
+on_dates "00:15" "00:15" save_tag a4 unique_commit a4 tree -p a3 -p b4 -p c3
+on_dates "00:16" "00:16" save_tag l3 unique_commit l3 tree -p a4
+on_dates "00:17" "00:17" save_tag l4 unique_commit l4 tree -p l3
+on_dates "00:18" "00:18" save_tag l5 unique_commit l5 tree -p l4
+on_dates "00:19" "00:19" save_tag m1 unique_commit m1 tree -p a4 -p c3
+on_dates "00:20" "00:20" save_tag m2 unique_commit m2 tree -p c3 -p a4
+on_dates "00:21" "00:21" hide_error save_tag alt_root unique_commit alt_root tree
+on_dates "00:22" "00:22" save_tag r0 unique_commit r0 tree -p alt_root
+on_dates "00:23" "00:23" save_tag r1 unique_commit r1 tree -p r0
+on_dates "00:24" "00:24" save_tag l5r1 unique_commit l5r1 tree -p l5 -p r1
+on_dates "00:25" "00:25" save_tag r1l5 unique_commit r1l5 tree -p r1 -p l5
 
 
-#
-# note: as of 20/6, it isn't possible to create duplicate parents, so this
-# can't be tested.
-#
-#on_committer_date "1971-08-16 00:00:20" save_tag m3 unique_commit m3 tree -p c3 -p a4 -p c3
 hide_error save_tag e1 as_author e@example.com unique_commit e1 tree
 save_tag e2 as_author e@example.com unique_commit e2 tree -p e1
 save_tag f1 as_author f@example.com unique_commit f1 tree -p e1
@@ -105,6 +100,50 @@
 root
 EOF
 
+test_output_expect_success 'simple date order' 'git rev-list --date-order  HEAD' <<EOF
+l5
+l4
+l3
+a4
+b4
+a3
+a2
+c3
+c2
+b3
+b2
+c1
+b1
+a1
+a0
+l2
+l1
+l0
+root
+EOF
+
+test_output_expect_success 'simple author-date order' 'git rev-list --author-date-order  HEAD' <<EOF
+l5
+l4
+l3
+a4
+b4
+c3
+c2
+b3
+b2
+c1
+b1
+a3
+a2
+a1
+a0
+l2
+l1
+l0
+root
+EOF
+
 test_output_expect_success 'two diamonds topo order (g6)' 'git rev-list --topo-order  g4' <<EOF
 g4
 h2
diff --git a/t/t6006-rev-list-format.sh b/t/t6006-rev-list-format.sh
index 0393c9f..9874403 100755
--- a/t/t6006-rev-list-format.sh
+++ b/t/t6006-rev-list-format.sh
@@ -1,20 +1,45 @@
 #!/bin/sh
 
+# Copyright (c) 2009 Jens Lehmann
+# Copyright (c) 2011 Alexey Shumkin (+ non-UTF-8 commit encoding tests)
+
 test_description='git rev-list --pretty=format test'
 
 . ./test-lib.sh
 . "$TEST_DIRECTORY"/lib-terminal.sh
 
 test_tick
+# String "added" in German
+# (translated with Google Translate),
+# encoded in UTF-8, used as a commit log message below.
+added=$(printf "added (hinzugef\303\274gt) foo")
+added_iso88591=$(echo "$added" | iconv -f utf-8 -t iso8859-1)
+# same but "changed"
+changed=$(printf "changed (ge\303\244ndert) foo")
+changed_iso88591=$(echo "$changed" | iconv -f utf-8 -t iso8859-1)
+
 test_expect_success 'setup' '
-touch foo && git add foo && git commit -m "added foo" &&
-  echo changed >foo && git commit -a -m "changed foo"
+	: >foo &&
+	git add foo &&
+	git config i18n.commitEncoding iso8859-1 &&
+	git commit -m "$added_iso88591" &&
+	head1=$(git rev-parse --verify HEAD) &&
+	head1_short=$(git rev-parse --verify --short $head1) &&
+	tree1=$(git rev-parse --verify HEAD:) &&
+	tree1_short=$(git rev-parse --verify --short $tree1) &&
+	echo "$changed" > foo &&
+	git commit -a -m "$changed_iso88591" &&
+	head2=$(git rev-parse --verify HEAD) &&
+	head2_short=$(git rev-parse --verify --short $head2) &&
+	tree2=$(git rev-parse --verify HEAD:) &&
+	tree2_short=$(git rev-parse --verify --short $tree2)
+	git config --unset i18n.commitEncoding
 '
 
-# usage: test_format name format_string <expected_output
+# usage: test_format name format_string [failure] <expected_output
 test_format () {
 	cat >expect.$1
-	test_expect_success "format $1" "
+	test_expect_${3:-success} "format $1" "
 		git rev-list --pretty=format:'$2' master >output.$1 &&
 		test_cmp expect.$1 output.$1
 	"
@@ -32,49 +57,49 @@
 	test_cmp expect "$1"
 }
 
-test_format percent %%h <<'EOF'
-commit 131a310eb913d107dd3c09a65d1651175898735d
+test_format percent %%h <<EOF
+commit $head2
 %h
-commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
+commit $head1
 %h
 EOF
 
-test_format hash %H%n%h <<'EOF'
-commit 131a310eb913d107dd3c09a65d1651175898735d
-131a310eb913d107dd3c09a65d1651175898735d
-131a310
-commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
-86c75cfd708a0e5868dc876ed5b8bb66c80b4873
-86c75cf
+test_format hash %H%n%h <<EOF
+commit $head2
+$head2
+$head2_short
+commit $head1
+$head1
+$head1_short
 EOF
 
-test_format tree %T%n%t <<'EOF'
-commit 131a310eb913d107dd3c09a65d1651175898735d
-fe722612f26da5064c32ca3843aa154bdb0b08a0
-fe72261
-commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
-4d5fcadc293a348e88f777dc0920f11e7d71441c
-4d5fcad
+test_format tree %T%n%t <<EOF
+commit $head2
+$tree2
+$tree2_short
+commit $head1
+$tree1
+$tree1_short
 EOF
 
-test_format parents %P%n%p <<'EOF'
-commit 131a310eb913d107dd3c09a65d1651175898735d
-86c75cfd708a0e5868dc876ed5b8bb66c80b4873
-86c75cf
-commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
+test_format parents %P%n%p <<EOF
+commit $head2
+$head1
+$head1_short
+commit $head1
 
 
 EOF
 
 # we don't test relative here
-test_format author %an%n%ae%n%ad%n%aD%n%at <<'EOF'
-commit 131a310eb913d107dd3c09a65d1651175898735d
+test_format author %an%n%ae%n%ad%n%aD%n%at <<EOF
+commit $head2
 A U Thor
 author@example.com
 Thu Apr 7 15:13:13 2005 -0700
 Thu, 7 Apr 2005 15:13:13 -0700
 1112911993
-commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
+commit $head1
 A U Thor
 author@example.com
 Thu Apr 7 15:13:13 2005 -0700
@@ -82,14 +107,14 @@
 1112911993
 EOF
 
-test_format committer %cn%n%ce%n%cd%n%cD%n%ct <<'EOF'
-commit 131a310eb913d107dd3c09a65d1651175898735d
+test_format committer %cn%n%ce%n%cd%n%cD%n%ct <<EOF
+commit $head2
 C O Mitter
 committer@example.com
 Thu Apr 7 15:13:13 2005 -0700
 Thu, 7 Apr 2005 15:13:13 -0700
 1112911993
-commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
+commit $head1
 C O Mitter
 committer@example.com
 Thu Apr 7 15:13:13 2005 -0700
@@ -97,43 +122,45 @@
 1112911993
 EOF
 
-test_format encoding %e <<'EOF'
-commit 131a310eb913d107dd3c09a65d1651175898735d
-commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
+test_format encoding %e <<EOF
+commit $head2
+iso8859-1
+commit $head1
+iso8859-1
 EOF
 
-test_format subject %s <<'EOF'
-commit 131a310eb913d107dd3c09a65d1651175898735d
-changed foo
-commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
-added foo
+test_format subject %s <<EOF
+commit $head2
+$changed
+commit $head1
+$added
 EOF
 
-test_format body %b <<'EOF'
-commit 131a310eb913d107dd3c09a65d1651175898735d
-commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
+test_format body %b <<EOF
+commit $head2
+commit $head1
 EOF
 
-test_format raw-body %B <<'EOF'
-commit 131a310eb913d107dd3c09a65d1651175898735d
-changed foo
+test_format raw-body %B <<EOF
+commit $head2
+$changed
 
-commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
-added foo
+commit $head1
+$added
 
 EOF
 
-test_format colors %Credfoo%Cgreenbar%Cbluebaz%Cresetxyzzy <<'EOF'
-commit 131a310eb913d107dd3c09a65d1651175898735d
+test_format colors %Credfoo%Cgreenbar%Cbluebaz%Cresetxyzzy <<EOF
+commit $head2
 foobarbazxyzzy
-commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
+commit $head1
 foobarbazxyzzy
 EOF
 
-test_format advanced-colors '%C(red yellow bold)foo%C(reset)' <<'EOF'
-commit 131a310eb913d107dd3c09a65d1651175898735d
+test_format advanced-colors '%C(red yellow bold)foo%C(reset)' <<EOF
+commit $head2
 foo
-commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
+commit $head1
 foo
 EOF
 
@@ -179,46 +206,71 @@
 	)
 '
 
-cat >commit-msg <<'EOF'
+iconv -f utf-8 -t iso8859-1 > commit-msg <<EOF
 Test printing of complex bodies
 
 This commit message is much longer than the others,
 and it will be encoded in iso8859-1. We should therefore
-include an iso8859 character: ¡bueno!
+include an iso8859 character: ¡bueno!
 EOF
+
 test_expect_success 'setup complex body' '
-git config i18n.commitencoding iso8859-1 &&
-  echo change2 >foo && git commit -a -F commit-msg
+	git config i18n.commitencoding iso8859-1 &&
+	echo change2 >foo && git commit -a -F commit-msg &&
+	head3=$(git rev-parse --verify HEAD) &&
+	head3_short=$(git rev-parse --short $head3)
 '
 
-test_format complex-encoding %e <<'EOF'
-commit 1ed88da4a5b5ed8c449114ac131efc62178734c3
+test_format complex-encoding %e <<EOF
+commit $head3
 iso8859-1
-commit 131a310eb913d107dd3c09a65d1651175898735d
-commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
+commit $head2
+iso8859-1
+commit $head1
+iso8859-1
 EOF
 
-test_format complex-subject %s <<'EOF'
-commit 1ed88da4a5b5ed8c449114ac131efc62178734c3
+test_format complex-subject %s <<EOF
+commit $head3
 Test printing of complex bodies
-commit 131a310eb913d107dd3c09a65d1651175898735d
-changed foo
-commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
-added foo
+commit $head2
+$changed_iso88591
+commit $head1
+$added_iso88591
 EOF
 
-test_format complex-body %b <<'EOF'
-commit 1ed88da4a5b5ed8c449114ac131efc62178734c3
-This commit message is much longer than the others,
-and it will be encoded in iso8859-1. We should therefore
-include an iso8859 character: ¡bueno!
+test_expect_success 'prepare expected messages (for test %b)' '
+	cat <<-EOF >expected.utf-8 &&
+	commit $head3
+	This commit message is much longer than the others,
+	and it will be encoded in iso8859-1. We should therefore
+	include an iso8859 character: ¡bueno!
 
-commit 131a310eb913d107dd3c09a65d1651175898735d
-commit 86c75cfd708a0e5868dc876ed5b8bb66c80b4873
+	commit $head2
+	commit $head1
+	EOF
+	iconv -f utf-8 -t iso8859-1 expected.utf-8 >expected.iso8859-1
+'
+
+test_format complex-body %b <expected.iso8859-1
+
+# Git uses i18n.commitEncoding if no i18n.logOutputEncoding set
+# so unset i18n.commitEncoding to test encoding conversion
+git config --unset i18n.commitEncoding
+
+test_format complex-subject-commitencoding-unset %s <<EOF
+commit $head3
+Test printing of complex bodies
+commit $head2
+$changed
+commit $head1
+$added
 EOF
 
+test_format complex-body-commitencoding-unset %b <expected.utf-8
+
 test_expect_success '%x00 shows NUL' '
-	echo  >expect commit 1ed88da4a5b5ed8c449114ac131efc62178734c3 &&
+	echo  >expect commit $head3 &&
 	echo >>expect fooQbar &&
 	git rev-list -1 --format=foo%x00bar HEAD >actual.nul &&
 	nul_to_q <actual.nul >actual &&
@@ -265,12 +317,12 @@
 
 test_expect_success 'add SP before non-empty (1)' '
 	git show -s --pretty=format:"%s% bThanks" HEAD^^ >actual &&
-	test $(wc -w <actual) = 2
+	test $(wc -w <actual) = 3
 '
 
 test_expect_success 'add SP before non-empty (2)' '
 	git show -s --pretty=format:"%s% sThanks" HEAD^^ >actual &&
-	test $(wc -w <actual) = 4
+	test $(wc -w <actual) = 6
 '
 
 test_expect_success '--abbrev' '
diff --git a/t/t6012-rev-list-simplify.sh b/t/t6012-rev-list-simplify.sh
index dd6dc84..fde5e71 100755
--- a/t/t6012-rev-list-simplify.sh
+++ b/t/t6012-rev-list-simplify.sh
@@ -14,21 +14,24 @@
 
 test_expect_success setup '
 	echo "Hi there" >file &&
-	git add file &&
-	test_tick && git commit -m "Initial file" &&
+	echo "initial" >lost &&
+	git add file lost &&
+	test_tick && git commit -m "Initial file and lost" &&
 	note A &&
 
 	git branch other-branch &&
 
 	echo "Hello" >file &&
-	git add file &&
-	test_tick && git commit -m "Modified file" &&
+	echo "second" >lost &&
+	git add file lost &&
+	test_tick && git commit -m "Modified file and lost" &&
 	note B &&
 
 	git checkout other-branch &&
 
 	echo "Hello" >file &&
-	git add file &&
+	>lost &&
+	git add file lost &&
 	test_tick && git commit -m "Modified the file identically" &&
 	note C &&
 
@@ -37,7 +40,9 @@
 	test_tick && git commit -m "Add another file" &&
 	note D &&
 
-	test_tick && git merge -m "merge" master &&
+	test_tick &&
+	test_must_fail git merge -m "merge" master &&
+	>lost && git commit -a -m "merge" &&
 	note E &&
 
 	echo "Yet another" >elif &&
@@ -105,9 +110,27 @@
 check_result 'K I H E C B A' --full-history -- file
 check_result 'K I H E C B A' --full-history --topo-order -- file
 check_result 'K I H E C B A' --full-history --date-order -- file
-check_outcome failure 'I E C B A' --simplify-merges -- file
+check_result 'I E C B A' --simplify-merges -- file
 check_result 'I B A' -- file
 check_result 'I B A' --topo-order -- file
 check_result 'H' --first-parent -- another-file
 
+check_result 'E C B A' --full-history E -- lost
+test_expect_success 'full history simplification without parent' '
+	printf "%s\n" E C B A >expect &&
+	git log --pretty="$FMT" --full-history E -- lost |
+	unnote >actual &&
+	sed -e "s/^.*	\([^ ]*\) .*/\1/" >check <actual &&
+	test_cmp expect check || {
+		cat actual
+		false
+	}
+'
+
+test_expect_success '--full-diff is not affected by --parents' '
+	git log -p --pretty="%H" --full-diff -- file >expected &&
+	git log -p --pretty="%H" --full-diff --parents -- file >actual &&
+	test_cmp expected actual
+'
+
 test_done
diff --git a/t/t6019-rev-list-ancestry-path.sh b/t/t6019-rev-list-ancestry-path.sh
index 39b4cb0..dabebae 100755
--- a/t/t6019-rev-list-ancestry-path.sh
+++ b/t/t6019-rev-list-ancestry-path.sh
@@ -13,6 +13,13 @@
 #
 #  D..M -- M.t                 == M
 #  --ancestry-path D..M -- M.t == M
+#
+#  F...I                 == F G H I
+#  --ancestry-path F...I == F H I
+#
+#  G..M -- G.t                 == [nothing - was dropped in "-s ours" merge L]
+#  --ancestry-path G..M -- G.t == L
+#  --ancestry-path --simplify-merges G^..M -- G.t == G L
 
 . ./test-lib.sh
 
@@ -63,13 +70,52 @@
 	test_cmp expect actual
 '
 
-test_expect_success 'rev-list --ancestry-patch D..M -- M.t' '
+test_expect_success 'rev-list --ancestry-path D..M -- M.t' '
 	echo M >expect &&
 	git rev-list --ancestry-path --format=%s D..M -- M.t |
 	sed -e "/^commit /d" >actual &&
 	test_cmp expect actual
 '
 
+test_expect_success 'rev-list F...I' '
+	for c in F G H I; do echo $c; done >expect &&
+	git rev-list --format=%s F...I |
+	sed -e "/^commit /d" |
+	sort >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'rev-list --ancestry-path F...I' '
+	for c in F H I; do echo $c; done >expect &&
+	git rev-list --ancestry-path --format=%s F...I |
+	sed -e "/^commit /d" |
+	sort >actual &&
+	test_cmp expect actual
+'
+
+# G.t is dropped in an "-s ours" merge
+test_expect_success 'rev-list G..M -- G.t' '
+	>expect &&
+	git rev-list --format=%s G..M -- G.t |
+	sed -e "/^commit /d" >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'rev-list --ancestry-path G..M -- G.t' '
+	echo L >expect &&
+	git rev-list --ancestry-path --format=%s G..M -- G.t |
+	sed -e "/^commit /d" >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'rev-list --ancestry-path --simplify-merges G^..M -- G.t' '
+	for c in G L; do echo $c; done >expect &&
+	git rev-list --ancestry-path --simplify-merges --format=%s G^..M -- G.t |
+	sed -e "/^commit /d" |
+	sort >actual &&
+	test_cmp expect actual
+'
+
 #   b---bc
 #  / \ /
 # a   X
diff --git a/t/t6021-merge-criss-cross.sh b/t/t6021-merge-criss-cross.sh
index 331b9b0..d15b313 100755
--- a/t/t6021-merge-criss-cross.sh
+++ b/t/t6021-merge-criss-cross.sh
@@ -3,7 +3,7 @@
 # Copyright (c) 2005 Fredrik Kuivinen
 #
 
-# See http://marc.theaimsgroup.com/?l=git&m=111463358500362&w=2 for a
+# See http://marc.info/?l=git&m=111463358500362&w=2 for a
 # nice description of what this is about.
 
 
diff --git a/t/t6035-merge-dir-to-symlink.sh b/t/t6035-merge-dir-to-symlink.sh
index 2599ae5..9324ea4 100755
--- a/t/t6035-merge-dir-to-symlink.sh
+++ b/t/t6035-merge-dir-to-symlink.sh
@@ -3,7 +3,7 @@
 test_description='merging when a directory was replaced with a symlink'
 . ./test-lib.sh
 
-test_expect_success SYMLINKS 'create a commit where dir a/b changed to symlink' '
+test_expect_success 'create a commit where dir a/b changed to symlink' '
 	mkdir -p a/b/c a/b-2/c &&
 	> a/b/c/d &&
 	> a/b-2/c/d &&
@@ -12,12 +12,12 @@
 	git commit -m base &&
 	git tag start &&
 	rm -rf a/b &&
-	ln -s b-2 a/b &&
 	git add -A &&
+	test_ln_s_add b-2 a/b &&
 	git commit -m "dir to symlink"
 '
 
-test_expect_success SYMLINKS 'checkout does not clobber untracked symlink' '
+test_expect_success 'checkout does not clobber untracked symlink' '
 	git checkout HEAD^0 &&
 	git reset --hard master &&
 	git rm --cached a/b &&
@@ -25,7 +25,7 @@
 	test_must_fail git checkout start^0
 '
 
-test_expect_success SYMLINKS 'a/b-2/c/d is kept when clobbering symlink b' '
+test_expect_success 'a/b-2/c/d is kept when clobbering symlink b' '
 	git checkout HEAD^0 &&
 	git reset --hard master &&
 	git rm --cached a/b &&
@@ -34,14 +34,14 @@
 	test -f a/b-2/c/d
 '
 
-test_expect_success SYMLINKS 'checkout should not have deleted a/b-2/c/d' '
+test_expect_success 'checkout should not have deleted a/b-2/c/d' '
 	git checkout HEAD^0 &&
 	git reset --hard master &&
 	 git checkout start^0 &&
 	 test -f a/b-2/c/d
 '
 
-test_expect_success SYMLINKS 'setup for merge test' '
+test_expect_success 'setup for merge test' '
 	git reset --hard &&
 	test -f a/b-2/c/d &&
 	echo x > a/x &&
@@ -50,39 +50,51 @@
 	git tag baseline
 '
 
-test_expect_success SYMLINKS 'Handle D/F conflict, do not lose a/b-2/c/d in merge (resolve)' '
+test_expect_success 'Handle D/F conflict, do not lose a/b-2/c/d in merge (resolve)' '
 	git reset --hard &&
 	git checkout baseline^0 &&
 	git merge -s resolve master &&
-	test -h a/b &&
 	test -f a/b-2/c/d
 '
 
-test_expect_success SYMLINKS 'Handle D/F conflict, do not lose a/b-2/c/d in merge (recursive)' '
+test_expect_success SYMLINKS 'a/b was resolved as symlink' '
+	test -h a/b
+'
+
+test_expect_success 'Handle D/F conflict, do not lose a/b-2/c/d in merge (recursive)' '
 	git reset --hard &&
 	git checkout baseline^0 &&
 	git merge -s recursive master &&
-	test -h a/b &&
 	test -f a/b-2/c/d
 '
 
-test_expect_success SYMLINKS 'Handle F/D conflict, do not lose a/b-2/c/d in merge (resolve)' '
+test_expect_success SYMLINKS 'a/b was resolved as symlink' '
+	test -h a/b
+'
+
+test_expect_success 'Handle F/D conflict, do not lose a/b-2/c/d in merge (resolve)' '
 	git reset --hard &&
 	git checkout master^0 &&
 	git merge -s resolve baseline^0 &&
-	test -h a/b &&
 	test -f a/b-2/c/d
 '
 
-test_expect_success SYMLINKS 'Handle F/D conflict, do not lose a/b-2/c/d in merge (recursive)' '
+test_expect_success SYMLINKS 'a/b was resolved as symlink' '
+	test -h a/b
+'
+
+test_expect_success 'Handle F/D conflict, do not lose a/b-2/c/d in merge (recursive)' '
 	git reset --hard &&
 	git checkout master^0 &&
 	git merge -s recursive baseline^0 &&
-	test -h a/b &&
 	test -f a/b-2/c/d
 '
 
-test_expect_failure SYMLINKS 'do not lose untracked in merge (resolve)' '
+test_expect_success SYMLINKS 'a/b was resolved as symlink' '
+	test -h a/b
+'
+
+test_expect_failure 'do not lose untracked in merge (resolve)' '
 	git reset --hard &&
 	git checkout baseline^0 &&
 	>a/b/c/e &&
@@ -91,7 +103,7 @@
 	test -f a/b-2/c/d
 '
 
-test_expect_success SYMLINKS 'do not lose untracked in merge (recursive)' '
+test_expect_success 'do not lose untracked in merge (recursive)' '
 	git reset --hard &&
 	git checkout baseline^0 &&
 	>a/b/c/e &&
@@ -100,52 +112,61 @@
 	test -f a/b-2/c/d
 '
 
-test_expect_success SYMLINKS 'do not lose modifications in merge (resolve)' '
+test_expect_success 'do not lose modifications in merge (resolve)' '
 	git reset --hard &&
 	git checkout baseline^0 &&
 	echo more content >>a/b/c/d &&
 	test_must_fail git merge -s resolve master
 '
 
-test_expect_success SYMLINKS 'do not lose modifications in merge (recursive)' '
+test_expect_success 'do not lose modifications in merge (recursive)' '
 	git reset --hard &&
 	git checkout baseline^0 &&
 	echo more content >>a/b/c/d &&
 	test_must_fail git merge -s recursive master
 '
 
-test_expect_success SYMLINKS 'setup a merge where dir a/b-2 changed to symlink' '
+test_expect_success 'setup a merge where dir a/b-2 changed to symlink' '
 	git reset --hard &&
 	git checkout start^0 &&
 	rm -rf a/b-2 &&
-	ln -s b a/b-2 &&
 	git add -A &&
+	test_ln_s_add b a/b-2 &&
 	git commit -m "dir a/b-2 to symlink" &&
 	git tag test2
 '
 
-test_expect_success SYMLINKS 'merge should not have D/F conflicts (resolve)' '
+test_expect_success 'merge should not have D/F conflicts (resolve)' '
 	git reset --hard &&
 	git checkout baseline^0 &&
 	git merge -s resolve test2 &&
-	test -h a/b-2 &&
 	test -f a/b/c/d
 '
 
-test_expect_success SYMLINKS 'merge should not have D/F conflicts (recursive)' '
+test_expect_success SYMLINKS 'a/b-2 was resolved as symlink' '
+	test -h a/b-2
+'
+
+test_expect_success 'merge should not have D/F conflicts (recursive)' '
 	git reset --hard &&
 	git checkout baseline^0 &&
 	git merge -s recursive test2 &&
-	test -h a/b-2 &&
 	test -f a/b/c/d
 '
 
-test_expect_success SYMLINKS 'merge should not have F/D conflicts (recursive)' '
+test_expect_success SYMLINKS 'a/b-2 was resolved as symlink' '
+	test -h a/b-2
+'
+
+test_expect_success 'merge should not have F/D conflicts (recursive)' '
 	git reset --hard &&
 	git checkout -b foo test2 &&
 	git merge -s recursive baseline^0 &&
-	test -h a/b-2 &&
 	test -f a/b/c/d
 '
 
+test_expect_success SYMLINKS 'a/b-2 was resolved as symlink' '
+	test -h a/b-2
+'
+
 test_done
diff --git a/t/t6111-rev-list-treesame.sh b/t/t6111-rev-list-treesame.sh
new file mode 100755
index 0000000..88b84df
--- /dev/null
+++ b/t/t6111-rev-list-treesame.sh
@@ -0,0 +1,196 @@
+#!/bin/sh
+#
+#        ,---E--.   *H----------.             * marks !TREESAME parent paths
+#       /        \ /             \*
+# *A--*B---D--*F-*G---------K-*L-*M
+#   \     /*       \       /
+#    `-C-'          `-*I-*J
+#
+# A creates "file", B and F change it.
+# Odd merge G takes the old version from B.
+# I changes it, but J reverts it, so K is TREESAME to both parents.
+# H and L both change "file", and M merges those changes.
+
+test_description='TREESAME and limiting'
+
+. ./test-lib.sh
+
+note () {
+	git tag "$1"
+}
+
+unnote () {
+	git name-rev --tags --stdin | sed -e "s|$_x40 (tags/\([^)]*\))\([ 	]\)|\1\2|g"
+}
+
+test_expect_success setup '
+	test_commit "Initial file" file "Hi there" A &&
+	git branch other-branch &&
+
+	test_commit "file=Hello" file "Hello" B &&
+	git branch third-branch &&
+
+	git checkout other-branch &&
+	test_commit "Added other" other "Hello" C &&
+
+	git checkout master &&
+	test_merge D other-branch &&
+
+	git checkout third-branch &&
+	test_commit "Third file" third "Nothing" E &&
+
+	git checkout master &&
+	test_commit "file=Blah" file "Blah" F &&
+
+	test_tick && git merge --no-commit third-branch &&
+	git checkout third-branch file &&
+	git commit &&
+	note G &&
+	git branch fiddler-branch &&
+
+	git checkout -b part2-branch &&
+	test_commit "file=Part 2" file "Part 2" H &&
+
+	git checkout fiddler-branch &&
+	test_commit "Bad commit" file "Silly" I &&
+
+	test_tick && git revert I && note J &&
+
+	git checkout master &&
+	test_tick && git merge --no-ff fiddler-branch &&
+	note K
+
+	test_commit "file=Part 1" file "Part 1" L &&
+
+	test_tick && test_must_fail git merge part2-branch &&
+	test_commit M file "Parts 1+2"
+'
+
+check_outcome () {
+	outcome=$1
+	shift
+
+	case "$1" in
+	*"("*)
+		FMT="%P	%H | %s"
+		munge_actual="
+			s/^\([^	]*\)	\([^ ]*\) .*/(\1)\2/
+			s/ //g
+			s/()//
+		"
+		;;
+	*)
+		FMT="%H | %s"
+		munge_actual="s/^\([^ ]*\) .*/\1/"
+		;;
+	esac &&
+	printf "%s\n" $1 >expect &&
+	shift
+
+	param="$*" &&
+	test_expect_$outcome "log $param" '
+		git log --format="$FMT" $param |
+		unnote >actual &&
+		sed -e "$munge_actual" <actual >check &&
+		test_cmp expect check || {
+			cat actual
+			false
+		}
+	'
+}
+
+check_result () {
+	check_outcome success "$@"
+}
+
+# Odd merge G drops a change in F. Important that G is listed in all
+# except the most basic list. Achieving this means normal merge D will also be
+# shown in normal full-history, as we can't distinguish unless we do a
+# simplification pass. After simplification, D is dropped but G remains.
+# Also, merge simplification of G should not drop the parent B that the default
+# simple history follows.
+check_result 'M L K J I H G F E D C B A'
+check_result '(LH)M (K)L (GJ)K (I)J (G)I (G)H (FE)G (D)F (B)E (BC)D (A)C (A)B A'
+check_result 'M H L K J I G E F D C B A' --topo-order
+check_result 'M L H B A' -- file
+check_result '(LH)M (B)L (B)H (A)B A' --parents -- file
+check_result 'M L J I H G F D B A' --full-history -- file
+check_result '(LH)M (K)L (GJ)K (I)J (G)I (G)H (FB)G (D)F (BA)D (A)B A' --full-history --parents -- file
+check_result '(LH)M (G)H (J)L (I)J (G)I (FB)G (B)F (A)B A' --simplify-merges -- file
+check_result 'M L K G F D B A' --first-parent
+check_result 'M L G F B A' --first-parent -- file
+
+# Check that odd merge G remains shown when F is the bottom.
+check_result 'M L K J I H G E' F..M
+check_result 'M H L K J I G E' F..M --topo-order
+check_result 'M L H' F..M -- file
+check_result '(LH)M (B)L (B)H' --parents F..M -- file
+check_result 'M L J I H G' F..M --full-history -- file
+check_result '(LH)M (K)L (GJ)K (I)J (G)I (G)H (FB)G' F..M --full-history --parents -- file
+check_result '(LH)M (G)H (J)L (I)J (G)I (FB)G' F..M --simplify-merges -- file
+check_result 'M L K J I H G' F..M --ancestry-path
+check_result 'M L J I H G' F..M --ancestry-path -- file
+check_result '(LH)M (K)L (GJ)K (I)J (G)I (G)H (FE)G' F..M --ancestry-path --parents -- file
+check_result '(LH)M (G)H (J)L (I)J (G)I (FE)G' F..M --ancestry-path --simplify-merges -- file
+check_result 'M L K G' F..M --first-parent
+check_result 'M L G' F..M --first-parent -- file
+
+# Note that G is pruned when E is the bottom, even if it's the same commit list
+# If we want history since E, then we're quite happy to ignore G that took E.
+check_result 'M L K J I H G' E..M --ancestry-path
+check_result 'M L J I H' E..M --ancestry-path -- file
+check_result '(LH)M (K)L (EJ)K (I)J (E)I (E)H' E..M --ancestry-path --parents -- file
+check_result '(LH)M (E)H (J)L (I)J (E)I' E..M --ancestry-path --simplify-merges -- file
+
+# Should still be able to ignore I-J branch in simple log, despite limiting
+# to G.
+check_result 'M L K J I H' G..M
+check_result 'M H L K J I' G..M --topo-order
+check_result 'M L H' G..M -- file
+check_result '(LH)M (G)L (G)H' G..M --parents -- file
+check_result 'M L J I H' G..M --full-history -- file
+check_result 'M L K J I H' G..M --full-history --parents -- file
+check_result 'M H L J I' G..M --simplify-merges -- file
+check_result 'M L K J I H' G..M --ancestry-path
+check_result 'M L J I H' G..M --ancestry-path -- file
+check_result 'M L K J I H' G..M --ancestry-path --parents -- file
+check_result 'M H L J I' G..M --ancestry-path --simplify-merges -- file
+
+# B..F should be able to simplify the merge D from irrelevant side branch C.
+# Default log should also be free to follow B-D, and ignore C.
+# But --full-history shouldn't drop D on its own - without simplification,
+# we can't decide if the merge from INTERESTING commit C was sensible.
+check_result 'F D C' B..F
+check_result 'F' B..F -- file
+check_result '(B)F' B..F --parents -- file
+check_result 'F D' B..F --full-history -- file
+check_result '(D)F (BA)D' B..F --full-history --parents -- file
+check_result '(B)F' B..F --simplify-merges -- file
+check_result 'F D' B..F --ancestry-path
+check_result 'F' B..F --ancestry-path -- file
+check_result 'F' B..F --ancestry-path --parents -- file
+check_result 'F' B..F --ancestry-path --simplify-merges -- file
+check_result 'F D' B..F --first-parent
+check_result 'F' B..F --first-parent -- file
+
+# E...F should be equivalent to E F ^B, and be able to drop D as above.
+check_result 'F' E F ^B -- file # includes D
+check_result 'F' E...F -- file # includes D
+
+# Any sort of full history of C..F should show D, as it's the connection to C,
+# and it differs from it.
+check_result 'F D B' C..F
+check_result 'F B' C..F -- file
+check_result '(B)F (A)B' C..F --parents -- file
+check_result 'F D B' C..F --full-history -- file
+check_result '(D)F (BC)D (A)B' C..F --full-history --parents -- file
+check_result '(D)F (BC)D (A)B' C..F --simplify-merges -- file
+check_result 'F D' C..F --ancestry-path
+check_result 'F D' C..F --ancestry-path -- file
+check_result 'F D' C..F --ancestry-path --parents -- file
+check_result 'F D' C..F --ancestry-path --simplify-merges -- file
+check_result 'F D B' C..F --first-parent
+check_result 'F B' C..F --first-parent -- file
+
+
+test_done
diff --git a/t/t6120-describe.sh b/t/t6120-describe.sh
index f67aa6f..c0e5b2a 100755
--- a/t/t6120-describe.sh
+++ b/t/t6120-describe.sh
@@ -110,6 +110,9 @@
 check_describe B-0-* --long HEAD^^2^
 check_describe A-3-* --long HEAD^^2
 
+check_describe c-7-* --tags
+check_describe e-3-* --first-parent --tags
+
 : >err.expect
 check_describe A --all A^0
 test_expect_success 'no warning was displayed for A' '
@@ -171,4 +174,28 @@
 
 check_describe "test2-lightweight-*" --long --tags --match="test2-*" HEAD^
 
+test_expect_success 'name-rev with exact tags' '
+	echo A >expect &&
+	tag_object=$(git rev-parse refs/tags/A) &&
+	git name-rev --tags --name-only $tag_object >actual &&
+	test_cmp expect actual &&
+
+	echo "A^0" >expect &&
+	tagged_commit=$(git rev-parse "refs/tags/A^0") &&
+	git name-rev --tags --name-only $tagged_commit >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'describe --contains with the exact tags' '
+	echo "A^0" >expect &&
+	tag_object=$(git rev-parse refs/tags/A) &&
+	git describe --contains $tag_object >actual &&
+	test_cmp expect actual &&
+
+	echo "A^0" >expect &&
+	tagged_commit=$(git rev-parse "refs/tags/A^0") &&
+	git describe --contains $tagged_commit >actual &&
+	test_cmp expect actual
+'
+
 test_done
diff --git a/t/t7001-mv.sh b/t/t7001-mv.sh
index a845b15..101816e 100755
--- a/t/t7001-mv.sh
+++ b/t/t7001-mv.sh
@@ -218,13 +218,13 @@
 
 rm -f dirty dirty2
 
-test_expect_success SYMLINKS 'git mv should overwrite symlink to a file' '
+test_expect_success 'git mv should overwrite symlink to a file' '
 
 	rm -fr .git &&
 	git init &&
 	echo 1 >moved &&
-	ln -s moved symlink &&
-	git add moved symlink &&
+	test_ln_s_add moved symlink &&
+	git add moved &&
 	test_must_fail git mv moved symlink &&
 	git mv -f moved symlink &&
 	! test -e moved &&
@@ -237,22 +237,26 @@
 
 rm -f moved symlink
 
-test_expect_success SYMLINKS 'git mv should overwrite file with a symlink' '
+test_expect_success 'git mv should overwrite file with a symlink' '
 
 	rm -fr .git &&
 	git init &&
 	echo 1 >moved &&
-	ln -s moved symlink &&
-	git add moved symlink &&
+	test_ln_s_add moved symlink &&
+	git add moved &&
 	test_must_fail git mv symlink moved &&
 	git mv -f symlink moved &&
 	! test -e symlink &&
-	test -h moved &&
 	git update-index --refresh &&
 	git diff-files --quiet
 
 '
 
+test_expect_success SYMLINKS 'check moved symlink' '
+
+	test -h moved
+'
+
 rm -f moved symlink
 
 test_done
diff --git a/t/t7011-skip-worktree-reading.sh b/t/t7011-skip-worktree-reading.sh
index 8f3b54d..88d60c1 100755
--- a/t/t7011-skip-worktree-reading.sh
+++ b/t/t7011-skip-worktree-reading.sh
@@ -91,12 +91,12 @@
 	test_cmp expected 1
 '
 
-test_expect_success 'ls-files --delete' '
+test_expect_success 'ls-files --deleted' '
 	setup_absent &&
 	test -z "$(git ls-files -d)"
 '
 
-test_expect_success 'ls-files --delete' '
+test_expect_success 'ls-files --deleted' '
 	setup_dirty &&
 	test -z "$(git ls-files -d)"
 '
diff --git a/t/t7102-reset.sh b/t/t7102-reset.sh
index df82ec9..8d4b50d 100755
--- a/t/t7102-reset.sh
+++ b/t/t7102-reset.sh
@@ -9,6 +9,19 @@
 
 . ./test-lib.sh
 
+commit_msg () {
+	# String "modify 2nd file (changed)" partly in German
+	# (translated with Google Translate),
+	# encoded in UTF-8, used as a commit log message below.
+	msg="modify 2nd file (ge\303\244ndert)\n"
+	if test -n "$1"
+	then
+		printf "$msg" | iconv -f utf-8 -t "$1"
+	else
+		printf "$msg"
+	fi
+}
+
 test_expect_success 'creating initial files and commits' '
 	test_tick &&
 	echo "1st file" >first &&
@@ -28,7 +41,7 @@
 
 	echo "1st line 2nd file" >secondfile &&
 	echo "2nd line 2nd file" >>secondfile &&
-	git commit -a -m "modify 2nd file" &&
+	git -c "i18n.commitEncoding=iso8859-1" commit -a -m "$(commit_msg iso8859-1)" &&
 	head5=$(git rev-parse --verify HEAD)
 '
 # git log --pretty=oneline # to see those SHA1 involved
@@ -44,6 +57,20 @@
 	done | test_cmp .cat_expect -
 }
 
+test_expect_success 'reset --hard message' '
+	hex=$(git log -1 --format="%h") &&
+	git reset --hard > .actual &&
+	echo HEAD is now at $hex $(commit_msg) > .expected &&
+	test_cmp .expected .actual
+'
+
+test_expect_success 'reset --hard message (iso8859-1 logoutputencoding)' '
+	hex=$(git log -1 --format="%h") &&
+	git -c "i18n.logOutputEncoding=iso8859-1" reset --hard > .actual &&
+	echo HEAD is now at $hex $(commit_msg iso8859-1) > .expected &&
+	test_cmp .expected .actual
+'
+
 >.diff_expect
 >.cached_expect
 cat >.cat_expect <<EOF
@@ -192,7 +219,8 @@
 	'changing files and redo the last commit should succeed' '
 	echo "3rd line 2nd file" >>secondfile &&
 	git commit -a -C ORIG_HEAD &&
-	check_changes 3d3b7be011a58ca0c179ae45d94e6c83c0b0cd0d &&
+	head4=$(git rev-parse --verify HEAD) &&
+	check_changes $head4 &&
 	test "$(git rev-parse ORIG_HEAD)" = \
 			$head5
 '
@@ -211,7 +239,7 @@
 	git reset --hard HEAD~2 &&
 	check_changes ddaefe00f1da16864591c61fdc7adb5d7cd6b74e &&
 	test "$(git rev-parse ORIG_HEAD)" = \
-			3d3b7be011a58ca0c179ae45d94e6c83c0b0cd0d
+			$head4
 '
 
 >.diff_expect
@@ -303,7 +331,7 @@
 
 	echo "1st line 2nd file" >secondfile &&
 	echo "2nd line 2nd file" >>secondfile &&
-	git commit -a -m "modify 2nd file" &&
+	git -c "i18n.commitEncoding=iso8859-1" commit -a -m "$(commit_msg iso8859-1)" &&
 	check_changes $head5
 '
 
@@ -326,10 +354,11 @@
 	git checkout branch2 &&
 	echo "3rd line in branch2" >>secondfile &&
 	git commit -a -m "change in branch2" &&
+	head3=$(git rev-parse --verify HEAD) &&
 
 	test_must_fail git pull . branch1 &&
 	git reset --hard &&
-	check_changes 77abb337073fb4369a7ad69ff6f5ec0e4d6b54bb
+	check_changes $head3
 '
 
 >.diff_expect
@@ -457,7 +486,7 @@
 	test_must_fail git diff --quiet -- secondfile &&
 	test -z "$(git diff --cached --name-only)" &&
 	test -f secondfile &&
-	test ! -s secondfile
+	test_must_be_empty secondfile
 
 '
 
diff --git a/t/t7201-co.sh b/t/t7201-co.sh
index be9672e..0c9ec0a 100755
--- a/t/t7201-co.sh
+++ b/t/t7201-co.sh
@@ -431,6 +431,7 @@
 
 test_expect_success \
     'checkout with --track fakes a sensible -b <name>' '
+    git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*" &&
     git update-ref refs/remotes/origin/koala/bear renamer &&
 
     git checkout --track origin/koala/bear &&
diff --git a/t/t7301-clean-interactive.sh b/t/t7301-clean-interactive.sh
new file mode 100755
index 0000000..3ae394e
--- /dev/null
+++ b/t/t7301-clean-interactive.sh
@@ -0,0 +1,475 @@
+#!/bin/sh
+
+test_description='git clean -i basic tests'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+
+	mkdir -p src &&
+	touch src/part1.c Makefile &&
+	echo build >.gitignore &&
+	echo \*.o >>.gitignore &&
+	git add . &&
+	git commit -m setup &&
+	touch src/part2.c README &&
+	git add .
+
+'
+
+test_expect_success 'git clean -i (c: clean hotkey)' '
+
+	mkdir -p build docs &&
+	touch a.out src/part3.c src/part3.h src/part4.c src/part4.h \
+	docs/manual.txt obj.o build/lib.so &&
+	echo c | git clean -i &&
+	test -f Makefile &&
+	test -f README &&
+	test -f src/part1.c &&
+	test -f src/part2.c &&
+	test ! -f a.out &&
+	test -f docs/manual.txt &&
+	test ! -f src/part3.c &&
+	test ! -f src/part3.h &&
+	test ! -f src/part4.c &&
+	test ! -f src/part4.h &&
+	test -f obj.o &&
+	test -f build/lib.so
+
+'
+
+test_expect_success 'git clean -i (cl: clean prefix)' '
+
+	mkdir -p build docs &&
+	touch a.out src/part3.c src/part3.h src/part4.c src/part4.h \
+	docs/manual.txt obj.o build/lib.so &&
+	echo cl | git clean -i &&
+	test -f Makefile &&
+	test -f README &&
+	test -f src/part1.c &&
+	test -f src/part2.c &&
+	test ! -f a.out &&
+	test -f docs/manual.txt &&
+	test ! -f src/part3.c &&
+	test ! -f src/part3.h &&
+	test ! -f src/part4.c &&
+	test ! -f src/part4.h &&
+	test -f obj.o &&
+	test -f build/lib.so
+
+'
+
+test_expect_success 'git clean -i (quit)' '
+
+	mkdir -p build docs &&
+	touch a.out src/part3.c src/part3.h src/part4.c src/part4.h \
+	docs/manual.txt obj.o build/lib.so &&
+	echo quit | git clean -i &&
+	test -f Makefile &&
+	test -f README &&
+	test -f src/part1.c &&
+	test -f src/part2.c &&
+	test -f a.out &&
+	test -f docs/manual.txt &&
+	test -f src/part3.c &&
+	test -f src/part3.h &&
+	test -f src/part4.c &&
+	test -f src/part4.h &&
+	test -f obj.o &&
+	test -f build/lib.so
+
+'
+
+test_expect_success 'git clean -i (Ctrl+D)' '
+
+	mkdir -p build docs &&
+	touch a.out src/part3.c src/part3.h src/part4.c src/part4.h \
+	docs/manual.txt obj.o build/lib.so &&
+	echo "\04" | git clean -i &&
+	test -f Makefile &&
+	test -f README &&
+	test -f src/part1.c &&
+	test -f src/part2.c &&
+	test -f a.out &&
+	test -f docs/manual.txt &&
+	test -f src/part3.c &&
+	test -f src/part3.h &&
+	test -f src/part4.c &&
+	test -f src/part4.h &&
+	test -f obj.o &&
+	test -f build/lib.so
+
+'
+
+test_expect_success 'git clean -id (filter all)' '
+
+	mkdir -p build docs &&
+	touch a.out src/part3.c src/part3.h src/part4.c src/part4.h \
+	docs/manual.txt obj.o build/lib.so &&
+	(echo f; echo "*"; echo; echo c) | \
+	git clean -id &&
+	test -f Makefile &&
+	test -f README &&
+	test -f src/part1.c &&
+	test -f src/part2.c &&
+	test -f a.out &&
+	test -f docs/manual.txt &&
+	test -f src/part3.c &&
+	test -f src/part3.h &&
+	test -f src/part4.c &&
+	test -f src/part4.h &&
+	test -f obj.o &&
+	test -f build/lib.so
+
+'
+
+test_expect_success 'git clean -id (filter patterns)' '
+
+	mkdir -p build docs &&
+	touch a.out src/part3.c src/part3.h src/part4.c src/part4.h \
+	docs/manual.txt obj.o build/lib.so &&
+	(echo f; echo "part3.* *.out"; echo; echo c) | \
+	git clean -id &&
+	test -f Makefile &&
+	test -f README &&
+	test -f src/part1.c &&
+	test -f src/part2.c &&
+	test -f a.out &&
+	test ! -f docs/manual.txt &&
+	test -f src/part3.c &&
+	test -f src/part3.h &&
+	test ! -f src/part4.c &&
+	test ! -f src/part4.h &&
+	test -f obj.o &&
+	test -f build/lib.so
+
+'
+
+test_expect_success 'git clean -id (filter patterns 2)' '
+
+	mkdir -p build docs &&
+	touch a.out src/part3.c src/part3.h src/part4.c src/part4.h \
+	docs/manual.txt obj.o build/lib.so &&
+	(echo f; echo "* !*.out"; echo; echo c) | \
+	git clean -id &&
+	test -f Makefile &&
+	test -f README &&
+	test -f src/part1.c &&
+	test -f src/part2.c &&
+	test ! -f a.out &&
+	test -f docs/manual.txt &&
+	test -f src/part3.c &&
+	test -f src/part3.h &&
+	test -f src/part4.c &&
+	test -f src/part4.h &&
+	test -f obj.o &&
+	test -f build/lib.so
+
+'
+
+test_expect_success 'git clean -id (select - all)' '
+
+	mkdir -p build docs &&
+	touch a.out src/part3.c src/part3.h src/part4.c src/part4.h \
+	docs/manual.txt obj.o build/lib.so &&
+	(echo s; echo "*"; echo; echo c) | \
+	git clean -id &&
+	test -f Makefile &&
+	test -f README &&
+	test -f src/part1.c &&
+	test -f src/part2.c &&
+	test ! -f a.out &&
+	test ! -f docs/manual.txt &&
+	test ! -f src/part3.c &&
+	test ! -f src/part3.h &&
+	test ! -f src/part4.c &&
+	test ! -f src/part4.h &&
+	test -f obj.o &&
+	test -f build/lib.so
+
+'
+
+test_expect_success 'git clean -id (select - none)' '
+
+	mkdir -p build docs &&
+	touch a.out src/part3.c src/part3.h src/part4.c src/part4.h \
+	docs/manual.txt obj.o build/lib.so &&
+	(echo s; echo; echo c) | \
+	git clean -id &&
+	test -f Makefile &&
+	test -f README &&
+	test -f src/part1.c &&
+	test -f src/part2.c &&
+	test -f a.out &&
+	test -f docs/manual.txt &&
+	test -f src/part3.c &&
+	test -f src/part3.h &&
+	test -f src/part4.c &&
+	test -f src/part4.h &&
+	test -f obj.o &&
+	test -f build/lib.so
+
+'
+
+test_expect_success 'git clean -id (select - number)' '
+
+	mkdir -p build docs &&
+	touch a.out src/part3.c src/part3.h src/part4.c src/part4.h \
+	docs/manual.txt obj.o build/lib.so &&
+	(echo s; echo 3; echo; echo c) | \
+	git clean -id &&
+	test -f Makefile &&
+	test -f README &&
+	test -f src/part1.c &&
+	test -f src/part2.c &&
+	test -f a.out &&
+	test -f docs/manual.txt &&
+	test ! -f src/part3.c &&
+	test -f src/part3.h &&
+	test -f src/part4.c &&
+	test -f src/part4.h &&
+	test -f obj.o &&
+	test -f build/lib.so
+
+'
+
+test_expect_success 'git clean -id (select - number 2)' '
+
+	mkdir -p build docs &&
+	touch a.out src/part3.c src/part3.h src/part4.c src/part4.h \
+	docs/manual.txt obj.o build/lib.so &&
+	(echo s; echo 2 3; echo 5; echo; echo c) | \
+	git clean -id &&
+	test -f Makefile &&
+	test -f README &&
+	test -f src/part1.c &&
+	test -f src/part2.c &&
+	test -f a.out &&
+	test ! -f docs/manual.txt &&
+	test ! -f src/part3.c &&
+	test -f src/part3.h &&
+	test ! -f src/part4.c &&
+	test -f src/part4.h &&
+	test -f obj.o &&
+	test -f build/lib.so
+
+'
+
+test_expect_success 'git clean -id (select - number 3)' '
+
+	mkdir -p build docs &&
+	touch a.out src/part3.c src/part3.h src/part4.c src/part4.h \
+	docs/manual.txt obj.o build/lib.so &&
+	(echo s; echo 3,4 5; echo; echo c) | \
+	git clean -id &&
+	test -f Makefile &&
+	test -f README &&
+	test -f src/part1.c &&
+	test -f src/part2.c &&
+	test -f a.out &&
+	test -f docs/manual.txt &&
+	test ! -f src/part3.c &&
+	test ! -f src/part3.h &&
+	test ! -f src/part4.c &&
+	test -f src/part4.h &&
+	test -f obj.o &&
+	test -f build/lib.so
+
+'
+
+test_expect_success 'git clean -id (select - filenames)' '
+
+	mkdir -p build docs &&
+	touch a.out foo.txt bar.txt baz.txt &&
+	(echo s; echo a.out fo ba bar; echo; echo c) | \
+	git clean -id &&
+	test -f Makefile &&
+	test ! -f a.out &&
+	test ! -f foo.txt &&
+	test ! -f bar.txt &&
+	test -f baz.txt &&
+	rm baz.txt
+
+'
+
+test_expect_success 'git clean -id (select - range)' '
+
+	mkdir -p build docs &&
+	touch a.out src/part3.c src/part3.h src/part4.c src/part4.h \
+	docs/manual.txt obj.o build/lib.so &&
+	(echo s; echo 1,3-4; echo 2; echo; echo c) | \
+	git clean -id &&
+	test -f Makefile &&
+	test -f README &&
+	test -f src/part1.c &&
+	test -f src/part2.c &&
+	test ! -f a.out &&
+	test ! -f src/part3.c &&
+	test ! -f src/part3.h &&
+	test -f src/part4.c &&
+	test -f src/part4.h &&
+	test ! -f docs/manual.txt &&
+	test -f obj.o &&
+	test -f build/lib.so
+
+'
+
+test_expect_success 'git clean -id (select - range 2)' '
+
+	mkdir -p build docs &&
+	touch a.out src/part3.c src/part3.h src/part4.c src/part4.h \
+	docs/manual.txt obj.o build/lib.so &&
+	(echo s; echo 4- 1; echo; echo c) | \
+	git clean -id &&
+	test -f Makefile &&
+	test -f README &&
+	test -f src/part1.c &&
+	test -f src/part2.c &&
+	test ! -f a.out &&
+	test -f docs/manual.txt &&
+	test -f src/part3.c &&
+	test ! -f src/part3.h &&
+	test ! -f src/part4.c &&
+	test ! -f src/part4.h &&
+	test -f obj.o &&
+	test -f build/lib.so
+
+'
+
+test_expect_success 'git clean -id (inverse select)' '
+
+	mkdir -p build docs &&
+	touch a.out src/part3.c src/part3.h src/part4.c src/part4.h \
+	docs/manual.txt obj.o build/lib.so &&
+	(echo s; echo "*"; echo -5- 1 -2; echo; echo c) | \
+	git clean -id &&
+	test -f Makefile &&
+	test -f README &&
+	test -f src/part1.c &&
+	test -f src/part2.c &&
+	test ! -f a.out &&
+	test -f docs/manual.txt &&
+	test ! -f src/part3.c &&
+	test ! -f src/part3.h &&
+	test -f src/part4.c &&
+	test -f src/part4.h &&
+	test -f obj.o &&
+	test -f build/lib.so
+
+'
+
+test_expect_success 'git clean -id (ask)' '
+
+	mkdir -p build docs &&
+	touch a.out src/part3.c src/part3.h src/part4.c src/part4.h \
+	docs/manual.txt obj.o build/lib.so &&
+	(echo a; echo Y; echo y; echo no; echo yes; echo bad; echo) | \
+	git clean -id &&
+	test -f Makefile &&
+	test -f README &&
+	test -f src/part1.c &&
+	test -f src/part2.c &&
+	test ! -f a.out &&
+	test ! -f docs/manual.txt &&
+	test -f src/part3.c &&
+	test ! -f src/part3.h &&
+	test -f src/part4.c &&
+	test -f src/part4.h &&
+	test -f obj.o &&
+	test -f build/lib.so
+
+'
+
+test_expect_success 'git clean -id (ask - Ctrl+D)' '
+
+	mkdir -p build docs &&
+	touch a.out src/part3.c src/part3.h src/part4.c src/part4.h \
+	docs/manual.txt obj.o build/lib.so &&
+	(echo a; echo Y; echo no; echo yes; echo "\04") | \
+	git clean -id &&
+	test -f Makefile &&
+	test -f README &&
+	test -f src/part1.c &&
+	test -f src/part2.c &&
+	test ! -f a.out &&
+	test -f docs/manual.txt &&
+	test ! -f src/part3.c &&
+	test -f src/part3.h &&
+	test -f src/part4.c &&
+	test -f src/part4.h &&
+	test -f obj.o &&
+	test -f build/lib.so
+
+'
+
+test_expect_success 'git clean -id with prefix and path (filter)' '
+
+	mkdir -p build docs &&
+	touch a.out src/part3.c src/part3.h src/part4.c src/part4.h \
+	docs/manual.txt obj.o build/lib.so &&
+	(cd build/ && \
+	 (echo f; echo "docs"; echo "*.h"; echo ; echo c) | \
+	 git clean -id ..) &&
+	test -f Makefile &&
+	test -f README &&
+	test -f src/part1.c &&
+	test -f src/part2.c &&
+	test ! -f a.out &&
+	test -f docs/manual.txt &&
+	test ! -f src/part3.c &&
+	test -f src/part3.h &&
+	test ! -f src/part4.c &&
+	test -f src/part4.h &&
+	test -f obj.o &&
+	test -f build/lib.so
+
+'
+
+test_expect_success 'git clean -id with prefix and path (select by name)' '
+
+	mkdir -p build docs &&
+	touch a.out src/part3.c src/part3.h src/part4.c src/part4.h \
+	docs/manual.txt obj.o build/lib.so &&
+	(cd build/ && \
+	 (echo s; echo "../docs/"; echo "../src/part3.c"; \
+	  echo "../src/part4.c";  echo; echo c) | \
+	 git clean -id ..) &&
+	test -f Makefile &&
+	test -f README &&
+	test -f src/part1.c &&
+	test -f src/part2.c &&
+	test -f a.out &&
+	test ! -f docs/manual.txt &&
+	test ! -f src/part3.c &&
+	test -f src/part3.h &&
+	test ! -f src/part4.c &&
+	test -f src/part4.h &&
+	test -f obj.o &&
+	test -f build/lib.so
+
+'
+
+test_expect_success 'git clean -id with prefix and path (ask)' '
+
+	mkdir -p build docs &&
+	touch a.out src/part3.c src/part3.h src/part4.c src/part4.h \
+	docs/manual.txt obj.o build/lib.so &&
+	(cd build/ && \
+	 (echo a; echo Y; echo y; echo no; echo yes; echo bad; echo) | \
+	 git clean -id ..) &&
+	test -f Makefile &&
+	test -f README &&
+	test -f src/part1.c &&
+	test -f src/part2.c &&
+	test ! -f a.out &&
+	test ! -f docs/manual.txt &&
+	test -f src/part3.c &&
+	test ! -f src/part3.h &&
+	test -f src/part4.c &&
+	test -f src/part4.h &&
+	test -f obj.o &&
+	test -f build/lib.so
+
+'
+
+test_done
diff --git a/t/t7400-submodule-basic.sh b/t/t7400-submodule-basic.sh
index ff26535..a39d074 100755
--- a/t/t7400-submodule-basic.sh
+++ b/t/t7400-submodule-basic.sh
@@ -18,6 +18,16 @@
 	git branch initial
 '
 
+test_expect_success 'configuration parsing' '
+	test_when_finished "rm -f .gitmodules" &&
+	cat >.gitmodules <<-\EOF &&
+	[submodule "s"]
+		path
+		ignore
+	EOF
+	test_must_fail git status
+'
+
 test_expect_success 'setup - repository in init subdirectory' '
 	mkdir init &&
 	(
@@ -78,7 +88,7 @@
 	(
 		cd addtest &&
 		git submodule add -q "$submodurl" submod >actual &&
-		test ! -s actual &&
+		test_must_be_empty actual &&
 		echo "gitdir: ../.git/modules/submod" >expect &&
 		test_cmp expect submod/.git &&
 		(
@@ -212,6 +222,32 @@
 	test_cmp empty untracked
 '
 
+test_expect_success 'submodule add in subdirectory' '
+	echo "refs/heads/master" >expect &&
+	>empty &&
+
+	mkdir addtest/sub &&
+	(
+		cd addtest/sub &&
+		git submodule add "$submodurl" ../realsubmod3 &&
+		git submodule init
+	) &&
+
+	rm -f heads head untracked &&
+	inspect addtest/realsubmod3 ../.. &&
+	test_cmp expect heads &&
+	test_cmp expect head &&
+	test_cmp empty untracked
+'
+
+test_expect_success 'submodule add in subdirectory with relative path should fail' '
+	(
+		cd addtest/sub &&
+		test_must_fail git submodule add ../../ submod3 2>../../output.err
+	) &&
+	test_i18ngrep toplevel output.err
+'
+
 test_expect_success 'setup - add an example entry to .gitmodules' '
 	GIT_CONFIG=.gitmodules \
 	git config submodule.example.url git://example.com/init.git
@@ -308,7 +344,7 @@
 
 	mkdir init &&
 	git submodule update -q >update.out &&
-	test ! -s update.out &&
+	test_must_be_empty update.out &&
 
 	inspect init &&
 	test_cmp expect head-sha1
@@ -319,6 +355,26 @@
 	grep "^ $rev1" list
 '
 
+test_expect_success 'status "up-to-date" from subdirectory' '
+	mkdir -p sub &&
+	(
+		cd sub &&
+		git submodule status >../list
+	) &&
+	grep "^ $rev1" list &&
+	grep "\\.\\./init" list
+'
+
+test_expect_success 'status "up-to-date" from subdirectory with path' '
+	mkdir -p sub &&
+	(
+		cd sub &&
+		git submodule status ../init >../list
+	) &&
+	grep "^ $rev1" list &&
+	grep "\\.\\./init" list
+'
+
 test_expect_success 'status should be "modified" after submodule commit' '
 	(
 		cd init &&
@@ -399,6 +455,25 @@
 	git rev-parse --resolve-git-dir init/.git
 '
 
+test_expect_success 'update --init from subdirectory' '
+	mv init init2 &&
+	git config -f .gitmodules submodule.example.url "$(pwd)/init2" &&
+	git config --remove-section submodule.example &&
+	test_must_fail git config submodule.example.url &&
+
+	mkdir -p sub &&
+	(
+		cd sub &&
+		git submodule update ../init >update.out &&
+		cat update.out &&
+		test_i18ngrep "not initialized" update.out &&
+		test_must_fail git rev-parse --resolve-git-dir ../init/.git &&
+
+		git submodule update --init ../init
+	) &&
+	git rev-parse --resolve-git-dir init/.git
+'
+
 test_expect_success 'do not add files from a submodule' '
 
 	git reset --hard &&
@@ -696,7 +771,7 @@
 		rm -rf repo &&
 		git rm repo &&
 		git submodule add -q --name repo_new "$submodurl/bare.git" repo >actual &&
-		test ! -s actual &&
+		test_must_be_empty actual &&
 		echo "gitdir: ../.git/modules/submod" >expect &&
 		test_cmp expect submod/.git &&
 		(
@@ -772,6 +847,21 @@
 	rmdir init
 '
 
+test_expect_success 'submodule deinit from subdirectory' '
+	git submodule update --init &&
+	git config submodule.example.foo bar &&
+	mkdir -p sub &&
+	(
+		cd sub &&
+		git submodule deinit ../init >../output
+	) &&
+	grep "\\.\\./init" output &&
+	test -z "$(git config --get-regexp "submodule\.example\.")" &&
+	test -n "$(git config --get-regexp "submodule\.example2\.")" &&
+	test -f example2/.git &&
+	rmdir init
+'
+
 test_expect_success 'submodule deinit . deinits all initialized submodules' '
 	git submodule update --init &&
 	git config submodule.example.foo bar &&
@@ -868,4 +958,35 @@
 	test -n "$(git config --get-regexp "submodule\.example\.")"
 '
 
+test_expect_success 'submodule with UTF-8 name' '
+	svname=$(printf "\303\245 \303\244\303\266") &&
+	mkdir "$svname" &&
+	(
+		cd "$svname" &&
+		git init &&
+		>sub &&
+		git add sub &&
+		git commit -m "init sub"
+	) &&
+	test_config core.precomposeunicode true &&
+	git submodule add ./"$svname" &&
+	git submodule >&2 &&
+	test -n "$(git submodule | grep "$svname")"
+'
+
+test_expect_success 'submodule add clone shallow submodule' '
+	mkdir super &&
+	pwd=$(pwd)
+	(
+		cd super &&
+		git init &&
+		git submodule add --depth=1 file://"$pwd"/example2 submodule &&
+		(
+			cd submodule &&
+			test 1 = $(git log --oneline | wc -l)
+		)
+	)
+'
+
+
 test_done
diff --git a/t/t7401-submodule-summary.sh b/t/t7401-submodule-summary.sh
index 30b429e..ac2434c 100755
--- a/t/t7401-submodule-summary.sh
+++ b/t/t7401-submodule-summary.sh
@@ -45,6 +45,42 @@
 	test_cmp expected actual
 "
 
+test_expect_success 'added submodule (subdirectory)' "
+	mkdir sub &&
+	(
+		cd sub &&
+		git submodule summary >../actual
+	) &&
+	cat >expected <<-EOF &&
+* ../sm1 0000000...$head1 (2):
+  > Add foo2
+
+EOF
+	test_cmp expected actual
+"
+
+test_expect_success 'added submodule (subdirectory only)' "
+	(
+		cd sub &&
+		git submodule summary . >../actual
+	) &&
+	>expected &&
+	test_cmp expected actual
+"
+
+test_expect_success 'added submodule (subdirectory with explicit path)' "
+	(
+		cd sub &&
+		git submodule summary ../sm1 >../actual
+	) &&
+	cat >expected <<-EOF &&
+* ../sm1 0000000...$head1 (2):
+  > Add foo2
+
+EOF
+	test_cmp expected actual
+"
+
 commit_file sm1 &&
 head2=$(add_file sm1 foo3)
 
@@ -76,8 +112,8 @@
 )
 
 test_expect_success 'modified submodule(backward)' "
-    git submodule summary >actual &&
-    cat >expected <<-EOF &&
+	git submodule summary >actual &&
+	cat >expected <<-EOF &&
 * sm1 $head2...$head3 (2):
   < Add foo3
   < Add foo2
@@ -89,8 +125,8 @@
 head4=$(add_file sm1 foo4 foo5) &&
 head4_full=$(GIT_DIR=sm1/.git git rev-parse --verify HEAD)
 test_expect_success 'modified submodule(backward and forward)' "
-    git submodule summary >actual &&
-    cat >expected <<-EOF &&
+	git submodule summary >actual &&
+	cat >expected <<-EOF &&
 * sm1 $head2...$head4 (4):
   > Add foo5
   > Add foo4
@@ -102,15 +138,15 @@
 "
 
 test_expect_success '--summary-limit' "
-    git submodule summary -n 3 >actual &&
-    cat >expected <<-EOF &&
+	git submodule summary -n 3 >actual &&
+	cat >expected <<-EOF &&
 * sm1 $head2...$head4 (4):
   > Add foo5
   > Add foo4
   < Add foo3
 
 EOF
-    test_cmp expected actual
+	test_cmp expected actual
 "
 
 commit_file sm1 &&
@@ -122,8 +158,8 @@
 mv sm1-bak sm1
 
 test_expect_success 'typechanged submodule(submodule->blob), --cached' "
-    git submodule summary --cached >actual &&
-    cat >expected <<-EOF &&
+	git submodule summary --cached >actual &&
+	cat >expected <<-EOF &&
 * sm1 $head4(submodule)->$head5(blob) (3):
   < Add foo5
 
@@ -132,59 +168,59 @@
 "
 
 test_expect_success 'typechanged submodule(submodule->blob), --files' "
-    git submodule summary --files >actual &&
-    cat >expected <<-EOF &&
+	git submodule summary --files >actual &&
+	cat >expected <<-EOF &&
 * sm1 $head5(blob)->$head4(submodule) (3):
   > Add foo5
 
 EOF
-    test_i18ncmp actual expected
+	test_i18ncmp actual expected
 "
 
 rm -rf sm1 &&
 git checkout-index sm1
 test_expect_success 'typechanged submodule(submodule->blob)' "
-    git submodule summary >actual &&
-    cat >expected <<-EOF &&
+	git submodule summary >actual &&
+	cat >expected <<-EOF &&
 * sm1 $head4(submodule)->$head5(blob):
 
 EOF
-    test_i18ncmp actual expected
+	test_i18ncmp actual expected
 "
 
 rm -f sm1 &&
 test_create_repo sm1 &&
 head6=$(add_file sm1 foo6 foo7)
 test_expect_success 'nonexistent commit' "
-    git submodule summary >actual &&
-    cat >expected <<-EOF &&
+	git submodule summary >actual &&
+	cat >expected <<-EOF &&
 * sm1 $head4...$head6:
   Warn: sm1 doesn't contain commit $head4_full
 
 EOF
-    test_i18ncmp actual expected
+	test_i18ncmp actual expected
 "
 
 commit_file
 test_expect_success 'typechanged submodule(blob->submodule)' "
-    git submodule summary >actual &&
-    cat >expected <<-EOF &&
+	git submodule summary >actual &&
+	cat >expected <<-EOF &&
 * sm1 $head5(blob)->$head6(submodule) (2):
   > Add foo7
 
 EOF
-    test_i18ncmp expected actual
+	test_i18ncmp expected actual
 "
 
 commit_file sm1 &&
 rm -rf sm1
 test_expect_success 'deleted submodule' "
-    git submodule summary >actual &&
-    cat >expected <<-EOF &&
+	git submodule summary >actual &&
+	cat >expected <<-EOF &&
 * sm1 $head6...0000000:
 
 EOF
-    test_cmp expected actual
+	test_cmp expected actual
 "
 
 test_create_repo sm2 &&
@@ -192,43 +228,43 @@
 git add sm2
 
 test_expect_success 'multiple submodules' "
-    git submodule summary >actual &&
-    cat >expected <<-EOF &&
+	git submodule summary >actual &&
+	cat >expected <<-EOF &&
 * sm1 $head6...0000000:
 
 * sm2 0000000...$head7 (2):
   > Add foo9
 
 EOF
-    test_cmp expected actual
+	test_cmp expected actual
 "
 
 test_expect_success 'path filter' "
-    git submodule summary sm2 >actual &&
-    cat >expected <<-EOF &&
+	git submodule summary sm2 >actual &&
+	cat >expected <<-EOF &&
 * sm2 0000000...$head7 (2):
   > Add foo9
 
 EOF
-    test_cmp expected actual
+	test_cmp expected actual
 "
 
 commit_file sm2
 test_expect_success 'given commit' "
-    git submodule summary HEAD^ >actual &&
-    cat >expected <<-EOF &&
+	git submodule summary HEAD^ >actual &&
+	cat >expected <<-EOF &&
 * sm1 $head6...0000000:
 
 * sm2 0000000...$head7 (2):
   > Add foo9
 
 EOF
-    test_cmp expected actual
+	test_cmp expected actual
 "
 
 test_expect_success '--for-status' "
-    git submodule summary --for-status HEAD^ >actual &&
-    test_i18ncmp actual - <<EOF
+	git submodule summary --for-status HEAD^ >actual &&
+	test_i18ncmp actual - <<EOF
 # Submodule changes to be committed:
 #
 # * sm1 $head6...0000000:
@@ -240,14 +276,14 @@
 "
 
 test_expect_success 'fail when using --files together with --cached' "
-    test_must_fail git submodule summary --files --cached
+	test_must_fail git submodule summary --files --cached
 "
 
 test_expect_success 'should not fail in an empty repo' "
-    git init xyzzy &&
-    cd xyzzy &&
-    git submodule summary >output 2>&1 &&
-    test_cmp output /dev/null
+	git init xyzzy &&
+	cd xyzzy &&
+	git submodule summary >output 2>&1 &&
+	test_cmp output /dev/null
 "
 
 test_done
diff --git a/t/t7403-submodule-sync.sh b/t/t7403-submodule-sync.sh
index 94e26c4..79bc135 100755
--- a/t/t7403-submodule-sync.sh
+++ b/t/t7403-submodule-sync.sh
@@ -11,216 +11,338 @@
 . ./test-lib.sh
 
 test_expect_success setup '
-	echo file > file &&
+	echo file >file &&
 	git add file &&
 	test_tick &&
 	git commit -m upstream &&
 	git clone . super &&
 	git clone super submodule &&
-	(cd submodule &&
-	 git submodule add ../submodule sub-submodule &&
-	 test_tick &&
-	 git commit -m "sub-submodule"
+	(
+		cd submodule &&
+		git submodule add ../submodule sub-submodule &&
+		test_tick &&
+		git commit -m "sub-submodule"
 	) &&
-	(cd super &&
-	 git submodule add ../submodule submodule &&
-	 test_tick &&
-	 git commit -m "submodule"
+	(
+		cd super &&
+		git submodule add ../submodule submodule &&
+		test_tick &&
+		git commit -m "submodule"
 	) &&
 	git clone super super-clone &&
-	(cd super-clone && git submodule update --init --recursive) &&
+	(
+		cd super-clone &&
+		git submodule update --init --recursive
+	) &&
 	git clone super empty-clone &&
-	(cd empty-clone && git submodule init) &&
+	(
+		cd empty-clone &&
+		git submodule init
+	) &&
 	git clone super top-only-clone &&
 	git clone super relative-clone &&
-	(cd relative-clone && git submodule update --init --recursive) &&
+	(
+		cd relative-clone &&
+		git submodule update --init --recursive
+	) &&
 	git clone super recursive-clone &&
-	(cd recursive-clone && git submodule update --init --recursive)
-'
-
-test_expect_success 'change submodule' '
-	(cd submodule &&
-	 echo second line >> file &&
-	 test_tick &&
-	 git commit -a -m "change submodule"
+	(
+		cd recursive-clone &&
+		git submodule update --init --recursive
 	)
 '
 
+test_expect_success 'change submodule' '
+	(
+		cd submodule &&
+		echo second line >>file &&
+		test_tick &&
+		git commit -a -m "change submodule"
+	)
+'
+
+reset_submodule_urls () {
+	local root
+	root=$(pwd) &&
+	(
+		cd super-clone/submodule &&
+		git config remote.origin.url "$root/submodule"
+	) &&
+	(
+		cd super-clone/submodule/sub-submodule &&
+		git config remote.origin.url "$root/submodule"
+	)
+}
+
 test_expect_success 'change submodule url' '
-	(cd super &&
-	 cd submodule &&
-	 git checkout master &&
-	 git pull
+	(
+		cd super &&
+		cd submodule &&
+		git checkout master &&
+		git pull
 	) &&
 	mv submodule moved-submodule &&
-	(cd moved-submodule &&
-	 git config -f .gitmodules submodule.sub-submodule.url ../moved-submodule &&
-	 test_tick &&
-	 git commit -a -m moved-sub-submodule
+	(
+		cd moved-submodule &&
+		git config -f .gitmodules submodule.sub-submodule.url ../moved-submodule &&
+		test_tick &&
+		git commit -a -m moved-sub-submodule
 	) &&
-	(cd super &&
-	 git config -f .gitmodules submodule.submodule.url ../moved-submodule &&
-	 test_tick &&
-	 git commit -a -m moved-submodule
+	(
+		cd super &&
+		git config -f .gitmodules submodule.submodule.url ../moved-submodule &&
+		test_tick &&
+		git commit -a -m moved-submodule
 	)
 '
 
 test_expect_success '"git submodule sync" should update submodule URLs' '
-	(cd super-clone &&
-	 git pull --no-recurse-submodules &&
-	 git submodule sync
+	(
+		cd super-clone &&
+		git pull --no-recurse-submodules &&
+		git submodule sync
 	) &&
-	test -d "$(cd super-clone/submodule &&
-	 git config remote.origin.url
+	test -d "$(
+		cd super-clone/submodule &&
+		git config remote.origin.url
 	)" &&
-	test ! -d "$(cd super-clone/submodule/sub-submodule &&
-	 git config remote.origin.url
+	test ! -d "$(
+		cd super-clone/submodule/sub-submodule &&
+		git config remote.origin.url
 	)" &&
-	(cd super-clone/submodule &&
-	 git checkout master &&
-	 git pull
+	(
+		cd super-clone/submodule &&
+		git checkout master &&
+		git pull
 	) &&
-	(cd super-clone &&
-	 test -d "$(git config submodule.submodule.url)"
+	(
+		cd super-clone &&
+		test -d "$(git config submodule.submodule.url)"
 	)
 '
 
 test_expect_success '"git submodule sync --recursive" should update all submodule URLs' '
-	(cd super-clone &&
-	 (cd submodule &&
-	  git pull --no-recurse-submodules
-	 ) &&
-	 git submodule sync --recursive
+	(
+		cd super-clone &&
+		(
+			cd submodule &&
+			git pull --no-recurse-submodules
+		) &&
+		git submodule sync --recursive
 	) &&
-	test -d "$(cd super-clone/submodule &&
-	 git config remote.origin.url
+	test -d "$(
+		cd super-clone/submodule &&
+		git config remote.origin.url
 	)" &&
-	test -d "$(cd super-clone/submodule/sub-submodule &&
-	 git config remote.origin.url
+	test -d "$(
+		cd super-clone/submodule/sub-submodule &&
+		git config remote.origin.url
 	)" &&
-	(cd super-clone/submodule/sub-submodule &&
-	 git checkout master &&
-	 git pull
+	(
+		cd super-clone/submodule/sub-submodule &&
+		git checkout master &&
+		git pull
+	)
+'
+
+test_expect_success 'reset submodule URLs' '
+	reset_submodule_urls super-clone
+'
+
+test_expect_success '"git submodule sync" should update submodule URLs - subdirectory' '
+	(
+		cd super-clone &&
+		git pull --no-recurse-submodules &&
+		mkdir -p sub &&
+		cd sub &&
+		git submodule sync >../../output
+	) &&
+	grep "\\.\\./submodule" output &&
+	test -d "$(
+		cd super-clone/submodule &&
+		git config remote.origin.url
+	)" &&
+	test ! -d "$(
+		cd super-clone/submodule/sub-submodule &&
+		git config remote.origin.url
+	)" &&
+	(
+		cd super-clone/submodule &&
+		git checkout master &&
+		git pull
+	) &&
+	(
+		cd super-clone &&
+		test -d "$(git config submodule.submodule.url)"
+	)
+'
+
+test_expect_success '"git submodule sync --recursive" should update all submodule URLs - subdirectory' '
+	(
+		cd super-clone &&
+		(
+			cd submodule &&
+			git pull --no-recurse-submodules
+		) &&
+		mkdir -p sub &&
+		cd sub &&
+		git submodule sync --recursive >../../output
+	) &&
+	grep "\\.\\./submodule/sub-submodule" output &&
+	test -d "$(
+		cd super-clone/submodule &&
+		git config remote.origin.url
+	)" &&
+	test -d "$(
+		cd super-clone/submodule/sub-submodule &&
+		git config remote.origin.url
+	)" &&
+	(
+		cd super-clone/submodule/sub-submodule &&
+		git checkout master &&
+		git pull
 	)
 '
 
 test_expect_success '"git submodule sync" should update known submodule URLs' '
-	(cd empty-clone &&
-	 git pull &&
-	 git submodule sync &&
-	 test -d "$(git config submodule.submodule.url)"
+	(
+		cd empty-clone &&
+		git pull &&
+		git submodule sync &&
+		test -d "$(git config submodule.submodule.url)"
 	)
 '
 
 test_expect_success '"git submodule sync" should not vivify uninteresting submodule' '
-	(cd top-only-clone &&
-	 git pull &&
-	 git submodule sync &&
-	 test -z "$(git config submodule.submodule.url)" &&
-	 git submodule sync submodule &&
-	 test -z "$(git config submodule.submodule.url)"
+	(
+		cd top-only-clone &&
+		git pull &&
+		git submodule sync &&
+		test -z "$(git config submodule.submodule.url)" &&
+		git submodule sync submodule &&
+		test -z "$(git config submodule.submodule.url)"
 	)
 '
 
 test_expect_success '"git submodule sync" handles origin URL of the form foo' '
-	(cd relative-clone &&
-	 git remote set-url origin foo &&
-	 git submodule sync &&
-	(cd submodule &&
-	 #actual fails with: "cannot strip off url foo
-	 test "$(git config remote.origin.url)" = "../submodule"
-	)
+	(
+		cd relative-clone &&
+		git remote set-url origin foo &&
+		git submodule sync &&
+		(
+			cd submodule &&
+			#actual fails with: "cannot strip off url foo
+			test "$(git config remote.origin.url)" = "../submodule"
+		)
 	)
 '
 
 test_expect_success '"git submodule sync" handles origin URL of the form foo/bar' '
-	(cd relative-clone &&
-	 git remote set-url origin foo/bar &&
-	 git submodule sync &&
-	(cd submodule &&
-	 #actual foo/submodule
-	 test "$(git config remote.origin.url)" = "../foo/submodule"
-	)
-	(cd submodule/sub-submodule &&
-	 test "$(git config remote.origin.url)" != "../../foo/submodule"
-	)
+	(
+		cd relative-clone &&
+		git remote set-url origin foo/bar &&
+		git submodule sync &&
+		(
+			cd submodule &&
+			#actual foo/submodule
+			test "$(git config remote.origin.url)" = "../foo/submodule"
+		) &&
+		(
+			cd submodule/sub-submodule &&
+			test "$(git config remote.origin.url)" != "../../foo/submodule"
+		)
 	)
 '
 
 test_expect_success '"git submodule sync --recursive" propagates changes in origin' '
-	(cd recursive-clone &&
-	 git remote set-url origin foo/bar &&
-	 git submodule sync --recursive &&
-	(cd submodule &&
-	 #actual foo/submodule
-	 test "$(git config remote.origin.url)" = "../foo/submodule"
-	)
-	(cd submodule/sub-submodule &&
-	 test "$(git config remote.origin.url)" = "../../foo/submodule"
-	)
+	(
+		cd recursive-clone &&
+		git remote set-url origin foo/bar &&
+		git submodule sync --recursive &&
+		(
+			cd submodule &&
+			#actual foo/submodule
+			test "$(git config remote.origin.url)" = "../foo/submodule"
+		) &&
+		(
+			cd submodule/sub-submodule &&
+			test "$(git config remote.origin.url)" = "../../foo/submodule"
+		)
 	)
 '
 
 test_expect_success '"git submodule sync" handles origin URL of the form ./foo' '
-	(cd relative-clone &&
-	 git remote set-url origin ./foo &&
-	 git submodule sync &&
-	(cd submodule &&
-	 #actual ./submodule
-	 test "$(git config remote.origin.url)" = "../submodule"
-	)
+	(
+		cd relative-clone &&
+		git remote set-url origin ./foo &&
+		git submodule sync &&
+		(
+			cd submodule &&
+			#actual ./submodule
+			test "$(git config remote.origin.url)" = "../submodule"
+		)
 	)
 '
 
 test_expect_success '"git submodule sync" handles origin URL of the form ./foo/bar' '
-	(cd relative-clone &&
-	 git remote set-url origin ./foo/bar &&
-	 git submodule sync &&
-	(cd submodule &&
-	 #actual ./foo/submodule
-	 test "$(git config remote.origin.url)" = "../foo/submodule"
-	)
+	(
+		cd relative-clone &&
+		git remote set-url origin ./foo/bar &&
+		git submodule sync &&
+		(
+			cd submodule &&
+			#actual ./foo/submodule
+			test "$(git config remote.origin.url)" = "../foo/submodule"
+		)
 	)
 '
 
 test_expect_success '"git submodule sync" handles origin URL of the form ../foo' '
-	(cd relative-clone &&
-	 git remote set-url origin ../foo &&
-	 git submodule sync &&
-	(cd submodule &&
-	 #actual ../submodule
-	 test "$(git config remote.origin.url)" = "../../submodule"
-	)
+	(
+		cd relative-clone &&
+		git remote set-url origin ../foo &&
+		git submodule sync &&
+		(
+			cd submodule &&
+			#actual ../submodule
+			test "$(git config remote.origin.url)" = "../../submodule"
+		)
 	)
 '
 
 test_expect_success '"git submodule sync" handles origin URL of the form ../foo/bar' '
-	(cd relative-clone &&
-	 git remote set-url origin ../foo/bar &&
-	 git submodule sync &&
-	(cd submodule &&
-	 #actual ../foo/submodule
-	 test "$(git config remote.origin.url)" = "../../foo/submodule"
-	)
+	(
+		cd relative-clone &&
+		git remote set-url origin ../foo/bar &&
+		git submodule sync &&
+		(
+			cd submodule &&
+			#actual ../foo/submodule
+			test "$(git config remote.origin.url)" = "../../foo/submodule"
+		)
 	)
 '
 
 test_expect_success '"git submodule sync" handles origin URL of the form ../foo/bar with deeply nested submodule' '
-	(cd relative-clone &&
-	 git remote set-url origin ../foo/bar &&
-	 mkdir -p a/b/c &&
-	 ( cd a/b/c &&
-	   git init &&
-	   :> .gitignore &&
-	   git add .gitignore &&
-	   test_tick &&
-	   git commit -m "initial commit" ) &&
-	 git submodule add ../bar/a/b/c ./a/b/c &&
-	 git submodule sync &&
-	(cd a/b/c &&
-	 #actual ../foo/bar/a/b/c
-	 test "$(git config remote.origin.url)" = "../../../../foo/bar/a/b/c"
-	)
+	(
+		cd relative-clone &&
+		git remote set-url origin ../foo/bar &&
+		mkdir -p a/b/c &&
+		(
+			cd a/b/c &&
+			git init &&
+			>.gitignore &&
+			git add .gitignore &&
+			test_tick &&
+			git commit -m "initial commit"
+		) &&
+		git submodule add ../bar/a/b/c ./a/b/c &&
+		git submodule sync &&
+		(
+			cd a/b/c &&
+			#actual ../foo/bar/a/b/c
+			test "$(git config remote.origin.url)" = "../../../../foo/bar/a/b/c"
+		)
 	)
 '
 
diff --git a/t/t7406-submodule-update.sh b/t/t7406-submodule-update.sh
index a4ffea0..f0b3305 100755
--- a/t/t7406-submodule-update.sh
+++ b/t/t7406-submodule-update.sh
@@ -58,7 +58,7 @@
 	 git submodule add ../merging merging &&
 	 test_tick &&
 	 git commit -m "rebasing"
-	)
+	) &&
 	(cd super &&
 	 git submodule add ../none none &&
 	 test_tick &&
@@ -80,6 +80,21 @@
 	)
 '
 
+test_expect_success 'submodule update from subdirectory' '
+	(cd super/submodule &&
+	 git reset --hard HEAD~1
+	) &&
+	mkdir super/sub &&
+	(cd super/sub &&
+	 (cd ../submodule &&
+	  compare_head
+	 ) &&
+	 git submodule update ../submodule &&
+	 cd ../submodule &&
+	 ! compare_head
+	)
+'
+
 apos="'";
 test_expect_success 'submodule update does not fetch already present commits' '
 	(cd submodule &&
@@ -279,6 +294,35 @@
 	)
 '
 
+test_expect_success 'submodule update - command in .git/config' '
+	(cd super &&
+	 git config submodule.submodule.update "!git checkout"
+	) &&
+	(cd super/submodule &&
+	  git reset --hard HEAD^
+	) &&
+	(cd super &&
+	 (cd submodule &&
+	  compare_head
+	 ) &&
+	 git submodule update submodule &&
+	 cd submodule &&
+	 ! compare_head
+	)
+'
+
+test_expect_success 'submodule update - command in .git/config catches failure' '
+	(cd super &&
+	 git config submodule.submodule.update "!false"
+	) &&
+	(cd super/submodule &&
+	  git reset --hard HEAD^
+	) &&
+	(cd super &&
+	 test_must_fail git submodule update submodule
+	)
+'
+
 test_expect_success 'submodule init picks up rebase' '
 	(cd super &&
 	 git config -f .gitmodules submodule.rebasing.update rebase &&
@@ -685,14 +729,24 @@
 test_expect_success SYMLINKS 'submodule update can handle symbolic links in pwd' '
 	mkdir -p linked/dir &&
 	ln -s linked/dir linkto &&
-	(
-		cd linkto &&
-		git clone "$TRASH_DIRECTORY"/super_update_r2 super &&
-		(
-			cd super &&
-			git submodule update --init --recursive
-		)
+	(cd linkto &&
+	 git clone "$TRASH_DIRECTORY"/super_update_r2 super &&
+	 (cd super &&
+	  git submodule update --init --recursive
+	 )
 	)
 '
 
+test_expect_success 'submodule update clone shallow submodule' '
+	git clone cloned super3 &&
+	pwd=$(pwd)
+	(cd super3 &&
+	 sed -e "s#url = ../#url = file://$pwd/#" <.gitmodules >.gitmodules.tmp &&
+	 mv -f .gitmodules.tmp .gitmodules &&
+	 git submodule update --init --depth=3
+	 (cd submodule &&
+	  test 1 = $(git log --oneline | wc -l)
+	 )
+	)
+'
 test_done
diff --git a/t/t7407-submodule-foreach.sh b/t/t7407-submodule-foreach.sh
index 107b4b7..be93f10 100755
--- a/t/t7407-submodule-foreach.sh
+++ b/t/t7407-submodule-foreach.sh
@@ -80,6 +80,22 @@
 	test_i18ncmp expect actual
 '
 
+cat >expect <<EOF
+Entering '../sub1'
+$pwd/clone-foo1-../sub1-$sub1sha1
+Entering '../sub3'
+$pwd/clone-foo3-../sub3-$sub3sha1
+EOF
+
+test_expect_success 'test "submodule foreach" from subdirectory' '
+	mkdir clone/sub &&
+	(
+		cd clone/sub &&
+		git submodule foreach "echo \$toplevel-\$name-\$sm_path-\$sha1" >../../actual
+	) &&
+	test_i18ncmp expect actual
+'
+
 test_expect_success 'setup nested submodules' '
 	git clone submodule nested1 &&
 	git clone submodule nested2 &&
@@ -129,7 +145,7 @@
 		git rev-parse --resolve-git-dir nested1/.git &&
 		test_must_fail git rev-parse --resolve-git-dir nested1/nested2/.git &&
 		git submodule foreach "git submodule update --init" &&
-		git rev-parse --resolve-git-dir nested1/nested1/nested2/.git
+		git rev-parse --resolve-git-dir nested1/nested2/.git &&
 		test_must_fail git rev-parse --resolve-git-dir nested1/nested2/nested3/.git
 	)
 '
diff --git a/t/t7500-commit.sh b/t/t7500-commit.sh
index 436b7b6..bdc1f29 100755
--- a/t/t7500-commit.sh
+++ b/t/t7500-commit.sh
@@ -13,9 +13,9 @@
 	expect=commit_msg_is.expect
 	actual=commit_msg_is.actual
 
-	printf "%s" "$(git log --pretty=format:%s%b -1)" >$expect &&
-	printf "%s" "$1" >$actual &&
-	test_i18ncmp $expect $actual
+	printf "%s" "$(git log --pretty=format:%s%b -1)" >"$actual" &&
+	printf "%s" "$1" >"$expect" &&
+	test_i18ncmp "$expect" "$actual"
 }
 
 # A sanity check to see if commit is working at all.
diff --git a/t/t7501-commit.sh b/t/t7501-commit.sh
index 195e747..99ce36f 100755
--- a/t/t7501-commit.sh
+++ b/t/t7501-commit.sh
@@ -524,4 +524,17 @@
 	test_i18ngrep " changed, 5 insertions" output
 '
 
+test_expect_success '--only works on to-be-born branch' '
+	# This test relies on having something in the index, as it
+	# would not otherwise actually prove much.  So check this.
+	test -n "$(git ls-files)" &&
+	git checkout --orphan orphan &&
+	echo foo >newfile &&
+	git add newfile &&
+	git commit --only newfile -m"--only on unborn branch" &&
+	echo newfile >expected &&
+	git ls-tree -r --name-only HEAD >actual &&
+	test_cmp expected actual
+'
+
 test_done
diff --git a/t/t7502-commit.sh b/t/t7502-commit.sh
index a4938b1..6313da2 100755
--- a/t/t7502-commit.sh
+++ b/t/t7502-commit.sh
@@ -361,6 +361,23 @@
 	test_cmp expect .git/result
 '
 
+test_expect_success 'do not fire editor if -m <msg> was given' '
+	echo tick >file &&
+	git add file &&
+	echo "editor not started" >.git/result &&
+	(GIT_EDITOR="\"$(pwd)/.git/FAKE_EDITOR\"" git commit -m tick) &&
+	test "$(cat .git/result)" = "editor not started"
+'
+
+test_expect_success 'do not fire editor if -m "" was given' '
+	echo tock >file &&
+	git add file &&
+	echo "editor not started" >.git/result &&
+	(GIT_EDITOR="\"$(pwd)/.git/FAKE_EDITOR\"" \
+	 git commit -m "" --allow-empty-message) &&
+	test "$(cat .git/result)" = "editor not started"
+'
+
 test_expect_success 'do not fire editor in the presence of conflicts' '
 
 	git clean -f &&
diff --git a/t/t7508-status.sh b/t/t7508-status.sh
index e2ffdac..ac3d0fe 100755
--- a/t/t7508-status.sh
+++ b/t/t7508-status.sh
@@ -1335,4 +1335,66 @@
 	git config -f .gitmodules  --remove-section submodule.subname
 '
 
+test_expect_success 'setup of test environment' '
+	git config status.showUntrackedFiles no &&
+	git status -s >expected_short &&
+	git status --no-short >expected_noshort
+'
+
+test_expect_success '"status.short=true" same as "-s"' '
+	git -c status.short=true status >actual &&
+	test_cmp expected_short actual
+'
+
+test_expect_success '"status.short=true" weaker than "--no-short"' '
+	git -c status.short=true status --no-short >actual &&
+	test_cmp expected_noshort actual
+'
+
+test_expect_success '"status.short=false" same as "--no-short"' '
+	git -c status.short=false status >actual &&
+	test_cmp expected_noshort actual
+'
+
+test_expect_success '"status.short=false" weaker than "-s"' '
+	git -c status.short=false status -s >actual &&
+	test_cmp expected_short actual
+'
+
+test_expect_success '"status.branch=true" same as "-b"' '
+	git status -sb >expected_branch &&
+	git -c status.branch=true status -s >actual &&
+	test_cmp expected_branch actual
+'
+
+test_expect_success '"status.branch=true" different from "--no-branch"' '
+	git status -s --no-branch  >expected_nobranch &&
+	git -c status.branch=true status -s >actual &&
+	test_must_fail test_cmp expected_nobranch actual
+'
+
+test_expect_success '"status.branch=true" weaker than "--no-branch"' '
+	git -c status.branch=true status -s --no-branch >actual &&
+	test_cmp expected_nobranch actual
+'
+
+test_expect_success '"status.branch=true" weaker than "--porcelain"' '
+       git -c status.branch=true status --porcelain >actual &&
+       test_cmp expected_nobranch actual
+'
+
+test_expect_success '"status.branch=false" same as "--no-branch"' '
+	git -c status.branch=false status -s >actual &&
+	test_cmp expected_nobranch actual
+'
+
+test_expect_success '"status.branch=false" weaker than "-b"' '
+	git -c status.branch=false status -sb >actual &&
+	test_cmp expected_branch actual
+'
+
+test_expect_success 'Restore default test environment' '
+	git config --unset status.showUntrackedFiles
+'
+
 test_done
diff --git a/t/t7512-status-help.sh b/t/t7512-status-help.sh
index bf08d4e..31a798f 100755
--- a/t/t7512-status-help.sh
+++ b/t/t7512-status-help.sh
@@ -77,7 +77,7 @@
 	ONTO=$(git rev-parse --short HEAD^^) &&
 	test_must_fail git rebase HEAD^ --onto HEAD^^ &&
 	cat >expected <<-EOF &&
-	# HEAD detached at $ONTO
+	# rebase in progress; onto $ONTO
 	# You are currently rebasing branch '\''rebase_conflicts'\'' on '\''$ONTO'\''.
 	#   (fix conflicts and then run "git rebase --continue")
 	#   (use "git rebase --skip" to skip this patch)
@@ -104,7 +104,7 @@
 	echo three >main.txt &&
 	git add main.txt &&
 	cat >expected <<-EOF &&
-	# HEAD detached at $ONTO
+	# rebase in progress; onto $ONTO
 	# You are currently rebasing branch '\''rebase_conflicts'\'' on '\''$ONTO'\''.
 	#   (all conflicts fixed: run "git rebase --continue")
 	#
@@ -136,7 +136,7 @@
 	ONTO=$(git rev-parse --short rebase_i_conflicts) &&
 	test_must_fail git rebase -i rebase_i_conflicts &&
 	cat >expected <<-EOF &&
-	# HEAD detached at $ONTO
+	# rebase in progress; onto $ONTO
 	# You are currently rebasing branch '\''rebase_i_conflicts_second'\'' on '\''$ONTO'\''.
 	#   (fix conflicts and then run "git rebase --continue")
 	#   (use "git rebase --skip" to skip this patch)
@@ -162,7 +162,7 @@
 	test_must_fail git rebase -i rebase_i_conflicts &&
 	git add main.txt &&
 	cat >expected <<-EOF &&
-	# HEAD detached at $ONTO
+	# rebase in progress; onto $ONTO
 	# You are currently rebasing branch '\''rebase_i_conflicts_second'\'' on '\''$ONTO'\''.
 	#   (all conflicts fixed: run "git rebase --continue")
 	#
@@ -188,10 +188,9 @@
 	export FAKE_LINES &&
 	test_when_finished "git rebase --abort" &&
 	ONTO=$(git rev-parse --short HEAD~2) &&
-	TGT=$(git rev-parse --short two_rebase_i) &&
 	git rebase -i HEAD~2 &&
 	cat >expected <<-EOF &&
-	# HEAD detached from $TGT
+	# rebase in progress; onto $ONTO
 	# You are currently editing a commit while rebasing branch '\''rebase_i_edit'\'' on '\''$ONTO'\''.
 	#   (use "git commit --amend" to amend the current commit)
 	#   (use "git rebase --continue" once you are satisfied with your changes)
@@ -216,9 +215,8 @@
 	ONTO=$(git rev-parse --short HEAD~3) &&
 	git rebase -i HEAD~3 &&
 	git reset HEAD^ &&
-	TGT=$(git rev-parse --short HEAD) &&
 	cat >expected <<-EOF &&
-	# HEAD detached at $TGT
+	# rebase in progress; onto $ONTO
 	# You are currently splitting a commit while rebasing branch '\''split_commit'\'' on '\''$ONTO'\''.
 	#   (Once your working directory is clean, run "git rebase --continue")
 	#
@@ -246,11 +244,10 @@
 	export FAKE_LINES &&
 	test_when_finished "git rebase --abort" &&
 	ONTO=$(git rev-parse --short HEAD~3) &&
-	TGT=$(git rev-parse --short three_amend) &&
 	git rebase -i HEAD~3 &&
 	git commit --amend -m "foo" &&
 	cat >expected <<-EOF &&
-	# HEAD detached from $TGT
+	# rebase in progress; onto $ONTO
 	# You are currently editing a commit while rebasing branch '\''amend_last'\'' on '\''$ONTO'\''.
 	#   (use "git commit --amend" to amend the current commit)
 	#   (use "git rebase --continue" once you are satisfied with your changes)
@@ -280,7 +277,7 @@
 	git rebase -i HEAD~3 &&
 	git rebase --continue &&
 	cat >expected <<-EOF &&
-	# HEAD detached from $ONTO
+	# rebase in progress; onto $ONTO
 	# You are currently editing a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''.
 	#   (use "git commit --amend" to amend the current commit)
 	#   (use "git rebase --continue" once you are satisfied with your changes)
@@ -302,7 +299,7 @@
 	git rebase --continue &&
 	git reset HEAD^ &&
 	cat >expected <<-EOF &&
-	# HEAD detached from $ONTO
+	# rebase in progress; onto $ONTO
 	# You are currently splitting a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''.
 	#   (Once your working directory is clean, run "git rebase --continue")
 	#
@@ -329,7 +326,7 @@
 	git rebase --continue &&
 	git commit --amend -m "foo" &&
 	cat >expected <<-EOF &&
-	# HEAD detached from $ONTO
+	# rebase in progress; onto $ONTO
 	# You are currently editing a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''.
 	#   (use "git commit --amend" to amend the current commit)
 	#   (use "git rebase --continue" once you are satisfied with your changes)
@@ -351,7 +348,7 @@
 	git commit --amend -m "a" &&
 	git rebase --continue &&
 	cat >expected <<-EOF &&
-	# HEAD detached from $ONTO
+	# rebase in progress; onto $ONTO
 	# You are currently editing a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''.
 	#   (use "git commit --amend" to amend the current commit)
 	#   (use "git rebase --continue" once you are satisfied with your changes)
@@ -374,7 +371,7 @@
 	git rebase --continue &&
 	git reset HEAD^ &&
 	cat >expected <<-EOF &&
-	# HEAD detached from $ONTO
+	# rebase in progress; onto $ONTO
 	# You are currently splitting a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''.
 	#   (Once your working directory is clean, run "git rebase --continue")
 	#
@@ -402,7 +399,7 @@
 	git rebase --continue &&
 	git commit --amend -m "d" &&
 	cat >expected <<-EOF &&
-	# HEAD detached from $ONTO
+	# rebase in progress; onto $ONTO
 	# You are currently editing a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''.
 	#   (use "git commit --amend" to amend the current commit)
 	#   (use "git rebase --continue" once you are satisfied with your changes)
@@ -426,7 +423,7 @@
 	git commit -m "e" &&
 	git rebase --continue &&
 	cat >expected <<-EOF &&
-	# HEAD detached from $ONTO
+	# rebase in progress; onto $ONTO
 	# You are currently editing a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''.
 	#   (use "git commit --amend" to amend the current commit)
 	#   (use "git rebase --continue" once you are satisfied with your changes)
@@ -451,7 +448,7 @@
 	git rebase --continue &&
 	git reset HEAD^ &&
 	cat >expected <<-EOF &&
-	# HEAD detached from $ONTO
+	# rebase in progress; onto $ONTO
 	# You are currently splitting a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''.
 	#   (Once your working directory is clean, run "git rebase --continue")
 	#
@@ -481,7 +478,7 @@
 	git rebase --continue &&
 	git commit --amend -m "h" &&
 	cat >expected <<-EOF &&
-	# HEAD detached from $ONTO
+	# rebase in progress; onto $ONTO
 	# You are currently editing a commit while rebasing branch '\''several_edits'\'' on '\''$ONTO'\''.
 	#   (use "git commit --amend" to amend the current commit)
 	#   (use "git rebase --continue" once you are satisfied with your changes)
@@ -510,7 +507,7 @@
 	cat >expected <<-\EOF &&
 	# On branch am_already_exists
 	# You are in the middle of an am session.
-	#   (fix conflicts and then run "git am --resolved")
+	#   (fix conflicts and then run "git am --continue")
 	#   (use "git am --skip" to skip this patch)
 	#   (use "git am --abort" to restore the original branch)
 	#
@@ -532,7 +529,7 @@
 	cat >expected <<-\EOF &&
 	# On branch am_not_exists
 	# You are in the middle of an am session.
-	#   (fix conflicts and then run "git am --resolved")
+	#   (fix conflicts and then run "git am --continue")
 	#   (use "git am --skip" to skip this patch)
 	#   (use "git am --abort" to restore the original branch)
 	#
@@ -601,7 +598,7 @@
 	ONTO=$(git rev-parse --short HEAD^^) &&
 	test_must_fail git rebase HEAD^ --onto HEAD^^ &&
 	cat >expected <<-EOF &&
-	# HEAD detached at $ONTO
+	# rebase in progress; onto $ONTO
 	# You are currently rebasing branch '\''statushints_disabled'\'' on '\''$ONTO'\''.
 	#
 	# Unmerged paths:
@@ -632,7 +629,8 @@
 	cat >expected <<-\EOF &&
 	# On branch cherry_branch
 	# You are currently cherry-picking.
-	#   (fix conflicts and run "git commit")
+	#   (fix conflicts and run "git cherry-pick --continue")
+	#   (use "git cherry-pick --abort" to cancel the cherry-pick operation)
 	#
 	# Unmerged paths:
 	#   (use "git add <file>..." to mark resolution)
@@ -655,7 +653,8 @@
 	cat >expected <<-\EOF &&
 	# On branch cherry_branch
 	# You are currently cherry-picking.
-	#   (all conflicts fixed: run "git commit")
+	#   (all conflicts fixed: run "git cherry-pick --continue")
+	#   (use "git cherry-pick --abort" to cancel the cherry-pick operation)
 	#
 	# Changes to be committed:
 	#
@@ -667,7 +666,7 @@
 	test_i18ncmp expected actual
 '
 
-test_expect_success 'status showing detached from a tag' '
+test_expect_success 'status showing detached at and from a tag' '
 	test_commit atag tagging &&
 	git checkout atag &&
 	cat >expected <<-\EOF
@@ -675,6 +674,14 @@
 	nothing to commit (use -u to show untracked files)
 	EOF
 	git status --untracked-files=no >actual &&
+	test_i18ncmp expected actual &&
+
+	git reset --hard HEAD^ &&
+	cat >expected <<-\EOF
+	# HEAD detached from atag
+	nothing to commit (use -u to show untracked files)
+	EOF
+	git status --untracked-files=no >actual &&
 	test_i18ncmp expected actual
 '
 
diff --git a/t/t7600-merge.sh b/t/t7600-merge.sh
index 2f70433..10aa028 100755
--- a/t/t7600-merge.sh
+++ b/t/t7600-merge.sh
@@ -316,7 +316,7 @@
 
 test_debug 'git log --graph --decorate --oneline --all'
 
-test_expect_success 'unsuccesful merge of c1 with c2 (squash, ff-only)' '
+test_expect_success 'unsuccessful merge of c1 with c2 (squash, ff-only)' '
 	git reset --hard c1 &&
 	test_must_fail git merge --squash --ff-only c2
 '
@@ -497,9 +497,15 @@
 	test_must_fail git merge --no-ff --squash c1
 '
 
-test_expect_success 'combining --ff-only and --no-ff is refused' '
-	test_must_fail git merge --ff-only --no-ff c1 &&
-	test_must_fail git merge --no-ff --ff-only c1
+test_expect_success 'option --ff-only overwrites --no-ff' '
+	git merge --no-ff --ff-only c1 &&
+	test_must_fail git merge --no-ff --ff-only c2
+'
+
+test_expect_success 'option --no-ff overrides merge.ff=only config' '
+	git reset --hard c0 &&
+	test_config merge.ff only &&
+	git merge --no-ff c1
 '
 
 test_expect_success 'merge c0 with c1 (ff overrides no-ff)' '
diff --git a/t/t7601-merge-pull-config.sh b/t/t7601-merge-pull-config.sh
index 25dac79..830a4c3 100755
--- a/t/t7601-merge-pull-config.sh
+++ b/t/t7601-merge-pull-config.sh
@@ -109,7 +109,7 @@
 '
 
 # First do the merge with resolve and recursive then verify that
-# recusive is chosen.
+# recursive is chosen.
 
 test_expect_success 'merge picks up the best result' '
 	git config --unset-all pull.twohead &&
diff --git a/t/t7607-merge-overwrite.sh b/t/t7607-merge-overwrite.sh
index 6547eb8..758a623 100755
--- a/t/t7607-merge-overwrite.sh
+++ b/t/t7607-merge-overwrite.sh
@@ -141,11 +141,10 @@
 	test_path_is_missing .git/MERGE_HEAD
 '
 
-test_expect_success SYMLINKS 'will not be confused by symlink in leading path' '
+test_expect_success 'will not be confused by symlink in leading path' '
 	git reset --hard c0 &&
 	rm -rf sub &&
-	ln -s sub2 sub &&
-	git add sub &&
+	test_ln_s_add sub2 sub &&
 	git commit -m ln &&
 	git checkout sub
 '
diff --git a/t/t7800-difftool.sh b/t/t7800-difftool.sh
index a6bd99e..2418528 100755
--- a/t/t7800-difftool.sh
+++ b/t/t7800-difftool.sh
@@ -356,6 +356,13 @@
 	)
 '
 
+run_dir_diff_test 'difftool --dir-diff when worktree file is missing' '
+	test_when_finished git reset --hard &&
+	rm file2 &&
+	git difftool --dir-diff $symlinks --extcmd ls branch master >output &&
+	grep file2 output
+'
+
 write_script .git/CHECK_SYMLINKS <<\EOF
 for f in file file2 sub/sub
 do
@@ -378,6 +385,25 @@
 	test_cmp actual expect
 '
 
+write_script modify-right-file <<\EOF
+echo "new content" >"$2/file"
+EOF
+
+run_dir_diff_test 'difftool --dir-diff syncs worktree with unstaged change' '
+	test_when_finished git reset --hard &&
+	echo "orig content" >file &&
+	git difftool -d $symlinks --extcmd "$(pwd)/modify-right-file" branch &&
+	echo "new content" >expect &&
+	test_cmp expect file
+'
+
+run_dir_diff_test 'difftool --dir-diff syncs worktree without unstaged change' '
+	test_when_finished git reset --hard &&
+	git difftool -d $symlinks --extcmd "$(pwd)/modify-right-file" branch &&
+	echo "new content" >expect &&
+	test_cmp expect file
+'
+
 write_script modify-file <<\EOF
 echo "new content" >file
 EOF
diff --git a/t/t8001-annotate.sh b/t/t8001-annotate.sh
index 41962f0..72176e4 100755
--- a/t/t8001-annotate.sh
+++ b/t/t8001-annotate.sh
@@ -6,9 +6,9 @@
 PROG='git annotate'
 . "$TEST_DIRECTORY"/annotate-tests.sh
 
-test_expect_success 'Annotating an old revision works' '
-	git annotate file master >result &&
-	awk "{ print \$3; }" <result >authors &&
+test_expect_success 'annotate old revision' '
+	git annotate file master >actual &&
+	awk "{ print \$3; }" <actual >authors &&
 	test 2 = $(grep A <authors | wc -l) &&
 	test 2 = $(grep B <authors | wc -l)
 '
diff --git a/t/t8002-blame.sh b/t/t8002-blame.sh
index e2896cf..5cdf3f1 100755
--- a/t/t8002-blame.sh
+++ b/t/t8002-blame.sh
@@ -7,8 +7,16 @@
 . "$TEST_DIRECTORY"/annotate-tests.sh
 
 PROG='git blame -c -e'
-test_expect_success 'Blame --show-email works' '
-    check_count "<A@test.git>" 1 "<B@test.git>" 1 "<B1@test.git>" 1 "<B2@test.git>" 1 "<author@example.com>" 1 "<C@test.git>" 1 "<D@test.git>" 1 "<E at test dot git>" 1
+test_expect_success 'blame --show-email' '
+	check_count \
+		"<A@test.git>" 1 \
+		"<B@test.git>" 1 \
+		"<B1@test.git>" 1 \
+		"<B2@test.git>" 1 \
+		"<author@example.com>" 1 \
+		"<C@test.git>" 1 \
+		"<D@test.git>" 1 \
+		"<E at test dot git>" 1
 '
 
 test_done
diff --git a/t/t8003-blame-corner-cases.sh b/t/t8003-blame-corner-cases.sh
index 230143c..e7cac1d 100755
--- a/t/t8003-blame-corner-cases.sh
+++ b/t/t8003-blame-corner-cases.sh
@@ -175,6 +175,12 @@
 	grep "has only 2 lines" errors
 '
 
+test_expect_success 'blame parses <end> part of -L' '
+	git blame -L1,1 tres >out &&
+	cat out &&
+	test $(wc -l < out) -eq 1
+'
+
 test_expect_success 'indent of line numbers, nine lines' '
 	git blame nine_lines >actual &&
 	test $(grep -c "  " actual) = 0
diff --git a/t/t8006-blame-textconv.sh b/t/t8006-blame-textconv.sh
index bf6caa4..7683515 100755
--- a/t/t8006-blame-textconv.sh
+++ b/t/t8006-blame-textconv.sh
@@ -18,17 +18,13 @@
 	echo "bin: test number 0" >zero.bin &&
 	echo "bin: test 1" >one.bin &&
 	echo "bin: test number 2" >two.bin &&
-	if test_have_prereq SYMLINKS; then
-		ln -s one.bin symlink.bin
-	fi &&
+	test_ln_s_add one.bin symlink.bin &&
 	git add . &&
 	GIT_AUTHOR_NAME=Number1 git commit -a -m First --date="2010-01-01 18:00:00" &&
 	echo "bin: test 1 version 2" >one.bin &&
 	echo "bin: test number 2 version 2" >>two.bin &&
-	if test_have_prereq SYMLINKS; then
-		rm symlink.bin &&
-		ln -s two.bin symlink.bin
-	fi &&
+	rm -f symlink.bin &&
+	test_ln_s_add two.bin symlink.bin &&
 	GIT_AUTHOR_NAME=Number2 git commit -a -m Second --date="2010-01-01 20:00:00"
 '
 
@@ -135,7 +131,7 @@
 
 # cp two.bin three.bin  and make small tweak
 # (this will direct blame -C -C three.bin to consider two.bin and symlink.bin)
-test_expect_success SYMLINKS 'make another new commit' '
+test_expect_success 'make another new commit' '
 	cat >three.bin <<\EOF &&
 bin: test number 2
 bin: test number 2 version 2
@@ -146,7 +142,7 @@
 	GIT_AUTHOR_NAME=Number4 git commit -a -m Fourth --date="2010-01-01 23:00:00"
 '
 
-test_expect_success SYMLINKS 'blame on last commit (-C -C, symlink)' '
+test_expect_success 'blame on last commit (-C -C, symlink)' '
 	git blame -C -C three.bin >blame &&
 	find_blame <blame >result &&
 	cat >expected <<\EOF &&
diff --git a/t/t8007-cat-file-textconv.sh b/t/t8007-cat-file-textconv.sh
index 78a0085..b95e102 100755
--- a/t/t8007-cat-file-textconv.sh
+++ b/t/t8007-cat-file-textconv.sh
@@ -12,9 +12,7 @@
 
 test_expect_success 'setup ' '
 	echo "bin: test" >one.bin &&
-	if test_have_prereq SYMLINKS; then
-		ln -s one.bin symlink.bin
-	fi &&
+	test_ln_s_add one.bin symlink.bin &&
 	git add . &&
 	GIT_AUTHOR_NAME=Number1 git commit -a -m First --date="2010-01-01 18:00:00" &&
 	echo "bin: test version 2" >one.bin &&
@@ -72,14 +70,14 @@
 	test_cmp expected result
 '
 
-test_expect_success SYMLINKS 'cat-file without --textconv (symlink)' '
+test_expect_success 'cat-file without --textconv (symlink)' '
 	git cat-file blob :symlink.bin >result &&
 	printf "%s" "one.bin" >expected
 	test_cmp expected result
 '
 
 
-test_expect_success SYMLINKS 'cat-file --textconv on index (symlink)' '
+test_expect_success 'cat-file --textconv on index (symlink)' '
 	! git cat-file --textconv :symlink.bin 2>result &&
 	cat >expected <<\EOF &&
 fatal: git cat-file --textconv: unable to run textconv on :symlink.bin
@@ -87,7 +85,7 @@
 	test_cmp expected result
 '
 
-test_expect_success SYMLINKS 'cat-file --textconv on HEAD (symlink)' '
+test_expect_success 'cat-file --textconv on HEAD (symlink)' '
 	! git cat-file --textconv HEAD:symlink.bin 2>result &&
 	cat >expected <<EOF &&
 fatal: git cat-file --textconv: unable to run textconv on HEAD:symlink.bin
diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh
index ebd5c5d..2813aa9 100755
--- a/t/t9001-send-email.sh
+++ b/t/t9001-send-email.sh
@@ -171,6 +171,81 @@
 EOF
 "
 
+test_suppress_self () {
+	test_commit $3 &&
+	test_when_finished "git reset --hard HEAD^" &&
+
+	write_script cccmd-sed <<-EOF &&
+		sed -n -e s/^cccmd--//p "\$1"
+	EOF
+
+	git commit --amend --author="$1 <$2>" -F - &&
+	clean_fake_sendmail &&
+	git format-patch --stdout -1 >"suppress-self-$3.patch" &&
+
+	git send-email --from="$1 <$2>" \
+		--to=nobody@example.com \
+		--cc-cmd=./cccmd-sed \
+		--suppress-cc=self \
+		--smtp-server="$(pwd)/fake.sendmail" \
+		suppress-self-$3.patch &&
+
+	mv msgtxt1 msgtxt1-$3 &&
+	sed -e '/^$/q' msgtxt1-$3 >"msghdr1-$3" &&
+	>"expected-no-cc-$3" &&
+
+	(grep '^Cc:' msghdr1-$3 >"actual-no-cc-$3";
+	 test_cmp expected-no-cc-$3 actual-no-cc-$3)
+}
+
+test_suppress_self_unquoted () {
+	test_suppress_self "$1" "$2" "unquoted-$3" <<-EOF
+		test suppress-cc.self unquoted-$3 with name $1 email $2
+
+		unquoted-$3
+
+		cccmd--$1 <$2>
+
+		Cc: $1 <$2>
+		Signed-off-by: $1 <$2>
+	EOF
+}
+
+test_suppress_self_quoted () {
+	test_suppress_self "$1" "$2" "quoted-$3" <<-EOF
+		test suppress-cc.self quoted-$3 with name $1 email $2
+
+		quoted-$3
+
+		cccmd--"$1" <$2>
+
+		Cc: $1 <$2>
+		Cc: "$1" <$2>
+		Signed-off-by: $1 <$2>
+		Signed-off-by: "$1" <$2>
+	EOF
+}
+
+test_expect_success $PREREQ 'self name is suppressed' "
+	test_suppress_self_unquoted 'A U Thor' 'author@example.com' \
+		'self_name_suppressed'
+"
+
+test_expect_success $PREREQ 'self name with dot is suppressed' "
+	test_suppress_self_quoted 'A U. Thor' 'author@example.com' \
+		'self_name_dot_suppressed'
+"
+
+test_expect_success $PREREQ 'non-ascii self name is suppressed' "
+	test_suppress_self_quoted 'Füñný Nâmé' 'odd_?=mail@example.com' \
+		'non_ascii_self_suppressed'
+"
+
+test_expect_success $PREREQ 'sanitized self name is suppressed' "
+	test_suppress_self_unquoted '\"A U. Thor\"' 'author@example.com' \
+		'self_name_sanitized_suppressed'
+"
+
 test_expect_success $PREREQ 'Show all headers' '
 	git send-email \
 		--dry-run \
@@ -881,6 +956,20 @@
 	grep "^From: Füñný Nâmé <odd_?=mail@example.com>" msgtxt1
 '
 
+test_expect_success $PREREQ 'utf8 sender is not duplicated' '
+	clean_fake_sendmail &&
+	test_commit weird_sender &&
+	test_when_finished "git reset --hard HEAD^" &&
+	git commit --amend --author "Füñný Nâmé <odd_?=mail@example.com>" &&
+	git format-patch --stdout -1 >funny_name.patch &&
+	git send-email --from="Füñný Nâmé <odd_?=mail@example.com>" \
+	  --to=nobody@example.com \
+	  --smtp-server="$(pwd)/fake.sendmail" \
+	  funny_name.patch &&
+	grep "^From: " msgtxt1 >msgfrom &&
+	test_line_count = 1 msgfrom
+'
+
 test_expect_success $PREREQ 'sendemail.composeencoding works' '
 	clean_fake_sendmail &&
 	git config sendemail.composeencoding iso-8859-1 &&
@@ -1003,55 +1092,6 @@
 	grep "In-Reply-To: " stdout
 '
 
-test_expect_success $PREREQ 'warning with an implicit --chain-reply-to' '
-	git send-email \
-	--dry-run \
-	--from="Example <nobody@example.com>" \
-	--to=nobody@example.com \
-	outdir/000?-*.patch 2>errors >out &&
-	grep "no-chain-reply-to" errors
-'
-
-test_expect_success $PREREQ 'no warning with an explicit --chain-reply-to' '
-	git send-email \
-	--dry-run \
-	--from="Example <nobody@example.com>" \
-	--to=nobody@example.com \
-	--chain-reply-to \
-	outdir/000?-*.patch 2>errors >out &&
-	! grep "no-chain-reply-to" errors
-'
-
-test_expect_success $PREREQ 'no warning with an explicit --no-chain-reply-to' '
-	git send-email \
-	--dry-run \
-	--from="Example <nobody@example.com>" \
-	--to=nobody@example.com \
-	--nochain-reply-to \
-	outdir/000?-*.patch 2>errors >out &&
-	! grep "no-chain-reply-to" errors
-'
-
-test_expect_success $PREREQ 'no warning with sendemail.chainreplyto = false' '
-	git config sendemail.chainreplyto false &&
-	git send-email \
-	--dry-run \
-	--from="Example <nobody@example.com>" \
-	--to=nobody@example.com \
-	outdir/000?-*.patch 2>errors >out &&
-	! grep "no-chain-reply-to" errors
-'
-
-test_expect_success $PREREQ 'no warning with sendemail.chainreplyto = true' '
-	git config sendemail.chainreplyto true &&
-	git send-email \
-	--dry-run \
-	--from="Example <nobody@example.com>" \
-	--to=nobody@example.com \
-	outdir/000?-*.patch 2>errors >out &&
-	! grep "no-chain-reply-to" errors
-'
-
 test_expect_success $PREREQ 'sendemail.to works' '
 	git config --replace-all sendemail.to "Somebody <somebody@ex.com>" &&
 	git send-email \
diff --git a/t/t9020-remote-svn.sh b/t/t9020-remote-svn.sh
index d9f6b73..4d81ba1 100755
--- a/t/t9020-remote-svn.sh
+++ b/t/t9020-remote-svn.sh
@@ -24,7 +24,7 @@
 	rm -fr .git &&
 	git init &&
 	#git remote add svnsim testsvn::sim:///$TEST_DIRECTORY/t9020/example.svnrdump
-	# let's reuse an exisiting dump file!?
+	# let's reuse an existing dump file!?
 	git remote add svnsim testsvn::sim://$TEST_DIRECTORY/t9154/svn.dump
 	git remote add svnfile testsvn::file://$TEST_DIRECTORY/t9154/svn.dump
 }
diff --git a/t/t9112-git-svn-md5less-file.sh b/t/t9112-git-svn-md5less-file.sh
index a61d671..9861c71 100755
--- a/t/t9112-git-svn-md5less-file.sh
+++ b/t/t9112-git-svn-md5less-file.sh
@@ -7,7 +7,7 @@
 # Loading a node from a svn dumpfile without a Text-Content-Length
 # field causes svn to neglect to store or report an md5sum.  (it will
 # calculate one if you had put Text-Content-Length: 0).  This showed
-# up in a repository creted with cvs2svn.
+# up in a repository created with cvs2svn.
 
 cat > dumpfile.svn <<EOF
 SVN-fs-dump-format-version: 1
diff --git a/t/t9114-git-svn-dcommit-merge.sh b/t/t9114-git-svn-dcommit-merge.sh
index 3077851..f524d2f 100755
--- a/t/t9114-git-svn-dcommit-merge.sh
+++ b/t/t9114-git-svn-dcommit-merge.sh
@@ -48,7 +48,7 @@
 test_expect_success 'setup git mirror and merge' '
 	git svn init "$svnrepo" -t tags -T trunk -b branches &&
 	git svn fetch &&
-	git checkout --track -b svn remotes/trunk &&
+	git checkout -b svn remotes/trunk &&
 	git checkout -b merge &&
 	echo new file > new_file &&
 	git add new_file &&
diff --git a/t/t9147-git-svn-include-paths.sh b/t/t9147-git-svn-include-paths.sh
new file mode 100755
index 0000000..a90ff58
--- /dev/null
+++ b/t/t9147-git-svn-include-paths.sh
@@ -0,0 +1,149 @@
+#!/bin/sh
+#
+# Copyright (c) 2013 Paul Walmsley - based on t9134 by Vitaly Shukela
+#
+
+test_description='git svn property tests'
+. ./lib-git-svn.sh
+
+test_expect_success 'setup test repository' '
+	svn_cmd co "$svnrepo" s &&
+	(
+		cd s &&
+		mkdir qqq www xxx &&
+		echo test_qqq > qqq/test_qqq.txt &&
+		echo test_www > www/test_www.txt &&
+		echo test_xxx > xxx/test_xxx.txt &&
+		svn_cmd add qqq &&
+		svn_cmd add www &&
+		svn_cmd add xxx &&
+		svn_cmd commit -m "create some files" &&
+		svn_cmd up &&
+		echo hi >> www/test_www.txt &&
+		svn_cmd commit -m "modify www/test_www.txt" &&
+		svn_cmd up
+	)
+'
+
+test_expect_success 'clone an SVN repository with filter to include qqq directory' '
+	git svn clone --include-paths="qqq" "$svnrepo" g &&
+	echo test_qqq > expect &&
+	for i in g/*/*.txt; do cat $i >> expect2; done &&
+	test_cmp expect expect2
+'
+
+
+test_expect_success 'init+fetch an SVN repository with included qqq directory' '
+	git svn init "$svnrepo" c &&
+	( cd c && git svn fetch --include-paths="qqq" ) &&
+	rm expect2 &&
+	echo test_qqq > expect &&
+	for i in c/*/*.txt; do cat $i >> expect2; done &&
+	test_cmp expect expect2
+'
+
+test_expect_success 'verify include-paths config saved by clone' '
+	(
+	    cd g &&
+	    git config --get svn-remote.svn.include-paths | fgrep "qqq"
+	)
+'
+
+test_expect_success 'SVN-side change outside of www' '
+	(
+		cd s &&
+		echo b >> qqq/test_qqq.txt &&
+		svn_cmd commit -m "SVN-side change outside of www" &&
+		svn_cmd up &&
+		svn_cmd log -v | fgrep "SVN-side change outside of www"
+	)
+'
+
+test_expect_success 'update git svn-cloned repo (config include)' '
+	(
+		cd g &&
+		git svn rebase &&
+		printf "test_qqq\nb\n" > expect &&
+		for i in */*.txt; do cat $i >> expect2; done &&
+		test_cmp expect2 expect &&
+		rm expect expect2
+	)
+'
+
+test_expect_success 'update git svn-cloned repo (option include)' '
+	(
+		cd c &&
+		git svn rebase --include-paths="qqq" &&
+		printf "test_qqq\nb\n" > expect &&
+		for i in */*.txt; do cat $i >> expect2; done &&
+		test_cmp expect2 expect &&
+		rm expect expect2
+	)
+'
+
+test_expect_success 'SVN-side change inside of ignored www' '
+	(
+		cd s &&
+		echo zaq >> www/test_www.txt
+		svn_cmd commit -m "SVN-side change inside of www/test_www.txt" &&
+		svn_cmd up &&
+		svn_cmd log -v | fgrep "SVN-side change inside of www/test_www.txt"
+	)
+'
+
+test_expect_success 'update git svn-cloned repo (config include)' '
+	(
+		cd g &&
+		git svn rebase &&
+		printf "test_qqq\nb\n" > expect &&
+		for i in */*.txt; do cat $i >> expect2; done &&
+		test_cmp expect2 expect &&
+		rm expect expect2
+	)
+'
+
+test_expect_success 'update git svn-cloned repo (option include)' '
+	(
+		cd c &&
+		git svn rebase --include-paths="qqq" &&
+		printf "test_qqq\nb\n" > expect &&
+		for i in */*.txt; do cat $i >> expect2; done &&
+		test_cmp expect2 expect &&
+		rm expect expect2
+	)
+'
+
+test_expect_success 'SVN-side change in and out of included qqq' '
+	(
+		cd s &&
+		echo cvf >> www/test_www.txt
+		echo ygg >> qqq/test_qqq.txt
+		svn_cmd commit -m "SVN-side change in and out of ignored www" &&
+		svn_cmd up &&
+		svn_cmd log -v | fgrep "SVN-side change in and out of ignored www"
+	)
+'
+
+test_expect_success 'update git svn-cloned repo again (config include)' '
+	(
+		cd g &&
+		git svn rebase &&
+		printf "test_qqq\nb\nygg\n" > expect &&
+		for i in */*.txt; do cat $i >> expect2; done &&
+		test_cmp expect2 expect &&
+		rm expect expect2
+	)
+'
+
+test_expect_success 'update git svn-cloned repo again (option include)' '
+	(
+		cd c &&
+		git svn rebase --include-paths="qqq" &&
+		printf "test_qqq\nb\nygg\n" > expect &&
+		for i in */*.txt; do cat $i >> expect2; done &&
+		test_cmp expect2 expect &&
+		rm expect expect2
+	)
+'
+
+test_done
diff --git a/t/t9161-git-svn-mergeinfo-push.sh b/t/t9161-git-svn-mergeinfo-push.sh
index 6ef0c0b..1eab701 100755
--- a/t/t9161-git-svn-mergeinfo-push.sh
+++ b/t/t9161-git-svn-mergeinfo-push.sh
@@ -88,7 +88,6 @@
 	test "$mergeinfo" = "/branches/svnb1:2-4,7-9,13-18
 /branches/svnb2:3,8,16-17
 /branches/svnb3:4,9
-/branches/svnb4:5-6,10-12
 /branches/svnb5:6,11"
 	'
 
diff --git a/t/t9167-git-svn-cmd-branch-subproject.sh b/t/t9167-git-svn-cmd-branch-subproject.sh
new file mode 100755
index 0000000..53def87
--- /dev/null
+++ b/t/t9167-git-svn-cmd-branch-subproject.sh
@@ -0,0 +1,48 @@
+#!/bin/sh
+#
+# Copyright (c) 2013 Tobias Schulte
+#
+
+test_description='git svn branch for subproject clones'
+. ./lib-git-svn.sh
+
+test_expect_success 'initialize svnrepo' '
+	mkdir import &&
+	(
+		cd import &&
+		mkdir -p trunk/project branches tags &&
+		(
+			cd trunk/project &&
+			echo foo > foo
+		) &&
+		svn_cmd import -m "import for git-svn" . "$svnrepo" >/dev/null
+	) &&
+	rm -rf import &&
+	svn_cmd co "$svnrepo"/trunk/project trunk/project &&
+	(
+		cd trunk/project &&
+		echo bar >> foo &&
+		svn_cmd ci -m "updated trunk"
+	) &&
+	rm -rf trunk
+'
+
+test_expect_success 'import into git' '
+	git svn init --trunk=trunk/project --branches=branches/*/project \
+		--tags=tags/*/project "$svnrepo" &&
+	git svn fetch &&
+	git checkout remotes/trunk
+'
+
+test_expect_success 'git svn branch tests' '
+	test_must_fail git svn branch a &&
+	git svn branch --parents a &&
+	test_must_fail git svn branch -t tag1 &&
+	git svn branch --parents -t tag1 &&
+	test_must_fail git svn branch --tag tag2 &&
+	git svn branch --parents --tag tag2 &&
+	test_must_fail git svn tag tag3 &&
+	git svn tag --parents tag3
+'
+
+test_done
diff --git a/t/t9350-fast-export.sh b/t/t9350-fast-export.sh
index 2471bc6..34c2d8f 100755
--- a/t/t9350-fast-export.sh
+++ b/t/t9350-fast-export.sh
@@ -396,7 +396,7 @@
 test_expect_success 'tag-obj_tag'     'git fast-export tag-obj_tag'
 test_expect_success 'tag-obj_tag-obj' 'git fast-export tag-obj_tag-obj'
 
-test_expect_success SYMLINKS 'directory becomes symlink'        '
+test_expect_success 'directory becomes symlink'        '
 	git init dirtosymlink &&
 	git init result &&
 	(
@@ -408,8 +408,7 @@
 		git add foo/world bar/world &&
 		git commit -q -mone &&
 		git rm -r foo &&
-		ln -s bar foo &&
-		git add foo &&
+		test_ln_s_add bar foo &&
 		git commit -q -mtwo
 	) &&
 	(
diff --git a/t/t9402-git-cvsserver-refs.sh b/t/t9402-git-cvsserver-refs.sh
index 735a018..db69af2 100755
--- a/t/t9402-git-cvsserver-refs.sh
+++ b/t/t9402-git-cvsserver-refs.sh
@@ -330,7 +330,7 @@
 
 test_expect_success 'validate basic diffs saved during above cvswork2 edits' '
 	test $(grep Index: cvsEdit1.diff | wc -l) = 1 &&
-	test ! -s cvsEdit2-empty.diff &&
+	test_must_be_empty cvsEdit2-empty.diff &&
 	test $(grep Index: cvsEdit2-N.diff | wc -l) = 1 &&
 	test $(grep Index: cvsEdit3.diff | wc -l) = 3 &&
 	rm -rf diffSandbox &&
@@ -456,20 +456,20 @@
 
 test_expect_success 'cvs diff -r v1 -u' '
 	( cd cvswork && cvs -f diff -r v1 -u ) >cvsDiff.out 2>cvs.log &&
-	test ! -s cvsDiff.out &&
-	test ! -s cvs.log
+	test_must_be_empty cvsDiff.out &&
+	test_must_be_empty cvs.log
 '
 
 test_expect_success 'cvs diff -N -r v2 -u' '
 	( cd cvswork && ! cvs -f diff -N -r v2 -u ) >cvsDiff.out 2>cvs.log &&
-	test ! -s cvs.log &&
+	test_must_be_empty cvs.log &&
 	test -s cvsDiff.out &&
 	check_diff cvsDiff.out v2 v1 >check_diff.out 2>&1
 '
 
 test_expect_success 'cvs diff -N -r v2 -r v1.2' '
 	( cd cvswork && ! cvs -f diff -N -r v2 -r v1.2 -u ) >cvsDiff.out 2>cvs.log &&
-	test ! -s cvs.log &&
+	test_must_be_empty cvs.log &&
 	test -s cvsDiff.out &&
 	check_diff cvsDiff.out v2 v1.2 >check_diff.out 2>&1
 '
@@ -488,7 +488,7 @@
 
 test_expect_success 'check [cvswork3] diff' '
 	( cd cvswork3 && ! cvs -f diff -N -u ) >"$WORKDIR/cvsDiff.out" 2>cvs.log &&
-	test ! -s cvs.log &&
+	test_must_be_empty cvs.log &&
 	test -s cvsDiff.out &&
 	test $(grep Index: cvsDiff.out | wc -l) = 3 &&
 	test_cmp cvsDiff.out cvswork3edit.diff &&
diff --git a/t/t9500-gitweb-standalone-no-errors.sh b/t/t9500-gitweb-standalone-no-errors.sh
index 6783c14..6fca193 100755
--- a/t/t9500-gitweb-standalone-no-errors.sh
+++ b/t/t9500-gitweb-standalone-no-errors.sh
@@ -156,10 +156,10 @@
 	 git commit -a -m "File renamed." &&
 	 gitweb_run "p=.git;a=commitdiff"'
 
-test_expect_success SYMLINKS \
+test_expect_success \
 	'commitdiff(0): file to symlink' \
 	'rm renamed_file &&
-	 ln -s file renamed_file &&
+	 test_ln_s_add file renamed_file &&
 	 git commit -a -m "File to symlink." &&
 	 gitweb_run "p=.git;a=commitdiff"'
 
@@ -212,15 +212,14 @@
 # ----------------------------------------------------------------------
 # commitdiff testing (taken from t4114-apply-typechange.sh)
 
-test_expect_success SYMLINKS 'setup typechange commits' '
+test_expect_success 'setup typechange commits' '
 	echo "hello world" > foo &&
 	echo "hi planet" > bar &&
 	git update-index --add foo bar &&
 	git commit -m initial &&
 	git branch initial &&
 	rm -f foo &&
-	ln -s bar foo &&
-	git update-index foo &&
+	test_ln_s_add bar foo &&
 	git commit -m "foo symlinked to bar" &&
 	git branch foo-symlinked-to-bar &&
 	rm -f foo &&
@@ -361,11 +360,7 @@
 	 echo "Changed" >> 04-rename-to &&
 	 test_chmod +x 05-mode-change &&
 	 rm -f 06-file-or-symlink &&
-	 if test_have_prereq SYMLINKS; then
-		ln -s 01-change 06-file-or-symlink
-	 else
-		printf %s 01-change > 06-file-or-symlink
-	 fi &&
+	 test_ln_s_add 01-change 06-file-or-symlink &&
 	 echo "Changed and have mode changed" > 07-change-mode-change	&&
 	 test_chmod +x 07-change-mode-change &&
 	 git commit -a -m "Large commit" &&
diff --git a/t/t9801-git-p4-branch.sh b/t/t9801-git-p4-branch.sh
index 9730821..2bf142d 100755
--- a/t/t9801-git-p4-branch.sh
+++ b/t/t9801-git-p4-branch.sh
@@ -469,9 +469,11 @@
 		View: //depot/usecs/b1/... //depot/usecs/b3/...
 		EOF
 
-		echo b3/b3-file3 >b3/b3-file3 &&
-		p4 add b3/b3-file3 &&
-		p4 submit -d "b3/b3-file3"
+		echo b3/b3-file3_1 >b3/b3-file3_1 &&
+		echo b3/b3-file3_2 >b3/b3-file3_2 &&
+		p4 add b3/b3-file3_1 &&
+		p4 add b3/b3-file3_2 &&
+		p4 submit -d "b3/b3-file3_1 b3/b3-file3_2"
 	)
 '
 
@@ -487,6 +489,21 @@
 	)
 '
 
+test_expect_success 'use-client-spec detect-branches skips files in branches' '
+	client_view "//depot/usecs/... //client/..." \
+		    "-//depot/usecs/b3/b3-file3_1 //client/b3/b3-file3_1" &&
+	test_when_finished cleanup_git &&
+	test_create_repo "$git" &&
+	(
+		cd "$git" &&
+		git p4 sync --detect-branches --use-client-spec //depot/usecs@all &&
+		git checkout -b master p4/usecs/b3 &&
+		test_path_is_file b1-file1 &&
+		test_path_is_file b3-file3_2 &&
+		test_path_is_missing b3-file3_1
+	)
+'
+
 test_expect_success 'kill p4d' '
 	kill_p4d
 '
diff --git a/t/t9802-git-p4-filetype.sh b/t/t9802-git-p4-filetype.sh
index eeefa67..a82744b 100755
--- a/t/t9802-git-p4-filetype.sh
+++ b/t/t9802-git-p4-filetype.sh
@@ -28,7 +28,7 @@
 		test_cmp f-unix-orig f-unix &&
 
 		# make sure stored in repo as unix newlines
-		# use sed to eat python-appened newline
+		# use sed to eat python-appended newline
 		p4 -G print //depot/f-unix | marshal_dump data 2 |\
 		    sed \$d >f-unix-p4-print &&
 		test_cmp f-unix-orig f-unix-p4-print &&
@@ -95,7 +95,7 @@
 		git init &&
 		echo "* eol=lf" >.gitattributes &&
 		git p4 sync //depot@all &&
-		git checkout master &&
+		git checkout -b master p4/master &&
 		test_cmp "$cli"/f-unix-orig f-unix &&
 		test_cmp "$cli"/f-win-as-lf f-win
 	)
@@ -109,7 +109,7 @@
 		git init &&
 		echo "* eol=crlf" >.gitattributes &&
 		git p4 sync //depot@all &&
-		git checkout master &&
+		git checkout -b master p4/master &&
 		test_cmp "$cli"/f-unix-as-crlf f-unix &&
 		test_cmp "$cli"/f-win-orig f-win
 	)
diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
index 6d9d141..2d4beb5 100755
--- a/t/t9902-completion.sh
+++ b/t/t9902-completion.sh
@@ -69,7 +69,7 @@
 	local -a COMPREPLY _words
 	local _cword
 	_words=( $1 )
-	test "${1: -1}" == ' ' && _words+=('')
+	test "${1: -1}" = ' ' && _words[${#_words[@]}+1]=''
 	(( _cword = ${#_words[@]} - 1 ))
 	__git_wrap__git_main && print_comp
 }
@@ -122,6 +122,140 @@
 
 invalid_variable_name='${foo.bar}'
 
+actual="$TRASH_DIRECTORY/actual"
+
+test_expect_success 'setup for __gitdir tests' '
+	mkdir -p subdir/subsubdir &&
+	git init otherrepo
+'
+
+test_expect_success '__gitdir - from command line (through $__git_dir)' '
+	echo "$TRASH_DIRECTORY/otherrepo/.git" >expected &&
+	(
+		__git_dir="$TRASH_DIRECTORY/otherrepo/.git" &&
+		__gitdir >"$actual"
+	) &&
+	test_cmp expected "$actual"
+'
+
+test_expect_success '__gitdir - repo as argument' '
+	echo "otherrepo/.git" >expected &&
+	__gitdir "otherrepo" >"$actual" &&
+	test_cmp expected "$actual"
+'
+
+test_expect_success '__gitdir - remote as argument' '
+	echo "remote" >expected &&
+	__gitdir "remote" >"$actual" &&
+	test_cmp expected "$actual"
+'
+
+test_expect_success '__gitdir - .git directory in cwd' '
+	echo ".git" >expected &&
+	__gitdir >"$actual" &&
+	test_cmp expected "$actual"
+'
+
+test_expect_success '__gitdir - .git directory in parent' '
+	echo "$(pwd -P)/.git" >expected &&
+	(
+		cd subdir/subsubdir &&
+		__gitdir >"$actual"
+	) &&
+	test_cmp expected "$actual"
+'
+
+test_expect_success '__gitdir - cwd is a .git directory' '
+	echo "." >expected &&
+	(
+		cd .git &&
+		__gitdir >"$actual"
+	) &&
+	test_cmp expected "$actual"
+'
+
+test_expect_success '__gitdir - parent is a .git directory' '
+	echo "$(pwd -P)/.git" >expected &&
+	(
+		cd .git/refs/heads &&
+		__gitdir >"$actual"
+	) &&
+	test_cmp expected "$actual"
+'
+
+test_expect_success '__gitdir - $GIT_DIR set while .git directory in cwd' '
+	echo "$TRASH_DIRECTORY/otherrepo/.git" >expected &&
+	(
+		GIT_DIR="$TRASH_DIRECTORY/otherrepo/.git" &&
+		export GIT_DIR &&
+		__gitdir >"$actual"
+	) &&
+	test_cmp expected "$actual"
+'
+
+test_expect_success '__gitdir - $GIT_DIR set while .git directory in parent' '
+	echo "$TRASH_DIRECTORY/otherrepo/.git" >expected &&
+	(
+		GIT_DIR="$TRASH_DIRECTORY/otherrepo/.git" &&
+		export GIT_DIR &&
+		cd subdir &&
+		__gitdir >"$actual"
+	) &&
+	test_cmp expected "$actual"
+'
+
+test_expect_success '__gitdir - non-existing $GIT_DIR' '
+	(
+		GIT_DIR="$TRASH_DIRECTORY/non-existing" &&
+		export GIT_DIR &&
+		test_must_fail __gitdir
+	)
+'
+
+test_expect_success '__gitdir - gitfile in cwd' '
+	echo "$(pwd -P)/otherrepo/.git" >expected &&
+	echo "gitdir: $TRASH_DIRECTORY/otherrepo/.git" >subdir/.git &&
+	test_when_finished "rm -f subdir/.git" &&
+	(
+		cd subdir &&
+		__gitdir >"$actual"
+	) &&
+	test_cmp expected "$actual"
+'
+
+test_expect_success '__gitdir - gitfile in parent' '
+	echo "$(pwd -P)/otherrepo/.git" >expected &&
+	echo "gitdir: $TRASH_DIRECTORY/otherrepo/.git" >subdir/.git &&
+	test_when_finished "rm -f subdir/.git" &&
+	(
+		cd subdir/subsubdir &&
+		__gitdir >"$actual"
+	) &&
+	test_cmp expected "$actual"
+'
+
+test_expect_success SYMLINKS '__gitdir - resulting path avoids symlinks' '
+	echo "$(pwd -P)/otherrepo/.git" >expected &&
+	mkdir otherrepo/dir &&
+	test_when_finished "rm -rf otherrepo/dir" &&
+	ln -s otherrepo/dir link &&
+	test_when_finished "rm -f link" &&
+	(
+		cd link &&
+		__gitdir >"$actual"
+	) &&
+	test_cmp expected "$actual"
+'
+
+test_expect_success '__gitdir - not a git repository' '
+	(
+		cd subdir/subsubdir &&
+		GIT_CEILING_DIRECTORIES="$TRASH_DIRECTORY" &&
+		export GIT_CEILING_DIRECTORIES &&
+		test_must_fail __gitdir
+	)
+'
+
 test_expect_success '__gitcomp - trailing space - options' '
 	test_gitcomp "--re" "--dry-run --reuse-message= --reedit-message=
 		--reset-author" <<-EOF
@@ -231,6 +365,7 @@
 	--exec-path Z
 	--exec-path=
 	--html-path Z
+	--man-path Z
 	--info-path Z
 	--work-tree=
 	--namespace=
@@ -347,4 +482,81 @@
 	test_completion "git send-email ma" "master "
 '
 
+test_expect_success 'complete files' '
+	git init tmp && cd tmp &&
+	test_when_finished "cd .. && rm -rf tmp" &&
+
+	echo "expected" > .gitignore &&
+	echo "out" >> .gitignore &&
+
+	git add .gitignore &&
+	test_completion "git commit " ".gitignore" &&
+
+	git commit -m ignore &&
+
+	touch new &&
+	test_completion "git add " "new" &&
+
+	git add new &&
+	git commit -a -m new &&
+	test_completion "git add " "" &&
+
+	git mv new modified &&
+	echo modify > modified &&
+	test_completion "git add " "modified" &&
+
+	touch untracked &&
+
+	: TODO .gitignore should not be here &&
+	test_completion "git rm " <<-\EOF &&
+	.gitignore
+	modified
+	EOF
+
+	test_completion "git clean " "untracked" &&
+
+	: TODO .gitignore should not be here &&
+	test_completion "git mv " <<-\EOF &&
+	.gitignore
+	modified
+	EOF
+
+	mkdir dir &&
+	touch dir/file-in-dir &&
+	git add dir/file-in-dir &&
+	git commit -m dir &&
+
+	mkdir untracked-dir &&
+
+	: TODO .gitignore should not be here &&
+	test_completion "git mv modified " <<-\EOF &&
+	.gitignore
+	dir
+	modified
+	untracked
+	untracked-dir
+	EOF
+
+	test_completion "git commit " "modified" &&
+
+	: TODO .gitignore should not be here &&
+	test_completion "git ls-files " <<-\EOF
+	.gitignore
+	dir
+	modified
+	EOF
+
+	touch momified &&
+	test_completion "git add mom" "momified"
+'
+
+test_expect_failure 'complete with tilde expansion' '
+	git init tmp && cd tmp &&
+	test_when_finished "cd .. && rm -rf tmp" &&
+
+	touch ~/tmp/file &&
+
+	test_completion "git add ~/tmp/" "~/tmp/file"
+'
+
 test_done
diff --git a/t/t9903-bash-prompt.sh b/t/t9903-bash-prompt.sh
index 083b319..3c3e4e8 100755
--- a/t/t9903-bash-prompt.sh
+++ b/t/t9903-bash-prompt.sh
@@ -10,528 +10,558 @@
 . "$GIT_BUILD_DIR/contrib/completion/git-prompt.sh"
 
 actual="$TRASH_DIRECTORY/actual"
+c_red='\\[\\e[31m\\]'
+c_green='\\[\\e[32m\\]'
+c_lblue='\\[\\e[1;34m\\]'
+c_clear='\\[\\e[0m\\]'
 
 test_expect_success 'setup for prompt tests' '
-	mkdir -p subdir/subsubdir &&
 	git init otherrepo &&
-	echo 1 > file &&
+	echo 1 >file &&
 	git add file &&
 	test_tick &&
 	git commit -m initial &&
 	git tag -a -m msg1 t1 &&
 	git checkout -b b1 &&
-	echo 2 > file &&
+	echo 2 >file &&
 	git commit -m "second b1" file &&
-	echo 3 > file &&
+	echo 3 >file &&
 	git commit -m "third b1" file &&
 	git tag -a -m msg2 t2 &&
 	git checkout -b b2 master &&
-	echo 0 > file &&
+	echo 0 >file &&
 	git commit -m "second b2" file &&
-	echo 00 > file &&
+	echo 00 >file &&
 	git commit -m "another b2" file &&
-	echo 000 > file &&
+	echo 000 >file &&
 	git commit -m "yet another b2" file &&
 	git checkout master
 '
 
-test_expect_success 'gitdir - from command line (through $__git_dir)' '
-	echo "$TRASH_DIRECTORY/otherrepo/.git" > expected &&
-	(
-		__git_dir="$TRASH_DIRECTORY/otherrepo/.git" &&
-		__gitdir > "$actual"
-	) &&
-	test_cmp expected "$actual"
-'
-
-test_expect_success 'gitdir - repo as argument' '
-	echo "otherrepo/.git" > expected &&
-	__gitdir "otherrepo" > "$actual" &&
-	test_cmp expected "$actual"
-'
-
-test_expect_success 'gitdir - remote as argument' '
-	echo "remote" > expected &&
-	__gitdir "remote" > "$actual" &&
-	test_cmp expected "$actual"
-'
-
-test_expect_success 'gitdir - .git directory in cwd' '
-	echo ".git" > expected &&
-	__gitdir > "$actual" &&
-	test_cmp expected "$actual"
-'
-
-test_expect_success 'gitdir - .git directory in parent' '
-	echo "$(pwd -P)/.git" > expected &&
-	(
-		cd subdir/subsubdir &&
-		__gitdir > "$actual"
-	) &&
-	test_cmp expected "$actual"
-'
-
-test_expect_success 'gitdir - cwd is a .git directory' '
-	echo "." > expected &&
-	(
-		cd .git &&
-		__gitdir > "$actual"
-	) &&
-	test_cmp expected "$actual"
-'
-
-test_expect_success 'gitdir - parent is a .git directory' '
-	echo "$(pwd -P)/.git" > expected &&
-	(
-		cd .git/refs/heads &&
-		__gitdir > "$actual"
-	) &&
-	test_cmp expected "$actual"
-'
-
-test_expect_success 'gitdir - $GIT_DIR set while .git directory in cwd' '
-	echo "$TRASH_DIRECTORY/otherrepo/.git" > expected &&
-	(
-		GIT_DIR="$TRASH_DIRECTORY/otherrepo/.git" &&
-		export GIT_DIR &&
-		__gitdir > "$actual"
-	) &&
-	test_cmp expected "$actual"
-'
-
-test_expect_success 'gitdir - $GIT_DIR set while .git directory in parent' '
-	echo "$TRASH_DIRECTORY/otherrepo/.git" > expected &&
-	(
-		GIT_DIR="$TRASH_DIRECTORY/otherrepo/.git" &&
-		export GIT_DIR &&
-		cd subdir &&
-		__gitdir > "$actual"
-	) &&
-	test_cmp expected "$actual"
-'
-
-test_expect_success 'gitdir - non-existing $GIT_DIR' '
-	(
-		GIT_DIR="$TRASH_DIRECTORY/non-existing" &&
-		export GIT_DIR &&
-		test_must_fail __gitdir
-	)
-'
-
-test_expect_success 'gitdir - gitfile in cwd' '
-	echo "$(pwd -P)/otherrepo/.git" > expected &&
-	echo "gitdir: $TRASH_DIRECTORY/otherrepo/.git" > subdir/.git &&
-	test_when_finished "rm -f subdir/.git" &&
-	(
-		cd subdir &&
-		__gitdir > "$actual"
-	) &&
-	test_cmp expected "$actual"
-'
-
-test_expect_success 'gitdir - gitfile in parent' '
-	echo "$(pwd -P)/otherrepo/.git" > expected &&
-	echo "gitdir: $TRASH_DIRECTORY/otherrepo/.git" > subdir/.git &&
-	test_when_finished "rm -f subdir/.git" &&
-	(
-		cd subdir/subsubdir &&
-		__gitdir > "$actual"
-	) &&
-	test_cmp expected "$actual"
-'
-
-test_expect_success SYMLINKS 'gitdir - resulting path avoids symlinks' '
-	echo "$(pwd -P)/otherrepo/.git" > expected &&
-	mkdir otherrepo/dir &&
-	test_when_finished "rm -rf otherrepo/dir" &&
-	ln -s otherrepo/dir link &&
-	test_when_finished "rm -f link" &&
-	(
-		cd link &&
-		__gitdir > "$actual"
-	) &&
-	test_cmp expected "$actual"
-'
-
-test_expect_success 'gitdir - not a git repository' '
-	(
-		cd subdir/subsubdir &&
-		GIT_CEILING_DIRECTORIES="$TRASH_DIRECTORY" &&
-		export GIT_CEILING_DIRECTORIES &&
-		test_must_fail __gitdir
-	)
-'
-
 test_expect_success 'prompt - branch name' '
-	printf " (master)" > expected &&
-	__git_ps1 > "$actual" &&
+	printf " (master)" >expected &&
+	__git_ps1 >"$actual" &&
+	test_cmp expected "$actual"
+'
+
+test_expect_success SYMLINKS 'prompt - branch name - symlink symref' '
+	printf " (master)" >expected &&
+	test_when_finished "git checkout master" &&
+	test_config core.preferSymlinkRefs true &&
+	git checkout master &&
+	__git_ps1 >"$actual" &&
+	test_cmp expected "$actual"
+'
+
+test_expect_success 'prompt - unborn branch' '
+	printf " (unborn)" >expected &&
+	git checkout --orphan unborn &&
+	test_when_finished "git checkout master" &&
+	__git_ps1 >"$actual" &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - detached head' '
-	printf " ((%s...))" $(git log -1 --format="%h" b1^) > expected &&
+	printf " ((%s...))" $(git log -1 --format="%h" --abbrev=13 b1^) >expected &&
+	test_config core.abbrev 13 &&
 	git checkout b1^ &&
 	test_when_finished "git checkout master" &&
-	__git_ps1 > "$actual" &&
+	__git_ps1 >"$actual" &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - describe detached head - contains' '
-	printf " ((t2~1))" > expected &&
+	printf " ((t2~1))" >expected &&
 	git checkout b1^ &&
 	test_when_finished "git checkout master" &&
 	(
 		GIT_PS1_DESCRIBE_STYLE=contains &&
-		__git_ps1 > "$actual"
+		__git_ps1 >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - describe detached head - branch' '
-	printf " ((b1~1))" > expected &&
+	printf " ((b1~1))" >expected &&
 	git checkout b1^ &&
 	test_when_finished "git checkout master" &&
 	(
 		GIT_PS1_DESCRIBE_STYLE=branch &&
-		__git_ps1 > "$actual"
+		__git_ps1 >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - describe detached head - describe' '
-	printf " ((t1-1-g%s))" $(git log -1 --format="%h" b1^) > expected &&
+	printf " ((t1-1-g%s))" $(git log -1 --format="%h" b1^) >expected &&
 	git checkout b1^ &&
 	test_when_finished "git checkout master" &&
 	(
 		GIT_PS1_DESCRIBE_STYLE=describe &&
-		__git_ps1 > "$actual"
+		__git_ps1 >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - describe detached head - default' '
-	printf " ((t2))" > expected &&
+	printf " ((t2))" >expected &&
 	git checkout --detach b1 &&
 	test_when_finished "git checkout master" &&
-	__git_ps1 > "$actual" &&
+	__git_ps1 >"$actual" &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - inside .git directory' '
-	printf " (GIT_DIR!)" > expected &&
+	printf " (GIT_DIR!)" >expected &&
 	(
 		cd .git &&
-		__git_ps1 > "$actual"
+		__git_ps1 >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - deep inside .git directory' '
-	printf " (GIT_DIR!)" > expected &&
+	printf " (GIT_DIR!)" >expected &&
 	(
 		cd .git/refs/heads &&
-		__git_ps1 > "$actual"
+		__git_ps1 >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - inside bare repository' '
-	printf " (BARE:master)" > expected &&
+	printf " (BARE:master)" >expected &&
 	git init --bare bare.git &&
 	test_when_finished "rm -rf bare.git" &&
 	(
 		cd bare.git &&
-		__git_ps1 > "$actual"
+		__git_ps1 >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - interactive rebase' '
-	printf " (b1|REBASE-i 2/3)" > expected
-	echo "#!$SHELL_PATH" >fake_editor.sh &&
-	cat >>fake_editor.sh <<\EOF &&
-echo "exec echo" > "$1"
-echo "edit $(git log -1 --format="%h")" >> "$1"
-echo "exec echo" >> "$1"
-EOF
+	printf " (b1|REBASE-i 2/3)" >expected
+	write_script fake_editor.sh <<-\EOF &&
+		echo "exec echo" >"$1"
+		echo "edit $(git log -1 --format="%h")" >>"$1"
+		echo "exec echo" >>"$1"
+	EOF
 	test_when_finished "rm -f fake_editor.sh" &&
-	chmod a+x fake_editor.sh &&
 	test_set_editor "$TRASH_DIRECTORY/fake_editor.sh" &&
 	git checkout b1 &&
 	test_when_finished "git checkout master" &&
 	git rebase -i HEAD^ &&
 	test_when_finished "git rebase --abort"
-	__git_ps1 > "$actual" &&
+	__git_ps1 >"$actual" &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - rebase merge' '
-	printf " (b2|REBASE-m 1/3)" > expected &&
+	printf " (b2|REBASE-m 1/3)" >expected &&
 	git checkout b2 &&
 	test_when_finished "git checkout master" &&
 	test_must_fail git rebase --merge b1 b2 &&
 	test_when_finished "git rebase --abort" &&
-	__git_ps1 > "$actual" &&
+	__git_ps1 >"$actual" &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - rebase' '
-	printf " ((t2)|REBASE 1/3)" > expected &&
+	printf " (b2|REBASE 1/3)" >expected &&
 	git checkout b2 &&
 	test_when_finished "git checkout master" &&
 	test_must_fail git rebase b1 b2 &&
 	test_when_finished "git rebase --abort" &&
-	__git_ps1 > "$actual" &&
+	__git_ps1 >"$actual" &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - merge' '
-	printf " (b1|MERGING)" > expected &&
+	printf " (b1|MERGING)" >expected &&
 	git checkout b1 &&
 	test_when_finished "git checkout master" &&
 	test_must_fail git merge b2 &&
 	test_when_finished "git reset --hard" &&
-	__git_ps1 > "$actual" &&
+	__git_ps1 >"$actual" &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - cherry-pick' '
-	printf " (master|CHERRY-PICKING)" > expected &&
+	printf " (master|CHERRY-PICKING)" >expected &&
 	test_must_fail git cherry-pick b1 &&
 	test_when_finished "git reset --hard" &&
-	__git_ps1 > "$actual" &&
+	__git_ps1 >"$actual" &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - bisect' '
-	printf " (master|BISECTING)" > expected &&
+	printf " (master|BISECTING)" >expected &&
 	git bisect start &&
 	test_when_finished "git bisect reset" &&
-	__git_ps1 > "$actual" &&
+	__git_ps1 >"$actual" &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - dirty status indicator - clean' '
-	printf " (master)" > expected &&
+	printf " (master)" >expected &&
 	(
 		GIT_PS1_SHOWDIRTYSTATE=y &&
-		__git_ps1 > "$actual"
+		__git_ps1 >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - dirty status indicator - dirty worktree' '
-	printf " (master *)" > expected &&
-	echo "dirty" > file &&
+	printf " (master *)" >expected &&
+	echo "dirty" >file &&
 	test_when_finished "git reset --hard" &&
 	(
 		GIT_PS1_SHOWDIRTYSTATE=y &&
-		__git_ps1 > "$actual"
+		__git_ps1 >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - dirty status indicator - dirty index' '
-	printf " (master +)" > expected &&
-	echo "dirty" > file &&
+	printf " (master +)" >expected &&
+	echo "dirty" >file &&
 	test_when_finished "git reset --hard" &&
 	git add -u &&
 	(
 		GIT_PS1_SHOWDIRTYSTATE=y &&
-		__git_ps1 > "$actual"
+		__git_ps1 >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - dirty status indicator - dirty index and worktree' '
-	printf " (master *+)" > expected &&
-	echo "dirty index" > file &&
+	printf " (master *+)" >expected &&
+	echo "dirty index" >file &&
 	test_when_finished "git reset --hard" &&
 	git add -u &&
-	echo "dirty worktree" > file &&
+	echo "dirty worktree" >file &&
 	(
 		GIT_PS1_SHOWDIRTYSTATE=y &&
-		__git_ps1 > "$actual"
+		__git_ps1 >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - dirty status indicator - before root commit' '
-	printf " (master #)" > expected &&
+	printf " (master #)" >expected &&
 	(
 		GIT_PS1_SHOWDIRTYSTATE=y &&
 		cd otherrepo &&
-		__git_ps1 > "$actual"
+		__git_ps1 >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - dirty status indicator - shell variable unset with config disabled' '
-	printf " (master)" > expected &&
-	echo "dirty" > file &&
+	printf " (master)" >expected &&
+	echo "dirty" >file &&
 	test_when_finished "git reset --hard" &&
 	test_config bash.showDirtyState false &&
 	(
 		sane_unset GIT_PS1_SHOWDIRTYSTATE &&
-		__git_ps1 > "$actual"
+		__git_ps1 >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - dirty status indicator - shell variable unset with config enabled' '
-	printf " (master)" > expected &&
-	echo "dirty" > file &&
+	printf " (master)" >expected &&
+	echo "dirty" >file &&
 	test_when_finished "git reset --hard" &&
 	test_config bash.showDirtyState true &&
 	(
 		sane_unset GIT_PS1_SHOWDIRTYSTATE &&
-		__git_ps1 > "$actual"
+		__git_ps1 >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - dirty status indicator - shell variable set with config disabled' '
-	printf " (master)" > expected &&
-	echo "dirty" > file &&
+	printf " (master)" >expected &&
+	echo "dirty" >file &&
 	test_when_finished "git reset --hard" &&
 	test_config bash.showDirtyState false &&
 	(
 		GIT_PS1_SHOWDIRTYSTATE=y &&
-		__git_ps1 > "$actual"
+		__git_ps1 >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - dirty status indicator - shell variable set with config enabled' '
-	printf " (master *)" > expected &&
-	echo "dirty" > file &&
+	printf " (master *)" >expected &&
+	echo "dirty" >file &&
 	test_when_finished "git reset --hard" &&
 	test_config bash.showDirtyState true &&
 	(
 		GIT_PS1_SHOWDIRTYSTATE=y &&
-		__git_ps1 > "$actual"
+		__git_ps1 >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - dirty status indicator - not shown inside .git directory' '
-	printf " (GIT_DIR!)" > expected &&
-	echo "dirty" > file &&
+	printf " (GIT_DIR!)" >expected &&
+	echo "dirty" >file &&
 	test_when_finished "git reset --hard" &&
 	(
 		GIT_PS1_SHOWDIRTYSTATE=y &&
 		cd .git &&
-		__git_ps1 > "$actual"
+		__git_ps1 >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - stash status indicator - no stash' '
-	printf " (master)" > expected &&
+	printf " (master)" >expected &&
 	(
 		GIT_PS1_SHOWSTASHSTATE=y &&
-		__git_ps1 > "$actual"
+		__git_ps1 >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - stash status indicator - stash' '
-	printf " (master $)" > expected &&
+	printf " (master $)" >expected &&
 	echo 2 >file &&
 	git stash &&
 	test_when_finished "git stash drop" &&
+	git pack-refs --all &&
 	(
 		GIT_PS1_SHOWSTASHSTATE=y &&
-		__git_ps1 > "$actual"
+		__git_ps1 >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - stash status indicator - not shown inside .git directory' '
-	printf " (GIT_DIR!)" > expected &&
+	printf " (GIT_DIR!)" >expected &&
 	echo 2 >file &&
 	git stash &&
 	test_when_finished "git stash drop" &&
 	(
 		GIT_PS1_SHOWSTASHSTATE=y &&
 		cd .git &&
-		__git_ps1 > "$actual"
+		__git_ps1 >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - untracked files status indicator - no untracked files' '
-	printf " (master)" > expected &&
+	printf " (master)" >expected &&
 	(
 		GIT_PS1_SHOWUNTRACKEDFILES=y &&
 		cd otherrepo &&
-		__git_ps1 > "$actual"
+		__git_ps1 >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - untracked files status indicator - untracked files' '
-	printf " (master %%)" > expected &&
+	printf " (master %%)" >expected &&
 	(
 		GIT_PS1_SHOWUNTRACKEDFILES=y &&
-		__git_ps1 > "$actual"
+		__git_ps1 >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - untracked files status indicator - shell variable unset with config disabled' '
-	printf " (master)" > expected &&
+	printf " (master)" >expected &&
 	test_config bash.showUntrackedFiles false &&
 	(
 		sane_unset GIT_PS1_SHOWUNTRACKEDFILES &&
-		__git_ps1 > "$actual"
+		__git_ps1 >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - untracked files status indicator - shell variable unset with config enabled' '
-	printf " (master)" > expected &&
+	printf " (master)" >expected &&
 	test_config bash.showUntrackedFiles true &&
 	(
 		sane_unset GIT_PS1_SHOWUNTRACKEDFILES &&
-		__git_ps1 > "$actual"
+		__git_ps1 >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - untracked files status indicator - shell variable set with config disabled' '
-	printf " (master)" > expected &&
+	printf " (master)" >expected &&
 	test_config bash.showUntrackedFiles false &&
 	(
 		GIT_PS1_SHOWUNTRACKEDFILES=y &&
-		__git_ps1 > "$actual"
+		__git_ps1 >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - untracked files status indicator - shell variable set with config enabled' '
-	printf " (master %%)" > expected &&
+	printf " (master %%)" >expected &&
 	test_config bash.showUntrackedFiles true &&
 	(
 		GIT_PS1_SHOWUNTRACKEDFILES=y &&
-		__git_ps1 > "$actual"
+		__git_ps1 >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - untracked files status indicator - not shown inside .git directory' '
-	printf " (GIT_DIR!)" > expected &&
+	printf " (GIT_DIR!)" >expected &&
 	(
 		GIT_PS1_SHOWUNTRACKEDFILES=y &&
 		cd .git &&
-		__git_ps1 > "$actual"
+		__git_ps1 >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
 
 test_expect_success 'prompt - format string starting with dash' '
-	printf -- "-master" > expected &&
-	__git_ps1 "-%s" > "$actual" &&
+	printf -- "-master" >expected &&
+	__git_ps1 "-%s" >"$actual" &&
+	test_cmp expected "$actual"
+'
+
+test_expect_success 'prompt - pc mode' '
+	printf "BEFORE: (master):AFTER" >expected &&
+	printf "" >expected_output &&
+	(
+		__git_ps1 "BEFORE:" ":AFTER" >"$actual" &&
+		test_cmp expected_output "$actual" &&
+		printf "%s" "$PS1" >"$actual"
+	) &&
+	test_cmp expected "$actual"
+'
+
+test_expect_success 'prompt - bash color pc mode - branch name' '
+	printf "BEFORE: (${c_green}master${c_clear}):AFTER" >expected &&
+	(
+		GIT_PS1_SHOWCOLORHINTS=y &&
+		__git_ps1 "BEFORE:" ":AFTER" >"$actual"
+		printf "%s" "$PS1" >"$actual"
+	) &&
+	test_cmp expected "$actual"
+'
+
+test_expect_success 'prompt - bash color pc mode - detached head' '
+	printf "BEFORE: (${c_red}(%s...)${c_clear}):AFTER" $(git log -1 --format="%h" b1^) >expected &&
+	git checkout b1^ &&
+	test_when_finished "git checkout master" &&
+	(
+		GIT_PS1_SHOWCOLORHINTS=y &&
+		__git_ps1 "BEFORE:" ":AFTER" &&
+		printf "%s" "$PS1" >"$actual"
+	) &&
+	test_cmp expected "$actual"
+'
+
+test_expect_success 'prompt - bash color pc mode - dirty status indicator - dirty worktree' '
+	printf "BEFORE: (${c_green}master${c_clear} ${c_red}*${c_clear}):AFTER" >expected &&
+	echo "dirty" >file &&
+	test_when_finished "git reset --hard" &&
+	(
+		GIT_PS1_SHOWDIRTYSTATE=y &&
+		GIT_PS1_SHOWCOLORHINTS=y &&
+		__git_ps1 "BEFORE:" ":AFTER" &&
+		printf "%s" "$PS1" >"$actual"
+	) &&
+	test_cmp expected "$actual"
+'
+
+test_expect_success 'prompt - bash color pc mode - dirty status indicator - dirty index' '
+	printf "BEFORE: (${c_green}master${c_clear} ${c_green}+${c_clear}):AFTER" >expected &&
+	echo "dirty" >file &&
+	test_when_finished "git reset --hard" &&
+	git add -u &&
+	(
+		GIT_PS1_SHOWDIRTYSTATE=y &&
+		GIT_PS1_SHOWCOLORHINTS=y &&
+		__git_ps1 "BEFORE:" ":AFTER" &&
+		printf "%s" "$PS1" >"$actual"
+	) &&
+	test_cmp expected "$actual"
+'
+
+test_expect_success 'prompt - bash color pc mode - dirty status indicator - dirty index and worktree' '
+	printf "BEFORE: (${c_green}master${c_clear} ${c_red}*${c_green}+${c_clear}):AFTER" >expected &&
+	echo "dirty index" >file &&
+	test_when_finished "git reset --hard" &&
+	git add -u &&
+	echo "dirty worktree" >file &&
+	(
+		GIT_PS1_SHOWCOLORHINTS=y &&
+		GIT_PS1_SHOWDIRTYSTATE=y &&
+		__git_ps1 "BEFORE:" ":AFTER" &&
+		printf "%s" "$PS1" >"$actual"
+	) &&
+	test_cmp expected "$actual"
+'
+
+test_expect_success 'prompt - bash color pc mode - dirty status indicator - before root commit' '
+	printf "BEFORE: (${c_green}master${c_clear} ${c_green}#${c_clear}):AFTER" >expected &&
+	(
+		GIT_PS1_SHOWDIRTYSTATE=y &&
+		GIT_PS1_SHOWCOLORHINTS=y &&
+		cd otherrepo &&
+		__git_ps1 "BEFORE:" ":AFTER" &&
+		printf "%s" "$PS1" >"$actual"
+	) &&
+	test_cmp expected "$actual"
+'
+
+test_expect_success 'prompt - bash color pc mode - inside .git directory' '
+	printf "BEFORE: (${c_green}GIT_DIR!${c_clear}):AFTER" >expected &&
+	echo "dirty" >file &&
+	test_when_finished "git reset --hard" &&
+	(
+		GIT_PS1_SHOWDIRTYSTATE=y &&
+		GIT_PS1_SHOWCOLORHINTS=y &&
+		cd .git &&
+		__git_ps1 "BEFORE:" ":AFTER" &&
+		printf "%s" "$PS1" >"$actual"
+	) &&
+	test_cmp expected "$actual"
+'
+
+test_expect_success 'prompt - bash color pc mode - stash status indicator' '
+	printf "BEFORE: (${c_green}master${c_clear} ${c_lblue}\$${c_clear}):AFTER" >expected &&
+	echo 2 >file &&
+	git stash &&
+	test_when_finished "git stash drop" &&
+	(
+		GIT_PS1_SHOWSTASHSTATE=y &&
+		GIT_PS1_SHOWCOLORHINTS=y &&
+		__git_ps1 "BEFORE:" ":AFTER" &&
+		printf "%s" "$PS1" >"$actual"
+	) &&
+	test_cmp expected "$actual"
+'
+
+test_expect_success 'prompt - bash color pc mode - untracked files status indicator' '
+	printf "BEFORE: (${c_green}master${c_clear} ${c_red}%%${c_clear}):AFTER" >expected &&
+	(
+		GIT_PS1_SHOWUNTRACKEDFILES=y &&
+		GIT_PS1_SHOWCOLORHINTS=y &&
+		__git_ps1 "BEFORE:" ":AFTER" &&
+		printf "%s" "$PS1" >"$actual"
+	) &&
+	test_cmp expected "$actual"
+'
+
+test_expect_success 'prompt - zsh color pc mode' '
+	printf "BEFORE: (%%F{green}master%%f):AFTER" >expected &&
+	(
+		ZSH_VERSION=5.0.0 &&
+		GIT_PS1_SHOWCOLORHINTS=y &&
+		__git_ps1 "BEFORE:" ":AFTER" >"$actual"
+		printf "%s" "$PS1" >"$actual"
+	) &&
 	test_cmp expected "$actual"
 '
 
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index 5251009..a7e9aac 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -343,6 +343,7 @@
 }
 
 test_expect_failure () {
+	test_start_
 	test "$#" = 3 && { test_prereq=$1; shift; } || test_prereq=
 	test "$#" = 2 ||
 	error "bug in the test script: not 2 or 3 parameters to test-expect-failure"
@@ -357,10 +358,11 @@
 			test_known_broken_failure_ "$1"
 		fi
 	fi
-	echo >&3 ""
+	test_finish_
 }
 
 test_expect_success () {
+	test_start_
 	test "$#" = 3 && { test_prereq=$1; shift; } || test_prereq=
 	test "$#" = 2 ||
 	error "bug in the test script: not 2 or 3 parameters to test-expect-success"
@@ -375,7 +377,7 @@
 			test_failure_ "$@"
 		fi
 	fi
-	echo >&3 ""
+	test_finish_
 }
 
 # test_external runs external test scripts that provide continuous
@@ -609,6 +611,18 @@
 	$GIT_TEST_CMP "$@"
 }
 
+# Check if the file expected to be empty is indeed empty, and barfs
+# otherwise.
+
+test_must_be_empty () {
+	if test -s "$1"
+	then
+		echo "'$1' is not empty, it contains:"
+		cat "$1"
+		return 1
+	fi
+}
+
 # Tests that its two parameters refer to the same revision
 test_cmp_rev () {
 	git rev-parse --verify "$1" >expect.rev &&
@@ -679,3 +693,20 @@
 		mv .git/hooks .git/hooks-disabled
 	) || exit
 }
+
+# This function helps on symlink challenged file systems when it is not
+# important that the file system entry is a symbolic link.
+# Use test_ln_s_add instead of "ln -s x y && git add y" to add a
+# symbolic link entry y to the index.
+
+test_ln_s_add () {
+	if test_have_prereq SYMLINKS
+	then
+		ln -s "$1" "$2" &&
+		git update-index --add "$2"
+	else
+		printf '%s' "$1" >"$2" &&
+		ln_s_obj=$(git hash-object -w "$2") &&
+		git update-index --add --cacheinfo 120000 $ln_s_obj "$2"
+	fi
+}
diff --git a/t/test-lib.sh b/t/test-lib.sh
index ca6bdef..1aa27bd 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -54,8 +54,8 @@
 	# do not redirect again
 	;;
 *' --tee '*|*' --va'*)
-	mkdir -p test-results
-	BASE=test-results/$(basename "$0" .sh)
+	mkdir -p "$TEST_OUTPUT_DIRECTORY/test-results"
+	BASE="$TEST_OUTPUT_DIRECTORY/test-results/$(basename "$0" .sh)"
 	(GIT_TEST_TEE_STARTED=done ${SHELL_PATH} "$0" "$@" 2>&1;
 	 echo $? > $BASE.exit) | tee $BASE.out
 	test "$(cat $BASE.exit)" = 0
@@ -92,6 +92,7 @@
 	print join("\n", @vars);
 ')
 unset XDG_CONFIG_HOME
+unset GITPERLLIB
 GIT_AUTHOR_EMAIL=author@example.com
 GIT_AUTHOR_NAME='A U Thor'
 GIT_COMMITTER_EMAIL=committer@example.com
@@ -184,6 +185,9 @@
 		help=t; shift ;;
 	-v|--v|--ve|--ver|--verb|--verbo|--verbos|--verbose)
 		verbose=t; shift ;;
+	--verbose-only=*)
+		verbose_only=$(expr "z$1" : 'z[^=]*=\(.*\)')
+		shift ;;
 	-q|--q|--qu|--qui|--quie|--quiet)
 		# Ignore --quiet under a TAP::Harness. Saying how many tests
 		# passed without the ok/not ok details is always an error.
@@ -198,17 +202,39 @@
 	--valgrind=*)
 		valgrind=$(expr "z$1" : 'z[^=]*=\(.*\)')
 		shift ;;
+	--valgrind-only=*)
+		valgrind_only=$(expr "z$1" : 'z[^=]*=\(.*\)')
+		shift ;;
+	--valgrind-parallel=*)
+		valgrind_parallel=$(expr "z$1" : 'z[^=]*=\(.*\)')
+		shift ;;
+	--valgrind-only-stride=*)
+		valgrind_only_stride=$(expr "z$1" : 'z[^=]*=\(.*\)')
+		shift ;;
+	--valgrind-only-offset=*)
+		valgrind_only_offset=$(expr "z$1" : 'z[^=]*=\(.*\)')
+		shift ;;
 	--tee)
 		shift ;; # was handled already
 	--root=*)
 		root=$(expr "z$1" : 'z[^=]*=\(.*\)')
 		shift ;;
+	--statusprefix=*)
+		statusprefix=$(expr "z$1" : 'z[^=]*=\(.*\)')
+		shift ;;
 	*)
 		echo "error: unknown test option '$1'" >&2; exit 1 ;;
 	esac
 done
 
-test -n "$valgrind" && verbose=t
+if test -n "$valgrind_only" || test -n "$valgrind_only_stride"
+then
+	test -z "$valgrind" && valgrind=memcheck
+	test -z "$verbose" && verbose_only="$valgrind_only"
+elif test -n "$valgrind"
+then
+	verbose=t
+fi
 
 if test -n "$color"
 then
@@ -303,12 +329,12 @@
 
 test_ok_ () {
 	test_success=$(($test_success + 1))
-	say_color "" "ok $test_count - $@"
+	say_color "" "${statusprefix}ok $test_count - $@"
 }
 
 test_failure_ () {
 	test_failure=$(($test_failure + 1))
-	say_color error "not ok $test_count - $1"
+	say_color error "${statusprefix}not ok $test_count - $1"
 	shift
 	echo "$@" | sed -e 's/^/#	/'
 	test "$immediate" = "" || { GIT_EXIT_OK=t; exit 1; }
@@ -316,18 +342,83 @@
 
 test_known_broken_ok_ () {
 	test_fixed=$(($test_fixed+1))
-	say_color error "ok $test_count - $@ # TODO known breakage vanished"
+	say_color error "${statusprefix}ok $test_count - $@ # TODO known breakage vanished"
 }
 
 test_known_broken_failure_ () {
 	test_broken=$(($test_broken+1))
-	say_color warn "not ok $test_count - $@ # TODO known breakage"
+	say_color warn "${statusprefix}not ok $test_count - $@ # TODO known breakage"
 }
 
 test_debug () {
 	test "$debug" = "" || eval "$1"
 }
 
+match_pattern_list () {
+	arg="$1"
+	shift
+	test -z "$*" && return 1
+	for pattern_
+	do
+		case "$arg" in
+		$pattern_)
+			return 0
+		esac
+	done
+	return 1
+}
+
+maybe_teardown_verbose () {
+	test -z "$verbose_only" && return
+	exec 4>/dev/null 3>/dev/null
+	verbose=
+}
+
+last_verbose=t
+maybe_setup_verbose () {
+	test -z "$verbose_only" && return
+	if match_pattern_list $test_count $verbose_only ||
+		{ test -n "$valgrind_only_stride" &&
+		expr $test_count "%" $valgrind_only_stride - $valgrind_only_offset = 0 >/dev/null; }
+	then
+		exec 4>&2 3>&1
+		# Emit a delimiting blank line when going from
+		# non-verbose to verbose.  Within verbose mode the
+		# delimiter is printed by test_expect_*.  The choice
+		# of the initial $last_verbose is such that before
+		# test 1, we do not print it.
+		test -z "$last_verbose" && echo >&3 ""
+		verbose=t
+	else
+		exec 4>/dev/null 3>/dev/null
+		verbose=
+	fi
+	last_verbose=$verbose
+}
+
+maybe_teardown_valgrind () {
+	test -z "$GIT_VALGRIND" && return
+	GIT_VALGRIND_ENABLED=
+}
+
+maybe_setup_valgrind () {
+	test -z "$GIT_VALGRIND" && return
+	if test -z "$valgrind_only" && test -z "$valgrind_only_stride"
+	then
+		GIT_VALGRIND_ENABLED=t
+		return
+	fi
+	GIT_VALGRIND_ENABLED=
+	if match_pattern_list $test_count $valgrind_only
+	then
+		GIT_VALGRIND_ENABLED=t
+	elif test -n "$valgrind_only_stride" &&
+		expr $test_count "%" $valgrind_only_stride - $valgrind_only_offset = 0 >/dev/null
+	then
+		GIT_VALGRIND_ENABLED=t
+	fi
+}
+
 test_eval_ () {
 	# This is a separate function because some tests use
 	# "return" to end a test_expect_success block early.
@@ -337,8 +428,10 @@
 test_run_ () {
 	test_cleanup=:
 	expecting_failure=$2
+	setup_malloc_check
 	test_eval_ "$1"
 	eval_ret=$?
+	teardown_malloc_check
 
 	if test -z "$immediate" || test $eval_ret = 0 || test -n "$expecting_failure"
 	then
@@ -353,17 +446,24 @@
 	return "$eval_ret"
 }
 
-test_skip () {
+test_start_ () {
 	test_count=$(($test_count+1))
+	maybe_setup_verbose
+	maybe_setup_valgrind
+}
+
+test_finish_ () {
+	echo >&3 ""
+	maybe_teardown_valgrind
+	maybe_teardown_verbose
+}
+
+test_skip () {
 	to_skip=
-	for skp in $GIT_SKIP_TESTS
-	do
-		case $this_test.$test_count in
-		$skp)
-			to_skip=t
-			break
-		esac
-	done
+	if match_pattern_list $this_test.$test_count $GIT_SKIP_TESTS
+	then
+		to_skip=t
+	fi
 	if test -z "$to_skip" && test -n "$test_prereq" &&
 	   ! test_have_prereq "$test_prereq"
 	then
@@ -377,8 +477,8 @@
 			of_prereq=" of $test_prereq"
 		fi
 
-		say_color skip >&3 "skipping test: $@"
-		say_color skip "ok $test_count # skip $1 (missing $missing_prereq${of_prereq})"
+		say_color skip >&3 "${statusprefix}skipping test: $@"
+		say_color skip "${statusprefix}ok $test_count # skip $1 (missing $missing_prereq${of_prereq})"
 		: true
 		;;
 	*)
@@ -395,6 +495,8 @@
 test_done () {
 	GIT_EXIT_OK=t
 
+	# Note: t0000 relies on $HARNESS_ACTIVE disabling the .counts
+	# output file
 	if test -z "$HARNESS_ACTIVE"
 	then
 		test_results_dir="$TEST_OUTPUT_DIRECTORY/test-results"
@@ -414,11 +516,11 @@
 
 	if test "$test_fixed" != 0
 	then
-		say_color error "# $test_fixed known breakage(s) vanished; please update test(s)"
+		say_color error "${statusprefix}# $test_fixed known breakage(s) vanished; please update test(s)"
 	fi
 	if test "$test_broken" != 0
 	then
-		say_color warn "# still have $test_broken known breakage(s)"
+		say_color warn "${statusprefix}# still have $test_broken known breakage(s)"
 	fi
 	if test "$test_broken" != 0 || test "$test_fixed" != 0
 	then
@@ -441,9 +543,9 @@
 		then
 			if test $test_remaining -gt 0
 			then
-				say_color pass "# passed all $msg"
+				say_color pass "${statusprefix}# passed all $msg"
 			fi
-			say "1..$test_count$skip_all"
+			say "${statusprefix}1..$test_count$skip_all"
 		fi
 
 		test -d "$remove_trash" &&
@@ -457,8 +559,8 @@
 	*)
 		if test $test_external_has_tap -eq 0
 		then
-			say_color error "# failed $test_failure among $msg"
-			say "1..$test_count"
+			say_color error "${statusprefix}# failed $test_failure among $msg"
+			say "${statusprefix}1..$test_count"
 		fi
 
 		exit 1 ;;
@@ -466,6 +568,9 @@
 	esac
 }
 
+
+# Set up a directory that we can put in PATH which redirects all git
+# calls to 'valgrind git ...'.
 if test -n "$valgrind"
 then
 	make_symlink () {
@@ -513,31 +618,43 @@
 		make_symlink "$symlink_target" "$GIT_VALGRIND/bin/$base" || exit
 	}
 
-	# override all git executables in TEST_DIRECTORY/..
-	GIT_VALGRIND=$TEST_DIRECTORY/valgrind
-	mkdir -p "$GIT_VALGRIND"/bin
-	for file in $GIT_BUILD_DIR/git* $GIT_BUILD_DIR/test-*
-	do
-		make_valgrind_symlink $file
-	done
-	# special-case the mergetools loadables
-	make_symlink "$GIT_BUILD_DIR"/mergetools "$GIT_VALGRIND/bin/mergetools"
-	OLDIFS=$IFS
-	IFS=:
-	for path in $PATH
-	do
-		ls "$path"/git-* 2> /dev/null |
-		while read file
+	# In the case of --valgrind-parallel, we only need to do the
+	# wrapping once, in the main script.  The worker children all
+	# have $valgrind_only_stride set, so we can skip based on that.
+	if test -z "$valgrind_only_stride"
+	then
+		# override all git executables in TEST_DIRECTORY/..
+		GIT_VALGRIND=$TEST_DIRECTORY/valgrind
+		mkdir -p "$GIT_VALGRIND"/bin
+		for file in $GIT_BUILD_DIR/git* $GIT_BUILD_DIR/test-*
 		do
-			make_valgrind_symlink "$file"
+			make_valgrind_symlink $file
 		done
-	done
-	IFS=$OLDIFS
+		# special-case the mergetools loadables
+		make_symlink "$GIT_BUILD_DIR"/mergetools "$GIT_VALGRIND/bin/mergetools"
+		OLDIFS=$IFS
+		IFS=:
+		for path in $PATH
+		do
+			ls "$path"/git-* 2> /dev/null |
+			while read file
+			do
+				make_valgrind_symlink "$file"
+			done
+		done
+		IFS=$OLDIFS
+	fi
 	PATH=$GIT_VALGRIND/bin:$PATH
 	GIT_EXEC_PATH=$GIT_VALGRIND/bin
 	export GIT_VALGRIND
 	GIT_VALGRIND_MODE="$valgrind"
 	export GIT_VALGRIND_MODE
+	GIT_VALGRIND_ENABLED=t
+	if test -n "$valgrind_only" || test -n "$valgrind_only_stride"
+	then
+		GIT_VALGRIND_ENABLED=
+	fi
+	export GIT_VALGRIND_ENABLED
 elif test -n "$GIT_TEST_INSTALLED"
 then
 	GIT_EXEC_PATH=$($GIT_TEST_INSTALLED/git --exec-path)  ||
@@ -622,21 +739,53 @@
 else
 	mkdir -p "$TRASH_DIRECTORY"
 fi
+
+# Gross hack to spawn N sub-instances of the tests in parallel, and
+# summarize the results.  Note that if this is enabled, the script
+# terminates at the end of this 'if' block.
+if test -n "$valgrind_parallel"
+then
+	for i in $(test_seq 1 $valgrind_parallel)
+	do
+		root="$TRASH_DIRECTORY/vgparallel-$i"
+		mkdir "$root"
+		TEST_OUTPUT_DIRECTORY="$root" \
+			${SHELL_PATH} "$0" \
+			--root="$root" --statusprefix="[$i] " \
+			--valgrind="$valgrind" \
+			--valgrind-only-stride="$valgrind_parallel" \
+			--valgrind-only-offset="$i" &
+		pids="$pids $!"
+	done
+	trap "kill $pids" INT TERM HUP
+	wait $pids
+	trap - INT TERM HUP
+	for i in $(test_seq 1 $valgrind_parallel)
+	do
+		root="$TRASH_DIRECTORY/vgparallel-$i"
+		eval "$(cat "$root/test-results/$(basename "$0" .sh)"-*.counts |
+			sed 's/^\([a-z][a-z]*\) \([0-9][0-9]*\)/inner_\1=\2/')"
+		test_count=$(expr $test_count + $inner_total)
+		test_success=$(expr $test_success + $inner_success)
+		test_fixed=$(expr $test_fixed + $inner_fixed)
+		test_broken=$(expr $test_broken + $inner_broken)
+		test_failure=$(expr $test_failure + $inner_failed)
+	done
+	test_done
+fi
+
 # Use -P to resolve symlinks in our working directory so that the cwd
 # in subprocesses like git equals our $PWD (for pathname comparisons).
 cd -P "$TRASH_DIRECTORY" || exit 1
 
 this_test=${0##*/}
 this_test=${this_test%%-*}
-for skp in $GIT_SKIP_TESTS
-do
-	case "$this_test" in
-	$skp)
-		say_color info >&3 "skipping test $this_test altogether"
-		skip_all="skip all tests in $this_test"
-		test_done
-	esac
-done
+if match_pattern_list "$this_test" $GIT_SKIP_TESTS
+then
+	say_color info >&3 "skipping test $this_test altogether"
+	skip_all="skip all tests in $this_test"
+	test_done
+fi
 
 # Provide an implementation of the 'yes' utility
 yes () {
@@ -676,6 +825,7 @@
 	test_set_prereq MINGW
 	test_set_prereq NOT_CYGWIN
 	test_set_prereq SED_STRIPS_CR
+	test_set_prereq GREP_STRIPS_CR
 	;;
 *CYGWIN*)
 	test_set_prereq POSIXPERM
@@ -683,6 +833,7 @@
 	test_set_prereq NOT_MINGW
 	test_set_prereq CYGWIN
 	test_set_prereq SED_STRIPS_CR
+	test_set_prereq GREP_STRIPS_CR
 	;;
 *)
 	test_set_prereq POSIXPERM
@@ -737,7 +888,14 @@
 
 test_lazy_prereq PIPE '
 	# test whether the filesystem supports FIFOs
-	rm -f testfifo && mkfifo testfifo
+	case $(uname -s) in
+	CYGWIN*)
+		false
+		;;
+	*)
+		rm -f testfifo && mkfifo testfifo
+		;;
+	esac
 '
 
 test_lazy_prereq SYMLINKS '
diff --git a/t/valgrind/analyze.sh b/t/valgrind/analyze.sh
index d8105d9..2ffc80f 100755
--- a/t/valgrind/analyze.sh
+++ b/t/valgrind/analyze.sh
@@ -1,6 +1,10 @@
 #!/bin/sh
 
-out_prefix=$(dirname "$0")/../test-results/valgrind.out
+# Get TEST_OUTPUT_DIRECTORY from GIT-BUILD-OPTIONS if it's there...
+. "$(dirname "$0")/../../GIT-BUILD-OPTIONS"
+# ... otherwise set it to the default value.
+: ${TEST_OUTPUT_DIRECTORY=$(dirname "$0")/..}
+
 output=
 count=0
 total_count=0
@@ -115,7 +119,7 @@
 	finish_output
 }
 
-for test_script in "$(dirname "$0")"/../test-results/*.out
+for test_script in "$TEST_OUTPUT_DIRECTORY"/test-results/*.out
 do
 	handle_one $test_script
 done
diff --git a/t/valgrind/valgrind.sh b/t/valgrind/valgrind.sh
index 6b87c91..4215303 100755
--- a/t/valgrind/valgrind.sh
+++ b/t/valgrind/valgrind.sh
@@ -4,6 +4,9 @@
 
 TOOL_OPTIONS='--leak-check=no'
 
+test -z "$GIT_VALGRIND_ENABLED" &&
+exec "$GIT_VALGRIND"/../../"$base" "$@"
+
 case "$GIT_VALGRIND_MODE" in
 memcheck-fast)
 	;;
diff --git a/templates/hooks--pre-commit.sample b/templates/hooks--pre-commit.sample
index 18c4829..586e3bf 100755
--- a/templates/hooks--pre-commit.sample
+++ b/templates/hooks--pre-commit.sample
@@ -15,13 +15,13 @@
 	against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
 fi
 
-# If you want to allow non-ascii filenames set this variable to true.
+# If you want to allow non-ASCII filenames set this variable to true.
 allownonascii=$(git config hooks.allownonascii)
 
 # Redirect output to stderr.
 exec 1>&2
 
-# Cross platform projects tend to avoid non-ascii filenames; prevent
+# Cross platform projects tend to avoid non-ASCII filenames; prevent
 # them from being added to the repository. We exploit the fact that the
 # printable range starts at the space character and ends with tilde.
 if [ "$allownonascii" != "true" ] &&
@@ -31,18 +31,17 @@
 	test $(git diff --cached --name-only --diff-filter=A -z $against |
 	  LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0
 then
-	echo "Error: Attempt to add a non-ascii file name."
-	echo
-	echo "This can cause problems if you want to work"
-	echo "with people on other platforms."
-	echo
-	echo "To be portable it is advisable to rename the file ..."
-	echo
-	echo "If you know what you are doing you can disable this"
-	echo "check using:"
-	echo
-	echo "  git config hooks.allownonascii true"
-	echo
+	cat <<\EOF
+Error: Attempt to add a non-ASCII file name.
+
+This can cause problems if you want to work with people on other platforms.
+
+To be portable it is advisable to rename the file.
+
+If you know what you are doing you can disable this check using:
+
+  git config hooks.allownonascii true
+EOF
 	exit 1
 fi
 
diff --git a/templates/hooks--pre-push.sample b/templates/hooks--pre-push.sample
old mode 100644
new mode 100755
index 15ab6d8..1f3bceb
--- a/templates/hooks--pre-push.sample
+++ b/templates/hooks--pre-push.sample
@@ -30,6 +30,7 @@
 	if [ "$local_sha" = $z40 ]
 	then
 		# Handle delete
+		:
 	else
 		if [ "$remote_sha" = $z40 ]
 		then
diff --git a/test-chmtime.c b/test-chmtime.c
index 02b42ba..0df7487 100644
--- a/test-chmtime.c
+++ b/test-chmtime.c
@@ -56,7 +56,7 @@
 	return 1;
 }
 
-int main(int argc, const char *argv[])
+int main(int argc, char *argv[])
 {
 	static int verbose;
 
@@ -84,15 +84,15 @@
 		if (stat(argv[i], &sb) < 0) {
 			fprintf(stderr, "Failed to stat %s: %s\n",
 			        argv[i], strerror(errno));
-			return -1;
+			return 1;
 		}
 
-#ifdef WIN32
+#ifdef GIT_WINDOWS_NATIVE
 		if (!(sb.st_mode & S_IWUSR) &&
 				chmod(argv[i], sb.st_mode | S_IWUSR)) {
 			fprintf(stderr, "Could not make user-writable %s: %s",
 				argv[i], strerror(errno));
-			return -1;
+			return 1;
 		}
 #endif
 
@@ -107,7 +107,7 @@
 		if (utb.modtime != sb.st_mtime && utime(argv[i], &utb) < 0) {
 			fprintf(stderr, "Failed to modify time on %s: %s\n",
 			        argv[i], strerror(errno));
-			return -1;
+			return 1;
 		}
 	}
 
@@ -115,5 +115,5 @@
 
 usage:
 	fprintf(stderr, "usage: %s %s\n", argv[0], usage_str);
-	return -1;
+	return 1;
 }
diff --git a/test-dump-cache-tree.c b/test-dump-cache-tree.c
index a6ffdf3..47eab97 100644
--- a/test-dump-cache-tree.c
+++ b/test-dump-cache-tree.c
@@ -59,6 +59,8 @@
 	struct cache_tree *another = cache_tree();
 	if (read_cache() < 0)
 		die("unable to read index file");
-	cache_tree_update(another, active_cache, active_nr, WRITE_TREE_DRY_RUN);
+	cache_tree_update(another,
+			  (const struct cache_entry * const *)active_cache,
+			  active_nr, WRITE_TREE_DRY_RUN);
 	return dump_cache_tree(active_cache_tree, another, "");
 }
diff --git a/test-index-version.c b/test-index-version.c
index bfaad9e..05d4699 100644
--- a/test-index-version.c
+++ b/test-index-version.c
@@ -1,6 +1,6 @@
 #include "cache.h"
 
-int main(int argc, const char **argv)
+int main(int argc, char **argv)
 {
 	struct cache_header hdr;
 	int version;
diff --git a/test-mergesort.c b/test-mergesort.c
index 3f388b4..ea3b959 100644
--- a/test-mergesort.c
+++ b/test-mergesort.c
@@ -22,7 +22,7 @@
 	return strcmp(x->text, y->text);
 }
 
-int main(int argc, const char **argv)
+int main(int argc, char **argv)
 {
 	struct line *line, *p = NULL, *lines = NULL;
 	struct strbuf sb = STRBUF_INIT;
diff --git a/test-parse-options.c b/test-parse-options.c
index 3c9510a..434e8b8 100644
--- a/test-parse-options.c
+++ b/test-parse-options.c
@@ -29,7 +29,7 @@
 	return 0;
 }
 
-int main(int argc, const char **argv)
+int main(int argc, char **argv)
 {
 	const char *prefix = "prefix/";
 	const char *usage[] = {
@@ -81,7 +81,7 @@
 	};
 	int i;
 
-	argc = parse_options(argc, argv, prefix, options, usage, 0);
+	argc = parse_options(argc, (const char **)argv, prefix, options, usage, 0);
 
 	printf("boolean: %d\n", boolean);
 	printf("integer: %u\n", integer);
diff --git a/test-path-utils.c b/test-path-utils.c
index 0092cbf..bb975e4 100644
--- a/test-path-utils.c
+++ b/test-path-utils.c
@@ -28,6 +28,19 @@
 	return 1;
 }
 
+static void normalize_argv_string(const char **var, const char *input)
+{
+	if (!strcmp(input, "<null>"))
+		*var = NULL;
+	else if (!strcmp(input, "<empty>"))
+		*var = "";
+	else
+		*var = input;
+
+	if (*var && (**var == '<' || **var == '('))
+		die("Bad value: %s\n", input);
+}
+
 int main(int argc, char **argv)
 {
 	if (argc == 3 && !strcmp(argv[1], "normalize_path_copy")) {
@@ -103,6 +116,25 @@
 		return 0;
 	}
 
+	if (argc == 3 && !strcmp(argv[1], "mingw_path")) {
+		puts(argv[2]);
+		return 0;
+	}
+
+	if (argc == 4 && !strcmp(argv[1], "relative_path")) {
+		struct strbuf sb = STRBUF_INIT;
+		const char *in, *prefix, *rel;
+		normalize_argv_string(&in, argv[2]);
+		normalize_argv_string(&prefix, argv[3]);
+		rel = relative_path(in, prefix, &sb);
+		if (!rel)
+			puts("(null)");
+		else
+			puts(strlen(rel) > 0 ? rel : "(empty)");
+		strbuf_release(&sb);
+		return 0;
+	}
+
 	fprintf(stderr, "%s: unknown function name: %s\n", argv[0],
 		argv[1] ? argv[1] : "(there was none)");
 	return 1;
diff --git a/test-prio-queue.c b/test-prio-queue.c
new file mode 100644
index 0000000..7be72f0
--- /dev/null
+++ b/test-prio-queue.c
@@ -0,0 +1,39 @@
+#include "cache.h"
+#include "prio-queue.h"
+
+static int intcmp(const void *va, const void *vb, void *data)
+{
+	const int *a = va, *b = vb;
+	return *a - *b;
+}
+
+static void show(int *v)
+{
+	if (!v)
+		printf("NULL\n");
+	else
+		printf("%d\n", *v);
+	free(v);
+}
+
+int main(int argc, char **argv)
+{
+	struct prio_queue pq = { intcmp };
+
+	while (*++argv) {
+		if (!strcmp(*argv, "get"))
+			show(prio_queue_get(&pq));
+		else if (!strcmp(*argv, "dump")) {
+			int *v;
+			while ((v = prio_queue_get(&pq)))
+			       show(v);
+		}
+		else {
+			int *v = malloc(sizeof(*v));
+			*v = atoi(*argv);
+			prio_queue_put(&pq, v);
+		}
+	}
+
+	return 0;
+}
diff --git a/test-read-cache.c b/test-read-cache.c
new file mode 100644
index 0000000..b25bcf1
--- /dev/null
+++ b/test-read-cache.c
@@ -0,0 +1,13 @@
+#include "cache.h"
+
+int main (int argc, char **argv)
+{
+	int i, cnt = 1;
+	if (argc == 2)
+		cnt = strtol(argv[1], NULL, 0);
+	for (i = 0; i < cnt; i++) {
+		read_cache();
+		discard_cache();
+	}
+	return 0;
+}
diff --git a/test-subprocess.c b/test-subprocess.c
index f2d4c0d..93525eb 100644
--- a/test-subprocess.c
+++ b/test-subprocess.c
@@ -1,7 +1,7 @@
 #include "cache.h"
 #include "run-command.h"
 
-int main(int argc, const char **argv)
+int main(int argc, char **argv)
 {
 	struct child_process cp;
 	int nogit = 0;
@@ -15,6 +15,6 @@
 	}
 	memset(&cp, 0, sizeof(cp));
 	cp.git_cmd = 1;
-	cp.argv = argv + 1;
+	cp.argv = (const char **)argv + 1;
 	return run_command(&cp);
 }
diff --git a/thread-utils.c b/thread-utils.c
index 7f4b76a..97396a7 100644
--- a/thread-utils.c
+++ b/thread-utils.c
@@ -24,7 +24,7 @@
 	long ncpus;
 #endif
 
-#ifdef _WIN32
+#ifdef GIT_WINDOWS_NATIVE
 	SYSTEM_INFO info;
 	GetSystemInfo(&info);
 
diff --git a/trace.c b/trace.c
index 5ec0e3b..3d744d1 100644
--- a/trace.c
+++ b/trace.c
@@ -75,6 +75,7 @@
 	strbuf_release(&buf);
 }
 
+__attribute__((format (printf, 2, 3)))
 static void trace_printf_key(const char *key, const char *fmt, ...)
 {
 	va_list ap;
diff --git a/transport-helper.c b/transport-helper.c
index 5f8d075..63cabc3 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -11,6 +11,7 @@
 #include "thread-utils.h"
 #include "sigchain.h"
 #include "argv-array.h"
+#include "refs.h"
 
 static int debug;
 
@@ -47,7 +48,7 @@
 		die_errno("Full write to remote helper failed");
 }
 
-static int recvline_fh(FILE *helper, struct strbuf *buffer)
+static int recvline_fh(FILE *helper, struct strbuf *buffer, const char *name)
 {
 	strbuf_reset(buffer);
 	if (debug)
@@ -65,7 +66,7 @@
 
 static int recvline(struct helper_data *helper, struct strbuf *buffer)
 {
-	return recvline_fh(helper->out, buffer);
+	return recvline_fh(helper->out, buffer, helper->name);
 }
 
 static void xchgline(struct helper_data *helper, struct strbuf *buffer)
@@ -214,10 +215,11 @@
 		int i;
 		data->refspec_nr = refspec_nr;
 		data->refspecs = parse_fetch_refspec(refspec_nr, refspecs);
-		for (i = 0; i < refspec_nr; i++) {
+		for (i = 0; i < refspec_nr; i++)
 			free((char *)refspecs[i]);
-		}
 		free(refspecs);
+	} else if (data->import || data->bidi_import || data->export) {
+		warning("This remote helper should implement refspec capability.");
 	}
 	strbuf_release(&buf);
 	if (debug)
@@ -474,7 +476,7 @@
 	 * were fetching.
 	 *
 	 * (If no "refspec" capability was specified, for historical
-	 * reasons we default to *:*.)
+	 * reasons we default to the equivalent of *:*.)
 	 *
 	 * Store the result in to_fetch[i].old_sha1.  Callers such
 	 * as "git fetch" can use the value to write feedback to the
@@ -541,7 +543,7 @@
 		goto exit;
 
 	sendline(data, &cmdbuf);
-	recvline_fh(input, &cmdbuf);
+	recvline_fh(input, &cmdbuf, name);
 	if (!strcmp(cmdbuf.buf, "")) {
 		data->no_disconnect_req = 1;
 		if (debug)
@@ -623,7 +625,7 @@
 	return -1;
 }
 
-static void push_update_ref_status(struct strbuf *buf,
+static int push_update_ref_status(struct strbuf *buf,
 				   struct ref **ref,
 				   struct ref *remote_refs)
 {
@@ -689,7 +691,7 @@
 		*ref = find_ref_by_name(remote_refs, refname);
 	if (!*ref) {
 		warning("helper reported unexpected status of %s", refname);
-		return;
+		return 1;
 	}
 
 	if ((*ref)->status != REF_STATUS_NONE) {
@@ -698,11 +700,12 @@
 		 * status reported by the remote helper if the latter is 'no match'.
 		 */
 		if (status == REF_STATUS_NONE)
-			return;
+			return 1;
 	}
 
 	(*ref)->status = status;
 	(*ref)->remote_status = msg;
+	return !(status == REF_STATUS_OK);
 }
 
 static void push_update_refs_status(struct helper_data *data,
@@ -711,11 +714,24 @@
 	struct strbuf buf = STRBUF_INIT;
 	struct ref *ref = remote_refs;
 	for (;;) {
+		char *private;
+
 		recvline(data, &buf);
 		if (!buf.len)
 			break;
 
-		push_update_ref_status(&buf, &ref, remote_refs);
+		if (push_update_ref_status(&buf, &ref, remote_refs))
+			continue;
+
+		if (!data->refspecs)
+			continue;
+
+		/* propagate back the update to the remote namespace */
+		private = apply_refspecs(data->refspecs, data->refspec_nr, ref->name);
+		if (!private)
+			continue;
+		update_ref("update by helper", private, ref->new_sha1, NULL, 0, 0);
+		free(private);
 	}
 	strbuf_release(&buf);
 }
@@ -790,6 +806,14 @@
 	struct string_list revlist_args = STRING_LIST_INIT_NODUP;
 	struct strbuf buf = STRBUF_INIT;
 
+	if (!data->refspecs)
+		die("remote-helper doesn't support push; refspec needed");
+
+	if (flags & TRANSPORT_PUSH_DRY_RUN) {
+		if (set_helper_option(transport, "dry-run", "true") != 0)
+			die("helper %s does not support dry-run", data->name);
+	}
+
 	helper = get_helper(transport);
 
 	write_constant(helper->in, "export\n");
@@ -800,22 +824,25 @@
 		char *private;
 		unsigned char sha1[20];
 
-		if (!data->refspecs)
-			continue;
+		if (ref->deletion)
+			die("remote-helpers do not support ref deletion");
+
 		private = apply_refspecs(data->refspecs, data->refspec_nr, ref->name);
 		if (private && !get_sha1(private, sha1)) {
 			strbuf_addf(&buf, "^%s", private);
 			string_list_append(&revlist_args, strbuf_detach(&buf, NULL));
+			hashcpy(ref->old_sha1, sha1);
 		}
 		free(private);
 
-		if (ref->deletion) {
+		if (ref->deletion)
 			die("remote-helpers do not support ref deletion");
-		}
 
-		if (ref->peer_ref)
+		if (ref->peer_ref) {
+			if (strcmp(ref->peer_ref->name, ref->name))
+				die("remote-helpers do not support old:new syntax");
 			string_list_append(&revlist_args, ref->peer_ref->name);
-
+		}
 	}
 
 	if (get_exporter(transport, &exporter, &revlist_args))
@@ -955,6 +982,7 @@
 #define PBUFFERSIZE 8192
 
 /* Print bidirectional transfer loop debug message. */
+__attribute__((format (printf, 1, 2)))
 static void transfer_debug(const char *fmt, ...)
 {
 	va_list args;
@@ -1040,7 +1068,7 @@
 		return -1;
 	} else if (bytes == 0) {
 		transfer_debug("%s EOF (with %i bytes in buffer)",
-			t->src_name, t->bufuse);
+			t->src_name, (int)t->bufuse);
 		t->state = SSTATE_FLUSHING;
 	} else if (bytes > 0) {
 		t->bufuse += bytes;
@@ -1104,7 +1132,7 @@
 #ifndef NO_PTHREADS
 
 /*
- * Join thread, with apporiate errors on failure. Name is name for the
+ * Join thread, with appropriate errors on failure. Name is name for the
  * thread (for error messages). Returns 0 on success, 1 on failure.
  */
 static int tloop_join(pthread_t thread, const char *name)
@@ -1170,7 +1198,7 @@
 }
 
 /*
- * Join process, with apporiate errors on failure. Name is name for the
+ * Join process, with appropriate errors on failure. Name is name for the
  * process (for error messages). Returns 0 on success, 1 on failure.
  */
 static int tloop_join(pid_t pid, const char *name)
diff --git a/transport.c b/transport.c
index ba5d8af..de25588 100644
--- a/transport.c
+++ b/transport.c
@@ -534,6 +534,8 @@
 	args.quiet = (transport->verbose < 0);
 	args.no_progress = !transport->progress;
 	args.depth = data->options.depth;
+	args.check_self_contained_and_connected =
+		data->options.check_self_contained_and_connected;
 
 	if (!data->got_remote_heads) {
 		connect_setup(transport, 0, 0);
@@ -551,6 +553,8 @@
 		refs = NULL;
 	data->conn = NULL;
 	data->got_remote_heads = 0;
+	data->options.self_contained_and_connected =
+		args.self_contained_and_connected;
 
 	free_refs(refs_tmp);
 
@@ -871,6 +875,8 @@
 	transport->push_refs = git_transport_push;
 	transport->disconnect = disconnect_git;
 	transport->smart_options = &(data->options);
+
+	transport->cannot_reuse = 1;
 }
 
 static int is_local(const char *url)
@@ -1228,7 +1234,7 @@
 		 * then local and remote refs are likely to still be equal.
 		 * Just feed them all to the fetch method in that case.
 		 * This condition shouldn't be met in a non-deepening fetch
-		 * (see builtin-fetch.c:quickfetch()).
+		 * (see builtin/fetch.c:quickfetch()).
 		 */
 		heads = xmalloc(nr_refs * sizeof(*heads));
 		for (rm = refs; rm; rm = rm->next)
diff --git a/transport.h b/transport.h
index fcb1d25..96e0ede 100644
--- a/transport.h
+++ b/transport.h
@@ -8,6 +8,8 @@
 	unsigned thin : 1;
 	unsigned keep : 1;
 	unsigned followtags : 1;
+	unsigned check_self_contained_and_connected : 1;
+	unsigned self_contained_and_connected : 1;
 	int depth;
 	const char *uploadpack;
 	const char *receivepack;
@@ -25,6 +27,12 @@
 	 */
 	unsigned got_remote_refs : 1;
 
+	/*
+	 * Transports that call take-over destroys the data specific to
+	 * the transport type while doing so, and cannot be reused.
+	 */
+	unsigned cannot_reuse : 1;
+
 	/**
 	 * Returns 0 if successful, positive if the option is not
 	 * recognized or is inapplicable, and negative if the option
@@ -168,7 +176,7 @@
 int transport_helper_init(struct transport *transport, const char *name);
 int bidirectional_transfer_loop(int input, int output);
 
-/* common methods used by transport.c and builtin-send-pack.c */
+/* common methods used by transport.c and builtin/send-pack.c */
 void transport_verify_remote_names(int nr_heads, const char **heads);
 
 void transport_update_tracking_ref(struct remote *remote, struct ref *ref, int verbose);
diff --git a/tree-walk.c b/tree-walk.c
index 6e30ef9..c626135 100644
--- a/tree-walk.c
+++ b/tree-walk.c
@@ -323,7 +323,6 @@
 
 int traverse_trees(int n, struct tree_desc *t, struct traverse_info *info)
 {
-	int ret = 0;
 	int error = 0;
 	struct name_entry *entry = xmalloc(n*sizeof(*entry));
 	int i;
@@ -341,6 +340,7 @@
 		strbuf_setlen(&base, info->pathlen);
 	}
 	for (;;) {
+		int trees_used;
 		unsigned long mask, dirmask;
 		const char *first = NULL;
 		int first_len = 0;
@@ -404,15 +404,14 @@
 		if (interesting < 0)
 			break;
 		if (interesting) {
-			ret = info->fn(n, mask, dirmask, entry, info);
-			if (ret < 0) {
-				error = ret;
+			trees_used = info->fn(n, mask, dirmask, entry, info);
+			if (trees_used < 0) {
+				error = trees_used;
 				if (!info->show_all_errors)
 					break;
 			}
-			mask &= ret;
+			mask &= trees_used;
 		}
-		ret = 0;
 		for (i = 0; i < n; i++)
 			if (mask & (1ul << i))
 				update_extended_entry(tx + i, entry + i);
diff --git a/tree-walk.h b/tree-walk.h
index 2bf0db9..ae04b64 100644
--- a/tree-walk.h
+++ b/tree-walk.h
@@ -46,7 +46,7 @@
 	int pathlen;
 	struct pathspec *pathspec;
 
-	unsigned long conflicts;
+	unsigned long df_conflicts;
 	traverse_callback_t fn;
 	void *data;
 	int show_all_errors;
diff --git a/tree.c b/tree.c
index 62fed63..c0e568c 100644
--- a/tree.c
+++ b/tree.c
@@ -159,7 +159,7 @@
 	 * sort at the end.
 	 */
 	for (i = 0; !fn && i < active_nr; i++) {
-		struct cache_entry *ce = active_cache[i];
+		const struct cache_entry *ce = active_cache[i];
 		if (ce_stage(ce) == stage)
 			fn = read_one_entry;
 	}
diff --git a/unpack-trees.c b/unpack-trees.c
index ede4299..bf01717 100644
--- a/unpack-trees.c
+++ b/unpack-trees.c
@@ -116,14 +116,20 @@
 			ADD_CACHE_OK_TO_ADD | ADD_CACHE_OK_TO_REPLACE);
 }
 
-static void add_entry(struct unpack_trees_options *o, struct cache_entry *ce,
-	unsigned int set, unsigned int clear)
+static struct cache_entry *dup_entry(const struct cache_entry *ce)
 {
 	unsigned int size = ce_size(ce);
 	struct cache_entry *new = xmalloc(size);
 
 	memcpy(new, ce, size);
-	do_add_entry(o, new, set, clear);
+	return new;
+}
+
+static void add_entry(struct unpack_trees_options *o,
+		      const struct cache_entry *ce,
+		      unsigned int set, unsigned int clear)
+{
+	do_add_entry(o, dup_entry(ce), set, clear);
 }
 
 /*
@@ -173,7 +179,7 @@
  * Unlink the last component and schedule the leading directories for
  * removal, such that empty directories get removed.
  */
-static void unlink_entry(struct cache_entry *ce)
+static void unlink_entry(const struct cache_entry *ce)
 {
 	if (!check_leading_path(ce->name, ce_namelen(ce)))
 		return;
@@ -193,7 +199,7 @@
 
 	if (o->update && o->verbose_update) {
 		for (total = cnt = 0; cnt < index->cache_nr; cnt++) {
-			struct cache_entry *ce = index->cache[cnt];
+			const struct cache_entry *ce = index->cache[cnt];
 			if (ce->ce_flags & (CE_UPDATE | CE_WT_REMOVE))
 				total++;
 		}
@@ -206,7 +212,7 @@
 	if (o->update)
 		git_attr_set_direction(GIT_ATTR_CHECKOUT, &o->result);
 	for (i = 0; i < index->cache_nr; i++) {
-		struct cache_entry *ce = index->cache[i];
+		const struct cache_entry *ce = index->cache[i];
 
 		if (ce->ce_flags & CE_WT_REMOVE) {
 			display_progress(progress, ++cnt);
@@ -235,8 +241,11 @@
 	return errs != 0;
 }
 
-static int verify_uptodate_sparse(struct cache_entry *ce, struct unpack_trees_options *o);
-static int verify_absent_sparse(struct cache_entry *ce, enum unpack_trees_error_types, struct unpack_trees_options *o);
+static int verify_uptodate_sparse(const struct cache_entry *ce,
+				  struct unpack_trees_options *o);
+static int verify_absent_sparse(const struct cache_entry *ce,
+				enum unpack_trees_error_types,
+				struct unpack_trees_options *o);
 
 static int apply_sparse_checkout(struct cache_entry *ce, struct unpack_trees_options *o)
 {
@@ -291,7 +300,8 @@
 	return 0;
 }
 
-static inline int call_unpack_fn(struct cache_entry **src, struct unpack_trees_options *o)
+static inline int call_unpack_fn(const struct cache_entry * const *src,
+				 struct unpack_trees_options *o)
 {
 	int ret = o->fn(src, o);
 	if (ret > 0)
@@ -320,7 +330,7 @@
 		index->cache[i]->ce_flags &= ~(CE_UNPACKED | CE_ADDED | CE_NEW_SKIP_WORKTREE);
 }
 
-static int locate_in_src_index(struct cache_entry *ce,
+static int locate_in_src_index(const struct cache_entry *ce,
 			       struct unpack_trees_options *o)
 {
 	struct index_state *index = o->src_index;
@@ -366,7 +376,7 @@
 	return NULL;
 }
 
-static void add_same_unmerged(struct cache_entry *ce,
+static void add_same_unmerged(const struct cache_entry *ce,
 			      struct unpack_trees_options *o)
 {
 	struct index_state *index = o->src_index;
@@ -388,7 +398,7 @@
 static int unpack_index_entry(struct cache_entry *ce,
 			      struct unpack_trees_options *o)
 {
-	struct cache_entry *src[MAX_UNPACK_TREES + 1] = { NULL, };
+	const struct cache_entry *src[MAX_UNPACK_TREES + 1] = { NULL, };
 	int ret;
 
 	src[0] = ce;
@@ -454,7 +464,7 @@
 	newinfo.pathspec = info->pathspec;
 	newinfo.name = *p;
 	newinfo.pathlen += tree_entry_len(p) + 1;
-	newinfo.conflicts |= df_conflicts;
+	newinfo.df_conflicts |= df_conflicts;
 
 	for (i = 0; i < n; i++, dirmask >>= 1) {
 		const unsigned char *sha1 = NULL;
@@ -555,17 +565,12 @@
 {
 	int i;
 	struct unpack_trees_options *o = info->data;
-	unsigned long conflicts;
+	unsigned long conflicts = info->df_conflicts | dirmask;
 
 	/* Do we have *only* directories? Nothing to do */
 	if (mask == dirmask && !src[0])
 		return 0;
 
-	conflicts = info->conflicts;
-	if (o->merge)
-		conflicts >>= 1;
-	conflicts |= dirmask;
-
 	/*
 	 * Ok, we've filled in up to any potential index entry in src[0],
 	 * now do the rest.
@@ -590,8 +595,16 @@
 		src[i + o->merge] = create_ce_entry(info, names + i, stage);
 	}
 
-	if (o->merge)
-		return call_unpack_fn(src, o);
+	if (o->merge) {
+		int rc = call_unpack_fn((const struct cache_entry * const *)src,
+					o);
+		for (i = 0; i < n; i++) {
+			struct cache_entry *ce = src[i + o->merge];
+			if (ce != o->df_conflict_entry)
+				free(ce);
+		}
+		return rc;
+	}
 
 	for (i = 0; i < n; i++)
 		if (src[i] && src[i] != o->df_conflict_entry)
@@ -637,7 +650,7 @@
 	int p_len = tree_entry_len(p);
 
 	for (pos = o->cache_bottom; pos < index->cache_nr; pos++) {
-		struct cache_entry *ce = index->cache[pos];
+		const struct cache_entry *ce = index->cache[pos];
 		const char *ce_name, *ce_slash;
 		int cmp, ce_len;
 
@@ -789,13 +802,6 @@
 
 	/* Now handle any directories.. */
 	if (dirmask) {
-		unsigned long conflicts = mask & ~dirmask;
-		if (o->merge) {
-			conflicts <<= 1;
-			if (src[0])
-				conflicts |= 1;
-		}
-
 		/* special case: "diff-index --cached" looking at a tree */
 		if (o->diff_index_cached &&
 		    n == 1 && dirmask == 1 && S_ISDIR(names->mode)) {
@@ -814,7 +820,7 @@
 			}
 		}
 
-		if (traverse_trees_recursive(n, dirmask, conflicts,
+		if (traverse_trees_recursive(n, dirmask, mask & ~dirmask,
 					     names, info) < 0)
 			return -1;
 		return mask;
@@ -995,7 +1001,9 @@
 		       select_flag, skip_wt_flag, el);
 }
 
-static int verify_absent(struct cache_entry *, enum unpack_trees_error_types, struct unpack_trees_options *);
+static int verify_absent(const struct cache_entry *,
+			 enum unpack_trees_error_types,
+			 struct unpack_trees_options *);
 /*
  * N-way merge "len" trees.  Returns 0 on success, -1 on failure to manipulate the
  * resulting index, -2 on failure to reflect the changes to the work tree.
@@ -1165,12 +1173,13 @@
 
 /* Here come the merge functions */
 
-static int reject_merge(struct cache_entry *ce, struct unpack_trees_options *o)
+static int reject_merge(const struct cache_entry *ce,
+			struct unpack_trees_options *o)
 {
 	return add_rejected_path(o, ERROR_WOULD_OVERWRITE, ce->name);
 }
 
-static int same(struct cache_entry *a, struct cache_entry *b)
+static int same(const struct cache_entry *a, const struct cache_entry *b)
 {
 	if (!!a != !!b)
 		return 0;
@@ -1187,9 +1196,9 @@
  * When a CE gets turned into an unmerged entry, we
  * want it to be up-to-date
  */
-static int verify_uptodate_1(struct cache_entry *ce,
-				   struct unpack_trees_options *o,
-				   enum unpack_trees_error_types error_type)
+static int verify_uptodate_1(const struct cache_entry *ce,
+			     struct unpack_trees_options *o,
+			     enum unpack_trees_error_types error_type)
 {
 	struct stat st;
 
@@ -1228,7 +1237,7 @@
 		add_rejected_path(o, error_type, ce->name);
 }
 
-static int verify_uptodate(struct cache_entry *ce,
+static int verify_uptodate(const struct cache_entry *ce,
 			   struct unpack_trees_options *o)
 {
 	if (!o->skip_sparse_checkout && (ce->ce_flags & CE_NEW_SKIP_WORKTREE))
@@ -1236,13 +1245,14 @@
 	return verify_uptodate_1(ce, o, ERROR_NOT_UPTODATE_FILE);
 }
 
-static int verify_uptodate_sparse(struct cache_entry *ce,
+static int verify_uptodate_sparse(const struct cache_entry *ce,
 				  struct unpack_trees_options *o)
 {
 	return verify_uptodate_1(ce, o, ERROR_SPARSE_NOT_UPTODATE_FILE);
 }
 
-static void invalidate_ce_path(struct cache_entry *ce, struct unpack_trees_options *o)
+static void invalidate_ce_path(const struct cache_entry *ce,
+			       struct unpack_trees_options *o)
 {
 	if (ce)
 		cache_tree_invalidate_path(o->src_index->cache_tree, ce->name);
@@ -1255,16 +1265,16 @@
  * Currently, git does not checkout subprojects during a superproject
  * checkout, so it is not going to overwrite anything.
  */
-static int verify_clean_submodule(struct cache_entry *ce,
-				      enum unpack_trees_error_types error_type,
-				      struct unpack_trees_options *o)
+static int verify_clean_submodule(const struct cache_entry *ce,
+				  enum unpack_trees_error_types error_type,
+				  struct unpack_trees_options *o)
 {
 	return 0;
 }
 
-static int verify_clean_subdirectory(struct cache_entry *ce,
-				      enum unpack_trees_error_types error_type,
-				      struct unpack_trees_options *o)
+static int verify_clean_subdirectory(const struct cache_entry *ce,
+				     enum unpack_trees_error_types error_type,
+				     struct unpack_trees_options *o)
 {
 	/*
 	 * we are about to extract "ce->name"; we would not want to lose
@@ -1343,18 +1353,18 @@
  */
 static int icase_exists(struct unpack_trees_options *o, const char *name, int len, struct stat *st)
 {
-	struct cache_entry *src;
+	const struct cache_entry *src;
 
 	src = index_name_exists(o->src_index, name, len, 1);
 	return src && !ie_match_stat(o->src_index, src, st, CE_MATCH_IGNORE_VALID|CE_MATCH_IGNORE_SKIP_WORKTREE);
 }
 
 static int check_ok_to_remove(const char *name, int len, int dtype,
-			      struct cache_entry *ce, struct stat *st,
+			      const struct cache_entry *ce, struct stat *st,
 			      enum unpack_trees_error_types error_type,
 			      struct unpack_trees_options *o)
 {
-	struct cache_entry *result;
+	const struct cache_entry *result;
 
 	/*
 	 * It may be that the 'lstat()' succeeded even though
@@ -1405,9 +1415,9 @@
  * We do not want to remove or overwrite a working tree file that
  * is not tracked, unless it is ignored.
  */
-static int verify_absent_1(struct cache_entry *ce,
-				 enum unpack_trees_error_types error_type,
-				 struct unpack_trees_options *o)
+static int verify_absent_1(const struct cache_entry *ce,
+			   enum unpack_trees_error_types error_type,
+			   struct unpack_trees_options *o)
 {
 	int len;
 	struct stat st;
@@ -1440,7 +1450,7 @@
 	}
 }
 
-static int verify_absent(struct cache_entry *ce,
+static int verify_absent(const struct cache_entry *ce,
 			 enum unpack_trees_error_types error_type,
 			 struct unpack_trees_options *o)
 {
@@ -1449,9 +1459,9 @@
 	return verify_absent_1(ce, error_type, o);
 }
 
-static int verify_absent_sparse(struct cache_entry *ce,
-			 enum unpack_trees_error_types error_type,
-			 struct unpack_trees_options *o)
+static int verify_absent_sparse(const struct cache_entry *ce,
+				enum unpack_trees_error_types error_type,
+				struct unpack_trees_options *o)
 {
 	enum unpack_trees_error_types orphaned_error = error_type;
 	if (orphaned_error == ERROR_WOULD_LOSE_UNTRACKED_OVERWRITTEN)
@@ -1460,10 +1470,12 @@
 	return verify_absent_1(ce, orphaned_error, o);
 }
 
-static int merged_entry(struct cache_entry *merge, struct cache_entry *old,
-		struct unpack_trees_options *o)
+static int merged_entry(const struct cache_entry *ce,
+			const struct cache_entry *old,
+			struct unpack_trees_options *o)
 {
 	int update = CE_UPDATE;
+	struct cache_entry *merge = dup_entry(ce);
 
 	if (!old) {
 		/*
@@ -1481,8 +1493,11 @@
 		update |= CE_ADDED;
 		merge->ce_flags |= CE_NEW_SKIP_WORKTREE;
 
-		if (verify_absent(merge, ERROR_WOULD_LOSE_UNTRACKED_OVERWRITTEN, o))
+		if (verify_absent(merge,
+				  ERROR_WOULD_LOSE_UNTRACKED_OVERWRITTEN, o)) {
+			free(merge);
 			return -1;
+		}
 		invalidate_ce_path(merge, o);
 	} else if (!(old->ce_flags & CE_CONFLICTED)) {
 		/*
@@ -1496,8 +1511,10 @@
 			copy_cache_entry(merge, old);
 			update = 0;
 		} else {
-			if (verify_uptodate(old, o))
+			if (verify_uptodate(old, o)) {
+				free(merge);
 				return -1;
+			}
 			/* Migrate old flags over */
 			update |= old->ce_flags & (CE_SKIP_WORKTREE | CE_NEW_SKIP_WORKTREE);
 			invalidate_ce_path(old, o);
@@ -1510,12 +1527,13 @@
 		invalidate_ce_path(old, o);
 	}
 
-	add_entry(o, merge, update, CE_STAGEMASK);
+	do_add_entry(o, merge, update, CE_STAGEMASK);
 	return 1;
 }
 
-static int deleted_entry(struct cache_entry *ce, struct cache_entry *old,
-		struct unpack_trees_options *o)
+static int deleted_entry(const struct cache_entry *ce,
+			 const struct cache_entry *old,
+			 struct unpack_trees_options *o)
 {
 	/* Did it exist in the index? */
 	if (!old) {
@@ -1530,7 +1548,8 @@
 	return 1;
 }
 
-static int keep_entry(struct cache_entry *ce, struct unpack_trees_options *o)
+static int keep_entry(const struct cache_entry *ce,
+		      struct unpack_trees_options *o)
 {
 	add_entry(o, ce, 0, 0);
 	return 1;
@@ -1552,11 +1571,12 @@
 }
 #endif
 
-int threeway_merge(struct cache_entry **stages, struct unpack_trees_options *o)
+int threeway_merge(const struct cache_entry * const *stages,
+		   struct unpack_trees_options *o)
 {
-	struct cache_entry *index;
-	struct cache_entry *head;
-	struct cache_entry *remote = stages[o->head_idx + 1];
+	const struct cache_entry *index;
+	const struct cache_entry *head;
+	const struct cache_entry *remote = stages[o->head_idx + 1];
 	int count;
 	int head_match = 0;
 	int remote_match = 0;
@@ -1641,7 +1661,7 @@
 	if (o->aggressive) {
 		int head_deleted = !head;
 		int remote_deleted = !remote;
-		struct cache_entry *ce = NULL;
+		const struct cache_entry *ce = NULL;
 
 		if (index)
 			ce = index;
@@ -1724,11 +1744,12 @@
  * "carry forward" rule, please see <Documentation/git-read-tree.txt>.
  *
  */
-int twoway_merge(struct cache_entry **src, struct unpack_trees_options *o)
+int twoway_merge(const struct cache_entry * const *src,
+		 struct unpack_trees_options *o)
 {
-	struct cache_entry *current = src[0];
-	struct cache_entry *oldtree = src[1];
-	struct cache_entry *newtree = src[2];
+	const struct cache_entry *current = src[0];
+	const struct cache_entry *oldtree = src[1];
+	const struct cache_entry *newtree = src[2];
 
 	if (o->merge_size != 2)
 		return error("Cannot do a twoway merge of %d trees",
@@ -1790,11 +1811,11 @@
  * Keep the index entries at stage0, collapse stage1 but make sure
  * stage0 does not have anything there.
  */
-int bind_merge(struct cache_entry **src,
-		struct unpack_trees_options *o)
+int bind_merge(const struct cache_entry * const *src,
+	       struct unpack_trees_options *o)
 {
-	struct cache_entry *old = src[0];
-	struct cache_entry *a = src[1];
+	const struct cache_entry *old = src[0];
+	const struct cache_entry *a = src[1];
 
 	if (o->merge_size != 1)
 		return error("Cannot do a bind merge of %d trees",
@@ -1814,10 +1835,11 @@
  * The rule is:
  * - take the stat information from stage0, take the data from stage1
  */
-int oneway_merge(struct cache_entry **src, struct unpack_trees_options *o)
+int oneway_merge(const struct cache_entry * const *src,
+		 struct unpack_trees_options *o)
 {
-	struct cache_entry *old = src[0];
-	struct cache_entry *a = src[1];
+	const struct cache_entry *old = src[0];
+	const struct cache_entry *a = src[1];
 
 	if (o->merge_size != 1)
 		return error("Cannot do a oneway merge of %d trees",
diff --git a/unpack-trees.h b/unpack-trees.h
index 5e432f5..36a73a6 100644
--- a/unpack-trees.h
+++ b/unpack-trees.h
@@ -8,7 +8,7 @@
 struct unpack_trees_options;
 struct exclude_list;
 
-typedef int (*merge_fn_t)(struct cache_entry **src,
+typedef int (*merge_fn_t)(const struct cache_entry * const *src,
 		struct unpack_trees_options *options);
 
 enum unpack_trees_error_types {
@@ -77,9 +77,13 @@
 extern int unpack_trees(unsigned n, struct tree_desc *t,
 		struct unpack_trees_options *options);
 
-int threeway_merge(struct cache_entry **stages, struct unpack_trees_options *o);
-int twoway_merge(struct cache_entry **src, struct unpack_trees_options *o);
-int bind_merge(struct cache_entry **src, struct unpack_trees_options *o);
-int oneway_merge(struct cache_entry **src, struct unpack_trees_options *o);
+int threeway_merge(const struct cache_entry * const *stages,
+		   struct unpack_trees_options *o);
+int twoway_merge(const struct cache_entry * const *src,
+		 struct unpack_trees_options *o);
+int bind_merge(const struct cache_entry * const *src,
+	       struct unpack_trees_options *o);
+int oneway_merge(const struct cache_entry * const *src,
+		 struct unpack_trees_options *o);
 
 #endif
diff --git a/upload-pack.c b/upload-pack.c
index bfa6279c..127e59a 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -592,7 +592,7 @@
 				die("invalid shallow line: %s", line);
 			object = parse_object(sha1);
 			if (!object)
-				die("did not find object for %s", line);
+				continue;
 			if (object->type != OBJ_COMMIT)
 				die("invalid shallow object %s", sha1_to_hex(sha1));
 			if (!(object->flags & CLIENT_SHALLOW)) {
diff --git a/utf8.h b/utf8.h
index 32a7bfb..65d0e42 100644
--- a/utf8.h
+++ b/utf8.h
@@ -10,6 +10,7 @@
 int is_utf8(const char *text);
 int is_encoding_utf8(const char *name);
 int same_encoding(const char *, const char *);
+__attribute__((format (printf, 2, 3)))
 int utf8_fprintf(FILE *, const char *, ...);
 
 void strbuf_add_wrapped_text(struct strbuf *buf,
diff --git a/wildmatch.c b/wildmatch.c
index 7192bdc..f91ba99 100644
--- a/wildmatch.c
+++ b/wildmatch.c
@@ -196,6 +196,11 @@
 					}
 					if (t_ch <= p_ch && t_ch >= prev_ch)
 						matched = 1;
+					else if ((flags & WM_CASEFOLD) && ISLOWER(t_ch)) {
+						uchar t_ch_upper = toupper(t_ch);
+						if (t_ch_upper <= p_ch && t_ch_upper >= prev_ch)
+							matched = 1;
+					}
 					p_ch = 0; /* This makes "prev_ch" get set to 0. */
 				} else if (p_ch == '[' && p[1] == ':') {
 					const uchar *s;
@@ -245,6 +250,8 @@
 					} else if (CC_EQ(s,i, "upper")) {
 						if (ISUPPER(t_ch))
 							matched = 1;
+						else if ((flags & WM_CASEFOLD) && ISLOWER(t_ch))
+							matched = 1;
 					} else if (CC_EQ(s,i, "xdigit")) {
 						if (ISXDIGIT(t_ch))
 							matched = 1;
diff --git a/wrap-for-bin.sh b/wrap-for-bin.sh
index 53a8dd0..701d233 100644
--- a/wrap-for-bin.sh
+++ b/wrap-for-bin.sh
@@ -14,7 +14,7 @@
 	GIT_TEMPLATE_DIR='@@BUILD_DIR@@/templates/blt'
 	export GIT_TEMPLATE_DIR
 fi
-GITPERLLIB='@@BUILD_DIR@@/perl/blib/lib'
+GITPERLLIB='@@BUILD_DIR@@/perl/blib/lib'"${GITPERLLIB:+:$GITPERLLIB}"
 GIT_TEXTDOMAINDIR='@@BUILD_DIR@@/po/build/locale'
 PATH='@@BUILD_DIR@@/bin-wrappers:'"$PATH"
 export GIT_EXEC_PATH GITPERLLIB PATH GIT_TEXTDOMAINDIR
diff --git a/wrapper.c b/wrapper.c
index bac59d2..f92b147 100644
--- a/wrapper.c
+++ b/wrapper.c
@@ -131,6 +131,14 @@
 }
 
 /*
+ * Limit size of IO chunks, because huge chunks only cause pain.  OS X
+ * 64-bit is buggy, returning EINVAL if len >= INT_MAX; and even in
+ * the absense of bugs, large chunks can result in bad latencies when
+ * you decide to kill the process.
+ */
+#define MAX_IO_SIZE (8*1024*1024)
+
+/*
  * xread() is the same a read(), but it automatically restarts read()
  * operations with a recoverable error (EAGAIN and EINTR). xread()
  * DOES NOT GUARANTEE that "len" bytes is read even if the data is available.
@@ -138,6 +146,8 @@
 ssize_t xread(int fd, void *buf, size_t len)
 {
 	ssize_t nr;
+	if (len > MAX_IO_SIZE)
+	    len = MAX_IO_SIZE;
 	while (1) {
 		nr = read(fd, buf, len);
 		if ((nr < 0) && (errno == EAGAIN || errno == EINTR))
@@ -154,6 +164,8 @@
 ssize_t xwrite(int fd, const void *buf, size_t len)
 {
 	ssize_t nr;
+	if (len > MAX_IO_SIZE)
+	    len = MAX_IO_SIZE;
 	while (1) {
 		nr = write(fd, buf, len);
 		if ((nr < 0) && (errno == EAGAIN || errno == EINTR))
@@ -322,7 +334,7 @@
 		template[5] = letters[v % num_letters]; v /= num_letters;
 
 		fd = open(pattern, O_CREAT | O_EXCL | O_RDWR, mode);
-		if (fd > 0)
+		if (fd >= 0)
 			return fd;
 		/*
 		 * Fatal error (EPERM, ENOSPC etc).
@@ -408,18 +420,24 @@
 	warning(_("unable to access '%s': %s"), path, strerror(errno));
 }
 
-int access_or_warn(const char *path, int mode)
+static int access_error_is_ok(int err, unsigned flag)
+{
+	return err == ENOENT || err == ENOTDIR ||
+		((flag & ACCESS_EACCES_OK) && err == EACCES);
+}
+
+int access_or_warn(const char *path, int mode, unsigned flag)
 {
 	int ret = access(path, mode);
-	if (ret && errno != ENOENT && errno != ENOTDIR)
+	if (ret && !access_error_is_ok(errno, flag))
 		warn_on_inaccessible(path);
 	return ret;
 }
 
-int access_or_die(const char *path, int mode)
+int access_or_die(const char *path, int mode, unsigned flag)
 {
 	int ret = access(path, mode);
-	if (ret && errno != ENOENT && errno != ENOTDIR)
+	if (ret && !access_error_is_ok(errno, flag))
 		die_errno(_("unable to access '%s'"), path);
 	return ret;
 }
diff --git a/wt-status.c b/wt-status.c
index bf84a86..cb24f1f 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -127,6 +127,7 @@
 	s->change.strdup_strings = 1;
 	s->untracked.strdup_strings = 1;
 	s->ignored.strdup_strings = 1;
+	s->show_branch = -1;  /* unspecified */
 }
 
 static void wt_status_print_unmerged_header(struct wt_status *s)
@@ -243,7 +244,7 @@
 	struct strbuf onebuf = STRBUF_INIT;
 	const char *one, *how = _("bug");
 
-	one = quote_path(it->string, -1, &onebuf, s->prefix);
+	one = quote_path(it->string, s->prefix, &onebuf);
 	status_printf(s, color(WT_STATUS_HEADER, s), "\t");
 	switch (d->stagemask) {
 	case 1: how = _("both deleted:"); break;
@@ -297,8 +298,8 @@
 		    change_type);
 	}
 
-	one = quote_path(one_name, -1, &onebuf, s->prefix);
-	two = quote_path(two_name, -1, &twobuf, s->prefix);
+	one = quote_path(one_name, s->prefix, &onebuf);
+	two = quote_path(two_name, s->prefix, &twobuf);
 
 	status_printf(s, color(WT_STATUS_HEADER, s), "\t");
 	switch (status) {
@@ -371,7 +372,7 @@
 static int unmerged_mask(const char *path)
 {
 	int pos, mask;
-	struct cache_entry *ce;
+	const struct cache_entry *ce;
 
 	pos = cache_name_pos(path, strlen(path));
 	if (0 <= pos)
@@ -475,7 +476,7 @@
 	for (i = 0; i < active_nr; i++) {
 		struct string_list_item *it;
 		struct wt_status_change_data *d;
-		struct cache_entry *ce = active_cache[i];
+		const struct cache_entry *ce = active_cache[i];
 
 		if (!ce_path_match(ce, &pathspec))
 			continue;
@@ -706,8 +707,7 @@
 		struct string_list_item *it;
 		const char *path;
 		it = &(l->items[i]);
-		path = quote_path(it->string, strlen(it->string),
-				  &buf, s->prefix);
+		path = quote_path(it->string, s->prefix, &buf);
 		if (column_active(s->colopts)) {
 			string_list_append(&output, path);
 			continue;
@@ -826,7 +826,7 @@
 	if (advice_status_hints) {
 		if (!state->am_empty_patch)
 			status_printf_ln(s, color,
-				_("  (fix conflicts and then run \"git am --resolved\")"));
+				_("  (fix conflicts and then run \"git am --continue\")"));
 		status_printf_ln(s, color,
 			_("  (use \"git am --skip\" to skip this patch)"));
 		status_printf_ln(s, color,
@@ -955,10 +955,12 @@
 	if (advice_status_hints) {
 		if (has_unmerged(s))
 			status_printf_ln(s, color,
-				_("  (fix conflicts and run \"git commit\")"));
+				_("  (fix conflicts and run \"git cherry-pick --continue\")"));
 		else
 			status_printf_ln(s, color,
-				_("  (all conflicts fixed: run \"git commit\")"));
+				_("  (all conflicts fixed: run \"git cherry-pick --continue\")"));
+		status_printf_ln(s, color,
+			_("  (use \"git cherry-pick --abort\" to cancel the cherry-pick operation)"));
 	}
 	wt_status_print_trailer(s);
 }
@@ -1035,7 +1037,6 @@
 }
 
 struct grab_1st_switch_cbdata {
-	int found;
 	struct strbuf buf;
 	unsigned char nsha1[20];
 };
@@ -1059,7 +1060,6 @@
 	for (end = target; *end && *end != '\n'; end++)
 		;
 	strbuf_add(&cb->buf, target, end - target);
-	cb->found = 1;
 	return 1;
 }
 
@@ -1176,7 +1176,10 @@
 			branch_name += 11;
 		else if (!strcmp(branch_name, "HEAD")) {
 			branch_status_color = color(WT_STATUS_NOBRANCH, s);
-			if (state.detached_from) {
+			if (state.rebase_in_progress || state.rebase_interactive_in_progress) {
+				on_what = _("rebase in progress; onto ");
+				branch_name = state.onto;
+			} else if (state.detached_from) {
 				unsigned char sha1[20];
 				branch_name = state.detached_from;
 				if (!get_sha1("HEAD", sha1) &&
@@ -1289,7 +1292,7 @@
 	} else {
 		struct strbuf onebuf = STRBUF_INIT;
 		const char *one;
-		one = quote_path(it->string, -1, &onebuf, s->prefix);
+		one = quote_path(it->string, s->prefix, &onebuf);
 		printf(" %s\n", one);
 		strbuf_release(&onebuf);
 	}
@@ -1317,7 +1320,7 @@
 		struct strbuf onebuf = STRBUF_INIT;
 		const char *one;
 		if (d->head_path) {
-			one = quote_path(d->head_path, -1, &onebuf, s->prefix);
+			one = quote_path(d->head_path, s->prefix, &onebuf);
 			if (*one != '"' && strchr(one, ' ') != NULL) {
 				putchar('"');
 				strbuf_addch(&onebuf, '"');
@@ -1326,7 +1329,7 @@
 			printf("%s -> ", one);
 			strbuf_release(&onebuf);
 		}
-		one = quote_path(it->string, -1, &onebuf, s->prefix);
+		one = quote_path(it->string, s->prefix, &onebuf);
 		if (*one != '"' && strchr(one, ' ') != NULL) {
 			putchar('"');
 			strbuf_addch(&onebuf, '"');
@@ -1345,7 +1348,7 @@
 	} else {
 		struct strbuf onebuf = STRBUF_INIT;
 		const char *one;
-		one = quote_path(it->string, -1, &onebuf, s->prefix);
+		one = quote_path(it->string, s->prefix, &onebuf);
 		color_fprintf(s->fp, color(WT_STATUS_UNTRACKED, s), "%s", sign);
 		printf(" %s\n", one);
 		strbuf_release(&onebuf);
diff --git a/wt-status.h b/wt-status.h
index 4121bc2..fb7152e 100644
--- a/wt-status.h
+++ b/wt-status.h
@@ -96,9 +96,9 @@
 void wt_shortstatus_print(struct wt_status *s);
 void wt_porcelain_print(struct wt_status *s);
 
-void status_printf_ln(struct wt_status *s, const char *color, const char *fmt, ...)
-	;
-void status_printf(struct wt_status *s, const char *color, const char *fmt, ...)
-	;
+__attribute__((format (printf, 3, 4)))
+void status_printf_ln(struct wt_status *s, const char *color, const char *fmt, ...);
+__attribute__((format (printf, 3, 4)))
+void status_printf(struct wt_status *s, const char *color, const char *fmt, ...);
 
 #endif /* STATUS_H */
diff --git a/xdiff/xdiff.h b/xdiff/xdiff.h
index 219a3bb..c033991 100644
--- a/xdiff/xdiff.h
+++ b/xdiff/xdiff.h
@@ -39,6 +39,8 @@
 #define XDF_DIFF_ALGORITHM_MASK (XDF_PATIENCE_DIFF | XDF_HISTOGRAM_DIFF)
 #define XDF_DIFF_ALG(x) ((x) & XDF_DIFF_ALGORITHM_MASK)
 
+#define XDF_IGNORE_BLANK_LINES (1 << 7)
+
 #define XDL_EMIT_FUNCNAMES (1 << 0)
 #define XDL_EMIT_COMMON (1 << 1)
 #define XDL_EMIT_FUNCCONTEXT (1 << 2)
diff --git a/xdiff/xdiffi.c b/xdiff/xdiffi.c
index b2eb6db..2358a2d 100644
--- a/xdiff/xdiffi.c
+++ b/xdiff/xdiffi.c
@@ -394,6 +394,7 @@
 	xch->i2 = i2;
 	xch->chg1 = chg1;
 	xch->chg2 = chg2;
+	xch->ignore = 0;
 
 	return xch;
 }
@@ -544,7 +545,9 @@
 	xdchange_t *xch, *xche;
 
 	for (xch = xscr; xch; xch = xche->next) {
-		xche = xdl_get_hunk(xch, xecfg);
+		xche = xdl_get_hunk(&xch, xecfg);
+		if (!xch)
+			break;
 		if (xecfg->hunk_func(xch->i1, xche->i1 + xche->chg1 - xch->i1,
 				     xch->i2, xche->i2 + xche->chg2 - xch->i2,
 				     ecb->priv) < 0)
@@ -553,6 +556,27 @@
 	return 0;
 }
 
+static void xdl_mark_ignorable(xdchange_t *xscr, xdfenv_t *xe, long flags)
+{
+	xdchange_t *xch;
+
+	for (xch = xscr; xch; xch = xch->next) {
+		int ignore = 1;
+		xrecord_t **rec;
+		long i;
+
+		rec = &xe->xdf1.recs[xch->i1];
+		for (i = 0; i < xch->chg1 && ignore; i++)
+			ignore = xdl_blankline(rec[i]->ptr, rec[i]->size, flags);
+
+		rec = &xe->xdf2.recs[xch->i2];
+		for (i = 0; i < xch->chg2 && ignore; i++)
+			ignore = xdl_blankline(rec[i]->ptr, rec[i]->size, flags);
+
+		xch->ignore = ignore;
+	}
+}
+
 int xdl_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
 	     xdemitconf_t const *xecfg, xdemitcb_t *ecb) {
 	xdchange_t *xscr;
@@ -571,6 +595,9 @@
 		return -1;
 	}
 	if (xscr) {
+		if (xpp->flags & XDF_IGNORE_BLANK_LINES)
+			xdl_mark_ignorable(xscr, &xe, xpp->flags);
+
 		if (ef(&xe, xscr, ecb, xecfg) < 0) {
 
 			xdl_free_script(xscr);
diff --git a/xdiff/xdiffi.h b/xdiff/xdiffi.h
index 7a92ea9..8b81206 100644
--- a/xdiff/xdiffi.h
+++ b/xdiff/xdiffi.h
@@ -41,6 +41,7 @@
 	struct s_xdchange *next;
 	long i1, i2;
 	long chg1, chg2;
+	int ignore;
 } xdchange_t;
 
 
diff --git a/xdiff/xemit.c b/xdiff/xemit.c
index d11dbf9..4d86458 100644
--- a/xdiff/xemit.c
+++ b/xdiff/xemit.c
@@ -56,16 +56,51 @@
 /*
  * Starting at the passed change atom, find the latest change atom to be included
  * inside the differential hunk according to the specified configuration.
+ * Also advance xscr if the first changes must be discarded.
  */
-xdchange_t *xdl_get_hunk(xdchange_t *xscr, xdemitconf_t const *xecfg) {
-	xdchange_t *xch, *xchp;
+xdchange_t *xdl_get_hunk(xdchange_t **xscr, xdemitconf_t const *xecfg)
+{
+	xdchange_t *xch, *xchp, *lxch;
 	long max_common = 2 * xecfg->ctxlen + xecfg->interhunkctxlen;
+	long max_ignorable = xecfg->ctxlen;
+	unsigned long ignored = 0; /* number of ignored blank lines */
 
-	for (xchp = xscr, xch = xscr->next; xch; xchp = xch, xch = xch->next)
-		if (xch->i1 - (xchp->i1 + xchp->chg1) > max_common)
+	/* remove ignorable changes that are too far before other changes */
+	for (xchp = *xscr; xchp && xchp->ignore; xchp = xchp->next) {
+		xch = xchp->next;
+
+		if (xch == NULL ||
+		    xch->i1 - (xchp->i1 + xchp->chg1) >= max_ignorable)
+			*xscr = xch;
+	}
+
+	if (*xscr == NULL)
+		return NULL;
+
+	lxch = *xscr;
+
+	for (xchp = *xscr, xch = xchp->next; xch; xchp = xch, xch = xch->next) {
+		long distance = xch->i1 - (xchp->i1 + xchp->chg1);
+		if (distance > max_common)
 			break;
 
-	return xchp;
+		if (distance < max_ignorable && (!xch->ignore || lxch == xchp)) {
+			lxch = xch;
+			ignored = 0;
+		} else if (distance < max_ignorable && xch->ignore) {
+			ignored += xch->chg2;
+		} else if (lxch != xchp &&
+			   xch->i1 + ignored - (lxch->i1 + lxch->chg1) > max_common) {
+			break;
+		} else if (!xch->ignore) {
+			lxch = xch;
+			ignored = 0;
+		} else {
+			ignored += xch->chg2;
+		}
+	}
+
+	return lxch;
 }
 
 
@@ -139,7 +174,9 @@
 		return xdl_emit_common(xe, xscr, ecb, xecfg);
 
 	for (xch = xscr; xch; xch = xche->next) {
-		xche = xdl_get_hunk(xch, xecfg);
+		xche = xdl_get_hunk(&xch, xecfg);
+		if (!xch)
+			break;
 
 		s1 = XDL_MAX(xch->i1 - xecfg->ctxlen, 0);
 		s2 = XDL_MAX(xch->i2 - xecfg->ctxlen, 0);
diff --git a/xdiff/xemit.h b/xdiff/xemit.h
index c2e2e83..d297107 100644
--- a/xdiff/xemit.h
+++ b/xdiff/xemit.h
@@ -27,7 +27,7 @@
 typedef int (*emit_func_t)(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
 			   xdemitconf_t const *xecfg);
 
-xdchange_t *xdl_get_hunk(xdchange_t *xscr, xdemitconf_t const *xecfg);
+xdchange_t *xdl_get_hunk(xdchange_t **xscr, xdemitconf_t const *xecfg);
 int xdl_emit_diff(xdfenv_t *xe, xdchange_t *xscr, xdemitcb_t *ecb,
 		  xdemitconf_t const *xecfg);
 
diff --git a/xdiff/xutils.c b/xdiff/xutils.c
index 9504eae..62cb23d 100644
--- a/xdiff/xutils.c
+++ b/xdiff/xutils.c
@@ -143,6 +143,19 @@
 	return nl + 1;
 }
 
+int xdl_blankline(const char *line, long size, long flags)
+{
+	long i;
+
+	if (!(flags & XDF_WHITESPACE_FLAGS))
+		return (size <= 1);
+
+	for (i = 0; i < size && XDL_ISSPACE(line[i]); i++)
+		;
+
+	return (i == size);
+}
+
 int xdl_recmatch(const char *l1, long s1, const char *l2, long s2, long flags)
 {
 	int i1, i2;
diff --git a/xdiff/xutils.h b/xdiff/xutils.h
index ad1428e..4646ce5 100644
--- a/xdiff/xutils.h
+++ b/xdiff/xutils.h
@@ -32,6 +32,7 @@
 void xdl_cha_free(chastore_t *cha);
 void *xdl_cha_alloc(chastore_t *cha);
 long xdl_guess_lines(mmfile_t *mf, long sample);
+int xdl_blankline(const char *line, long size, long flags);
 int xdl_recmatch(const char *l1, long s1, const char *l2, long s2, long flags);
 unsigned long xdl_hash_record(char const **data, char const *top, long flags);
 unsigned int xdl_hashbits(unsigned int size);