threads / patch / 18531

patch, 2 partsinit: support --import to add all files and commit right after init

Subject: [PATCH 1/2] init: support --import to add all files and commit right after init

## tl;dr

14 messages between Mar 25, 2009 and Mar 28, 2009. Diffs are folded; open one to read it.

replies: 13people: 5as markdown or json

Nguyễn Thái Ngọc Duy· Mar 25, 2009, 10:58 UTC · lore

This is equivalent to "git init;git add .;git commit -q -m blah". I find myself doing that too many times, hence this shortcut.

In future, --fast-import support would also be nice if the import directory has a lot of files.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 Documentation/git-init.txt |   17 ++++++++++++++-
 builtin-init-db.c          |   49 ++++++++++++++++++++++++++++++++++++++++---
 t/t0001-init.sh            |   44 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 105 insertions(+), 5 deletions(-)
Show changes to 3 files +105 −5

Documentation/git-init.txt, builtin-init-db.c, t/t0001-init.sh

diff --git a/Documentation/git-init.txt b/Documentation/git-init.txt
index 71749c0..ab75c10 100644
--- a/Documentation/git-init.txt
+++ b/Documentation/git-init.txt
@@ -8,7 +8,8 @@ git-init - Create an empty git repository or reinitialize an existing one
 
 SYNOPSIS
 --------
-'git init' [-q | --quiet] [--bare] [--template=<template_directory>] [--shared[=<permissions>]]
+'git init' [-q | --quiet] [--bare] [--template=<template_directory>]
+           [--shared[=<permissions>]] [-m|--import [<message>]]
 
 
 OPTIONS
@@ -68,6 +69,20 @@ By default, the configuration flag receive.denyNonFastForwards is enabled
 in shared repositories, so that you cannot force a non fast-forwarding push
 into it.
 
+-m <message>::
+--import <message>::
+
+Commit everything to the newly initialized repository. This is equivalent to:
+
+----------------
+$ git init
+$ git add .
+$ git commit -q -m <message>
+----------------
+
+If no message is given, "Initial commit" will be used.
+This option does not work with `--bare` nor already initialized repository.
+
 --
 
 
diff --git a/builtin-init-db.c b/builtin-init-db.c
index ee3911f..3ace4ca 100644
--- a/builtin-init-db.c
+++ b/builtin-init-db.c
@@ -6,6 +6,7 @@
 #include "cache.h"
 #include "builtin.h"
 #include "exec_cmd.h"
+#include "run-command.h"
 
 #ifndef DEFAULT_GIT_TEMPLATE_DIR
 #define DEFAULT_GIT_TEMPLATE_DIR "/usr/share/git-core/templates"
@@ -19,6 +20,7 @@
 
 static int init_is_bare_repository = 0;
 static int init_shared_repository = -1;
