threads / rfc / 6049

patchRe: [RFC/PATCH] Implement poor-man's submodule support in pre-commit hook

Subject: Re: [RFC/PATCH] Implement poor-man's submodule support in pre-commit hook

## tl;dr

11 messages between Dec 20, 2006 and Dec 21, 2006. Diffs are folded; open one to read it.

replies: 10people: 5as markdown or json

Andy Parkins· Dec 20, 2006, 09:01 UTC · lore

[RFC/PATCH] Implement poor-man's submodule support in pre-commit hook

Make a file called .gitmodules. In it, list the paths containing a submodule. Add that file to the index.

This addition to the pre-commit hook finds that file and pulls the HEAD hash out of each of the listed submodule repositories. That hash is then listed to the .gitmodules file along with the submodule name and .gitmodules is added back to the repository.

You've now got poor-man's submodule support. Any commits to the submodule will change the hash and hence the .gitmodules file will be different and therefore will show up as "modified" to git.

It's not got any nice UI for checking out (obviously) or merging; but it does at least record the state of a project with a bit of manual work to check out the right commit in the submodule.

Problems:
 - git-prune in the submodule could destroy supermodule-referenced
   commits
 - no checkout support
 - no merge support (other than what git provides for the .gitmodule
   file)
 - no check for dirty submodule before commit
Signed-off-by: Andy Parkins <andyparkins@gmail.com>
---
 templates/hooks--pre-commit |   31 ++++++++++++++++++++++++++++++-
 1 files changed, 30 insertions(+), 1 deletions(-)
Show changes to templates/hooks--pre-commit +30 −1
diff --git a/templates/hooks--pre-commit b/templates/hooks--pre-commit
index 723a9ef..7a71d81 100644
--- a/templates/hooks--pre-commit
+++ b/templates/hooks--pre-commit
@@ -67,5 +67,34 @@ perl -e '
 	}
     }
     exit($found_bad);
-'
+' || exit 1
+
+# Enable poor-man's submodule support when .gitmodules is present
+# Simply create a .gitmodules file listing the paths in your repository
+# that contain other git repositories; each line will be replaced with the
+# path followed by the hash of the current HEAD of the submodule.
+# When the submodule changes hash this file will be different from the
+# version in the repository and a change will be noted - voila, submodules.
+# Of course there is no checkout support, but at least the current state
+# will be accurately recorded
+if [ -f .gitmodules ]; then
+	cat .gitmodules |
+	while read subdir hash
+	do
+		# XXX: check if the line is a comment
+
+		# XXX: really need a check here and quit if the submodule is
+		# dirty
+
+		echo "$subdir $(GIT_DIR=$subdir/.git git-rev-parse HEAD)"
+	done > .gitmodules
+
+	# This relies on the .gitmodules file having already been added to
+	# the repository - perhaps this should be automated?
+	git-update-index .gitmodules ||
+	(
+	echo "Submodule tracker file is not tracked by this repository." >&2
+	exit 1
+	)
+fi
 
-- 
1.4.4.2.g95ee-dirty
Andy Parkins· Dec 20, 2006, 10:08 UTC · re: Andy Parkins · lore
Hello,
Help...
> +if [ -f .gitmodules ]; then

This doesn't work because git-commit is not necessarily in the root of the working tree. How do I safely get that root? While ${GIT_DIR}/.. would work it is not guaranteed.

Andy
-- 
Dr Andy Parkins, M Eng (hons), MIEE
Brian Gernhardt· Dec 20, 2006, 11:49 UTC · re: Andy Parkins · lore
On Dec 20, 2006, at 5:08 AM, Andy Parkins wrote:
Show 11 quoted lines
> Hello,
>
> Help...
>
>> +if [ -f .gitmodules ]; then
>
> This doesn't work because git-commit is not necessarily in the root  
> of the
> working tree.  How do I safely get that root?  While ${GIT_DIR}/..  
> would work
> it is not guaranteed.

The way to do that seems to be "git rev-parse --git-dir". I'm not sure why it's not just "git --git-dir" or similar (probably just historical reasons), but there you go.

