threads / discuss / 50137

Regression in git-subtree.sh, introduced in 2.20.1, after 315a84f9aa0e2e629b0680068646b0032518ebed

Subject: Regression in git-subtree.sh, introduced in 2.20.1, after 315a84f9aa0e2e629b0680068646b0032518ebed

## tl;dr

12 messages between Dec 31, 2018 and Jan 3, 2019.

replies: 11people: 4as markdown or json

Marc Balmer· Dec 31, 2018, 10:28 UTC · lore
Hi
One of the last three commits in git-subtree.sh introduced a regression leading to a segfault.
Here is the error message when I try to split out my i18n files:
$ git subtree split --prefix=i18n
cache for e39a2a0c6431773a5d831eb3cb7f1cd40d0da623 already exists!
   (Lots of output omitted)
436/627 (1819) [1455]       <- Stays at 436/ while the numbers in () and [] increase, then segfaults:
/usr/libexec/git-core/git-subtree: line 751: 54693 Done                    eval "$grl"
    54694 Segmentation fault      (core dumped) | while read rev parents; do
   process_split_commit "$rev" "$parents" 0;
done
Please note that this regression can not easily be reproduced, normally a subtree split just works.
Reverting the last three commits "fixes" the issue.  So I kindly ask the last three commits to be reverted.
Duy Nguyen· Dec 31, 2018, 10:51 UTC · re: Marc Balmer · lore

Re: Regression in git-subtree.sh, introduced in 2.20.1, after 315a84f9aa0e2e629b0680068646b0032518ebed

On Mon, Dec 31, 2018 at 5:44 PM Marc Balmer <marc@msys.ch> wrote:
Show 13 quoted lines
>
> Hi
>
> One of the last three commits in git-subtree.sh introduced a regression leading to a segfault.
>
> Here is the error message when I try to split out my i18n files:
>
> $ git subtree split --prefix=i18n
> cache for e39a2a0c6431773a5d831eb3cb7f1cd40d0da623 already exists!
>    (Lots of output omitted)
> 436/627 (1819) [1455]       <- Stays at 436/ while the numbers in () and [] increase, then segfaults:
> /usr/libexec/git-core/git-subtree: line 751: 54693 Done                    eval "$grl"
>     54694 Segmentation fault      (core dumped) | while read rev parents; do

Do you still have this core dump? Could you run it and see if it's "git" that crashed (and where) or "sh"?

Show 6 quoted lines
>    process_split_commit "$rev" "$parents" 0;
> done
>
> Please note that this regression can not easily be reproduced, normally a subtree split just works.
>
> Reverting the last three commits "fixes" the issue.  So I kindly ask the last three commits to be reverted.
Please provide the SHA-1 of the "good" commit you tested.
-- 
Duy
Marc Balmer· Dec 31, 2018, 11:12 UTC · re: Duy Nguyen · lore

Re: Regression in git-subtree.sh, introduced in 2.20.1, after 315a84f9aa0e2e629b0680068646b0032518ebed

Show 19 quoted lines
> Am 31.12.2018 um 11:51 schrieb Duy Nguyen <pclouds@gmail.com>:
> 
> On Mon, Dec 31, 2018 at 5:44 PM Marc Balmer <marc@msys.ch> wrote:
>> 
>> Hi
>> 
>> One of the last three commits in git-subtree.sh introduced a regression leading to a segfault.
>> 
>> Here is the error message when I try to split out my i18n files:
>> 
>> $ git subtree split --prefix=i18n
>> cache for e39a2a0c6431773a5d831eb3cb7f1cd40d0da623 already exists!
>>   (Lots of output omitted)
>> 436/627 (1819) [1455]       <- Stays at 436/ while the numbers in () and [] increase, then segfaults:
>> /usr/libexec/git-core/git-subtree: line 751: 54693 Done                    eval "$grl"
>>    54694 Segmentation fault      (core dumped) | while read rev parents; do
> 
> Do you still have this core dump? Could you run it and see if it's
> "git" that crashed (and where) or "sh"?
It is /usr/bin/bash that segfaults.  My guess is, that it runs out of memory (as described above, git-subtree enters an infinite loop untils it segafults).
Show 9 quoted lines
> 
>>   process_split_commit "$rev" "$parents" 0;
>> done
>> 
>> Please note that this regression can not easily be reproduced, normally a subtree split just works.
>> 
>> Reverting the last three commits "fixes" the issue.  So I kindly ask the last three commits to be reverted.
> 
> Please provide the SHA-1 of the "good" commit you tested.
I reverted these three commits (actually the last three commits to contrib/subtree/git-subtree.sh):

