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

Subsystems: documentation, the rest

STALE3738d

14 messages, 5 authors, 2016-06-15 · open the first message on its own page

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

From: Nguyễn Thái Ngọc Duy <hidden>
Date: 2016-06-15 22:46:28

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 <redacted>
---
 Documentation/git-init.txt |   17 ++++++++++++++-
 builtin-init-db.c          |   49 ++++++++++++++++++++++++++++++++++++++++---
 t/t0001-init.sh            |   44 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 105 insertions(+), 5 deletions(-)
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

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

From: Jeff King <hidden>
Date: 2016-06-15 22:46:28

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

-Peff

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

From: Santi Béjar <hidden>
Date: 2016-06-15 22:46:28

2009/3/25 Nguyễn Thái Ngọc Duy [off-list ref]:
+-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

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

From: Johannes Schindelin <hidden>
Date: 2016-06-15 22:46:28

Hi,

On Wed, 25 Mar 2009, Santi Béjar wrote:
2009/3/25 Nguyễn Thái Ngọc Duy [off-list ref]:
quoted
+-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

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

From: Jeff King <hidden>
Date: 2016-06-15 22:46:28

On Wed, Mar 25, 2009 at 01:38:30PM +0100, Johannes Schindelin wrote:
quoted
quoted
+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

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

From: Santi Béjar <hidden>
Date: 2016-06-15 22:46:28

2009/3/25 Jeff King [off-list ref]:
On Wed, Mar 25, 2009 at 01:38:30PM +0100, Johannes Schindelin wrote:
quoted
quoted
quoted
+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

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

From: Nguyen Thai Ngoc Duy <hidden>
Date: 2016-06-15 22:46:28

2009/3/25 Jeff King [off-list ref]:
On Wed, Mar 25, 2009 at 09:58:40PM +1100, Nguyễn Thái Ngọc Duy wrote:
quoted
-'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.
quoted
+             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

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

From: Markus Heidelberg <hidden>
Date: 2016-06-15 22:46:29

Santi Béjar, 25.03.2009:
2009/3/25 Jeff King [off-list ref]:
quoted
On Wed, Mar 25, 2009 at 01:38:30PM +0100, Johannes Schindelin wrote:
quoted
quoted
quoted
+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

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

From: Johannes Schindelin <hidden>
Date: 2016-06-15 22:46:29

Hi,

On Thu, 26 Mar 2009, Markus Heidelberg wrote:
Santi Béjar, 25.03.2009:
quoted
2009/3/25 Jeff King [off-list ref]:
quoted
On Wed, Mar 25, 2009 at 01:38:30PM +0100, Johannes Schindelin wrote:
quoted
quoted
quoted
+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

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

From: Jeff King <hidden>
Date: 2016-06-15 22:46:29

On Fri, Mar 27, 2009 at 03:03:07AM +0100, Johannes Schindelin wrote:
_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

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

From: Jeff King <hidden>
Date: 2016-06-15 22:46:29

On Fri, Mar 27, 2009 at 01:06:26AM -0400, Jeff King wrote:
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

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

From: Markus Heidelberg <hidden>
Date: 2016-06-15 22:46:29

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

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

From: Johannes Schindelin <hidden>
Date: 2016-06-15 22:46:29

Hi,

On Sat, 28 Mar 2009, Markus Heidelberg wrote:
Johannes Schindelin, 27.03.2009:
quoted
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

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

From: Markus Heidelberg <hidden>
Date: 2016-06-15 22:46:29

Johannes Schindelin, 28.03.2009:
Hi,

On Sat, 28 Mar 2009, Markus Heidelberg wrote:
quoted
Johannes Schindelin, 27.03.2009:
quoted
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.
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
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help