ingydotnet / git-subrepo

MIT License
3.18k stars 263 forks source link

Endless fake conflicts when using the rebase strategy #445

Open feliperaul opened 4 years ago

feliperaul commented 4 years ago

I really gave this neat project a go, but my user experience on the last month has been very difficult due to the sheer amount of conflicts every time I use git subrepo pull with the rebase strategy.

I find myself having to solve conflicts on every single commit that has happened on the imported subrepo, and no matter how many times I resolve them, they always comeback on every single pull.

Also, I'm seeing a lot of conflicts that are not conflicts at all, like, for instance, this:

image

There''s no difference at all between those two lines, and yet I have to fix this every single time.

With 10+ commits on the imported repo, every single git subrepo pull is taking around 15 minutes to solve already, and they are all "fake" conflicts like this.

admorgan commented 4 years ago

I can see how this would be frustrating. Do you have a sample repository that I can look at so I can have a better understanding of what you are going through? My guess is that the two lines you have posted vary by line ending, a non printable character, and would not be addressed unless a fix was pushed up stream.

I am curious as to why you chose to use rebase instead of the merge strategy? The merge strategy would "remember" the line ending option that you desired and stop asking you to pick again.

feliperaul commented 4 years ago

@admorgan First of all, thanks for the quick reply in a sunday. This project is awesome!

I can confirm both lines are identical in my text editor.

But here's the reason why I chose the rebase strategy, and maybe you can help me think through this.

I have developed a Ansible playbook for Rails servers provisioning and deployment.

I keep it in a repo, let's call it ansible-playbook.

At the same time, I want all my Rails projects to have a /ops subfolder that contain that repo.

I use the rebase strategy because as soon as I clone the ansible-playbook inside the /ops subfolder, I need to change a lot of settings in the configuration files (like, for instance, project name, server IPs, credentials, and so on).

My workflow is very simple: the Rails projects never push to ansible-playbook. All the changes are done in ansible-playbook and then I use git subrepo pull ops inside the Rails projects to get the latest updates.

The reason I'm using the rebase strategy is so that changes made in the ansible-playbook files do not overwrite the settings I already did in each the Rails project. So I wish to (1) rewind all my changes made in that folder, (2) pull the latest updates from ansible-playbook repo into the project, (3) apply my changes over those updated files, which essentially is a rebase strategy, right?

Do you agree with this workflow?

admorgan commented 4 years ago

I agree with your workflow. Can you send me the full example diff. I am just trying to figure out what is going wrong so I can figure out how to address it.

MarkCallow commented 4 years ago

I have the same issue and I am using the default strategy, i.e. just git subrepo pull <subdir>. Any file that they have changed since the last pull, but I haven't is shown as having conflicts. Also any file that I have ever changed but they haven't is shown as having conflicts. In my latest pull 9 conflicts are flagged yet the only changes in the upstream repo since my last pull are to 3 files that I have never made changes to. For example the following "conflict" is shown in README.md

<<<<<<< HEAD
=======
Probably the most important concept to understand about Basis Universal before using it: The system supports **two** very different universal texture modes: The original "ETC1S" mode is low/medium quality, but the resulting file sizes are very small because the system has built-in compression for ETC1S texture format files. This is the command line encoding tool's default mode. ETC1S textures work best on images, photos, map data, or albedo/specular/etc. textures, but don't work as well on normal maps. There's the second "UASTC" mode, which is significantly higher quality (near-BC7 grade), and is usable on all texture types including complex normal maps. UASTC mode purposely does not have built-in file compression like ETC1S mode does, so the resulting files are quite large (8-bits/texel - same as BC7) compared to ETC1S mode. The UASTC encoder has an optional Rate Distortion Optimization (RDO) encoding mode (implemented as a post-process over the encoded UASTC texture data), which lowers the output data's entropy in a way that results in better compression when UASTC .basis files are compressed with Deflate/Zstd, etc. In UASTC mode, you must losslessly compress the file yourself.