19ad68d95d6f8104eca1e86f8d1dfae50c7fb268 68f8ff81513fb3599ef3dfc3dd11da36d868e91b 315a84f9aa0e2e629b0680068646b0032518ebed

And then it worked.
- Marc
-- 
> Duy
Duy Nguyen· Dec 31, 2018, 11:20 UTC · re: Marc Balmer · lore

Re: Regression in git-subtree.sh, introduced in 2.20.1, after 315a84f9aa0e2e629b0680068646b0032518ebed

On Mon, Dec 31, 2018 at 6:13 PM Marc Balmer <marc@msys.ch> wrote:
Show 24 quoted lines
>
>
>
> > Am 31.12.2018 um 11:51 schrieb Duy Nguyen <pclouds@gmail.com>:
> >
> > On Mon, Dec 31, 2018 at 5:44 PM Marc Balmer <marc@msys.ch> wrote:
> >>
> >> Hi
> >>
> >> One of the last three commits in git-subtree.sh introduced a regression leading to a segfault.
> >>
> >> Here is the error message when I try to split out my i18n files:
> >>
> >> $ git subtree split --prefix=i18n
> >> cache for e39a2a0c6431773a5d831eb3cb7f1cd40d0da623 already exists!
> >>   (Lots of output omitted)
> >> 436/627 (1819) [1455]       <- Stays at 436/ while the numbers in () and [] increase, then segfaults:
> >> /usr/libexec/git-core/git-subtree: line 751: 54693 Done                    eval "$grl"
> >>    54694 Segmentation fault      (core dumped) | while read rev parents; do
> >
> > Do you still have this core dump? Could you run it and see if it's
> > "git" that crashed (and where) or "sh"?
>
> It is /usr/bin/bash that segfaults.  My guess is, that it runs out of memory (as described above, git-subtree enters an infinite loop untils it segafults).

Ah that's better (I was worried about "git" crashing). The problematic commit should be 19ad68d95d (subtree: performance improvement for finding unexpected parent commits - 2018-10-12) then, although I can't see why.

I don't think we have any release coming up soon, so maybe Roger can still have some time to fix it instead of a just a revert.

Show 24 quoted lines
>
> >
> >>   process_split_commit "$rev" "$parents" 0;
> >> done
> >>
> >> Please note that this regression can not easily be reproduced, normally a subtree split just works.
> >>
> >> Reverting the last three commits "fixes" the issue.  So I kindly ask the last three commits to be reverted.
> >
> > Please provide the SHA-1 of the "good" commit you tested.
>
> I reverted these three commits (actually the last three commits to contrib/subtree/git-subtree.sh):
>
> 19ad68d95d6f8104eca1e86f8d1dfae50c7fb268
> 68f8ff81513fb3599ef3dfc3dd11da36d868e91b
> 315a84f9aa0e2e629b0680068646b0032518ebed
>
> And then it worked.
>
> - Marc
>
> --
> > Duy
>
-- 
Duy
Marc Balmer· Dec 31, 2018, 11:24 UTC · re: Duy Nguyen · lore

Re: Regression in git-subtree.sh, introduced in 2.20.1, after 315a84f9aa0e2e629b0680068646b0032518ebed

