Moving (renaming) submodules, recipe/script

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

Moving (renaming) submodules, recipe/script

From: W. Trevor King <hidden>
Date: 2016-06-15 22:55:40

Today I had to move my first submodule, and I discovered that Git's
support for this is pretty limited.  There have been a few patch
series attempting to address this [1,2], but none of them seems to
have pushed through into master (although I can't put my finger on a
reason for why).  There are also some SO postings discussing this
[3,4].  It would be nice if `git mv` worked out of the box on
submodules.  Failing that, there could be a `git submodule mv` command
that casts the appropriate spell.  Failing that, there could be a
recipe in Documentation/git-submodule.txt.  Here's the best I could
come up with for a `git-submodule-mv.sh`:

  #!/bin/sh
  # usage: git-submodule-mv.sh OLD NEW
  OLD=$(realpath --relative-to . "$1")
  NEW=$(realpath --relative-to . "$2")
  SHA=$(git ls-files -s "$OLD" | sed 's|^[0-9]* \([0-9a-f]*\) .*|\1|')
  NAME=$(git config -f .gitmodules --get-regexp 'submodule\..*\.path' "$OLD" |
    sed -e 's|^submodule.||' -e "s|.path $OLD\$||")
  GITDIR=$(realpath --relative-to "$NEW" .git/modules/"$NAME")
  git config -f .gitmodules submodule."$NAME".path "$NEW"
  git config -f .git/modules/"$NAME"/config core.worktree "../../../$NEW"
  git rm --cached "$OLD"
  mv "$OLD" "$NEW"
  echo "gitdir: $GITDIR" > "$NEW/.git"
  git update-index --add --cacheinfo 160000 "$SHA" "$NEW"

This only works from the repository root directory, and I'm sure makes
a number of poor assumptions (e.g. old-style submodules that don't use
`gitdir` links are not supported).  It does work for some simple test
cases.  The tricky parts (e.g. path -> name conversion) are already
worked out more robustly git-submodule.sh, so adding a new cmd_mv
shouldn't be very difficult.

Could something like this live somewhere in Git, or are we waiting for
a more integrated solution?

Cheers,
Trevor

[1]: http://thread.gmane.org/gmane.comp.version-control.git/88720
[2]: http://thread.gmane.org/gmane.comp.version-control.git/143250
[4]: http://stackoverflow.com/questions/4323558/moving-submodules-with-git
[3]: http://stackoverflow.com/questions/4604486/how-do-i-move-an-existing-git-submodule-within-a-git-repository

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

Re: Moving (renaming) submodules, recipe/script

From: Jonathan Nieder <hidden>
Date: 2016-06-15 22:55:40

(just cc-ing Jens and Peter, who might be interested)

W. Trevor King wrote:
Today I had to move my first submodule, and I discovered that Git's
support for this is pretty limited.  There have been a few patch
series attempting to address this [1,2], but none of them seems to
have pushed through into master (although I can't put my finger on a
reason for why).  There are also some SO postings discussing this
[3,4].  It would be nice if `git mv` worked out of the box on
submodules.  Failing that, there could be a `git submodule mv` command
that casts the appropriate spell.  Failing that, there could be a
recipe in Documentation/git-submodule.txt.  Here's the best I could
come up with for a `git-submodule-mv.sh`:

  #!/bin/sh
  # usage: git-submodule-mv.sh OLD NEW
  OLD=$(realpath --relative-to . "$1")
  NEW=$(realpath --relative-to . "$2")
  SHA=$(git ls-files -s "$OLD" | sed 's|^[0-9]* \([0-9a-f]*\) .*|\1|')
  NAME=$(git config -f .gitmodules --get-regexp 'submodule\..*\.path' "$OLD" |
    sed -e 's|^submodule.||' -e "s|.path $OLD\$||")
  GITDIR=$(realpath --relative-to "$NEW" .git/modules/"$NAME")
  git config -f .gitmodules submodule."$NAME".path "$NEW"
  git config -f .git/modules/"$NAME"/config core.worktree "../../../$NEW"
  git rm --cached "$OLD"
  mv "$OLD" "$NEW"
  echo "gitdir: $GITDIR" > "$NEW/.git"
  git update-index --add --cacheinfo 160000 "$SHA" "$NEW"

This only works from the repository root directory, and I'm sure makes
a number of poor assumptions (e.g. old-style submodules that don't use
`gitdir` links are not supported).  It does work for some simple test
cases.  The tricky parts (e.g. path -> name conversion) are already
worked out more robustly git-submodule.sh, so adding a new cmd_mv
shouldn't be very difficult.

Could something like this live somewhere in Git, or are we waiting for
a more integrated solution?

Cheers,
Trevor

[1]: http://thread.gmane.org/gmane.comp.version-control.git/88720
[2]: http://thread.gmane.org/gmane.comp.version-control.git/143250
[4]: http://stackoverflow.com/questions/4323558/moving-submodules-with-git
[3]: http://stackoverflow.com/questions/4604486/how-do-i-move-an-existing-git-submodule-within-a-git-repository

