Merge branch 'ta/new-command-howto'
* ta/new-command-howto:
Move ./technical/api-command.txt to ./howto/new-command.txt
diff --git a/.mailmap b/.mailmap
index bcf4f87..c7e8618 100644
--- a/.mailmap
+++ b/.mailmap
@@ -9,7 +9,9 @@
Alexander Gavrilov <angavrilov@gmail.com>
Aneesh Kumar K.V <aneesh.kumar@gmail.com>
Brian M. Carlson <sandals@crustytoothpaste.ath.cx>
+Cheng Renquan <crquan@gmail.com>
Chris Shoemaker <c.shoemaker@cox.net>
+Dan Johnson <computerdruid@gmail.com>
Dana L. How <danahow@gmail.com>
Dana L. How <how@deathvalley.cswitch.com>
Daniel Barkalow <barkalow@iabervon.org>
@@ -18,14 +20,18 @@
David S. Miller <davem@davemloft.net>
Deskin Miller <deskinm@umich.edu>
Dirk Süsserott <newsletter@dirk.my1.cc>
+Eric S. Raymond <esr@thyrsus.com>
Erik Faye-Lund <kusmabite@gmail.com> <kusmabite@googlemail.com>
Fredrik Kuivinen <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>
Horst H. von Brand <vonbrand@inf.utfsm.cl>
İsmail Dönmez <ismail@pardus.org.tr>
+Jakub Narębski <jnareb@gmail.com>
Jay Soffian <jaysoffian+git@gmail.com>
+Jeff King <peff@peff.net> <peff@github.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>
@@ -41,12 +47,21 @@
Junio C Hamano <gitster@pobox.com> <junio@kernel.org>
Junio C Hamano <gitster@pobox.com> <junkio@cox.net>
Karl Hasselström <kha@treskal.com>
+Kevin Leung <kevinlsk@gmail.com>
Kent Engstrom <kent@lysator.liu.se>
Lars Doelle <lars.doelle@on-line ! de>
Lars Doelle <lars.doelle@on-line.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@ppc970.osdl.org.(none)>
Lukas Sandström <lukass@etek.chalmers.se>
-Martin Langhoff <martin@laptop.org>
+Marc-André Lureau <marcandre.lureau@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>
Michael Coleman <tutufan@gmail.com>
Michael J Gruber <git@drmicha.warpmail.net> <michaeljgruber+gmane@fastmail.fm>
@@ -63,11 +78,13 @@
Ramsay Allan Jones <ramsay@ramsay1.demon.co.uk>
René Scharfe <rene.scharfe@lsrfire.ath.cx>
Robert Fitzsimons <robfitz@273k.net>
+Robert Zeh <robert.a.zeh@gmail.com>
Sam Vilain <sam@vilain.net>
Santi Béjar <sbejar@gmail.com>
Sean Estabrooks <seanlkml@sympatico.ca>
Shawn O. Pearce <spearce@spearce.org>
Steven Grimm <koreth@midwinter.com>
+Tay Ray Chuan <rctay89@gmail.com>
Theodore Ts'o <tytso@mit.edu>
Thomas Rast <trast@inf.ethz.ch> <trast@student.ethz.ch>
Tony Luck <tony.luck@intel.com>
diff --git a/Documentation/CodingGuidelines b/Documentation/CodingGuidelines
index 57da6aa..69f7e9b 100644
--- a/Documentation/CodingGuidelines
+++ b/Documentation/CodingGuidelines
@@ -112,6 +112,14 @@
- We try to keep to at most 80 characters per line.
+ - We try to support a wide range of C compilers to compile git with,
+ including old ones. That means that you should not use C99
+ initializers, even if a lot of compilers grok it.
+
+ - Variables have to be declared at the beginning of the block.
+
+ - NULL pointers shall be written as NULL, not as 0.
+
- When declaring pointers, the star sides with the variable
name, i.e. "char *string", not "char* string" or
"char * string". This makes it easier to understand code
diff --git a/Documentation/Makefile b/Documentation/Makefile
index 5243222..f3afcb6 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -32,7 +32,6 @@
SP_ARTICLES += howto/revert-a-faulty-merge
SP_ARTICLES += howto/recover-corrupted-blob-object
SP_ARTICLES += howto/rebuild-from-update-hook
-SP_ARTICLES += howto/rebuild-from-update-hook
SP_ARTICLES += howto/rebase-from-internal-branch
SP_ARTICLES += howto/maintain-git
API_DOCS = $(patsubst %.txt,%,$(filter-out technical/api-index-skel.txt technical/api-index.txt, $(wildcard technical/api-*.txt)))
diff --git a/Documentation/RelNotes/1.8.1.txt b/Documentation/RelNotes/1.8.1.txt
index 6aa24c6..fec1a06 100644
--- a/Documentation/RelNotes/1.8.1.txt
+++ b/Documentation/RelNotes/1.8.1.txt
@@ -116,11 +116,17 @@
* The remote helper interface to interact with subversion
repositories (one of the GSoC 2012 projects) has been merged.
+ * The documentation for git(1) was pointing at a page at an external
+ site for the list of authors that no longer existed. The link has
+ been updated to point at an alternative site.
+
Performance, Internal Implementation, etc.
* Compilation on Cygwin with newer header files are supported now.
+ * A couple of low-level implementation updates on MinGW.
+
* The logic to generate the initial advertisement from "upload-pack"
(i.e. what is invoked by "git fetch" on the other side of the
connection) to list what refs are available in the repository has
diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches
index 3d8b2fe..75935d5 100644
--- a/Documentation/SubmittingPatches
+++ b/Documentation/SubmittingPatches
@@ -9,6 +9,14 @@
- the first line of the commit message should be a short
description (50 characters is the soft limit, see DISCUSSION
in git-commit(1)), and should skip the full stop
+ - it is also conventional in most cases to prefix the
+ first line with "area: " where the area is a filename
+ or identifier for the general area of the code being
+ modified, e.g.
+ . archive: ustar header checksum is computed unsigned
+ . git-cherry-pick.txt: clarify the use of revision range notation
+ (if in doubt which identifier to use, run "git log --no-merges"
+ on the files you are modifying to see the current conventions)
- the body should provide a meaningful commit message, which:
. explains the problem the change tries to solve, iow, what
is wrong with the current code without the change.
@@ -119,19 +127,6 @@
run git diff --check on your changes before you commit.
-(1a) Try to be nice to older C compilers
-
-We try to support a wide range of C compilers to compile
-git with. That means that you should not use C99 initializers, even
-if a lot of compilers grok it.
-
-Also, variables have to be declared at the beginning of the block
-(you can check this with gcc, using the -Wdeclaration-after-statement
-option).
-
-Another thing: NULL pointers shall be written as NULL, not as 0.
-
-
(2) Generate your patch using git tools out of your commits.
git based diff tools generate unidiff which is the preferred format.
diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt
index f4f7e25..39f2c50 100644
--- a/Documentation/diff-options.txt
+++ b/Documentation/diff-options.txt
@@ -309,7 +309,11 @@
index (i.e. amount of addition/deletions compared to the
file's size). For example, `-M90%` means git should consider a
delete/add pair to be a rename if more than 90% of the file
- hasn't changed.
+ hasn't changed. Without a `%` sign, the number is to be read as
+ 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%`.
-C[<n>]::
--find-copies[=<n>]::
diff --git a/Documentation/fetch-options.txt b/Documentation/fetch-options.txt
index b4d6476..6e98bdf 100644
--- a/Documentation/fetch-options.txt
+++ b/Documentation/fetch-options.txt
@@ -57,14 +57,11 @@
ifndef::git-pull[]
-t::
--tags::
- Most of the tags are fetched automatically as branch
- heads are downloaded, but tags that do not point at
- objects reachable from the branch heads that are being
- tracked will not be fetched by this mechanism. This
- flag lets all tags and their associated objects be
- downloaded. The default behavior for a remote may be
- specified with the remote.<name>.tagopt setting. See
- linkgit:git-config[1].
+ 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
+ remote.$name.fetch variable) are overridden and not used.
--recurse-submodules[=yes|on-demand|no]::
This option controls if and under what conditions new commits of
diff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt
index 7958a47..6f04d22 100644
--- a/Documentation/git-checkout.txt
+++ b/Documentation/git-checkout.txt
@@ -21,18 +21,34 @@
also update `HEAD` to set the specified branch as the current
branch.
-'git checkout' [<branch>]::
-'git checkout' -b|-B <new_branch> [<start point>]::
-'git checkout' [--detach] [<commit>]::
-
- This form switches branches by updating the index, working
- tree, and HEAD to reflect the specified branch or commit.
+'git checkout' <branch>::
+ To prepare for working on <branch>, switch to it by updating
+ the index and the files in the working tree, and by pointing
+ HEAD at the branch. Local modifications to the files in the
+ working tree are kept, so that they can be committed to the
+ <branch>.
+
-If `-b` is given, a new branch is created as if linkgit:git-branch[1]
-were called and then checked out; in this case you can
-use the `--track` or `--no-track` options, which will be passed to
-'git branch'. As a convenience, `--track` without `-b` implies branch
-creation; see the description of `--track` below.
+If <branch> is not found but there does exist a tracking branch in
+exactly one remote (call it <remote>) with a matching name, treat as
+equivalent to
++
+------------
+$ git checkout -b <branch> --track <remote>/<branch>
+------------
++
+You could omit <branch>, in which case the command degenerates to
+"check out the current branch", which is a glorified no-op with a
+rather expensive side-effects to show only the tracking information,
+if exists, for the current branch.
+
+'git checkout' -b|-B <new_branch> [<start point>]::
+
+ Specifying `-b` causes a new branch to be created as if
+ linkgit:git-branch[1] were called and then checked out. In
+ this case you can use the `--track` or `--no-track` options,
+ which will be passed to 'git branch'. As a convenience,
+ `--track` without `-b` implies branch creation; see the
+ description of `--track` below.
+
If `-B` is given, <new_branch> is created if it doesn't exist; otherwise, it
is reset. This is the transactional equivalent of
@@ -45,6 +61,21 @@
that is to say, the branch is not reset/created unless "git checkout" is
successful.
+'git checkout' --detach [<branch>]::
+'git checkout' <commit>::
+
+ Prepare to work on top of <commit>, by detaching HEAD at it
+ (see "DETACHED HEAD" section), and updating the index and the
+ files in the working tree. Local modifications to the files
+ in the working tree are kept, so that the resulting working
+ tree will be the state recorded in the commit plus the local
+ modifications.
++
+Passing `--detach` forces this behavior in the case of a <branch> (without
+the option, giving a branch name to the command would check out the branch,
+instead of detaching HEAD at it), or the current commit,
+if no <branch> is specified.
+
'git checkout' [-p|--patch] [<tree-ish>] [--] <pathspec>...::
When <paths> or `--patch` are given, 'git checkout' does *not*
diff --git a/Documentation/git-diff.txt b/Documentation/git-diff.txt
index f8d0819..f8c0601 100644
--- a/Documentation/git-diff.txt
+++ b/Documentation/git-diff.txt
@@ -12,6 +12,7 @@
'git diff' [options] [<commit>] [--] [<path>...]
'git diff' [options] --cached [<commit>] [--] [<path>...]
'git diff' [options] <commit> <commit> [--] [<path>...]
+'git diff' [options] <blob> <blob>
'git diff' [options] [--no-index] [--] <path> <path>
DESCRIPTION
@@ -55,6 +56,11 @@
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
@@ -72,8 +78,7 @@
Just in case if you are doing something exotic, it should be
noted that all of the <commit> in the above description, except
in the last two forms that use ".." notations, can be any
-<tree>. The third form ('git diff <commit> <commit>') can also
-be used to compare two <blob> objects.
+<tree>.
For a more complete list of ways to spell <commit>, see
"SPECIFYING REVISIONS" section in linkgit:gitrevisions[7].
diff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt
index d1844ea..68bca1a 100644
--- a/Documentation/git-fast-import.txt
+++ b/Documentation/git-fast-import.txt
@@ -427,7 +427,7 @@
Here `<name>` is the person's display name (for example
``Com M Itter'') and `<email>` is the person's email address
-(``cm@example.com''). `LT` and `GT` are the literal less-than (\x3c)
+(``\cm@example.com''). `LT` and `GT` are the literal less-than (\x3c)
and greater-than (\x3e) symbols. These are required to delimit
the email address from the other fields in the line. Note that
`<name>` and `<email>` are free-form and may contain any sequence
diff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt
index 8b0d3ad..69decb1 100644
--- a/Documentation/git-svn.txt
+++ b/Documentation/git-svn.txt
@@ -628,10 +628,19 @@
Default: "svn"
--follow-parent::
+ This option is only relevant if we are tracking branches (using
+ one of the repository layout options --trunk, --tags,
+ --branches, --stdlayout). For each tracked branch, try to find
+ out where its revision was copied from, and set
+ a suitable parent in the first git commit for the branch.
This is especially helpful when we're tracking a directory
- that has been moved around within the repository, or if we
- started tracking a branch and never tracked the trunk it was
- descended from. This feature is enabled by default, use
+ that has been moved around within the repository. If this
+ feature is disabled, the branches created by 'git svn' will all
+ be linear and not share any history, meaning that there will be
+ no information on where branches were branched off or merged.
+ However, following long/convoluted histories can take a long
+ time, so disabling this feature may speed up the cloning
+ process. This feature is enabled by default, use
--no-follow-parent to disable it.
+
[verse]
@@ -739,7 +748,8 @@
BASIC EXAMPLES
--------------
-Tracking and contributing to the trunk of a Subversion-managed project:
+Tracking and contributing to the trunk of a Subversion-managed project
+(ignoring tags and branches):
------------------------------------------------------------------------
# Clone a repo (like git clone):
@@ -764,8 +774,10 @@
(complete with a trunk, tags and branches):
------------------------------------------------------------------------
-# Clone a repo (like git clone):
- git svn clone http://svn.example.com/project -T trunk -b branches -t tags
+# Clone a repo with standard SVN directory layout (like git clone):
+ git svn clone http://svn.example.com/project --stdlayout
+# Or, if the repo uses a non-standard directory layout:
+ git svn clone http://svn.example.com/project -T tr -b branch -t tag
# View all branches and tags you have cloned:
git branch -r
# Create a new branch in SVN
@@ -830,6 +842,52 @@
users keep history as linear as possible inside git to ease
compatibility with SVN (see the CAVEATS section below).
+HANDLING OF SVN BRANCHES
+------------------------
+If 'git svn' is configured to fetch branches (and --follow-branches
+is in effect), it sometimes creates multiple git branches for one
+SVN branch, where the addtional branches have names of the form
+'branchname@nnn' (with nnn an SVN revision number). These additional
+branches are created if 'git svn' cannot find a parent commit for the
+first commit in an SVN branch, to connect the branch to the history of
+the other branches.
+
+Normally, the first commit in an SVN branch consists
+of a copy operation. 'git svn' will read this commit to get the SVN
+revision the branch was created from. It will then try to find the
+git commit that corresponds to this SVN revision, and use that as the
+parent of the branch. However, it is possible that there is no suitable
+git commit to serve as parent. This will happen, among other reasons,
+if the SVN branch is a copy of a revision that was not fetched by 'git
+svn' (e.g. because it is an old revision that was skipped with
+'--revision'), or if in SVN a directory was copied that is not tracked
+by 'git svn' (such as a branch that is not tracked at all, or a
+subdirectory of a tracked branch). In these cases, 'git svn' will still
+create a git branch, but instead of using an existing git commit as the
+parent of the branch, it will read the SVN history of the directory the
+branch was copied from and create appropriate git commits. This is
+indicated by the message "Initializing parent: <branchname>".
+
+Additionally, it will create a special branch named
+'<branchname>@<SVN-Revision>', where <SVN-Revision> is the SVN revision
+number the branch was copied from. This branch will point to the newly
+created parent commit of the branch. If in SVN the branch was deleted
+and later recreated from a different version, there will be multiple
+such branches with an '@'.
+
+Note that this may mean that multiple git commits are created for a
+single SVN revision.
+
+An example: in an SVN repository with a standard
+trunk/tags/branches layout, a directory trunk/sub is created in r.100.
+In r.200, trunk/sub is branched by copying it to branches/. 'git svn
+clone -s' will then create a branch 'sub'. It will also create new git
+commits for r.100 through r.199 and use these as the history of branch
+'sub'. Thus there will be two git commits for each revision from r.100
+to r.199 (one containing trunk/, one containing trunk/sub/). Finally,
+it will create a branch 'sub@200' pointing to the new parent commit of
+branch 'sub' (i.e. the commit for r.200 and trunk/sub/).
+
CAVEATS
-------
@@ -871,6 +929,21 @@
you've already pushed to a remote repository for other users, and
dcommit with SVN is analogous to that.
+When cloning an SVN repository, if none of the options for describing
+the repository layout is used (--trunk, --tags, --branches,
+--stdlayout), 'git svn clone' will create a git repository with
+completely linear history, where branches and tags appear as separate
+directories in the working copy. While this is the easiest way to get a
+copy of a complete repository, for projects with many branches it will
+lead to a working copy many times larger than just the trunk. Thus for
+projects using the standard directory structure (trunk/branches/tags),
+it is recommended to clone with option '--stdlayout'. If the project
+uses a non-standard structure, and/or if branches and tags are not
+required, it is easiest to only clone one directory (typically trunk),
+without giving any repository layout options. If the full history with
+branches and tags is required, the options '--trunk' / '--branches' /
+'--tags' must be used.
+
When using multiple --branches or --tags, 'git svn' does not automatically
handle name collisions (for example, if two branches from different paths have
the same name, or if a branch and a tag have the same name). In these cases,
@@ -894,6 +967,12 @@
renamed and copied files is fully supported if they're similar enough
for git to detect them.
+In SVN, it is possible (though discouraged) to commit changes to a tag
+(because a tag is just a directory copy, thus technically the same as a
+branch). When cloning an SVN repository, 'git svn' cannot know if such a
+commit to a tag will happen in the future. Thus it acts conservatively
+and imports all SVN tags as branches, prefixing the tag name with 'tags/'.
+
CONFIGURATION
-------------
diff --git a/Documentation/git-tag.txt b/Documentation/git-tag.txt
index 247534e..6470cff 100644
--- a/Documentation/git-tag.txt
+++ b/Documentation/git-tag.txt
@@ -129,7 +129,7 @@
CONFIGURATION
-------------
By default, 'git tag' in sign-with-default mode (-s) will use your
-committer identity (of the form "Your Name <your@email.address>") to
+committer identity (of the form "Your Name <\your@email.address>") to
find a key. If you want to use a different default key, you can specify
it in the repository configuration as follows:
diff --git a/Documentation/mailmap.txt b/Documentation/mailmap.txt
index 288f04e..dd89fca 100644
--- a/Documentation/mailmap.txt
+++ b/Documentation/mailmap.txt
@@ -46,7 +46,7 @@
Joe R. Developer <joe@example.com>
------------
-Note how there is no need for an entry for <jane@laptop.(none)>, because the
+Note how there is no need for an entry for `<jane@laptop.(none)>`, because the
real name of that author is already correct.
Example 2: Your repository contains commits from the following
diff --git a/Documentation/technical/api-index-skel.txt b/Documentation/technical/api-index-skel.txt
index af7cc2e..730cfac 100644
--- a/Documentation/technical/api-index-skel.txt
+++ b/Documentation/technical/api-index-skel.txt
@@ -11,5 +11,3 @@
////////////////////////////////////////////////////////////////
// table of contents end
////////////////////////////////////////////////////////////////
-
-2007-11-24
diff --git a/Documentation/technical/index-format.txt b/Documentation/technical/index-format.txt
index 57d6f91..7324154 100644
--- a/Documentation/technical/index-format.txt
+++ b/Documentation/technical/index-format.txt
@@ -161,8 +161,9 @@
this span of index as a tree.
An entry can be in an invalidated state and is represented by having
- -1 in the entry_count field. In this case, there is no object name
- and the next entry starts immediately after the newline.
+ a negative number in the entry_count field. In this case, there is no
+ object name and the next entry starts immediately after the newline.
+ When writing an invalid entry, -1 should always be used as entry_count.
The entries are written out in the top-down, depth-first order. The
first entry represents the root level of the repository, followed by the
diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN
index 4bc073c..1a9e4a2 100755
--- a/GIT-VERSION-GEN
+++ b/GIT-VERSION-GEN
@@ -1,7 +1,7 @@
#!/bin/sh
GVF=GIT-VERSION-FILE
-DEF_VER=v1.8.1-rc1
+DEF_VER=v1.8.1-rc2
LF='
'
diff --git a/README b/README
index d2690ec..49713ea 100644
--- a/README
+++ b/README
@@ -19,9 +19,10 @@
unusually rich command set that provides both high-level operations
and full access to internals.
-Git is an Open Source project covered by the GNU General Public License.
-It was originally written by Linus Torvalds with help of a group of
-hackers around the net. It is currently maintained by Junio C Hamano.
+Git is an Open Source project covered by the GNU General Public
+License version 2 (some parts of it are under different licenses,
+compatible with the GPLv2). It was originally written by Linus
+Torvalds with help of a group of hackers around the net.
Please read the file INSTALL for installation instructions.
diff --git a/contrib/stats/mailmap.pl b/contrib/stats/mailmap.pl
index 4b852e2..9513f5e 100755
--- a/contrib/stats/mailmap.pl
+++ b/contrib/stats/mailmap.pl
@@ -1,38 +1,70 @@
-#!/usr/bin/perl -w
-my %mailmap = ();
-open I, "<", ".mailmap";
-while (<I>) {
- chomp;
- next if /^#/;
- if (my ($author, $mail) = /^(.*?)\s+<(.+)>$/) {
- $mailmap{$mail} = $author;
- }
-}
-close I;
+#!/usr/bin/perl
-my %mail2author = ();
-open I, "git log --pretty='format:%ae %an' |";
-while (<I>) {
- chomp;
- my ($mail, $author) = split(/\t/, $_);
- next if exists $mailmap{$mail};
- $mail2author{$mail} ||= {};
- $mail2author{$mail}{$author} ||= 0;
- $mail2author{$mail}{$author}++;
-}
-close I;
+use warnings 'all';
+use strict;
+use Getopt::Long;
-while (my ($mail, $authorcount) = each %mail2author) {
- # %$authorcount is ($author => $count);
- # sort and show the names from the most frequent ones.
- my @names = (map { $_->[0] }
- sort { $b->[1] <=> $a->[1] }
- map { [$_, $authorcount->{$_}] }
- keys %$authorcount);
- if (1 < @names) {
- for (@names) {
- print "$_ <$mail>\n";
+my $match_emails;
+my $match_names;
+my $order_by = 'count';
+Getopt::Long::Configure(qw(bundling));
+GetOptions(
+ 'emails|e!' => \$match_emails,
+ 'names|n!' => \$match_names,
+ 'count|c' => sub { $order_by = 'count' },
+ 'time|t' => sub { $order_by = 'stamp' },
+) or exit 1;
+$match_emails = 1 unless $match_names;
+
+my $email = {};
+my $name = {};
+
+open(my $fh, '-|', "git log --format='%at <%aE> %aN'");
+while(<$fh>) {
+ my ($t, $e, $n) = /(\S+) <(\S+)> (.*)/;
+ mark($email, $e, $n, $t);
+ mark($name, $n, $e, $t);
+}
+close($fh);
+
+if ($match_emails) {
+ foreach my $e (dups($email)) {
+ foreach my $n (vals($email->{$e})) {
+ show($n, $e, $email->{$e}->{$n});
}
+ print "\n";
}
}
+if ($match_names) {
+ foreach my $n (dups($name)) {
+ foreach my $e (vals($name->{$n})) {
+ show($n, $e, $name->{$n}->{$e});
+ }
+ print "\n";
+ }
+}
+exit 0;
+sub mark {
+ my ($h, $k, $v, $t) = @_;
+ my $e = $h->{$k}->{$v} ||= { count => 0, stamp => 0 };
+ $e->{count}++;
+ $e->{stamp} = $t unless $t < $e->{stamp};
+}
+
+sub dups {
+ my $h = shift;
+ return grep { keys($h->{$_}) > 1 } keys($h);
+}
+
+sub vals {
+ my $h = shift;
+ return sort {
+ $h->{$b}->{$order_by} <=> $h->{$a}->{$order_by}
+ } keys($h);
+}
+
+sub show {
+ my ($n, $e, $h) = @_;
+ print "$n <$e> ($h->{$order_by})\n";
+}
diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh
index 5189446..f5a79b1 100755
--- a/t/t7004-tag.sh
+++ b/t/t7004-tag.sh
@@ -1066,12 +1066,12 @@
'
# usage with rfc1991 signatures
-echo "rfc1991" > gpghome/gpg.conf
get_tag_header rfc1991-signed-tag $commit commit $time >expect
echo "RFC1991 signed tag" >>expect
echo '-----BEGIN PGP MESSAGE-----' >>expect
test_expect_success GPG \
'creating a signed tag with rfc1991' '
+ echo "rfc1991" >gpghome/gpg.conf &&
git tag -s -m "RFC1991 signed tag" rfc1991-signed-tag $commit &&
get_tag_msg rfc1991-signed-tag >actual &&
test_cmp expect actual
@@ -1085,6 +1085,7 @@
test_expect_success GPG \
'reediting a signed tag body omits signature' '
+ echo "rfc1991" >gpghome/gpg.conf &&
echo "RFC1991 signed tag" >expect &&
GIT_EDITOR=./fakeeditor git tag -f -s rfc1991-signed-tag $commit &&
test_cmp expect actual
@@ -1092,11 +1093,13 @@
test_expect_success GPG \
'verifying rfc1991 signature' '
+ echo "rfc1991" >gpghome/gpg.conf &&
git tag -v rfc1991-signed-tag
'
test_expect_success GPG \
'list tag with rfc1991 signature' '
+ echo "rfc1991" >gpghome/gpg.conf &&
echo "rfc1991-signed-tag RFC1991 signed tag" >expect &&
git tag -l -n1 rfc1991-signed-tag >actual &&
test_cmp expect actual &&