Show 35 quoted lines
> Am 31.12.2018 um 12:20 schrieb Duy Nguyen <pclouds@gmail.com>:
> 
> On Mon, Dec 31, 2018 at 6:13 PM Marc Balmer <marc@msys.ch> wrote:
>> 
>> 
>> 
>>> Am 31.12.2018 um 11:51 schrieb Duy Nguyen <pclouds@gmail.com>:
>>> 
>>> On Mon, Dec 31, 2018 at 5:44 PM Marc Balmer <marc@msys.ch> wrote:
>>>> 
>>>> Hi
>>>> 
>>>> One of the last three commits in git-subtree.sh introduced a regression leading to a segfault.
>>>> 
>>>> Here is the error message when I try to split out my i18n files:
>>>> 
>>>> $ git subtree split --prefix=i18n
>>>> cache for e39a2a0c6431773a5d831eb3cb7f1cd40d0da623 already exists!
>>>>  (Lots of output omitted)
>>>> 436/627 (1819) [1455]       <- Stays at 436/ while the numbers in () and [] increase, then segfaults:
>>>> /usr/libexec/git-core/git-subtree: line 751: 54693 Done                    eval "$grl"
>>>>   54694 Segmentation fault      (core dumped) | while read rev parents; do
>>> 
>>> Do you still have this core dump? Could you run it and see if it's
>>> "git" that crashed (and where) or "sh"?
>> 
>> It is /usr/bin/bash that segfaults.  My guess is, that it runs out of memory (as described above, git-subtree enters an infinite loop untils it segafults).
> 
> Ah that's better (I was worried about "git" crashing). The problematic
> commit should be 19ad68d95d (subtree: performance improvement for
> finding unexpected parent commits - 2018-10-12) then, although I can't
> see why.
> 
> I don't think we have any release coming up soon, so maybe Roger can
> still have some time to fix it instead of a just a revert.
In a (private) Email to me, he indicated that had no time for a fix.  Maybe he can speak up here?
In any case, if I can help testing, I am in.  I just don't know the inner workings of git-subtree.sh (I am a mere user of it...)
Show 29 quoted lines
> 
>> 
>>> 
>>>>  process_split_commit "$rev" "$parents" 0;
>>>> done
>>>> 
>>>> Please note that this regression can not easily be reproduced, normally a subtree split just works.
>>>> 
>>>> Reverting the last three commits "fixes" the issue.  So I kindly ask the last three commits to be reverted.
>>> 
>>> Please provide the SHA-1 of the "good" commit you tested.
>> 
>> I reverted these three commits (actually the last three commits to contrib/subtree/git-subtree.sh):
>> 
>> 19ad68d95d6f8104eca1e86f8d1dfae50c7fb268
>> 68f8ff81513fb3599ef3dfc3dd11da36d868e91b
>> 315a84f9aa0e2e629b0680068646b0032518ebed
>> 
>> And then it worked.
>> 
>> - Marc
>> 
>> --
>>> Duy
>> 
> 
> 
> -- 
> Duy
Duy Nguyen· Dec 31, 2018, 11:36 UTC · re: Marc Balmer · lore

Re: Regression in git-subtree.sh, introduced in 2.20.1, after 315a84f9aa0e2e629b0680068646b0032518ebed

On Mon, Dec 31, 2018 at 6:24 PM Marc Balmer <marc@msys.ch> wrote:
> In a (private) Email to me, he indicated that had no time for a fix.  Maybe he can speak up here?

Well, I guess Junio will revert when he's back after the holidays then. Meanwhile..

> In any case, if I can help testing, I am in.  I just don't know the inner workings of git-subtree.sh (I am a mere user of it...)

If the repo you're facing the problem is publicly available, that would be great so some of us could try reproduce.

Otherwise we'll need your help to track this problem down. in git-subtree script line 640 (or somewhere close)

    progress "$revcount/$revmax ($createcount) [$extracount]"
could you update it to show $parents and $rev as well, e.g.
    progress "$revcount/$revmax ($createcount) [$extracount] ($parents) ($rev)"
Then please run these commands and post the output here
    git rev-parse <that-rev>^@
and
    git show -s --pretty=%P <that-rev>
where <that-rev> is $rev from the last few progress lines before bash crashes.
-- 
Duy
Marc Balmer· Dec 31, 2018, 12:31 UTC · re: Duy Nguyen · lore

Re: Regression in git-subtree.sh, introduced in 2.20.1, after 315a84f9aa0e2e629b0680068646b0032518ebed