Re: Moving (renaming) submodules, recipe/script

From: Jens Lehmann <hidden>
Date: 2016-06-15 22:55:40

Am 07.01.2013 02:39, schrieb Jonathan Nieder:
(just cc-ing Jens and Peter, who might be interested)
I´m currently working on teaching mv to move submodules and intend
to send those patches to the list after finishing submodule deinit.
Please see
  https://github.com/jlehmann/git-submod-enhancements/commits/mv-submodules
for the current state of this series.
W. Trevor King wrote:
quoted
Today I had to move my first submodule, and I discovered that Git's
support for this is pretty limited.  There have been a few patch
series attempting to address this [1,2], but none of them seems to
have pushed through into master (although I can't put my finger on a
reason for why).  There are also some SO postings discussing this
[3,4].  It would be nice if `git mv` worked out of the box on
submodules.  Failing that, there could be a `git submodule mv` command
that casts the appropriate spell.  Failing that, there could be a
recipe in Documentation/git-submodule.txt.  Here's the best I could
come up with for a `git-submodule-mv.sh`:

  #!/bin/sh
  # usage: git-submodule-mv.sh OLD NEW
  OLD=$(realpath --relative-to . "$1")
  NEW=$(realpath --relative-to . "$2")
  SHA=$(git ls-files -s "$OLD" | sed 's|^[0-9]* \([0-9a-f]*\) .*|\1|')
  NAME=$(git config -f .gitmodules --get-regexp 'submodule\..*\.path' "$OLD" |
    sed -e 's|^submodule.||' -e "s|.path $OLD\$||")
  GITDIR=$(realpath --relative-to "$NEW" .git/modules/"$NAME")
  git config -f .gitmodules submodule."$NAME".path "$NEW"
  git config -f .git/modules/"$NAME"/config core.worktree "../../../$NEW"
  git rm --cached "$OLD"
  mv "$OLD" "$NEW"
  echo "gitdir: $GITDIR" > "$NEW/.git"
  git update-index --add --cacheinfo 160000 "$SHA" "$NEW"

This only works from the repository root directory, and I'm sure makes
a number of poor assumptions (e.g. old-style submodules that don't use
`gitdir` links are not supported).  It does work for some simple test
cases.  The tricky parts (e.g. path -> name conversion) are already
worked out more robustly git-submodule.sh, so adding a new cmd_mv
shouldn't be very difficult.

Could something like this live somewhere in Git, or are we waiting for
a more integrated solution?

Cheers,
Trevor

[1]: http://thread.gmane.org/gmane.comp.version-control.git/88720
[2]: http://thread.gmane.org/gmane.comp.version-control.git/143250
[4]: http://stackoverflow.com/questions/4323558/moving-submodules-with-git
[3]: http://stackoverflow.com/questions/4604486/how-do-i-move-an-existing-git-submodule-within-a-git-repository
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Re: Moving (renaming) submodules, recipe/script

From: W. Trevor King <hidden>
Date: 2016-06-15 22:55:41

On Mon, Jan 07, 2013 at 07:59:53AM +0100, Jens Lehmann wrote:
I´m currently working on teaching mv to move submodules and intend
to send those patches to the list after finishing submodule deinit.
Please see
  https://github.com/jlehmann/git-submod-enhancements/commits/mv-submodules
for the current state of this series.
Ah, that will be much better :).

It looks like my script tries to do all the right things though, so if
anyone needs to move a submodule before Jens' branch lands, you might
want to give it a try.

Cheers,
Trevor

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

Re: Moving (renaming) submodules, recipe/script

From: W. Trevor King <hidden>
Date: 2016-06-15 22:55:41

On Mon, Jan 07, 2013 at 07:59:53AM +0100, Jens Lehmann wrote:
Am 07.01.2013 02:39, schrieb Jonathan Nieder:
quoted
(just cc-ing Jens and Peter, who might be interested)
I´m currently working on teaching mv to move submodules and intend
to send those patches to the list after finishing submodule deinit.
Please see
  https://github.com/jlehmann/git-submod-enhancements/commits/mv-submodules
