{"thread":{"id":"13999","subject":"cvs2git with modules?","startedAt":"2008-06-17T11:21:42Z","lastAt":"2008-06-17T18:06:42Z","messageCount":4,"participants":["Kelly F. Hickel","Michael Haggerty","Geoffrey Irving"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"80131","messageId":"63BEA5E623E09F4D92233FB12A9F794302389A59@emailmn.mqsoftware.com","threadId":"13999","inReplyTo":null,"subject":"cvs2git with modules?","fromName":"Kelly F. Hickel","fromEmail":"kfh@mqsoftware.com","sentAt":"2008-06-17T11:21:42Z","receivedAt":"2008-06-17T11:21:42Z","isPatch":false,"sender":{"key":"kfh@mqsoftware.com","avatar":null},"body":"Hi All,\n\tI'm trying to use cvs2svn in cvs2git mode to convert a repo with a number of modules.  \nCan anyone tell me how to keep that module structure in the new git repo?  So, if in cvs there are two modules, \nModA and ModB, I want to see those two as top level directories in the git repo.\n\nI've tried putting adding the projects in my options file as below, but it puts the files ModA/* and ModB/* at the top level in the git repo.\n\n\nrun_options.add_project(\n    r'/home/foo/cvsrepo/ModA,\n    trunk_path=ModA',\n    symbol_transforms=[\n        ReplaceSubstringsSymbolTransform('\\\\','/'),\n        NormalizePathsSymbolTransform(),\n        ],\n    symbol_strategy_rules=[\n        UnambiguousUsageRule(),\n        BranchIfCommitsRule(),\n        HeuristicStrategyRule(),\n        HeuristicPreferredParentRule(),\n        ],\n    )\n\nrun_options.add_project(\n    r'/home/foo/cvsrepo/ModB,\n    trunk_path=ModB',\n    symbol_transforms=[\n        ReplaceSubstringsSymbolTransform('\\\\','/'),\n        NormalizePathsSymbolTransform(),\n        ],\n    symbol_strategy_rules=[\n        UnambiguousUsageRule(),\n        BranchIfCommitsRule(),\n        HeuristicStrategyRule(),\n        HeuristicPreferredParentRule(),\n        ],\n    )\n\n\n-- \n \nKelly F. Hickel\nSenior Software Architect\nMQSoftware, Inc\n952.345.8677\nkfh@mqsoftware.com\n"},{"id":"80148","messageId":"4857DC0C.8060902@alum.mit.edu","threadId":"13999","inReplyTo":"63BEA5E623E09F4D92233FB12A9F794302389A59@emailmn.mqsoftware.com","subject":"Re: cvs2git with modules?","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2008-06-17T15:45:16Z","receivedAt":"2008-06-17T15:45:16Z","isPatch":false,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"[I see you sent essentially the same question to both the git and the\ncvs2svn mailing lists.  I am replying on the git list with bcc to the\ncvs2svn list.  Followups please to git@vger.kernel.org.]\n\nKelly F. Hickel wrote:\n> I'm trying to use cvs2svn in cvs2git mode to convert a repo with a\n> number of modules.  Can anyone tell me how to keep that module\n> structure in the new git repo? So, if in cvs there are two modules,\n> ModA and ModB, I want to see those two as top level directories in\n> the git repo.\n> \n> I've tried putting adding the projects in my options file as below,\n> but it puts the files ModA/* and ModB/* at the top level in the git repo.\n> \n> run_options.add_project(\n>     r'/home/foo/cvsrepo/ModA,\n>     trunk_path=ModA',\n>     [...]\n>     )\n> \n> run_options.add_project(\n>     r'/home/foo/cvsrepo/ModB,\n>     trunk_path=ModB',\n>     [...]\n>     )\n\nI assume that what you mean is that the CVS repository contains\ndirectories like ModA/a, ModA/b, ModB/c, and ModB/d, but the resulting\ngit repository has only /a, /b, /c, and /d.  That is because cvs2git\ncompletely ignores the trunk_path argument to add_project().\n\nIt is strange that the code allows you to add multiple projects,\nconsidering that the cvs2git documentation[1] states that cvs2git only\nsupports converting single projects at a time.  I guess I forgot to\nbuild that check in.\n\nYou can get the result you want by treating ModA and ModB not as two\nseparate projects, but simply as two separate subdirectories within a\nbigger project; i.e.,\n\nrun_options.add_project(\n    r'/home/foo/cvsrepo,\n    [...]\n    )\n\n.  This is assuming that ModA and ModB are the only subdirectories\nwithin /home/foo/cvsrepo/; otherwise, make a copy of your CVS repo and\nremove the other subdirectories from the copy before the conversion.\n\nPlease note that when cvs2git is run this way, it treats tags and\nbranches as being global.  If you tagged your projects simultaneously,\nthen this is probably what you want.  But if you tagged your projects\nseparately, then tag names that happen to be the same across projects\nwill be considered the same.\n\nIt would be possible to add cvs2git support for multiproject\nconversions, but I was under the impression that it doesn't make much\nsense to put multiple projects into a single git repository.  But I'm a\nnovice git user, so I could very well be wrong about that.\n\nMichael\n\n[1] http://cvs2svn.tigris.org/cvs2git.html\n"},{"id":"80155","messageId":"7f9d599f0806171102w561ae5bfw594a3bc46eb9c8c1@mail.gmail.com","threadId":"13999","inReplyTo":"4857DC0C.8060902@alum.mit.edu","subject":"Re: cvs2git with modules?","fromName":"Geoffrey Irving","fromEmail":"irving@naml.us","sentAt":"2008-06-17T18:02:32Z","receivedAt":"2008-06-17T18:02:32Z","isPatch":false,"sender":{"key":"irving@naml.us","avatar":"https://gravatar.com/avatar/52d7452fcd134aac0fa12f57a3bb7ef5f3f7e73ca0ab36736d06c6a6132de718?d=mp&s=160"},"body":"On Tue, Jun 17, 2008 at 8:45 AM, Michael Haggerty <mhagger@alum.mit.edu> wrote:\n> [I see you sent essentially the same question to both the git and the\n> cvs2svn mailing lists.  I am replying on the git list with bcc to the\n> cvs2svn list.  Followups please to git@vger.kernel.org.]\n>\n> Kelly F. Hickel wrote:\n>> I'm trying to use cvs2svn in cvs2git mode to convert a repo with a\n>> number of modules.  Can anyone tell me how to keep that module\n>> structure in the new git repo? So, if in cvs there are two modules,\n>> ModA and ModB, I want to see those two as top level directories in\n>> the git repo.\n>>\n>> I've tried putting adding the projects in my options file as below,\n>> but it puts the files ModA/* and ModB/* at the top level in the git repo.\n>>\n>> run_options.add_project(\n>>     r'/home/foo/cvsrepo/ModA,\n>>     trunk_path=ModA',\n>>     [...]\n>>     )\n>>\n>> run_options.add_project(\n>>     r'/home/foo/cvsrepo/ModB,\n>>     trunk_path=ModB',\n>>     [...]\n>>     )\n>\n> I assume that what you mean is that the CVS repository contains\n> directories like ModA/a, ModA/b, ModB/c, and ModB/d, but the resulting\n> git repository has only /a, /b, /c, and /d.  That is because cvs2git\n> completely ignores the trunk_path argument to add_project().\n>\n> It is strange that the code allows you to add multiple projects,\n> considering that the cvs2git documentation[1] states that cvs2git only\n> supports converting single projects at a time.  I guess I forgot to\n> build that check in.\n>\n> You can get the result you want by treating ModA and ModB not as two\n> separate projects, but simply as two separate subdirectories within a\n> bigger project; i.e.,\n>\n> run_options.add_project(\n>    r'/home/foo/cvsrepo,\n>    [...]\n>    )\n>\n> .  This is assuming that ModA and ModB are the only subdirectories\n> within /home/foo/cvsrepo/; otherwise, make a copy of your CVS repo and\n> remove the other subdirectories from the copy before the conversion.\n>\n> Please note that when cvs2git is run this way, it treats tags and\n> branches as being global.  If you tagged your projects simultaneously,\n> then this is probably what you want.  But if you tagged your projects\n> separately, then tag names that happen to be the same across projects\n> will be considered the same.\n>\n> It would be possible to add cvs2git support for multiproject\n> conversions, but I was under the impression that it doesn't make much\n> sense to put multiple projects into a single git repository.  But I'm a\n> novice git user, so I could very well be wrong about that.\n>\n> Michael\n\nI haven't touched cvs2git, but I did modify git-cvsimport to handle\nsubmodules.  The patch is below.  The idea is that you first convert\nthe submodule parts from cvs to git, and then when you convert the\nparent project the submodules are continuously updated based on a\nsubmodule description file and the dates.\n\nTo use it, write a file in the same format as .gitmodules and pass it\nto cvs-import via -E.\n\nI eventually decided that submodules were getting in the way far more\nthan they were helping, so I stopped using this.  Perhaps someone else\nwill find it useful.\n\nGeoffrey\n\n>From 653fe2e8440893da06fa0eba9fd5c2c275435897 Mon Sep 17 00:00:00 2001\nFrom: Geoffrey Irving <irving@naml.us>\nDate: Thu, 12 Jun 2008 07:38:49 -0700\nSubject: [PATCH] cvsimport: add support for generating submodules\n\nAdd an -E <submodules> option to cvsimport to generate submodule links to\nother git repositories and to update them after each commit based on date.\nThis is useful when one is splitting up a cvs repository into separate git\nmodules which are strongly related to each other.\n---\n git-cvsimport.perl |   71 +++++++++++++++++++++++++++++++++++++++++++++++----\n 1 files changed, 65 insertions(+), 6 deletions(-)\n\ndiff --git a/git-cvsimport.perl b/git-cvsimport.perl\nindex cacbfc0..9b0285a 100755\n--- a/git-cvsimport.perl\n+++ b/git-cvsimport.perl\n@@ -29,8 +29,9 @@ use IPC::Open2;\n $SIG{'PIPE'}=\"IGNORE\";\n $ENV{'TZ'}=\"UTC\";\n\n-our ($opt_h,$opt_o,$opt_v,$opt_k,$opt_u,$opt_d,$opt_p,$opt_C,$opt_z,$opt_i,$opt_P,\n$opt_s,$opt_m,@opt_M,$opt_A,$opt_S,$opt_L, $opt_a, $opt_r);\n+our ($opt_h,$opt_o,$opt_v,$opt_k,$opt_u,$opt_d,$opt_p,$opt_C,$opt_z,$opt_i,$opt_P,\n$opt_s,$opt_m,@opt_M,$opt_A,$opt_S,$opt_E,$opt_L, $opt_a, $opt_r);\n my (%conv_author_name, %conv_author_email);\n+my (%submodule_path, %submodule_url);\n\n sub usage(;$) {\n        my $msg = shift;\n@@ -40,7 +41,7 @@ Usage: ${\\basename $0}     # fetch/update GIT from CVS\n        [-o branch-for-HEAD] [-h] [-v] [-d CVSROOT] [-A author-conv-file]\n        [-p opts-for-cvsps] [-P file] [-C GIT_repository] [-z fuzz] [-i] [-k]\n        [-u] [-s subst] [-a] [-m] [-M regex] [-S regex] [-L commitlimit]\n-       [-r remote] [CVS_module]\n+       [-E gitmodules-file] [-r remote] [CVS_module]\n END\n        exit(1);\n }\n@@ -88,6 +89,23 @@ sub write_author_info($) {\n        close ($f);\n }\n\n+sub read_submodule_info($) {\n+       my ($file) = @_;\n+       open(my $f, '-|', 'git-config', '--file', $file, '--list')\n+               or die \"Failed to read: $!\\n\";\n+\n+       while (<$f>) {\n+               /^submodule\\.(\\w+)\\.(path|url)=(.*)$/\n+                       or die \"Unknown submodule config line: $_\\n\";\n+               if ($2 eq 'path') {\n+                       $submodule_path{$1} = $3;\n+               } else {\n+                       $submodule_url{$1} = $3;\n+               }\n+       }\n+       close $f;\n+}\n+\n # convert getopts specs for use by git config\n sub read_repo_config {\n     # Split the string between characters, unless there is a ':'\n@@ -110,7 +128,7 @@ sub read_repo_config {\n        }\n }\n\n-my $opts = \"haivmkuo:d:p:r:C:z:s:M:P:A:S:L:\";\n+my $opts = \"haivmkuo:d:p:r:C:z:s:M:P:A:S:L:E:\";\n read_repo_config($opts);\n Getopt::Long::Configure( 'no_ignore_case', 'bundling' );\n\n@@ -610,6 +628,10 @@ if ($opt_A) {\n        write_author_info(\"$git_dir/cvs-authors\");\n }\n\n+# read submodule info\n+if ($opt_E) {\n+       read_submodule_info($opt_E);\n+}\n\n #\n # run cvsps into a file unless we are getting\n@@ -664,16 +686,19 @@ open(CVS, \"<$cvspsfile\") or die $!;\n\n my $state = 0;\n\n-sub update_index (\\@\\@) {\n+sub update_index (\\@\\@\\@) {\n        my $old = shift;\n        my $new = shift;\n+       my $submodules = shift;\n        open(my $fh, '|-', qw(git-update-index -z --index-info))\n                or die \"unable to open git-update-index: $!\";\n        print $fh\n                (map { \"0 0000000000000000000000000000000000000000\\t$_\\0\" }\n                        @$old),\n                (map { '100' . sprintf('%o', $_->[0]) . \" $_->[1]\\t$_->[2]\\0\" }\n-                       @$new)\n+                       @$new),\n+               (map { \"160000 commit $_->[0]\\t$_->[1]\\0\" }\n+                       @$submodules)\n                or die \"unable to write to git-update-index: $!\";\n        close $fh\n                or die \"unable to write to git-update-index: $!\";\n@@ -721,7 +746,41 @@ sub commit {\n        }\n         $ENV{GIT_INDEX_FILE} = $index{$branch};\n\n-       update_index(@old, @new);\n+       # add .gitmodules and find submodule commits\n+       my @submodules;\n+       if ($opt_E) {\n+               print \"Update .gitmodules\\n\" if $opt_v;\n+               my $pid = open(my $F, '-|');\n+               die $! unless defined $pid;\n+               if (!$pid) {\n+                   exec(\"git-hash-object\", \"-w\", $opt_E)\n+                               or die \"Cannot create object: $!\\n\";\n+               }\n+               my $sha = <$F>;\n+               chomp $sha;\n+               close $F;\n+               push(@new,[0644, $sha, \".gitmodules\"]);\n+\n+               for my $m (keys %submodule_path) {\n+                       my $search_date = $date + (defined $opt_z ?\n$opt_z : 300);\n+                       $ENV{\"GIT_DIR\"} = $submodule_url{$m};\n+                       open(my $f, '-|', 'git-log',\n\"--before=$search_date\", '-1', '--pretty=format:%H %ct')\n+                               or die \"Failed to extract submodule\ncommit id: $!\\n\";\n+                       $ENV{\"GIT_DIR\"} = $git_dir;\n+                       my $line = <$f>;\n+                       close $f;\n+                       if (defined $line) {\n+                               $line =~ /^([\\da-f]{40}) (\\d+)$/ or\ndie \"Failed to parse submodule log: $line\\n\";\n+                               push @submodules, [$1, $submodule_path{$m}];\n+                               if ($opt_v) {\n+                                       my $subdate = strftime(\"+0000\n%Y-%m-%d %H:%M:%S\",gmtime($2));\n+                                       print \"Updating submodule $m\nto $subdate\\n\";\n+                               }\n+                       }\n+               }\n+       }\n+\n+       update_index(@old, @new, @submodules);\n        @old = @new = ();\n        my $tree = write_tree();\n        my $parent = get_headref(\"$remote/$last_branch\");\n-- \n1.5.5.1.508.ga00f3\n"},{"id":"80156","messageId":"7f9d599f0806171106rb39f0e0m69f2f70090adb918@mail.gmail.com","threadId":"13999","inReplyTo":"7f9d599f0806171102w561ae5bfw594a3bc46eb9c8c1@mail.gmail.com","subject":"Re: cvs2git with modules?","fromName":"Geoffrey Irving","fromEmail":"irving@naml.us","sentAt":"2008-06-17T18:06:42Z","receivedAt":"2008-06-17T18:06:42Z","isPatch":false,"sender":{"key":"irving@naml.us","avatar":"https://gravatar.com/avatar/52d7452fcd134aac0fa12f57a3bb7ef5f3f7e73ca0ab36736d06c6a6132de718?d=mp&s=160"},"body":"On Tue, Jun 17, 2008 at 11:02 AM, Geoffrey Irving <irving@naml.us> wrote:\n> On Tue, Jun 17, 2008 at 8:45 AM, Michael Haggerty <mhagger@alum.mit.edu> wrote:\n>> [I see you sent essentially the same question to both the git and the\n>> cvs2svn mailing lists.  I am replying on the git list with bcc to the\n>> cvs2svn list.  Followups please to git@vger.kernel.org.]\n>>\n>> Kelly F. Hickel wrote:\n>>> I'm trying to use cvs2svn in cvs2git mode to convert a repo with a\n>>> number of modules.  Can anyone tell me how to keep that module\n>>> structure in the new git repo? So, if in cvs there are two modules,\n>>> ModA and ModB, I want to see those two as top level directories in\n>>> the git repo.\n>>>\n>>> I've tried putting adding the projects in my options file as below,\n>>> but it puts the files ModA/* and ModB/* at the top level in the git repo.\n>>>\n>>> run_options.add_project(\n>>>     r'/home/foo/cvsrepo/ModA,\n>>>     trunk_path=ModA',\n>>>     [...]\n>>>     )\n>>>\n>>> run_options.add_project(\n>>>     r'/home/foo/cvsrepo/ModB,\n>>>     trunk_path=ModB',\n>>>     [...]\n>>>     )\n>>\n>> I assume that what you mean is that the CVS repository contains\n>> directories like ModA/a, ModA/b, ModB/c, and ModB/d, but the resulting\n>> git repository has only /a, /b, /c, and /d.  That is because cvs2git\n>> completely ignores the trunk_path argument to add_project().\n>>\n>> It is strange that the code allows you to add multiple projects,\n>> considering that the cvs2git documentation[1] states that cvs2git only\n>> supports converting single projects at a time.  I guess I forgot to\n>> build that check in.\n>>\n>> You can get the result you want by treating ModA and ModB not as two\n>> separate projects, but simply as two separate subdirectories within a\n>> bigger project; i.e.,\n>>\n>> run_options.add_project(\n>>    r'/home/foo/cvsrepo,\n>>    [...]\n>>    )\n>>\n>> .  This is assuming that ModA and ModB are the only subdirectories\n>> within /home/foo/cvsrepo/; otherwise, make a copy of your CVS repo and\n>> remove the other subdirectories from the copy before the conversion.\n>>\n>> Please note that when cvs2git is run this way, it treats tags and\n>> branches as being global.  If you tagged your projects simultaneously,\n>> then this is probably what you want.  But if you tagged your projects\n>> separately, then tag names that happen to be the same across projects\n>> will be considered the same.\n>>\n>> It would be possible to add cvs2git support for multiproject\n>> conversions, but I was under the impression that it doesn't make much\n>> sense to put multiple projects into a single git repository.  But I'm a\n>> novice git user, so I could very well be wrong about that.\n>>\n>> Michael\n>\n> I haven't touched cvs2git, but I did modify git-cvsimport to handle\n> submodules.  The patch is below.  The idea is that you first convert\n> the submodule parts from cvs to git, and then when you convert the\n> parent project the submodules are continuously updated based on a\n> submodule description file and the dates.\n>\n> To use it, write a file in the same format as .gitmodules and pass it\n> to cvs-import via -E.\n>\n> I eventually decided that submodules were getting in the way far more\n> than they were helping, so I stopped using this.  Perhaps someone else\n> will find it useful.\n\nOops.  Copying and pasting the patch messed it up due to 80 character\nwrapping.  Trying again...\n\nGeoffrey\n\n\nFrom 653fe2e8440893da06fa0eba9fd5c2c275435897 Mon Sep 17 00:00:00 2001\nFrom: Geoffrey Irving <irving@naml.us>\nDate: Thu, 12 Jun 2008 07:38:49 -0700\nSubject: [PATCH] cvsimport: add support for generating submodules\n\nAdd an -E <submodules> option to cvsimport to generate submodule links to\nother git repositories and to update them after each commit based on date.\nThis is useful when one is splitting up a cvs repository into separate git\nmodules which are strongly related to each other.\n---\n git-cvsimport.perl |   71 +++++++++++++++++++++++++++++++++++++++++++++++----\n 1 files changed, 65 insertions(+), 6 deletions(-)\n\ndiff --git a/git-cvsimport.perl b/git-cvsimport.perl\nindex cacbfc0..9b0285a 100755\n--- a/git-cvsimport.perl\n+++ b/git-cvsimport.perl\n@@ -29,8 +29,9 @@ use IPC::Open2;\n $SIG{'PIPE'}=\"IGNORE\";\n $ENV{'TZ'}=\"UTC\";\n \n-our ($opt_h,$opt_o,$opt_v,$opt_k,$opt_u,$opt_d,$opt_p,$opt_C,$opt_z,$opt_i,$opt_P, $opt_s,$opt_m,@opt_M,$opt_A,$opt_S,$opt_L, $opt_a, $opt_r);\n+our ($opt_h,$opt_o,$opt_v,$opt_k,$opt_u,$opt_d,$opt_p,$opt_C,$opt_z,$opt_i,$opt_P, $opt_s,$opt_m,@opt_M,$opt_A,$opt_S,$opt_E,$opt_L, $opt_a, $opt_r);\n my (%conv_author_name, %conv_author_email);\n+my (%submodule_path, %submodule_url);\n \n sub usage(;$) {\n \tmy $msg = shift;\n@@ -40,7 +41,7 @@ Usage: ${\\basename $0}     # fetch/update GIT from CVS\n        [-o branch-for-HEAD] [-h] [-v] [-d CVSROOT] [-A author-conv-file]\n        [-p opts-for-cvsps] [-P file] [-C GIT_repository] [-z fuzz] [-i] [-k]\n        [-u] [-s subst] [-a] [-m] [-M regex] [-S regex] [-L commitlimit]\n-       [-r remote] [CVS_module]\n+       [-E gitmodules-file] [-r remote] [CVS_module]\n END\n \texit(1);\n }\n@@ -88,6 +89,23 @@ sub write_author_info($) {\n \tclose ($f);\n }\n \n+sub read_submodule_info($) {\n+\tmy ($file) = @_;\n+\topen(my $f, '-|', 'git-config', '--file', $file, '--list')\n+\t\tor die \"Failed to read: $!\\n\";\n+\n+\twhile (<$f>) {\n+\t\t/^submodule\\.(\\w+)\\.(path|url)=(.*)$/\n+\t\t\tor die \"Unknown submodule config line: $_\\n\";\n+\t\tif ($2 eq 'path') {\n+\t\t\t$submodule_path{$1} = $3;\n+\t\t} else {\n+\t\t\t$submodule_url{$1} = $3;\n+\t\t}\n+\t}\n+\tclose $f;\n+}\n+\n # convert getopts specs for use by git config\n sub read_repo_config {\n     # Split the string between characters, unless there is a ':'\n@@ -110,7 +128,7 @@ sub read_repo_config {\n \t}\n }\n \n-my $opts = \"haivmkuo:d:p:r:C:z:s:M:P:A:S:L:\";\n+my $opts = \"haivmkuo:d:p:r:C:z:s:M:P:A:S:L:E:\";\n read_repo_config($opts);\n Getopt::Long::Configure( 'no_ignore_case', 'bundling' );\n \n@@ -610,6 +628,10 @@ if ($opt_A) {\n \twrite_author_info(\"$git_dir/cvs-authors\");\n }\n \n+# read submodule info\n+if ($opt_E) {\n+\tread_submodule_info($opt_E);\n+}\n \n #\n # run cvsps into a file unless we are getting\n@@ -664,16 +686,19 @@ open(CVS, \"<$cvspsfile\") or die $!;\n \n my $state = 0;\n \n-sub update_index (\\@\\@) {\n+sub update_index (\\@\\@\\@) {\n \tmy $old = shift;\n \tmy $new = shift;\n+\tmy $submodules = shift;\n \topen(my $fh, '|-', qw(git-update-index -z --index-info))\n \t\tor die \"unable to open git-update-index: $!\";\n \tprint $fh\n \t\t(map { \"0 0000000000000000000000000000000000000000\\t$_\\0\" }\n \t\t\t@$old),\n \t\t(map { '100' . sprintf('%o', $_->[0]) . \" $_->[1]\\t$_->[2]\\0\" }\n-\t\t\t@$new)\n+\t\t\t@$new),\n+\t\t(map { \"160000 commit $_->[0]\\t$_->[1]\\0\" }\n+\t\t\t@$submodules)\n \t\tor die \"unable to write to git-update-index: $!\";\n \tclose $fh\n \t\tor die \"unable to write to git-update-index: $!\";\n@@ -721,7 +746,41 @@ sub commit {\n \t}\n         $ENV{GIT_INDEX_FILE} = $index{$branch};\n \n-\tupdate_index(@old, @new);\n+\t# add .gitmodules and find submodule commits\n+\tmy @submodules;\n+\tif ($opt_E) {\n+\t\tprint \"Update .gitmodules\\n\" if $opt_v;\n+\t\tmy $pid = open(my $F, '-|');\n+\t\tdie $! unless defined $pid;\n+\t\tif (!$pid) {\n+\t\t    exec(\"git-hash-object\", \"-w\", $opt_E)\n+\t\t\t\tor die \"Cannot create object: $!\\n\";\n+\t\t}\n+\t\tmy $sha = <$F>;\n+\t\tchomp $sha;\n+\t\tclose $F;\n+\t\tpush(@new,[0644, $sha, \".gitmodules\"]);\n+\n+\t\tfor my $m (keys %submodule_path) {\n+\t\t\tmy $search_date = $date + (defined $opt_z ? $opt_z : 300);\n+\t\t\t$ENV{\"GIT_DIR\"} = $submodule_url{$m};\n+\t\t\topen(my $f, '-|', 'git-log', \"--before=$search_date\", '-1', '--pretty=format:%H %ct')\n+\t\t\t\tor die \"Failed to extract submodule commit id: $!\\n\";\n+\t\t\t$ENV{\"GIT_DIR\"} = $git_dir;\n+\t\t\tmy $line = <$f>;\n+\t\t\tclose $f;\n+\t\t\tif (defined $line) {\n+\t\t\t\t$line =~ /^([\\da-f]{40}) (\\d+)$/ or die \"Failed to parse submodule log: $line\\n\";\n+\t\t\t\tpush @submodules, [$1, $submodule_path{$m}];\n+\t\t\t\tif ($opt_v) {\n+\t\t\t\t\tmy $subdate = strftime(\"+0000 %Y-%m-%d %H:%M:%S\",gmtime($2));\n+\t\t\t\t\tprint \"Updating submodule $m to $subdate\\n\";\n+\t\t\t\t}\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\tupdate_index(@old, @new, @submodules);\n \t@old = @new = ();\n \tmy $tree = write_tree();\n \tmy $parent = get_headref(\"$remote/$last_branch\");\n-- \n1.5.5.1.508.ga00f3\n\n"}]}