Show 12 quoted lines
> Am 31.12.2018 um 12:36 schrieb Duy Nguyen <pclouds@gmail.com>:
> 
> On Mon, Dec 31, 2018 at 6:24 PM Marc Balmer <marc@msys.ch> wrote:
>> In a (private) Email to me, he indicated that had no time for a fix.  Maybe he can speak up here?
> 
> Well, I guess Junio will revert when he's back after the holidays
> then. Meanwhile..
> 
>> In any case, if I can help testing, I am in.  I just don't know the inner workings of git-subtree.sh (I am a mere user of it...)
> 
> If the repo you're facing the problem is publicly available, that
> would be great so some of us could try reproduce.
Unfortunately it is not.
Show 9 quoted lines
> 
> Otherwise we'll need your help to track this problem down. in
> git-subtree script line 640 (or somewhere close)
> 
>    progress "$revcount/$revmax ($createcount) [$extracount]"
> 
> could you update it to show $parents and $rev as well, e.g.
> 
>    progress "$revcount/$revmax ($createcount) [$extracount] ($parents) ($rev)"
I did add this, plus changed progress to output a linefeed, and now just before the crash, the output looks like this:
436/627 (2013) [1649] (6e54a90a29e4e01fa2d6a42c232e02e08e912b2d) (2ca7b24e731ff91c94c9abf214686cb29cdc367e)
436/627 (2014) [1650] (1ef866e5a18012e80eed36315deb932c2b66d34a) (6e54a90a29e4e01fa2d6a42c232e02e08e912b2d)
436/627 (2015) [1651] (c8585f441548dd43f113a96ba48f6fa70363d388) (1ef866e5a18012e80eed36315deb932c2b66d34a)
436/627 (2016) [1652] (663bb110a58decfe889cf7c6b766f1d0c032ba39) (c8585f441548dd43f113a96ba48f6fa70363d388)
436/627 (2017) [1653] (edbdd28e009e52c8001bb54e53a56b059167e07d) (663bb110a58decfe889cf7c6b766f1d0c032ba39)
436/627 (2018) [1654] (c47739713912ae6e94714b9a1a6732407b236932) (edbdd28e009e52c8001bb54e53a56b059167e07d)
436/627 (2019) [1655] (d444823b97d9a8e53c4e721a44e4c49619d0b372) (c47739713912ae6e94714b9a1a6732407b236932)
436/627 (2020) [1656] (15a7ccecb2ca8bc47c77a997f8c74e7ac3b13325) (d444823b97d9a8e53c4e721a44e4c49619d0b372)
436/627 (2021) [1657] (b9bc5c9b33b100b57e23626ff422dac73f94384e) (15a7ccecb2ca8bc47c77a997f8c74e7ac3b13325)
436/627 (2022) [1658] (eec0f28c6fe5f7d664c41a913883d64cdf53c111) (b9bc5c9b33b100b57e23626ff422dac73f94384e)
436/627 (2023) [1659] (e0ddd9c60f71283996cfb169f1dbb77e8f7c4b94) (eec0f28c6fe5f7d664c41a913883d64cdf53c111)
436/627 (2024) [1660] (27b96988847caf3bfd71df2d7f58cbe6ba78208a) (e0ddd9c60f71283996cfb169f1dbb77e8f7c4b94)
436/627 (2025) [1661] (11e5861e50f88237ce362b6c7531e4e90bac86ac) (27b96988847caf3bfd71df2d7f58cbe6ba78208a)
/usr/libexec/git-core/git-subtree: line 751: 122202 Done                    eval "$grl"
     122203 Segmentation fault      (core dumped) | while read rev parents; do
    process_split_commit "$rev" "$parents" 0;
done
> 
> Then please run these commands and post the output here
> 
>    git rev-parse <that-rev>^@
Did that with the last three lines:

$ git rev-parse 27b96988847caf3bfd71df2d7f58cbe6ba78208a^@ 11e5861e50f88237ce362b6c7531e4e90bac86ac $ git rev-parse e0ddd9c60f71283996cfb169f1dbb77e8f7c4b94^@ 27b96988847caf3bfd71df2d7f58cbe6ba78208a $ git rev-parse eec0f28c6fe5f7d664c41a913883d64cdf53c111^@ e0ddd9c60f71283996cfb169f1dbb77e8f7c4b94

> 
> and
> 
>    git show -s --pretty=%P <that-rev>

$ git show -s --pretty=%P 27b96988847caf3bfd71df2d7f58cbe6ba78208a 11e5861e50f88237ce362b6c7531e4e90bac86ac $ git show -s --pretty=%P e0ddd9c60f71283996cfb169f1dbb77e8f7c4b94 27b96988847caf3bfd71df2d7f58cbe6ba78208a $ git show -s --pretty=%P eec0f28c6fe5f7d664c41a913883d64cdf53c111 e0ddd9c60f71283996cfb169f1dbb77e8f7c4b94

> 
> where <that-rev> is $rev from the last few progress lines before bash crashes.
> -- 
> Duy
Duy Nguyen· Jan 1, 2019, 13:19 UTC · re: Marc Balmer · lore

Re: Regression in git-subtree.sh, introduced in 2.20.1, after 315a84f9aa0e2e629b0680068646b0032518ebed