Jakub Narebski· Dec 20, 2006, 12:01 UTC · re: Brian Gernhardt · lore
Brian Gernhardt wrote:
Show 18 quoted lines
> 
> On Dec 20, 2006, at 5:08 AM, Andy Parkins wrote:
> 
>> Hello,
>>
>> Help...
>>
>>> +if [ -f .gitmodules ]; then
>>
>> This doesn't work because git-commit is not necessarily in the root  
>> of the
>> working tree.  How do I safely get that root?  While ${GIT_DIR}/..  
>> would work
>> it is not guaranteed.
> 
> The way to do that seems to be "git rev-parse --git-dir".  I'm not  
> sure why it's not just "git --git-dir" or similar (probably just  
> historical reasons), but there you go.

Because it is "git --git-dir=<PATH>" to set it (probably). Although it is not insurmountable difficulity...

-- 
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git
Andreas Ericsson· Dec 20, 2006, 12:35 UTC · re: Jakub Narebski · lore
Jakub Narebski wrote:
Show 20 quoted lines
> Brian Gernhardt wrote:
> 
>> On Dec 20, 2006, at 5:08 AM, Andy Parkins wrote:
>>
>>> Hello,
>>>
>>> Help...
>>>
>>>> +if [ -f .gitmodules ]; then
>>> This doesn't work because git-commit is not necessarily in the root  
>>> of the
>>> working tree.  How do I safely get that root?  While ${GIT_DIR}/..  
>>> would work
>>> it is not guaranteed.
>> The way to do that seems to be "git rev-parse --git-dir".  I'm not  
>> sure why it's not just "git --git-dir" or similar (probably just  
>> historical reasons), but there you go.
> 
> Because it is "git --git-dir=<PATH>" to set it (probably).
> Although it is not insurmountable difficulity...

AFAIR, the discussions long ago went along the lines of "if no argument is passed to any of the --*-dir options, print out the current value". If "git --git-dir" doesn't print the directory name of the .git directory inside the repo you're currently in, I'd consider it a bug.

-- 
Andreas Ericsson                   andreas.ericsson@op5.se
OP5 AB                             www.op5.se
Brian Gernhardt· Dec 20, 2006, 14:47 UTC · re: Andreas Ericsson · lore

[BUG] git --git-dir dies with bus error

On Dec 20, 2006, at 7:35 AM, Andreas Ericsson wrote:
Show 5 quoted lines
> AFAIR, the discussions long ago went along the lines of "if no  
> argument is passed to any of the --*-dir options, print out the  
> current value". If "git --git-dir" doesn't print the directory name  
> of the .git directory inside the repo you're currently in, I'd  
> consider it a bug.
Consider this a bug then:

$ git --git-dir Bus error $ git --version git version 1.4.4.1.GIT $ git rev-parse origin/master 8336afa563fbeff35e531396273065161181f04c $ gdb git (gdb) set args --git-dir (gdb) run Starting program: /usr/local/stow/git/src/git/git --git-dir Reading symbols for shared libraries ..+ done

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_PROTECTION_FAILURE at address: 0x00000000
0x900332e6 in setenv ()
(gdb) bt
#0  0x900332e6 in setenv ()
#1  0x00001f9e in handle_options (argv=0xbffff4a4, argc=0xbffff4a0)  
at git.c:76
#2  0x000022da in main (argc=1, argv=0xbffff504, envp=0xbffff50c) at  
git.c:346

My current HEAD (and installed version) just includes my "remove COLLISION_CHECK" patch on top of git master. This is on OS 10.4.8 with fink 0.26. It appears to be trying to set GIT_DIR to some non- set section of memory. Bad git, bad. I'd try to patch this myself (to at least display an error instead of dying), but I'm deep in my actual project code right now.

Jakub Narebski· Dec 20, 2006, 11:59 UTC · re: Andy Parkins · lore
Andy Parkins wrote:
Show 7 quoted lines
> Help...
> 
>> +if [ -f .gitmodules ]; then
> 
> This doesn't work because git-commit is not necessarily in the root of the 
> working tree.  How do I safely get that root?  While ${GIT_DIR}/.. would work 
> it is not guaranteed.