for the current state of this series.
Thinking about this a bit more, I'm not clear on how out-of-tree
updates (i.e. worktree in .git/modules/*/config) propogated during
branch checkouts (merges, rebases, etc.).  I just got a broken rebase
trying to move a trivial patch back before the submodule move, and Git
was confused about what had happened to the submodules.  Here's a
simple script that illustrates the problem:

  #!/bin/sh
  rm -rf a b c
  mkdir a
  (cd a
   git init
   echo a > README
   git add README
   git commit -am 'a'
  )
  git clone a b
  (cd b
   git submodule add ../a submod-1
   git commit -am 'add submodule at submod-1'
  )
  git clone b c
  (cd c
   git submodule update --init
  )
  (cd b
   git-submodule-mv.sh submod-1 submod-2
   git commit -am 'move submodule from submod-1 to submod-2'
  )
  (cd c
   git pull
   ls -d .git/modules/*
   cat .git/modules/submod-1/config
   ls -a submod*
  )

The end result is that `c` gets the `.gitmodules` path updates and new
gitlinked directory from the submodule move in `b` (using my
git-submodule-mv.sh posted earlier in this thread), but `submod-1` is
left lying around (because Git doesn't know that it can remove
submod-1/.git and submod-1/README).  The Git directory for the
submodule stays in .git/modules/submod-1/ (good), but the worktree in
.git/modules/submod-1/config still points to ../../../submod-1 (bad).

This means that submodule moves are possible, but anyone trying to
share them between several repositories (or trying to rebase across
the move within their own repository) is in for a world of suffering
;).  I'm not sure how this should be addressed, but I didn't see
anything handling it in Jens' new series.

Thanks,
Trevor

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy

Re: Moving (renaming) submodules, recipe/script

From: Jens Lehmann <hidden>
Date: 2016-06-15 22:55:41

Am 08.01.2013 15:32, schrieb W. Trevor King:
On Mon, Jan 07, 2013 at 07:59:53AM +0100, Jens Lehmann wrote:
quoted
Am 07.01.2013 02:39, schrieb Jonathan Nieder:
quoted
(just cc-ing Jens and Peter, who might be interested)
I´m currently working on teaching mv to move submodules and intend
to send those patches to the list after finishing submodule deinit.
Please see
  https://github.com/jlehmann/git-submod-enhancements/commits/mv-submodules
for the current state of this series.
Thinking about this a bit more, I'm not clear on how out-of-tree
updates (i.e. worktree in .git/modules/*/config) propogated during
branch checkouts (merges, rebases, etc.).  I just got a broken rebase
trying to move a trivial patch back before the submodule move, and Git
was confused about what had happened to the submodules.  Here's a
simple script that illustrates the problem:

  #!/bin/sh
  rm -rf a b c
  mkdir a
  (cd a
   git init
   echo a > README
   git add README
   git commit -am 'a'
  )
  git clone a b
  (cd b
   git submodule add ../a submod-1
   git commit -am 'add submodule at submod-1'
  )
  git clone b c
  (cd c
   git submodule update --init
  )
  (cd b
   git-submodule-mv.sh submod-1 submod-2
   git commit -am 'move submodule from submod-1 to submod-2'
  )
  (cd c
   git pull
   ls -d .git/modules/*
   cat .git/modules/submod-1/config
   ls -a submod*
  )

The end result is that `c` gets the `.gitmodules` path updates and new
gitlinked directory from the submodule move in `b` (using my
git-submodule-mv.sh posted earlier in this thread), but `submod-1` is
left lying around (because Git doesn't know that it can remove
submod-1/.git and submod-1/README).
That's just what current git does with removed submodules (but my
recursive submodule update series will handle that just fine).
 The Git directory for the
submodule stays in .git/modules/submod-1/ (good), but the worktree in
.git/modules/submod-1/config still points to ../../../submod-1 (bad).
You'll not only have to update the gitfile but also the core.worktree
setting in the repo. Sorry I missed that when you posted your script.
This means that submodule moves are possible, but anyone trying to
share them between several repositories (or trying to rebase across
the move within their own repository) is in for a world of suffering
;).  I'm not sure how this should be addressed, but I didn't see
anything handling it in Jens' new series.
If you adjust core.worktree properly you'll just have the old
submodule work tree lying around (just like you do after you rm'd
it) and everything apart from that should just work.

As I mentioned that will be fixed by recursive submodule checkout.
I'll see if I can polish my preliminary branch so that interested
people can play around with it if anyone is interested.

Re: Moving (renaming) submodules, recipe/script

From: W. Trevor King <hidden>
Date: 2016-06-15 22:55:41

On Tue, Jan 08, 2013 at 06:12:13PM +0100, Jens Lehmann wrote:
Am 08.01.2013 15:32, schrieb W. Trevor King:
quoted
 The Git directory for the
submodule stays in .git/modules/submod-1/ (good), but the worktree in
.git/modules/submod-1/config still points to ../../../submod-1 (bad).
You'll not only have to update the gitfile but also the core.worktree
setting in the repo. Sorry I missed that when you posted your script.
My git-submodule-mv.sh script does update core.worktree.  The problem
is that `git checkout`, `git merge`, etc. do not.
quoted
This means that submodule moves are possible, but anyone trying to
share them between several repositories (or trying to rebase across
the move within their own repository) is in for a world of suffering
;).  I'm not sure how this should be addressed, but I didn't see
anything handling it in Jens' new series.
If you adjust core.worktree properly you'll just have the old
submodule work tree lying around (just like you do after you rm'd
it) and everything apart from that should just work.

As I mentioned that will be fixed by recursive submodule checkout.
I'll see if I can polish my preliminary branch so that interested
people can play around with it if anyone is interested.
Sounds like a fix will be in here.  I'll definitely help put the
branch through its paces ;).

Trevor

-- 
This email may be signed or encrypted with GnuPG (http://www.gnupg.org).
For more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help