On Mon, Dec 31, 2018 at 01:31:21PM +0100, Marc Balmer wrote:
Show 74 quoted lines
> 
> 
> > Am 31.12.2018 um 12:36 schrieb Duy Nguyen <pclouds@gmail.com>:
> > 
> > On Mon, Dec 31, 2018 at 6:24 PM Marc Balmer <marc@msys.ch> wrote:
> >> In a (private) Email to me, he indicated that had no time for a fix.  Maybe he can speak up here?
> > 
> > Well, I guess Junio will revert when he's back after the holidays
> > then. Meanwhile..
> > 
> >> In any case, if I can help testing, I am in.  I just don't know the inner workings of git-subtree.sh (I am a mere user of it...)
> > 
> > If the repo you're facing the problem is publicly available, that
> > would be great so some of us could try reproduce.
> 
> Unfortunately it is not.
> 
> > 
> > Otherwise we'll need your help to track this problem down. in
> > git-subtree script line 640 (or somewhere close)
> > 
> >    progress "$revcount/$revmax ($createcount) [$extracount]"
> > 
> > could you update it to show $parents and $rev as well, e.g.
> > 
> >    progress "$revcount/$revmax ($createcount) [$extracount] ($parents) ($rev)"
> 
> I did add this, plus changed progress to output a linefeed, and now just before the crash, the output looks like this:
> 
> 436/627 (2013) [1649] (6e54a90a29e4e01fa2d6a42c232e02e08e912b2d) (2ca7b24e731ff91c94c9abf214686cb29cdc367e)
> 436/627 (2014) [1650] (1ef866e5a18012e80eed36315deb932c2b66d34a) (6e54a90a29e4e01fa2d6a42c232e02e08e912b2d)
> 436/627 (2015) [1651] (c8585f441548dd43f113a96ba48f6fa70363d388) (1ef866e5a18012e80eed36315deb932c2b66d34a)
> 436/627 (2016) [1652] (663bb110a58decfe889cf7c6b766f1d0c032ba39) (c8585f441548dd43f113a96ba48f6fa70363d388)
> 436/627 (2017) [1653] (edbdd28e009e52c8001bb54e53a56b059167e07d) (663bb110a58decfe889cf7c6b766f1d0c032ba39)
> 436/627 (2018) [1654] (c47739713912ae6e94714b9a1a6732407b236932) (edbdd28e009e52c8001bb54e53a56b059167e07d)
> 436/627 (2019) [1655] (d444823b97d9a8e53c4e721a44e4c49619d0b372) (c47739713912ae6e94714b9a1a6732407b236932)
> 436/627 (2020) [1656] (15a7ccecb2ca8bc47c77a997f8c74e7ac3b13325) (d444823b97d9a8e53c4e721a44e4c49619d0b372)
> 436/627 (2021) [1657] (b9bc5c9b33b100b57e23626ff422dac73f94384e) (15a7ccecb2ca8bc47c77a997f8c74e7ac3b13325)
> 436/627 (2022) [1658] (eec0f28c6fe5f7d664c41a913883d64cdf53c111) (b9bc5c9b33b100b57e23626ff422dac73f94384e)
> 436/627 (2023) [1659] (e0ddd9c60f71283996cfb169f1dbb77e8f7c4b94) (eec0f28c6fe5f7d664c41a913883d64cdf53c111)
> 436/627 (2024) [1660] (27b96988847caf3bfd71df2d7f58cbe6ba78208a) (e0ddd9c60f71283996cfb169f1dbb77e8f7c4b94)
> 436/627 (2025) [1661] (11e5861e50f88237ce362b6c7531e4e90bac86ac) (27b96988847caf3bfd71df2d7f58cbe6ba78208a)
> /usr/libexec/git-core/git-subtree: line 751: 122202 Done                    eval "$grl"
>      122203 Segmentation fault      (core dumped) | while read rev parents; do
>     process_split_commit "$rev" "$parents" 0;
> done
> 
> 
> > 
> > Then please run these commands and post the output here
> > 
> >    git rev-parse <that-rev>^@
> 
> Did that with the last three lines:
> 
> $ git rev-parse 27b96988847caf3bfd71df2d7f58cbe6ba78208a^@
> 11e5861e50f88237ce362b6c7531e4e90bac86ac
> $ git rev-parse e0ddd9c60f71283996cfb169f1dbb77e8f7c4b94^@
> 27b96988847caf3bfd71df2d7f58cbe6ba78208a
> $ git rev-parse eec0f28c6fe5f7d664c41a913883d64cdf53c111^@
> e0ddd9c60f71283996cfb169f1dbb77e8f7c4b94
> 
> > 
> > and
> > 
> >    git show -s --pretty=%P <that-rev>
> 
> $ git show -s --pretty=%P 27b96988847caf3bfd71df2d7f58cbe6ba78208a
> 11e5861e50f88237ce362b6c7531e4e90bac86ac
> $ git show -s --pretty=%P e0ddd9c60f71283996cfb169f1dbb77e8f7c4b94
> 27b96988847caf3bfd71df2d7f58cbe6ba78208a
> $ git show -s --pretty=%P eec0f28c6fe5f7d664c41a913883d64cdf53c111
> e0ddd9c60f71283996cfb169f1dbb77e8f7c4b94
> 