Do you want "git rev-parse --show-prefix" or "git rev-parse --show-cdup", or "git rev-parse --git-dir" perhaps? (Although here rev in rev-parse is misnomer).

-- 
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git
Andy Parkins· Dec 20, 2006, 12:11 UTC · re: Jakub Narebski · lore
On Wednesday 2006 December 20 11:59, Jakub Narebski wrote:
> Do you want "git rev-parse --show-prefix" or "git rev-parse --show-cdup",
> or "git rev-parse --git-dir" perhaps? (Although here rev in rev-parse is
> misnomer).

--show-cdup was the one. Thanks so much. I tried git-var, never even thought of git-rev-parse.

Andy
-- 
Dr Andy Parkins, M Eng (hons), MIEE
Junio C Hamano· Dec 20, 2006, 19:37 UTC · re: Andy Parkins · lore
Andy Parkins <andyparkins@gmail.com> writes:
Show 9 quoted lines
> Problems:
>  - git-prune in the submodule could destroy supermodule-referenced
>    commits
>  - no checkout support
>  - no merge support (other than what git provides for the .gitmodule
>    file)
>  - no check for dirty submodule before commit
>
> Signed-off-by: Andy Parkins <andyparkins@gmail.com>
I do not think these are insurmountable.

As you fix them and enhance the support, I suspect you would want a separate command to manage .gitmodule file and submodules referenced by it. I think it would be better to keep the patch to the template to the minimum (for example, run "git submodule update" if there is .gitmodules file at the toplevel), and implement the body of the processing in "git-submodule.sh", or something like that.

Andy Parkins· Dec 21, 2006, 08:39 UTC · re: Junio C Hamano · lore
On Wednesday 2006 December 20 19:37, Junio C Hamano wrote:
> I do not think these are insurmountable.

Me either. I wasn't really sure how warmly these patches would be received, so thought some small patches that make the feature highly might be more palatable. I actually don't think that the hook templates is the right place for this work; submodule support is not something you would customise per-repository, and so the hook scripts are manifestly the wrong place for this.

Show 7 quoted lines
> As you fix them and enhance the support, I suspect you would
> want a separate command to manage .gitmodule file and submodules
> referenced by it.  I think it would be better to keep the patch
> to the template to the minimum (for example, run "git submodule
> update" if there is .gitmodules file at the toplevel), and
> implement the body of the processing in "git-submodule.sh", or
> something like that.

That's an interesting idea. I was thinking that git-commit itself would have been the final target; but I certainly don't have any problem with a separate command.

Andy
-- 
Dr Andy Parkins, M Eng (hons), MIEE
andyparkins@gmail.com
Junio C Hamano· Dec 21, 2006, 08:49 UTC · re: Andy Parkins · lore
Andy Parkins <andyparkins@gmail.com> writes:
Show 11 quoted lines
>> As you fix them and enhance the support, I suspect you would
>> want a separate command to manage .gitmodule file and submodules
>> referenced by it.  I think it would be better to keep the patch
>> to the template to the minimum (for example, run "git submodule
>> update" if there is .gitmodules file at the toplevel), and
>> implement the body of the processing in "git-submodule.sh", or
>> something like that.
>
> That's an interesting idea.  I was thinking that git-commit
> itself would have been the final target; but I certainly don't
> have any problem with a separate command.
I do not think the commit command would be the "final" one.

When you have a loosely coupled subproject, sometimes you might want to check out subprojects recursively, so you would also want "checkout" action to "git submodule", which might hook into "git checkout" just like your patch hooked into "git commit". Similarly your future versions certainly would want to hook into "git fetch/pull".

Just like some peoples' workflow avoid "git pull" but do "git fetch" and "git merge" as separate steps, some people may want to disable the above "hooks", and prefer using "git submodule" from the command line as a separate step, especially if they want very loose coupling.

← back to recent threads