+static int reinit;
 
 static void safe_create_dir(const char *dir, int share)
 {
@@ -279,7 +281,7 @@ int init_db(const char *template_dir, unsigned int flags)
 {
 	const char *sha1_dir;
 	char *path;
-	int len, reinit;
+	int len;
 
 	safe_create_dir(get_git_dir(), 0);
 
@@ -363,8 +365,29 @@ static int guess_repository_type(const char *git_dir)
 	return 1;
 }
 
+static int import_files(const char *import_message)
+{
+	const char *args[6];
+	int i = 0;
+	int ret;
+
+	args[i++] = "add";
+	args[i++] = ".";
+	args[i] = NULL;
+	ret = run_command_v_opt(args, RUN_GIT_CMD);
+	if (ret)
+		return ret;
+	i = 0;
+	args[i++] = "commit";
+	args[i++] = "-q";
+	args[i++] = "-m";
+	args[i++] = import_message;
+	args[i] = NULL;
+	return run_command_v_opt(args, RUN_GIT_CMD);
+}
+
 static const char init_db_usage[] =
-"git init [-q | --quiet] [--bare] [--template=<template-directory>] [--shared[=<permissions>]]";
+"git init [-q | --quiet] [--bare] [--template=<template-directory>] [--shared[=<permissions>]] [-m|--import [<message>]]";
 
 /*
  * If you want to, you can share the DB area with any number of branches.
@@ -377,7 +400,8 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
 	const char *git_dir;
 	const char *template_dir = NULL;
 	unsigned int flags = 0;
-	int i;
+	const char *import_message = NULL;
+	int ret, i;
 
 	for (i = 1; i < argc; i++, argv++) {
 		const char *arg = argv[1];
@@ -392,12 +416,24 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
 			init_shared_repository = PERM_GROUP;
 		else if (!prefixcmp(arg, "--shared="))
 			init_shared_repository = git_config_perm("arg", arg+9);
+		else if (!strcmp(arg, "--import") || !strcmp(arg, "-m")) {
+			if (i+1 >= argc)
+				import_message = "Initial commit";
+			else {
+				import_message = argv[2];
+				i++;
+				argv++;
+			}
+		}
 		else if (!strcmp(arg, "-q") || !strcmp(arg, "--quiet"))
 			flags |= INIT_DB_QUIET;
 		else
 			usage(init_db_usage);
 	}
 
+	if (import_message && is_bare_repository_cfg == 1)
+		die("--import does not work with --bare");
+
 	/*
 	 * GIT_WORK_TREE makes sense only in conjunction with GIT_DIR
 	 * without --bare.  Catch the error early.
@@ -440,5 +476,10 @@ int cmd_init_db(int argc, const char **argv, const char *prefix)
 
 	set_git_dir(make_absolute_path(git_dir));
 
-	return init_db(template_dir, flags);
+	ret = init_db(template_dir, flags);
+	if (ret || !import_message)
+		return ret;
+	if (reinit)
+		die("--import does not work with already initialized repository");
+	return import_files(import_message);
 }
diff --git a/t/t0001-init.sh b/t/t0001-init.sh
index 5ac0a27..83a9e06 100755
--- a/t/t0001-init.sh
+++ b/t/t0001-init.sh
@@ -199,4 +199,48 @@ test_expect_success 'init honors global core.sharedRepository' '
 	x`git config -f shared-honor-global/.git/config core.sharedRepository`
 '
 
+test_expect_success 'init --import does not work with --bare' '
+	(
+		unset GIT_DIR GIT_WORK_TREE GIT_CONFIG
+		mkdir init-import-bare.git &&
+		cd init-import-bare.git &&
+		! git init --bare --import test
+	)
+
+'
+
+test_expect_success 'init --import no message' '
+	(
+		test_tick
+		unset GIT_DIR GIT_WORK_TREE GIT_CONFIG
+		mkdir init-import-nomsg &&
+		cd init-import-nomsg &&
+		touch foo bar &&
+		git init --import &&
+		test "$(git rev-parse HEAD)" = 4ff955458fd61a7b5d798b81e28c9249e8ebb5df
+	)
+'
+
+test_expect_success 'init --import' '
+	(
+		test_tick
+		unset GIT_DIR GIT_WORK_TREE GIT_CONFIG
+		mkdir init-import &&
+		cd init-import &&
+		touch foo bar &&
+		git init --import test &&
+		test "$(git rev-parse HEAD)" = 758aa5a579e42200a6fd4e4964c7e1dc1875d67d
+	)
+'
+
+test_expect_success 'init --import on already init(ed) should fail' '
+	(
+		test_tick
+		unset GIT_DIR GIT_WORK_TREE GIT_CONFIG
+		cd init-import &&
+		! git init --import testagain &&
+		test "$(git rev-parse HEAD)" = 758aa5a579e42200a6fd4e4964c7e1dc1875d67d
+	)
+'
+
 test_done
-- 
1.6.1.446.gc7851
Jeff King· Mar 25, 2009, 11:35 UTC · re: Nguyễn Thái Ngọc Duy · lore

Re: [PATCH 1/2] init: support --import to add all files and commit right after init

On Wed, Mar 25, 2009 at 09:58:40PM +1100, Nguyễn Thái Ngọc Duy wrote:
> -'git init' [-q | --quiet] [--bare] [--template=<template_directory>] [--shared[=<permissions>]]
> +'git init' [-q | --quiet] [--bare] [--template=<template_directory>]
> +           [--shared[=<permissions>]] [-m|--import [<message>]]

What happened to --import=? Whether or not "--import <arg>" works, the --long-opt= form should always work.

Show 9 quoted lines
> +		else if (!strcmp(arg, "--import") || !strcmp(arg, "-m")) {
> +			if (i+1 >= argc)
> +				import_message = "Initial commit";
> +			else {
> +				import_message = argv[2];
> +				i++;
> +				argv++;
> +			}
> +		}
This is the wrong way to do optional arguments. It means that
  git init --template=foo --import
is different from
  git init --import --template=foo
I think what you want is:
  else if (!strcmp(arg, "-m")) {
    if (i+1 >= argc)
      die("-m requires an import message");
    import_message = argv[2];
    i++;
    argv++;
  }
  else if (!strcmp(arg, "--import"))
    import_message = "Initial commit";
  else if (!prefixcmp(arg, "--import="))
      import_message = arg+9;

That is, --import has a message or not depending on the '=', and "-m" always has a message. If you want "-m" to optionally have a message then it must be used as

  git init -mfoo
-Peff
Nguyen Thai Ngoc Duy· Mar 25, 2009, 22:54 UTC · re: Jeff King · lore

Re: [PATCH 1/2] init: support --import to add all files and commit right after init

2009/3/25 Jeff King <peff@peff.net>:
Show 46 quoted lines
> On Wed, Mar 25, 2009 at 09:58:40PM +1100, Nguyễn Thái Ngọc Duy wrote:
>
>> -'git init' [-q | --quiet] [--bare] [--template=<template_directory>] [--shared[=<permissions>]]
>> +'git init' [-q | --quiet] [--bare] [--template=<template_directory>]
>> +           [--shared[=<permissions>]] [-m|--import [<message>]]
>
> What happened to --import=? Whether or not "--import <arg>" works, the
> --long-opt= form should always work.
>
>> +             else if (!strcmp(arg, "--import") || !strcmp(arg, "-m")) {
>> +                     if (i+1 >= argc)
>> +                             import_message = "Initial commit";
>> +                     else {
>> +                             import_message = argv[2];
>> +                             i++;
>> +                             argv++;
>> +                     }
>> +             }
>
> This is the wrong way to do optional arguments. It means that
>
>  git init --template=foo --import
>
> is different from
>
>  git init --import --template=foo
>
> I think what you want is:
>
>  else if (!strcmp(arg, "-m")) {
>    if (i+1 >= argc)
>      die("-m requires an import message");
>    import_message = argv[2];
>    i++;
>    argv++;
>  }
>  else if (!strcmp(arg, "--import"))
>    import_message = "Initial commit";
>  else if (!prefixcmp(arg, "--import="))
>      import_message = arg+9;
>
> That is, --import has a message or not depending on the '=', and "-m"
> always has a message. If you want "-m" to optionally have a message then
> it must be used as
>
>  git init -mfoo
Right. Should not work late (or send it in the same night). Will rework.
-- 
Duy
Santi Béjar· Mar 25, 2009, 11:56 UTC · re: Nguyễn Thái Ngọc Duy · lore

Re: [PATCH 1/2] init: support --import to add all files and commit right after init

2009/3/25 Nguyễn Thái Ngọc Duy <pclouds@gmail.com>:
Show 12 quoted lines
> +-m <message>::
> +--import <message>::
> +
> +Commit everything to the newly initialized repository. This is equivalent to:
> +
> +----------------
> +$ git init
> +$ git add .
> +$ git commit -q -m <message>
> +----------------
> +
> +If no message is given, "Initial commit" will be used.
Why a default message and not running the editor?
Santi
Johannes Schindelin· Mar 25, 2009, 12:38 UTC · re: Santi Béjar · lore

Re: [PATCH 1/2] init: support --import to add all files and commit right after init

Hi,
On Wed, 25 Mar 2009, Santi Béjar wrote:
Show 15 quoted lines
> 2009/3/25 Nguyễn Thái Ngọc Duy <pclouds@gmail.com>:
> > +-m <message>::
> > +--import <message>::
> > +
> > +Commit everything to the newly initialized repository. This is equivalent to:
> > +
> > +----------------
> > +$ git init
> > +$ git add .
> > +$ git commit -q -m <message>
> > +----------------
> > +
> > +If no message is given, "Initial commit" will be used.
> 
> Why a default message and not running the editor?
Because I would say "Initial commit" anyway.

Ciao, Dscho

Jeff King· Mar 25, 2009, 12:42 UTC · re: Johannes Schindelin · lore

Re: [PATCH 1/2] init: support --import to add all files and commit right after init

On Wed, Mar 25, 2009 at 01:38:30PM +0100, Johannes Schindelin wrote:
Show 5 quoted lines
> > > +If no message is given, "Initial commit" will be used.
> > 
> > Why a default message and not running the editor?
> 
> Because I would say "Initial commit" anyway.

Agreed. This feature is about convenience. If you really want to say something more exciting, then use "git commit" directly. Heck, you can even "git commit --amend" it afterwards.

-Peff
Santi Béjar· Mar 25, 2009, 12:49 UTC · re: Jeff King · lore

Re: [PATCH 1/2] init: support --import to add all files and commit right after init

2009/3/25 Jeff King <peff@peff.net>:
Show 7 quoted lines
> On Wed, Mar 25, 2009 at 01:38:30PM +0100, Johannes Schindelin wrote:
>
>> > > +If no message is given, "Initial commit" will be used.
>> >
>> > Why a default message and not running the editor?
>>
>> Because I would say "Initial commit" anyway.
And I would say "Commit inicial".
>
> Agreed. This feature is about convenience.
... for project in english.
> If you really want to say
> something more exciting, then use "git commit" directly. Heck, you can
> even "git commit --amend" it afterwards.
I can. But then it is no longer "convenience".

But anyway, it is like the "Merge branch..." commit message for merges. So nothing new.

Santi
Markus Heidelberg· Mar 26, 2009, 21:23 UTC · re: Santi Béjar · lore

Re: [PATCH 1/2] init: support --import to add all files and commit right after init

Santi Béjar, 25.03.2009:
Show 10 quoted lines
> 2009/3/25 Jeff King <peff@peff.net>:
> > On Wed, Mar 25, 2009 at 01:38:30PM +0100, Johannes Schindelin wrote:
> >
> >> > > +If no message is given, "Initial commit" will be used.
> >> >
> >> > Why a default message and not running the editor?
> >>
> >> Because I would say "Initial commit" anyway.
> 
> And I would say "Commit inicial".
And I would describe the current state in a few words.

Invoking an editor is more universal and I don't think the majority would be contented with "Initial commit".

Markus
Johannes Schindelin· Mar 27, 2009, 02:03 UTC · re: Markus Heidelberg · lore

Re: [PATCH 1/2] init: support --import to add all files and commit right after init

Hi,
On Thu, 26 Mar 2009, Markus Heidelberg wrote:
Show 16 quoted lines
> Santi Béjar, 25.03.2009:
> > 2009/3/25 Jeff King <peff@peff.net>:
> > > On Wed, Mar 25, 2009 at 01:38:30PM +0100, Johannes Schindelin wrote:
> > >
> > >> > > +If no message is given, "Initial commit" will be used.
> > >> >
> > >> > Why a default message and not running the editor?
> > >>
> > >> Because I would say "Initial commit" anyway.
> > 
> > And I would say "Commit inicial".
> 
> And I would describe the current state in a few words.
> 
> Invoking an editor is more universal and I don't think the majority
> would be contented with "Initial commit".

_Again_, as Peff pointed out, you are welcome to use the current method of git init && git add . && git commit, which _does_ launch an editor.

The fact that you want to spend much time (anyway) doing your initial commit does not allow you to inconvenience others.

Others who want to have a quick way to work safely with something they might need to change, and might then want to use the full power of Git to see what they changed. Without any need for a "nice" first commit.

Ciao, Dscho

Jeff King· Mar 27, 2009, 05:06 UTC · re: Johannes Schindelin · lore

Re: [PATCH 1/2] init: support --import to add all files and commit right after init

On Fri, Mar 27, 2009 at 03:03:07AM +0100, Johannes Schindelin wrote:
Show 5 quoted lines
> _Again_, as Peff pointed out, you are welcome to use the current method of 
> git init && git add . && git commit, which _does_ launch an editor.
> 
> The fact that you want to spend much time (anyway) doing your initial 
> commit does not allow you to inconvenience others.
Another option would be a patch on top of the original to allow
  git config --global init.importmessage 'Commit inicial'
or
  git config --global init.importeditor true

I have no interest in writing such a patch, but I don't see a reason to reject it.

-Peff
Jeff King· Mar 27, 2009, 05:08 UTC · re: Jeff King · lore

Re: [PATCH 1/2] init: support --import to add all files and commit right after init

On Fri, Mar 27, 2009 at 01:06:26AM -0400, Jeff King wrote:
Show 10 quoted lines
> Another option would be a patch on top of the original to allow
> 
>   git config --global init.importmessage 'Commit inicial'
> 
> or
> 
>   git config --global init.importeditor true
> 
> I have no interest in writing such a patch, but I don't see a reason to
> reject it.

Actually, there is one possible reason to reject it: scripts could not rely on the behavior of "--import" without it. But I think it is OK to make a conscious decision that this is a feature for _humans_, and that scripts can use "init && add && commit" (or they can be happy with dealing with the human's choice of editor or not).

-Peff
Markus Heidelberg· Mar 28, 2009, 10:58 UTC · re: Johannes Schindelin · lore

Re: [PATCH 1/2] init: support --import to add all files and commit right after init

Johannes Schindelin, 27.03.2009:
> Others who want to have a quick way to work safely with something they 
> might need to change, and might then want to use the full power of Git to 
> see what they changed.  Without any need for a "nice" first commit.

What's the difference between the first commit and the others? I don't see the reason, not to have a short description for it.

Markus
Johannes Schindelin· Mar 28, 2009, 12:39 UTC · re: Markus Heidelberg · lore

Re: [PATCH 1/2] init: support --import to add all files and commit right after init

Hi,
On Sat, 28 Mar 2009, Markus Heidelberg wrote:
Show 7 quoted lines
> Johannes Schindelin, 27.03.2009:
> > Others who want to have a quick way to work safely with something they 
> > might need to change, and might then want to use the full power of Git 
> > to see what they changed.  Without any need for a "nice" first commit.
> 
> What's the difference between the first commit and the others? I don't 
> see the reason, not to have a short description for it.
Maybe you can learn a new trick here:

$ tar xf /some/random/project.tar $ git init $ git add . $ git commit -m initial

and now one of two work flows:

# get the thing to work properly, or add a new feature, or clean up... $ git diff > diff.patch # send the diff to the maintainer, without ever committing

or

# make a patch series, use rebase -i to clean up after it # send the patch series to the maintainer of the random project

See?  The initial commit does not matter at all.

I do this so often that it stops being funny having to type three commands.

And having to edit a commit message I do not care about anyway everytime, just to please you, would not make it any funnier ;-)

I'll just repeat one of my favorite mantras: optimize for the common case, not for the uncommon case.

Ciao, Dscho

Markus Heidelberg· Mar 28, 2009, 13:09 UTC · re: Johannes Schindelin · lore

Re: [PATCH 1/2] init: support --import to add all files and commit right after init

Johannes Schindelin, 28.03.2009:
Show 31 quoted lines
> Hi,
> 
> On Sat, 28 Mar 2009, Markus Heidelberg wrote:
> 
> > Johannes Schindelin, 27.03.2009:
> > > Others who want to have a quick way to work safely with something they 
> > > might need to change, and might then want to use the full power of Git 
> > > to see what they changed.  Without any need for a "nice" first commit.
> > 
> > What's the difference between the first commit and the others? I don't 
> > see the reason, not to have a short description for it.
> 
> Maybe you can learn a new trick here:
> 
> $ tar xf /some/random/project.tar
> $ git init
> $ git add .
> $ git commit -m initial
> 
> and now one of two work flows:
> 
> # get the thing to work properly, or add a new feature, or clean up...
> $ git diff > diff.patch
> # send the diff to the maintainer, without ever committing
> 
> or
> 
> # make a patch series, use rebase -i to clean up after it
> # send the patch series to the maintainer of the random project
> 
> See?  The initial commit does not matter at all.

Yep, I only thought about own projects and didn't take this workflow into account. Although I have already used it myself and of course the initial commit is not interesting then.

Show 5 quoted lines
> I do this so often that it stops being funny having to type three 
> commands.
> 
> And having to edit a commit message I do not care about anyway everytime, 
> just to please you, would not make it any funnier ;-)

Understood :) But note, that my second mail was only about writing an initial commit message or not. I don't have objections against the default commit message with --import any more.

Markus

← back to recent threads