Basis Universal is not an image compression codec. It's a texture compression codec. It can be used just like an image compression codec, but that's not the only use case. Here's a [good intro](http://renderingpipeline.com/2012/07/texture-compression/) to GPU texture compression. If you're looking to primarily use the system as an image compression codec on sRGB photographic content, use the default ETC1S mode, because it has built-in compression. 

>>>>>>> refs/subrepo/lib/basisu/fetch

I have never edited this file since first initializing this subrepo, never mind since my last pull. This is not the only change they have made in the file since my last pull but only it is only one flagged as a conflict. The complete diff from upstream is:

diff --git a/README.md b/README.md
index aa95636..8e5dc90 100644
--- a/README.md
+++ b/README.md
@@ -17,6 +17,10 @@ Basis Universal supports "skip blocks" in ETC1S compressed texture arrays, which

 ### Important Usage Notes

+Probably the most important concept to understand about Basis Universal before using it: The system supports **two** very different universal texture modes: The original "ETC1S" mode is low/medium quality, but the resulting file sizes are very small because the system has built-in compression for ETC1S texture format files. This is the command line encoding tool's default mode. ETC1S textures work best on images, photos, map data, or albedo/specular/etc. textures, but don't work as well on normal maps. There's the second "UASTC" mode, which is significantly higher quality (near-BC7 grade), and is usable on all texture types including complex normal maps. UASTC mode purposely does not have built-in file compression like ETC1S mode does, so the resulting files are quite large (8-bits/texel - same as BC7) compared to ETC1S mode. The UASTC encoder has an optional Rate Distortion Optimization (RDO) encoding mode (implemented as a post-process over the encoded UASTC texture data), which lowers the output data's entropy in a way that results in better compression when UASTC .basis files are compressed with Deflate/Zstd, etc. In UASTC mode, you must losslessly compress the file yourself.
+
+Basis Universal is not an image compression codec. It's a texture compression codec. It can be used just like an image compression codec, but that's not the only use case. Here's a [good intro](http://renderingpipeline.com/2012/07/texture-compression/) to GPU texture compression. If you're looking to primarily use the system as an image compression codec on sRGB photographic content, use the default ETC1S mode, because it has built-in compression. 
+
 **The "-q X" option controls the output quality in ETC1S mode.** The default is quality level 128. "-q 255" will increase quality quite a bit. If you want even higher quality, try "-max_selectors 16128 -max_endpoints 16128" instead of -q. -q internally tries to set the codebook sizes (or the # of quantization intervals for endpoints/selectors) for you. You need to experiment with the quality level on your content.

 For tangent space normal maps, you should separate X into RGB and Y into Alpha, and provide the compressor with 32-bit/pixel input images. Or use the "-separate_rg_to_color_alpha" command line option which does this for you. The internal texture format that Basis Universal uses (ETC1S) doesn't handle tangent space normal maps encoded into RGB well. You need to separate the channels and recover Z in the pixel shader using z=sqrt(1-x^2-y^2).
@@ -150,7 +154,7 @@ After compression, the compressor transcodes all slices in the output .basis fil

 For best quality, you must supply basisu with original uncompressed source images. Any other type of lossy compression applied before basisu (including ETC1/BC1-5, BC7, JPEG, etc.) will cause multi-generational artifacts to appear in the final output textures. 

-For the maximum possible achievable quality with the current format and encoder (completely ignoring encoding speed!), use:
+For the maximum possible achievable ETC1S mode quality with the current format and encoder (completely ignoring encoding speed!), use:

 `basisu x.png -comp_level 5 -max_endpoints 16128 -max_selectors 16128 -no_selector_rdo -no_endpoint_rdo`

@@ -187,7 +191,10 @@ Note that -comp_level 2 is equivalent to the initial release's default, and -com
 ### More detailed examples

 `basisu x.png`\
-Compress sRGB image x.png to x.basis using default settings (multiple filenames OK)
+Compress sRGB image x.png to a ETC1S format x.basis file using default settings (multiple filenames OK). ETC1S format files are typically very small on disk (around .5-1.5 bits/texel).
+
+`basisu -uastc x.png`\
+Compress image x.png to a UASTC format x.basis file using default settings (multiple filenames OK). UASTC files are the same size as BC7 on disk (8-bpp). Be sure to compress UASTC .basis files yourself using Deflate, zstd, etc. To increase .basis file compressibility (trading off quality for smaller compressed files) use the "-uastc_rdo_q X" command line parameter.

 `basisu -q 255 x.png`\
 Compress sRGB image x.png to x.basis at max quality level achievable without  manually setting the codebook sizes (multiple filenames OK)
@@ -238,7 +245,7 @@ Note: The one exception to this promise are .basis textures marked as video. We

 ### Encoder speed

-Total time for basisu.exe to compress a 1024x1024 texture on a 7 year old 4-core 2.2GHz Core i7 laptop - timings are "without mipmaps/with mipmaps":
+Total time for basisu.exe to compress a 1024x1024 ETC1S texture on a 7 year old 4-core 2.2GHz Core i7 laptop - timings are "without mipmaps/with mipmaps":

 * -comp_level 0: 

Upstream's git log shows 4 commits to this file since my last pull. The first commit introduced the first paragraph of the conflicting change. The third commit, the second paragraph.

I do not know how to get the diff in tmp/subrepo/lib/basisu showing "their" changes between the previous pull and now.

The upstream repo is https://github.com/BinomialLLC/basis_universal. My repo that includes this as a subrepo is https://github.com/KhronosGroup/KTX-Software. Note I am still working on the latest pull, i.e. resolving these conflicts. I expect the result will appear on the repo later today.

MarkCallow commented 4 years ago

Here's a simpler example from the same pull:

<<<<<<< HEAD
            assert(ccell_results_rgb.m_low_endpoint.m_c[rot_comp] == ccell_results_rgb.m_high_endpoint.m_c[rot_comp]);

=======

>>>>>>> refs/subrepo/lib/basisu/fetch

This file was new 2 pulls ago. I have not made any changes to it. This is the only change in the file since then. The diff from upstream is:

diff --git a/basisu_uastc_enc.cpp b/basisu_uastc_enc.cpp
index ba5083a..c4fb9eb 100644
--- a/basisu_uastc_enc.cpp
+++ b/basisu_uastc_enc.cpp
@@ -1256,8 +1256,7 @@ namespace basisu
                        ccell_results_rgb.m_pSelectors_temp = &ccell_result_selectors_temp[0];

                        uint64_t part_err_rgb = color_cell_compression(255, &ccell_params_rgb, &ccell_results_rgb, &comp_params);
-                       assert(ccell_results_rgb.m_low_endpoint.m_c[rot_comp] == ccell_results_rgb.m_high_endpoint.m_c[rot_comp]);
-
+                       
                        color_cell_compressor_params ccell_params_a;
                        memset(&ccell_params_a, 0, sizeof(ccell_params_a));

The - + beside the empty lines are removal of a truly empty line with it being replaced by a line with 3 tab characters.

MarkCallow commented 4 years ago

I just did another pull and got a load more fake conflicts. This issue really needs to be fixed. Here is the list

        both added:      apg_bmp.c
    both modified:   basisu.vcxproj
    both modified:   basisu_enc.cpp
    both modified:   basisu_etc.cpp
    both added:      basisu_miniz.h
    both modified:   contrib/previewers/win/preview.png
    both modified:   contrib/single_file_transcoder/examples/testcard.png
    both modified:   encoder_lvl_vs_perf.png
    both added:      jpgd.cpp
    both modified:   transcoder/basisu.h
    both modified:   transcoder/basisu_transcoder.cpp
    both modified:   transcoder/basisu_transcoder.h
    both modified:   webgl/gltf/preview.png
    both modified:   webgl/texture/preview.png

I have never modified any of the .png images or the .vcxproj file. I did not add apg_bmp.c, basisu_miniz.h or jpgd.cpp. All were added by "them" before the last time I pulled the repo and so were in my subrepo before this pull. I did however modify jpgd.cpp to fix a compile warning. I haven't yet looked at the conflicts in the remaining files to see if they are genuine.

MarkCallow commented 4 years ago

There was exactly 1 conflicting change in all these files. The .c & .cpp files marked as "both added" had changes I had made which were marked as conflicts but no changes from "them". The other files, excepting the one with a genuine conflict, had changes from either me or them but not both. That last file also had conflicts shown wherever I or they had made changes but only in 1 line of the file had both of us made changes.

The pain of this is making subrepo unusable.

MarkCallow commented 4 years ago

Over in issue #409 I describe some major issues I have just had with git subrepo branch. Looking at that I see a couple of things that could be causing the endless fake conflicts:

  1. Commits pulled from the subrepo's upstream show up with different commit ids in the subrepo branch.
  2. git log on the subrepo branch that was created shows it includes every subrepo pull and every change I've ever made to the subrepo code. These are listed before the latest commit from the subrepo's upstream which was pulled in the most recent subrepo pull (in other words they were all applied after that most recent pull. This may be happening due to the commit id's being different.
MarkCallow commented 3 years ago

I have suffered from this again. This time I have made 0 changes to the code in the subrepo dir since the last pull from upstream and I have done no pushes (either directly to upstream or a clone of upstream.) At the last pull I did "use theirs" so the code after that pull was and is identical to upstream. I also did a git subrepo clean just before this latest pull. Nevertheless I get the following huge list of conflicts including bogus claims that certain files were added by both parties.

On branch subrepo/lib/basisu
You have unmerged paths.
  (fix conflicts and run "git commit")
  (use "git merge --abort" to abort the merge)

Changes to be committed:
    modified:   encoder/basisu_basis_file.h
    modified:   encoder/basisu_global_selector_palette_helpers.h
    new file:   encoder/basisu_kernels_declares.h
    new file:   encoder/basisu_kernels_imp.h
    new file:   encoder/basisu_kernels_sse.cpp
    new file:   encoder/cppspmd_flow.h
    new file:   encoder/cppspmd_math.h
    new file:   encoder/cppspmd_math_declares.h
    new file:   encoder/cppspmd_sse.h
    new file:   encoder/cppspmd_type_aliases.h
    new file:   transcoder/basisu_containers.h
    new file:   transcoder/basisu_containers_impl.h

Unmerged paths:
  (use "git add <file>..." to mark resolution)
    both modified:   CMakeLists.txt
    both modified:   README.md
    both modified:   basisu.vcxproj
    both modified:   basisu.vcxproj.filters
    both modified:   basisu_tool.cpp
    both modified:   encoder/basisu_backend.cpp
    both modified:   encoder/basisu_backend.h
    both modified:   encoder/basisu_basis_file.cpp
    both added:      encoder/basisu_bc7enc.cpp
    both added:      encoder/basisu_bc7enc.h
    both modified:   encoder/basisu_comp.cpp
    both modified:   encoder/basisu_comp.h
    both modified:   encoder/basisu_enc.cpp
    both modified:   encoder/basisu_enc.h
    added by us:     encoder/basisu_etc.cpp
    both modified:   encoder/basisu_etc.h
    both modified:   encoder/basisu_frontend.cpp
    both modified:   encoder/basisu_frontend.h
    both modified:   encoder/basisu_gpu_texture.cpp
    both modified:   encoder/basisu_gpu_texture.h
    both added:      encoder/basisu_miniz.h
    both added:      encoder/basisu_pvrtc1_4.cpp
    both modified:   encoder/basisu_pvrtc1_4.h
    both modified:   encoder/basisu_resample_filters.cpp
    both added:      encoder/basisu_uastc_enc.cpp
    both added:      encoder/basisu_uastc_enc.h
    both modified:   transcoder/basisu.h
    both modified:   transcoder/basisu_global_selector_palette.h
    both modified:   transcoder/basisu_transcoder.cpp
    both modified:   transcoder/basisu_transcoder.h
    both modified:   transcoder/basisu_transcoder_internal.h
    both added:      webgl/encode_test/index.html
    both added:      webgl/encoder/CMakeLists.txt
    both modified:   webgl/transcoder/basis_wrappers.cpp
    both modified:   webgl_videotest/basis.js
    both added:      webgl_videotest/basis.wasm
    both modified:   webgl_videotest/build.bat
    both modified:   webgl_videotest/build.sh

Here is the output from git log in the tmp/subrepo dir which shows no changes since the last merge.

commit 7203d14c6fd977f1496dbef210d0a5842b9be0ab (HEAD -> subrepo/lib/basisu, refs/subrepo/lib/basisu/branch)
Merge: 8b8e27e0 10feea83
Author: Mark Callow <github@callow.im>
Date:   Mon Jan 18 22:06:41 2021 +0900

    git subrepo commit (merge) lib/basisu

    subrepo:
      subdir:   "lib/basisu"
      merged:   "61785924"
    upstream:
      origin:   "https://github.com/BinomialLLC/basis_universal.git"
      branch:   "master"
      commit:   "ef70ddd7"
    git-subrepo:
      version:  "0.4.0"
      origin:   "https://github.com/MarkCallow/git-subrepo.git"
      commit:   "65b6406"

commit 8b8e27e0a65f7838779d4caee8bc5024b71a9a27
Author: MarkCallow <github@callow.im>
Date:   Wed Jun 3 16:52:50 2020 -0700

    Fix whitespace error.

commit 097cd1e6266a4a3b97506e312ef160d97535ee16
Author: MarkCallow <github@callow.im>
Date:   Wed Jun 3 16:43:14 2020 -0700

    Remove unneeded defines when building wrappers.

    Fix error compiling libktx when BASIS_SUPPORT_UASTC=0

Something is truly wrong with git subrepo's diffing.

MarkCallow commented 3 years ago

One especially strange item is

added by us:     encoder/basisu_etc.cpp

git subrepo pull reported it thus:

CONFLICT (rename/delete): basisu_etc.cpp deleted in refs/subrepo/lib/basisu/fetch and renamed to encoder/basisu_etc.cpp in HEAD. Version HEAD of encoder/basisu_etc.cpp left in tree.

The file has not been deleted from upstream. It is still there. Check for yourself.

https://github.com/BinomialLLC/basis_universal/blob/master/encoder/basisu_etc.cpp.

MarkCallow commented 3 years ago

I think I may have discovered why this happens.

I included a repo via git subrepo clone, have never made any edits to the code in that clone and have done several git subrepo pulls of it without trouble. On the latest git subrepo pull I got merge conflicts in 6 files. After resolving these via git checkout --theirs I looked at the resulting commit and at the .gitrepo file. Here is the .gitrepo file

; DO NOT EDIT (unless you know what you are doing)
;
; This subdirectory is a git "subrepo", and this file is maintained by the
; git-subrepo command. See https://github.com/git-commands/git-subrepo#readme
;
[subrepo]
    remote = https://github.com/ARM-software/astc-encoder.git
    branch = main
    commit = 2003150070c13536908714bd6eb031e678d7a2ca
    parent = 90c01d4fe24470b1065d99cecff49e9514e5fad3
    method = merge
    cmdver = 0.4.3

The parent commit is pointing at the commit immediately before the commit done by the original git subrepo clone. Shouldn't it be pointing to the commit immediately before the commit added by the latest git subrepo pull? Given where parent is pointing it looks like it is attempting to merge changes since the original clone (which it thinks were done in the clone) into the latest upstream. If so, it is no wonder there are "endless fake conflicts."

admorgan commented 3 years ago

If no files in the cloned repo have been modified by a commit, you are correct you should be seeing the parent SHA change when you perform a pull. A sample repo would be really helpful. Until then you should be able to ensure things are working correctly by checking to ensure that the parent is updated after a pull. I have a significant number of subrepos that always update the parent so there is evidence that it is working to some degree.

MarkCallow commented 3 years ago

The repo in question is https://github.com/KhronosGroup/KTX-Software in the default branch. The subrepo in question is lib/astc-encoder. HEAD~1 is the last pull. The parent commit shown in .gitrepo is 90c01d4 which you'll see was committed on May 17th and is immediately before the clone. If you look at the log you'll see more subrepo pulls but no commits that change the cloned code.

elasticdog commented 5 months ago

The parent commit is pointing at the commit immediately before the commit done by the original git subrepo clone.

I'm also seeing this behavior and haven't been able to find a way past the endless conflicts (I've tried both merge and rebase methods). I tried manually updating the parent to the most recent commit, which worked for a single subrepo pull, but trying to pull any additional upstream changes will start showing the conflict behavior once again. For me, the parent never seems to be getting updated automatically.

Any suggestions for other things to try?

MarkCallow commented 5 months ago

Any suggestions for other things to try?

After every git subrepo pull now I check the parent commit in the .gitrepo file. When it hasn't been updated, which is almost always, I manually update it to the commit just before the pull's commit. I've had no more trouble with conflicts since I started doing this.

BtW the title of this issue should be changed to remove mention of the rebase strategy since this problem happens with merge strategy too.

elasticdog commented 5 months ago

Right, but it sounds like that's the root of the bug where, for some reason, the parent commit is not being updated as expected (we shouldn't have to bump it manually every time). I'll play around a bit and see if I can find a way to reproduce this.

MarkCallow commented 5 months ago

I'll play around a bit and see if I can find a way to reproduce this.

Fantastic! I hope you are successful.

elasticdog commented 5 months ago

It seems as though the subrepo.parent commit SHA within the .gitrepo file stops getting updated as soon as you add any file into the sub-repository's directory and commit it to the parent repository. My understanding was that this should work without issue since it would just be a clean merge without conflicts?

Here are the steps I took to reproduce the observed behavior (let me know if you have any questions).

Initial Setup

First create a child repository, which will eventually be our subrepo:

~/tmp $ git init child
Initialized empty Git repository in /Users/elasticdog/tmp/child/.git/

~/tmp $ cd child/

~/tmp/child $ touch CHILD-README.md

~/tmp/child $ git add .

~/tmp/child $ git commit -m "Initial commit"
[main (root-commit) 7632d98] Initial commit
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 CHILD-README.md

Then create a parent repository, and clone the child subrepo into it:

~/tmp $ git init parent
Initialized empty Git repository in /Users/elasticdog/tmp/parent/.git/

~/tmp $ cd parent/

~/tmp/parent $ touch PARENT-README.md

~/tmp/parent $ git add .

~/tmp/parent $ git commit -m "Initial commit"
[main (root-commit) c6173b0] Initial commit
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 PARENT-README.md

~/tmp/parent $ git subrepo clone ../child/ child
Subrepo '../child' (main) cloned into 'child'.

Everything looks good so far:

~/tmp/parent $ git log
commit 82c5d4866b767ddb12930b433271c74b6a7870d0 (HEAD -> main)
Author: Example User <user@example.com>
Date:   Tue Jan 30 08:41:32 2024 -0800

    git subrepo clone ../child child

    subrepo:
      subdir:   "child"
      merged:   "7632d98"
    upstream:
      origin:   "../child"
      branch:   "main"
      commit:   "7632d98"
    git-subrepo:
      version:  "0.4.6"
      origin:   "https://github.com/Homebrew/brew"
      commit:   "cfac516ee"

commit c6173b04aee5bd80b24537e47b7333359872b3ea
Author: Example User <user@example.com>
Date:   Tue Jan 30 08:40:56 2024 -0800

    Initial commit

~/tmp/parent $ cat child/.gitrepo
; DO NOT EDIT (unless you know what you are doing)
;
; This subdirectory is a git "subrepo", and this file is maintained by the
; git-subrepo command. See https://github.com/ingydotnet/git-subrepo#readme
;
[subrepo]
        remote = ../child
        branch = main
        commit = 7632d989a46cec790c811be673f55753e9af45fc
        parent = c6173b04aee5bd80b24537e47b7333359872b3ea
        method = merge
        cmdver = 0.4.6

~/tmp/parent $ tree
.
├── child
│   └── CHILD-README.md
└── PARENT-README.md

2 directories, 2 files

Working as Expected

If there is a commit added to the child repository upstream:

~/tmp/child $ echo "# README" > CHILD-README.md

~/tmp/child $ git commit -a -m "Update README from within child repo"
[main c2c8a7a] Update README from within child repo
 1 file changed, 1 insertion(+)

~/tmp/child $ git log --pretty=oneline --abbrev-commit
c2c8a7a (HEAD -> main) Update README from within child repo
7632d98 Initial commit

...and then you pull the upstream commit into the parent repository, the subrepo.parent commit SHA gets bumped as expected:

~/tmp/parent $ git subrepo pull child
Subrepo 'child' pulled from '../child' (main).

~/tmp/parent $ git log
commit f270832835f61f6263588e6b348dbcaf4af9609e (HEAD -> main)
Author: Example User <user@example.com>
Date:   Tue Jan 30 09:19:04 2024 -0800

    git subrepo pull child

    subrepo:
      subdir:   "child"
      merged:   "c2c8a7a"
    upstream:
      origin:   "../child"
      branch:   "main"
      commit:   "c2c8a7a"
    git-subrepo:
      version:  "0.4.6"
      origin:   "https://github.com/Homebrew/brew"
      commit:   "cfac516ee"

commit 82c5d4866b767ddb12930b433271c74b6a7870d0
Author: Example User <user@example.com>
Date:   Tue Jan 30 08:41:32 2024 -0800

    git subrepo clone ../child child

    subrepo:
      subdir:   "child"
      merged:   "7632d98"
    upstream:
      origin:   "../child"
      branch:   "main"
      commit:   "7632d98"
    git-subrepo:
      version:  "0.4.6"
      origin:   "https://github.com/Homebrew/brew"
      commit:   "cfac516ee"

commit c6173b04aee5bd80b24537e47b7333359872b3ea
Author: Example User <user@example.com>
Date:   Tue Jan 30 08:40:56 2024 -0800

    Initial commit

~/tmp/parent $ cat child/.gitrepo
; DO NOT EDIT (unless you know what you are doing)
;
; This subdirectory is a git "subrepo", and this file is maintained by the
; git-subrepo command. See https://github.com/ingydotnet/git-subrepo#readme
;
[subrepo]
        remote = ../child
        branch = main
        commit = c2c8a7a77bf3b07257c686e76f9b10456615f144
        parent = 82c5d4866b767ddb12930b433271c74b6a7870d0
        method = merge
        cmdver = 0.4.6

Note that in the commit message from the subrepo pull, that the subrepo.merged and the upstream.commit SHAs still match.

Bumps Stop Working

If there is another commit added to the child repository upstream:

~/tmp/child $ echo "More upstream content" >> CHILD-README.md

~/tmp/child $ git commit -a -m "Add content from within child repo"
[main 93de538] Add content from within child repo
 1 file changed, 1 insertion(+), 1 deletion(-)

~/tmp/child $ git log --pretty=oneline --abbrev-commit
93de538 (HEAD -> main) Add content from within child repo
c2c8a7a Update README from within child repo
7632d98 Initial commit

...but then a file is also committed to the child sub-repository directly in the parent repo:

~/tmp/parent $ touch child/another-file.txt

~/tmp/parent $ git add child/another-file.txt

~/tmp/parent $ git commit -m "Add another file from within parent repo"
[main 6c872cc] Add another file from within parent repo
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 child/another-file.txt

...and then you pull the upstream commit into the parent repository, the subrepo.parent commit SHA will not be bumped:

~/tmp/parent $ git subrepo pull child
Subrepo 'child' pulled from '../child' (main).

~/tmp/parent $ git log
commit 90f685db0883bf16ef2b1822a7cad85cbbcc2d96 (HEAD -> main)
Author: Example User <user@example.com>
Date:   Tue Jan 30 10:03:45 2024 -0800

    git subrepo pull (merge) child

    subrepo:
      subdir:   "child"
      merged:   "92833a6"
    upstream:
      origin:   "../child"
      branch:   "main"
      commit:   "93de538"
    git-subrepo:
      version:  "0.4.6"
      origin:   "https://github.com/Homebrew/brew"
      commit:   "cfac516ee"

commit 6c872ccb60f08fd05102778c865cfb35b4866395
Author: Example User <user@example.com>
Date:   Tue Jan 30 10:00:10 2024 -0800

    Add another file from within parent repo

commit f270832835f61f6263588e6b348dbcaf4af9609e
Author: Example User <user@example.com>
Date:   Tue Jan 30 09:19:04 2024 -0800

    git subrepo pull child

    subrepo:
      subdir:   "child"
      merged:   "c2c8a7a"
    upstream:
      origin:   "../child"
      branch:   "main"
      commit:   "c2c8a7a"
    git-subrepo:
      version:  "0.4.6"
      origin:   "https://github.com/Homebrew/brew"
      commit:   "cfac516ee"

commit 82c5d4866b767ddb12930b433271c74b6a7870d0
Author: Example User <user@example.com>
Date:   Tue Jan 30 08:41:32 2024 -0800

    git subrepo clone ../child child

    subrepo:
      subdir:   "child"
      merged:   "7632d98"
    upstream:
      origin:   "../child"
      branch:   "main"
      commit:   "7632d98"
    git-subrepo:
      version:  "0.4.6"
      origin:   "https://github.com/Homebrew/brew"
      commit:   "cfac516ee"

commit c6173b04aee5bd80b24537e47b7333359872b3ea
Author: Example User <user@example.com>
Date:   Tue Jan 30 08:40:56 2024 -0800

    Initial commit

~/tmp/parent $ cat child/.gitrepo
; DO NOT EDIT (unless you know what you are doing)
;
; This subdirectory is a git "subrepo", and this file is maintained by the
; git-subrepo command. See https://github.com/ingydotnet/git-subrepo#readme
;
[subrepo]
        remote = ../child
        branch = main
        commit = 93de538218825ef6b8c56f28e8bffb3d4799d6ab
        parent = 82c5d4866b767ddb12930b433271c74b6a7870d0
        method = merge
        cmdver = 0.4.6

Note that in the commit message from the subrepo pull, that the subrepo.merged and the upstream.commit SHAs no longer match, but that's normal due to the merged content.

Result

At this point though, the expected subrepo.parent SHA should be 6c872ccb60f08fd05102778c865cfb35b4866395, but the actual SHA is still old value of 82c5d4866b767ddb12930b433271c74b6a7870d0.

~/tmp/parent $ git log --pretty=oneline --abbrev-commit
90f685d (HEAD -> main) git subrepo pull (merge) child
6c872cc Add another file from within parent repo
f270832 git subrepo pull child
82c5d48 git subrepo clone ../child child
c6173b0 Initial commit
MarkCallow commented 5 months ago

@elasticdog thank you for your thorough investigation. Hopefully there is enough here for the repo maintainer to figure out where the code is wrong and fix it.