Hmm.. I'm not that familiar with git-subtree.sh, so here's one last blind shot.

There's a format change between git-show and git-rev-parse. The former separates commits by spaces while the latter by newlines. Will this help?

diff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh
index 147201dc6c..23f570beee 100755
--- a/contrib/subtree/git-subtree.sh
+++ b/contrib/subtree/git-subtree.sh
@@ -633,7 +633,7 @@ process_split_commit () {
 	else
 		# processing commit without normal parent information;
 		# fetch from repo
-		parents=$(git rev-parse "$rev^@")
+		parents=$(git rev-parse "$rev^@" | tr '\n' ' ')
 		extracount=$(($extracount + 1))
 	fi
 
--
Duy
Marc Balmer· Jan 2, 2019, 09:13 UTC · re: Duy Nguyen · lore

Re: Regression in git-subtree.sh, introduced in 2.20.1, after 315a84f9aa0e2e629b0680068646b0032518ebed

Show 24 quoted lines
> [...]
> 
>> 
> 
> Hmm.. I'm not that familiar with git-subtree.sh, so here's one last
> blind shot.
> 
> There's a format change between git-show and git-rev-parse. The former
> separates commits by spaces while the latter by newlines. Will this
> help?
> 
> diff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh
> index 147201dc6c..23f570beee 100755
> --- a/contrib/subtree/git-subtree.sh
> +++ b/contrib/subtree/git-subtree.sh
> @@ -633,7 +633,7 @@ process_split_commit () {
> 	else
> 		# processing commit without normal parent information;
> 		# fetch from repo
> -		parents=$(git rev-parse "$rev^@")
> +		parents=$(git rev-parse "$rev^@" | tr '\n' ' ')
> 		extracount=$(($extracount + 1))
> 	fi
> 
Unfortunately, this did not change the situation.  It still segfaults.
> --
> Duy
Strain, Roger L.· Jan 2, 2019, 20:20 UTC · re: Marc Balmer · lore

RE: Regression in git-subtree.sh, introduced in 2.20.1, after 315a84f9aa0e2e629b0680068646b0032518ebed

Show 57 quoted lines
> -----Original Message-----
> From: Marc Balmer <marc@msys.ch>
> Sent: Monday, December 31, 2018 5:24 AM
> To: Duy Nguyen <pclouds@gmail.com>
> Cc: Git Mailing List <git@vger.kernel.org>; Strain, Roger L.
> <roger.strain@swri.org>; Junio C Hamano <gitster@pobox.com>
> Subject: Re: Regression in git-subtree.sh, introduced in 2.20.1, after
> 315a84f9aa0e2e629b0680068646b0032518ebed
> 
> 
> 
> > Am 31.12.2018 um 12:20 schrieb Duy Nguyen <pclouds@gmail.com>:
> >
> > On Mon, Dec 31, 2018 at 6:13 PM Marc Balmer <marc@msys.ch> wrote:
> >>
> >>
> >>
> >>> Am 31.12.2018 um 11:51 schrieb Duy Nguyen <pclouds@gmail.com>:
> >>>
> >>> On Mon, Dec 31, 2018 at 5:44 PM Marc Balmer <marc@msys.ch> wrote:
> >>>>
> >>>> Hi
> >>>>
> >>>> One of the last three commits in git-subtree.sh introduced a regression
> leading to a segfault.
> >>>>
> >>>> Here is the error message when I try to split out my i18n files:
> >>>>
> >>>> $ git subtree split --prefix=i18n
> >>>> cache for e39a2a0c6431773a5d831eb3cb7f1cd40d0da623 already exists!
> >>>>  (Lots of output omitted)
> >>>> 436/627 (1819) [1455]       <- Stays at 436/ while the numbers in () and []
> increase, then segfaults:
> >>>> /usr/libexec/git-core/git-subtree: line 751: 54693 Done                    eval
> "$grl"
> >>>>   54694 Segmentation fault      (core dumped) | while read rev parents;
> do
> >>>
> >>> Do you still have this core dump? Could you run it and see if it's
> >>> "git" that crashed (and where) or "sh"?
> >>
> >> It is /usr/bin/bash that segfaults.  My guess is, that it runs out of memory
> (as described above, git-subtree enters an infinite loop untils it segafults).
> >
> > Ah that's better (I was worried about "git" crashing). The problematic
> > commit should be 19ad68d95d (subtree: performance improvement for
> > finding unexpected parent commits - 2018-10-12) then, although I can't
> > see why.
> >
> > I don't think we have any release coming up soon, so maybe Roger can
> > still have some time to fix it instead of a just a revert.
> 
> In a (private) Email to me, he indicated that had no time for a fix.  Maybe he
> can speak up here?
> 
> In any case, if I can help testing, I am in.  I just don't know the inner workings
> of git-subtree.sh (I am a mere user of it...)
TL;DR: Current script uses git rev-list to retrieve all commits which are reachable from HEAD but not from <abc123>. Is there a syntax that will instead return all commits reachable from HEAD, but stop traversing when <abc123> is encountered? It's a subtle distinction, but important.
Long version:
While I don't have a lot of time to troubleshoot this as deeply as I'd like, I've at least tried to give it a little bit of thought. If we assume it's an out of memory problem, that's likely due to commit 315a84f9aa0e2e629b0680068646b0032518ebed, which introduced a recursive history search. It might be possible to refactor that logic to avoid the recursive approach, but shell scripting is not my native tongue, and I didn't immediately see the right way to do it. I can explain the problem the commit was trying to address, and if anyone has suggestions about how to better fix the problem, I'd love to hear them.
This part of the subtree script is attempting to identify all mainline commits which need to be evaluated for subtree content. When subtree rejoin commits are included, it short-circuits this process by identifying all commits which can be reached from the current HEAD, but which CANNOT be reached from any of the known subtree rejoin points. While this does simplify the number of commits that need to be evaluated, it causes the script to miss commits that do in fact need to be evaluated when merges bypass those rejoins. Consider the following:
(Apologies for the crude diagram, I'm having to use Outlook at work and have no idea if this will format properly.)
[A]--(B)--(D)--[E]---(G)
 \       /          /
  ---(C)-------(F)--
In this graph, [A] represents an initial commit, which is a subtree rejoin (presumably mapping to subtree commit A'). From this, commits B and C were created, then those two were merged as commit D, and a subtree operation was performed to push these changes to the subtree. The result was rejoined as commit [E] (mapping as subtree commit E'). We then have a commit F with a single parent of C, and a merge of E and F into commit G.
At this point, I want to push the commits through G back to the subtree. The original script used git rev-list to list all commits which can be reached from G, but which cannot be reached from known split points A and E. This results in a commit list of G, F. It then looks at commit F to determine how it fits into the subtree, sees that it has a parent C, and looks for what subtree commit C maps to. Unfortunately C wasn't included in the list of commits to evaluate, so that check failed, and the script treats F as an initial commit. The subtree generated then includes F' as a complete commit, unrelated to any previous commits in the subtree, rather than connecting it to C' as a parent.
The ideal solution to this would be a call to git rev-list (or another tool, if appropriate) that could actually generate a commit list of G, F, C in the above diagram. Rather than being "All commits I can reach from G but not from A or E", what it really needs is "All commits I can reach from G, but stop traversing the history any time I reach A or E". If someone with better knowledge can provide that command, I think we could restore the script to a non-recursive approach and give better information about the true progress of the command, rather than having to rely on the "extra count" I introduced to keep track of how many unexpected commits are being recursively evaluated because the initial rev-list didn't include them.
As an aside, there's still another problem that we've run into which is forcing us to still run a custom version of the subtree script. There's a section in the script commented "ugly.  is there no better way to tell if this is a subtree vs. a mainline commit?  Does it matter?" Unfortunately, that section isn't working properly in our repo at this point, and I've had to include a VERY ugly check that looks for the existence of a known file in our specific mainline repo to make this determination. I'm still trying to sort through a better approach that might work for others, but have come up blank to this point. If anyone else has thoughts, I'd really love to hear those as well.
Anyway, sorry for the novel, but I wanted to brain dump what I've learned in this process. If anyone can suggest a syntax for rev-list that gives the appropriate set of commits, I'd love to get that in place; otherwise we could definitely try to unwind the recursion approach, but my shell script naivety may get me in trouble.
-- 
Roger
Johannes Schindelin· Jan 3, 2019, 13:50 UTC · re: Strain, Roger L. · lore

RE: Regression in git-subtree.sh, introduced in 2.20.1, after 315a84f9aa0e2e629b0680068646b0032518ebed

Hi Roger,
On Wed, 2 Jan 2019, Strain, Roger L. wrote:
> TL;DR: Current script uses git rev-list to retrieve all commits which
> are reachable from HEAD but not from <abc123>. Is there a syntax that
> will instead return all commits reachable from HEAD, but stop traversing
> when <abc123> is encountered? It's a subtle distinction, but important.

Maybe you are looking for the --ancestry-path option? Essentially, `git rev-list --ancestry-path A..B` will list only commits that are reachable from B, not reachable from A, but that *can* reach A (i.e. that are descendants of A).

Ciao, Johannes

Strain, Roger L.· Jan 3, 2019, 15:30 UTC · re: Johannes Schindelin · lore

RE: Regression in git-subtree.sh, introduced in 2.20.1, after 315a84f9aa0e2e629b0680068646b0032518ebed

Show 22 quoted lines
> -----Original Message-----
> From: Johannes Schindelin <Johannes.Schindelin@gmx.de>
> 
> Hi Roger,
> 
> 
> On Wed, 2 Jan 2019, Strain, Roger L. wrote:
> 
> > TL;DR: Current script uses git rev-list to retrieve all commits which
> > are reachable from HEAD but not from <abc123>. Is there a syntax that
> > will instead return all commits reachable from HEAD, but stop
> traversing
> > when <abc123> is encountered? It's a subtle distinction, but
> important.
> 
> Maybe you are looking for the --ancestry-path option? Essentially, `git
> rev-list --ancestry-path A..B` will list only commits that are reachable
> from B, not reachable from A, but that *can* reach A (i.e. that are
> descendants of A).
> 
> Ciao,
> Johannes
Thanks for the suggestion, but I don't think that one does quite what is needed here. It did provide a good sample graph to consider, though. Subtree needs to rebuild history and tie things in to previously reconstructed commits. Here's the sample graph from the --ancestry-path portion of the git-rev-list manpage:
	    D---E-------F
	   /     \       \
	  B---C---G---H---I---J
	 /                     \
	A-------K---------------L--M
Subtree maps mainline commits to known subtree commits, so let's assume we have a mapping of D to D'. As documented, if we were to rev-list D..M normally, we'd get all commits except D itself, and D's ancestors B and A. So the "normal" result would be:
	        E-------F
	         \       \
	      C---G---H---I---J
	                       \
	        K---------------L--M
This is bad for subtree, because commit C's parent is B, which is not a known commit to subtree, and which wasn't included in the list of commits to convert. It therefore assumes C is an initial commit, which is wrong. Likewise K's parent A isn't in the list to convert, so K is assumed to be an initial commit, which also is wrong. (E is okay here, because E's parent is D, and D maps to D', so we can stitch that history together properly.)
By using --ancestry-path, we would instead get only the things directly between D and M, as documented:
	        E-------F
	         \       \
	          G---H---I---J
	                       \
	                        L--M
This actually moves us in the wrong direction, as now both G and L have one known parent and one unknown parent; I'm not sure how the script would handle this, but we actually end up with less information.
In this case, what I need is a way to trace back history along all merge parents, stopping only when I hit one of multiple known commits that I can directly tie back to. In this instance, subtree *knows* what D maps to, so any time D is encountered, we can stop tracing back. But if I can get to one of D's ancestors through another path, I need to keep following that path. Here's what I need for this to work properly:
	        E-------F
	         \       \
	  B---C---G---H---I---J
	 /                     \
	A-------K---------------L--M
To give one more example (since removing a single commit frankly isn't very interesting) let's say that I have known subtree mappings for both D = D' and G = G'. I would therefore need to find all commits which are ancestors of M, but stop tracing history when I reach *either* D or G. Note that if I can reach a commit from any other path, I still need to know about it. Here's what we ultimately would want to find:
	        E-------F
	                 \
	              H---I---J
	                       \
	A-------K---------------L--M
In this case, commit E will reference known commit D as a parent and maps to D', and is good. Commit H references known commit G as a parent and maps to G', and is good. Commit K references A, which itself is an initial commit so is converted to A' (just as it has been previous times subtree has run), and is good.
I'll keep digging around a little bit, but I'm starting to think the necessary plumbing for this operation might not exist. If I can't find it, I'll see if there's some way to unroll that recursive call.
-- 
Roger

← back to recent threads