{"thread":{"id":"11082","subject":"[PATCH] hg-to-git: handle an empty dir in hg by combining git commits","startedAt":"2007-12-01T17:59:23Z","lastAt":"2007-12-06T12:50:39Z","messageCount":8,"participants":["Mark Drago","Junio C Hamano","Nicolas Pitre"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"61592","messageId":"4751A0FB.6090705@gmail.com","threadId":"11082","inReplyTo":null,"subject":"[PATCH] hg-to-git: handle an empty dir in hg by combining git commits","fromName":"Mark Drago","fromEmail":"markdrago@gmail.com","sentAt":"2007-12-01T17:59:23Z","receivedAt":"2007-12-01T17:59:23Z","isPatch":true,"sender":{"key":"markdrago@gmail.com","avatar":"https://gravatar.com/avatar/44978f3f99c6ac0e3f95f9a6be0846a07005d7ce1fd17a28d175f745b4401e6d?d=mp&s=160"},"body":"I had a subversion repository which was then converted to hg and now is moving\nin to git.  The first commit in the svn repo was just the creation of the empty\ndirectory.  This made its way in to the hg repository fine, but converting from\nhg to git would cause an error.  The problem was that hg-to-git.py tries to\ncommit the change, git-commit fails, and then hg-to-git.py tries to checkout\nthe new revision and that fails (b/c it was not created).  This may have only\ncaused an error because it was the first commit in the repository.  If an empty\ndirectory was added in the middle of the repo somewhere things might have\nworked out fine.\n\nThis patch will detect that there are no changes to commit (using git-status),\nand will not perform the commit, but will instead combine the log messages of\nthat (non-)commit with the next commit.\n\nSigned-off-by: Mark Drago <markdrago@gmail.com>\n---\n contrib/hg-to-git/hg-to-git.py |   15 +++++++++++++--\n 1 files changed, 13 insertions(+), 2 deletions(-)\n\ndiff --git a/contrib/hg-to-git/hg-to-git.py b/contrib/hg-to-git/hg-to-git.py\nindex 6bff49b..06e1b41 100755\n--- a/contrib/hg-to-git/hg-to-git.py\n+++ b/contrib/hg-to-git/hg-to-git.py\n@@ -139,6 +139,7 @@ if not hgvers.has_key(\"0\"):\n     os.system('git-init-db')\n \n # loop through every hg changeset\n+previous_comment = None\n for cset in range(int(tip) + 1):\n \n     # incremental, already seen\n@@ -159,6 +160,8 @@ for cset in range(int(tip) + 1):\n \n     (fdcomment, filecomment) = tempfile.mkstemp()\n     csetcomment = os.popen('hg log -r %d -v | grep -v ^changeset: | grep -v ^parent: | grep -v ^user: | grep -v ^date | grep -v ^files: | grep -v ^description: | grep -v ^tag: | grep -v ^branch:' % cset).read().strip()\n+    if (previous_comment):\n+\tcsetcomment += previous_comment\n     os.write(fdcomment, csetcomment)\n     os.close(fdcomment)\n \n@@ -181,8 +184,8 @@ for cset in range(int(tip) + 1):\n         print 'tag:', tag\n     print '-----------------------------------------'\n \n-    # checkout the parent if necessary\n-    if cset != 0:\n+    # checkout the parent if there is a repo to checkout from\n+    if hgvers.has_key(\"0\"):\n         if hgbranch[str(cset)] == \"branch-\" + str(cset):\n             print 'creating new branch', hgbranch[str(cset)]\n             os.system('git-checkout -b %s %s' % (hgbranch[str(cset)], hgvers[parent]))\n@@ -210,6 +213,14 @@ for cset in range(int(tip) + 1):\n     # delete removed files\n     os.system('git-ls-files -x .hg --deleted | git-update-index --remove --stdin')\n \n+    # is there something that git will commit (maybe just empty dir was added)\n+    stat = os.system('git-status -a')\n+    if (stat != 0):\n+\tprint \"No changes git notices, will combine log with next commit (maybe empty dir?)\"\n+\tprevious_comment = \"\\n\\n--- hg-to-git merged commit ---\\n\\n\" + csetcomment\n+\tcontinue\n+    previous_comment = None\n+\n     # commit\n     os.system(getgitenv(user, date) + 'git-commit -a -F %s' % filecomment)\n     os.unlink(filecomment)\n-- \n1.5.2.4\n"},{"id":"61598","messageId":"7vd4tq41zt.fsf@gitster.siamese.dyndns.org","threadId":"11082","inReplyTo":"4751A0FB.6090705@gmail.com","subject":"Re: [PATCH] hg-to-git: handle an empty dir in hg by combining git commits","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-12-01T20:02:46Z","receivedAt":"2007-12-01T20:02:46Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Mark Drago <markdrago@gmail.com> writes:\n\n> This patch will detect that there are no changes to commit (using git-status),\n> and will not perform the commit, but will instead combine the log messages of\n> that (non-)commit with the next commit.\n\nI think a better approach would be to implement --no-tree-change-is-ok\noption to git-commit, strictly for use by foreign scm interface scripts\nlike yours.  It does not usually make sense to record a commit that has\nthe exact same tree as its sole parent commit and that is why git-commit\nprevents you from making that mistake, but when data from foreign scm is\ninvolved, it is a different story.  We are equipped to represent such a\n(perhaps insane, perhaps by mistake, or perhaps done on purpose) change\nand it is better to represent it bypassing the safety valve for native\nuse.\n"},{"id":"61750","messageId":"7v63zgkw0x.fsf@gitster.siamese.dyndns.org","threadId":"11082","inReplyTo":"7vd4tq41zt.fsf@gitster.siamese.dyndns.org","subject":"[PATCH] git-commit --allow-empty","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-12-03T08:44:14Z","receivedAt":"2007-12-03T08:44:14Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"It does not usually make sense to record a commit that has the exact\nsame tree as its sole parent commit and that is why git-commit prevents\nyou from making such a mistake, but when data from foreign scm is\ninvolved, it is a different story.  We are equipped to represent such an\n(perhaps insane, perhaps by mistake, or perhaps done on purpose) empty\nchange, and it is better to represent it bypassing the safety valve for\nnative use.\n\nThis is primarily for use by foreign scm interface scripts.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n\n * This is for 'next', on top of an earlier \"allow amending '-s ours' merge\".\n\n Documentation/git-commit.txt |    8 +++++++-\n builtin-commit.c             |    5 +++--\n 2 files changed, 10 insertions(+), 3 deletions(-)\n\ndiff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt\nindex d4bfd49..a7ef71f 100644\n--- a/Documentation/git-commit.txt\n+++ b/Documentation/git-commit.txt\n@@ -10,7 +10,7 @@ SYNOPSIS\n [verse]\n 'git-commit' [-a | --interactive] [-s] [-v] [-u]\n \t   [(-c | -C) <commit> | -F <file> | -m <msg> | --amend]\n-\t   [--no-verify] [-e] [--author <author>]\n+\t   [--allow-empty] [--no-verify] [-e] [--author <author>]\n \t   [--] [[-i | -o ]<file>...]\n \n DESCRIPTION\n@@ -89,6 +89,12 @@ OPTIONS\n \tThis option bypasses the pre-commit hook.\n \tSee also link:hooks.html[hooks].\n \n+--allow-empty::\n+\tUsually recording a commit that has the exact same tree as its\n+\tsole parent commit and the command prevents you from making such\n+\ta mistake.  This option bypasses the safety, and is primarily\n+\tfor use by foreign scm interface scripts.\n+\n -e|--edit::\n \tThe message taken from file with `-F`, command line with\n \t`-m`, and from file with `-C` are usually used as the\ndiff --git a/builtin-commit.c b/builtin-commit.c\nindex 6c2dc39..e635d99 100644\n--- a/builtin-commit.c\n+++ b/builtin-commit.c\n@@ -46,7 +46,7 @@ static enum {\n static char *logfile, *force_author, *template_file;\n static char *edit_message, *use_message;\n static int all, edit_flag, also, interactive, only, amend, signoff;\n-static int quiet, verbose, untracked_files, no_verify;\n+static int quiet, verbose, untracked_files, no_verify, allow_empty;\n \n static int no_edit, initial_commit, in_merge;\n const char *only_include_assumed;\n@@ -87,6 +87,7 @@ static struct option builtin_commit_options[] = {\n \tOPT_BOOLEAN('n', \"no-verify\", &no_verify, \"bypass pre-commit hook\"),\n \tOPT_BOOLEAN(0, \"amend\", &amend, \"amend previous commit\"),\n \tOPT_BOOLEAN(0, \"untracked-files\", &untracked_files, \"show all untracked files\"),\n+\tOPT_BOOLEAN(0, \"allow-empty\", &allow_empty, \"ok to record an empty change\"),\n \n \tOPT_END()\n };\n@@ -710,7 +711,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)\n \t}\n \n \tif (!prepare_log_message(index_file, prefix) && !in_merge &&\n-\t    !(amend && is_a_merge(head_sha1))) {\n+\t    !allow_empty && !(amend && is_a_merge(head_sha1))) {\n \t\trun_status(stdout, index_file, prefix);\n \t\trollback_index_files();\n \t\tunlink(commit_editmsg);\n-- \n1.5.3.7-2077-ga07a\n"},{"id":"61751","messageId":"7vzlwsjh1q.fsf@gitster.siamese.dyndns.org","threadId":"11082","inReplyTo":"7v63zgkw0x.fsf@gitster.siamese.dyndns.org","subject":"[PATCH] git-commit --allow-empty","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-12-03T08:53:05Z","receivedAt":"2007-12-03T08:53:05Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"It does not usually make sense to record a commit that has the exact\nsame tree as its sole parent commit and that is why git-commit prevents\nyou from making such a mistake, but when data from foreign scm is\ninvolved, it is a different story.  We are equipped to represent such an\n(perhaps insane, perhaps by mistake, or perhaps done on purpose) empty\nchange, and it is better to represent it bypassing the safety valve for\nnative use.\n\nThis is primarily for use by foreign scm interface scripts.\n\nSigned-off-by: Junio C Hamano <gitster@pobox.com>\n---\n\n * And this is for 'master'.\n\n Documentation/git-commit.txt |    8 +++++++-\n git-commit.sh                |   13 ++++++++++---\n t/t7501-commit.sh            |    7 +++++++\n 3 files changed, 24 insertions(+), 4 deletions(-)\n\ndiff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt\nindex d4bfd49..a7ef71f 100644\n--- a/Documentation/git-commit.txt\n+++ b/Documentation/git-commit.txt\n@@ -10,7 +10,7 @@ SYNOPSIS\n [verse]\n 'git-commit' [-a | --interactive] [-s] [-v] [-u]\n \t   [(-c | -C) <commit> | -F <file> | -m <msg> | --amend]\n-\t   [--no-verify] [-e] [--author <author>]\n+\t   [--allow-empty] [--no-verify] [-e] [--author <author>]\n \t   [--] [[-i | -o ]<file>...]\n \n DESCRIPTION\n@@ -89,6 +89,12 @@ OPTIONS\n \tThis option bypasses the pre-commit hook.\n \tSee also link:hooks.html[hooks].\n \n+--allow-empty::\n+\tUsually recording a commit that has the exact same tree as its\n+\tsole parent commit and the command prevents you from making such\n+\ta mistake.  This option bypasses the safety, and is primarily\n+\tfor use by foreign scm interface scripts.\n+\n -e|--edit::\n \tThe message taken from file with `-F`, command line with\n \t`-m`, and from file with `-C` are usually used as the\ndiff --git a/git-commit.sh b/git-commit.sh\nindex cef76a7..2c4a406 100755\n--- a/git-commit.sh\n+++ b/git-commit.sh\n@@ -74,6 +74,7 @@ trap '\n \n all=\n also=\n+allow_empty=f\n interactive=\n only=\n logfile=\n@@ -114,6 +115,10 @@ do\n \t-a|--a|--al|--all)\n \t\tall=t\n \t\t;;\n+\t--allo|--allow|--allow-|--allow-e|--allow-em|--allow-emp|\\\n+\t--allow-empt|--allow-empty)\n+\t\tallow_empty=t\n+\t\t;;\n \t--au=*|--aut=*|--auth=*|--autho=*|--author=*)\n \t\tforce_author=\"${1#*=}\"\n \t\t;;\n@@ -515,9 +520,11 @@ else\n \t# we need to check if there is anything to commit\n \trun_status >/dev/null\n fi\n-case \"$?,$PARENTS\" in\n-0,* | *,-p' '?*-p' '?*)\n-\t# a merge commit can record the same tree as its parent.\n+case \"$allow_empty,$?,$PARENTS\" in\n+t,* | ?,0,* | ?,*,-p' '?*-p' '?*)\n+\t# an explicit --allow-empty, or a merge commit can record the\n+\t# same tree as its parent.  Otherwise having commitable paths\n+\t# is required.\n \t;;\n *)\n \trm -f \"$GIT_DIR/COMMIT_EDITMSG\" \"$GIT_DIR/SQUASH_MSG\"\ndiff --git a/t/t7501-commit.sh b/t/t7501-commit.sh\nindex 2e7bcb0..0316ecf 100755\n--- a/t/t7501-commit.sh\n+++ b/t/t7501-commit.sh\n@@ -256,6 +256,13 @@ test_expect_success 'same tree (single parent)' '\n \n '\n \n+test_expect_success 'same tree (single parent) --allow-empty' '\n+\n+\tgit commit --allow-empty -m \"forced empty\" &&\n+\tgit cat-file commit HEAD | grep forced\n+\n+'\n+\n test_expect_success 'same tree (merge and amend merge)' '\n \n \tgit checkout -b side HEAD^ &&\n-- \n1.5.3.7-2077-ga07a\n"},{"id":"61794","messageId":"alpine.LFD.0.99999.0712031255560.9605@xanadu.home","threadId":"11082","inReplyTo":"7v63zgkw0x.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH] git-commit --allow-empty","fromName":"Nicolas Pitre","fromEmail":"nico@cam.org","sentAt":"2007-12-03T17:58:29Z","receivedAt":"2007-12-03T17:58:29Z","isPatch":true,"sender":{"key":"nico@fluxnic.net","avatar":"https://avatars.githubusercontent.com/u/702790?v=4"},"body":"On Mon, 3 Dec 2007, Junio C Hamano wrote:\n\n> +--allow-empty::\n> +\tUsually recording a commit that has the exact same tree as its\n> +\tsole parent commit and the command prevents you from making such\n> +\ta mistake.  This option bypasses the safety, and is primarily\n> +\tfor use by foreign scm interface scripts.\n\nThe first sentence is rather buggy I would say.\n\n\nNicolas\n"},{"id":"61800","messageId":"7vhciziqz9.fsf@gitster.siamese.dyndns.org","threadId":"11082","inReplyTo":"alpine.LFD.0.99999.0712031255560.9605@xanadu.home","subject":"Re: [PATCH] git-commit --allow-empty","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-12-03T18:16:10Z","receivedAt":"2007-12-03T18:16:10Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Nicolas Pitre <nico@cam.org> writes:\n\n> On Mon, 3 Dec 2007, Junio C Hamano wrote:\n>\n>> +--allow-empty::\n>> +\tUsually recording a commit that has the exact same tree as its\n>> +\tsole parent commit and the command prevents you from making such\n>> +\ta mistake.  This option bypasses the safety, and is primarily\n>> +\tfor use by foreign scm interface scripts.\n>\n> The first sentence is rather buggy I would say.\n\nIt indeed is.  Sorry.\n"},{"id":"61974","messageId":"7veje11v7f.fsf@gitster.siamese.dyndns.org","threadId":"11082","inReplyTo":"7vd4tq41zt.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH] hg-to-git: handle an empty dir in hg by combining git commits","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-12-05T07:01:24Z","receivedAt":"2007-12-05T07:01:24Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Mark Drago <markdrago@gmail.com> writes:\n>\n>> This patch will detect that there are no changes to commit (using git-status),\n>> and will not perform the commit, but will instead combine the log messages of\n>> that (non-)commit with the next commit.\n>\n> I think a better approach would be to implement --no-tree-change-is-ok\n> option to git-commit, strictly for use by foreign scm interface scripts\n> like yours.  It does not usually make sense to record a commit that has\n> the exact same tree as its sole parent commit and that is why git-commit\n> prevents you from making that mistake, but when data from foreign scm is\n> involved, it is a different story.  We are equipped to represent such a\n> (perhaps insane, perhaps by mistake, or perhaps done on purpose) change\n> and it is better to represent it bypassing the safety valve for native\n> use.\n\nSo I did \"git commit --allow-empty\".  With that, perhaps the following\nwill fix the issue?\n\nI won't be commiting this myself until I hear a positive Ack.\n\n---\n contrib/hg-to-git/hg-to-git.py |    2 +-\n 1 files changed, 1 insertions(+), 1 deletions(-)\n\ndiff --git a/contrib/hg-to-git/hg-to-git.py b/contrib/hg-to-git/hg-to-git.py\nindex 7a1c3e4..9befb92 100755\n--- a/contrib/hg-to-git/hg-to-git.py\n+++ b/contrib/hg-to-git/hg-to-git.py\n@@ -211,7 +211,7 @@ for cset in range(int(tip) + 1):\n     os.system('git-ls-files -x .hg --deleted | git-update-index --remove --stdin')\n \n     # commit\n-    os.system(getgitenv(user, date) + 'git-commit -a -F %s' % filecomment)\n+    os.system(getgitenv(user, date) + 'git commit --allow-empty -a -F %s' % filecomment)\n     os.unlink(filecomment)\n \n     # tag\n"},{"id":"62143","messageId":"af675f7f0712060450g2e9d0496y93749c2209bd0f0c@mail.gmail.com","threadId":"11082","inReplyTo":"7veje11v7f.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH] hg-to-git: handle an empty dir in hg by combining git commits","fromName":"Mark Drago","fromEmail":"markdrago@gmail.com","sentAt":"2007-12-06T12:50:39Z","receivedAt":"2007-12-06T12:50:39Z","isPatch":true,"sender":{"key":"markdrago@gmail.com","avatar":"https://gravatar.com/avatar/44978f3f99c6ac0e3f95f9a6be0846a07005d7ce1fd17a28d175f745b4401e6d?d=mp&s=160"},"body":"On Dec 5, 2007 2:01 AM, Junio C Hamano <gitster@pobox.com> wrote:\n>\n> Junio C Hamano <gitster@pobox.com> writes:\n>\n> > Mark Drago <markdrago@gmail.com> writes:\n> >\n> >> This patch will detect that there are no changes to commit (using git-status),\n> >> and will not perform the commit, but will instead combine the log messages of\n> >> that (non-)commit with the next commit.\n> >\n> > I think a better approach would be to implement --no-tree-change-is-ok\n> > option to git-commit, strictly for use by foreign scm interface scripts\n> > like yours.  It does not usually make sense to record a commit that has\n> > the exact same tree as its sole parent commit and that is why git-commit\n> > prevents you from making that mistake, but when data from foreign scm is\n> > involved, it is a different story.  We are equipped to represent such a\n> > (perhaps insane, perhaps by mistake, or perhaps done on purpose) change\n> > and it is better to represent it bypassing the safety valve for native\n> > use.\n>\n> So I did \"git commit --allow-empty\".  With that, perhaps the following\n> will fix the issue?\n>\n> I won't be commiting this myself until I hear a positive Ack.\n\nI gave this a test and it works perfectly well.  Commit away.\n\nThanks,\nMark.\n\n> ---\n>  contrib/hg-to-git/hg-to-git.py |    2 +-\n>  1 files changed, 1 insertions(+), 1 deletions(-)\n>\n> diff --git a/contrib/hg-to-git/hg-to-git.py b/contrib/hg-to-git/hg-to-git.py\n> index 7a1c3e4..9befb92 100755\n> --- a/contrib/hg-to-git/hg-to-git.py\n> +++ b/contrib/hg-to-git/hg-to-git.py\n> @@ -211,7 +211,7 @@ for cset in range(int(tip) + 1):\n>      os.system('git-ls-files -x .hg --deleted | git-update-index --remove --stdin')\n>\n>      # commit\n> -    os.system(getgitenv(user, date) + 'git-commit -a -F %s' % filecomment)\n> +    os.system(getgitenv(user, date) + 'git commit --allow-empty -a -F %s' % filecomment)\n>      os.unlink(filecomment)\n>\n>      # tag\n>\n"}]}