I am using SourceTree to interact with branches. Also, my git knowledge is extremely limited
I have a NAV-482 branch (/nav.git repository). Subtree branch is NAV-482-DLL (/nav.dll.git repository). Subtree name (and local relative path) is nav.dll
I have run into issue when I can pull changes from my subtree without any problem, but when I'm trying to push changes into it, I am failing with the followings error:
git push using: nav.dll.git NAV-482-DLL
fatal: remote error: upload-pack: not our ref 4fb3fa1d8661a6294e798912d39f3ffbbe60a9dd
fatal: the remote end hung up unexpectedly
fatal: could not rev-parse split hash 4fb3fa1d8661a6294e798912d39f3ffbbe60a9dd from commit 872b637c702ca5f45b41bdecbded976b47313b23
Jumping to the commit 872b637c702ca5f45b41bdecbded976b47313b23 shows that this one is back from 2017 where 4fb3fa1d8661a6294e798912d39f3ffbbe60a9dd is git-subtree-split
Not sure why push suddenly choose to die in that way, but now it is a problem.
From what I could find about this issue there are potentially multiple solutions:
Git push subtree fail unknown revision or path possibly due to missing git-subtree-split commit
suggest using git fetch <subtree rep> <hash> to get the commit in question. Unfortunalety it fails:
$ git fetch nav.dll.git 4fb3fa1d8661a6294e798912d39f3ffbbe60a9dd
fatal: remote error: upload-pack: not our ref 4fb3fa1d8661a6294e798912d39f3ffbbe60a9dd
fatal: the remote end hung up unexpectedly
As I understood this means that this commit is no longer in the repository
Removing invalid git-subtree-split hash suggest to use git subtree split --ignore-joins --rejoin and the persons seems to managed resolve the problem.
This one I am reluctant to try because to be honest, I straight up don't understand what this command will do.
As I understood it should look something like git subtree split -P NAV-482-DLL --ignore-joins --rejoin -b NAV-482-TEMP but what exactly is an expected result? Will it make a separate branch, or will it make a commit into a current checked out NAV-482 branch?
Is the a way to resolve the issue with the SourceTree UI or if there not, how should a proper git subtree split command look, or should I seek for another solution?
As I illustrated before, make sure to use Git 2.39+ (which includes a bug fix). And consider making a backup of your repository to prevent any accidental loss of data.
Make sure you are on the correct branch (
NAV-482) in your main repository (/nav.git).Execute the
git subtree splitcommand to recreate the subtree history.The command you mentioned should be correct:
-P NAV-482-DLL: specifies the prefix (path) of the subtree.--ignore-joins: ignores join commits created by previous subtree merges.--rejoin: creates a new join commit after the split.-b NAV-482-TEMP: creates a new branch with the split subtree.That command will create a new branch (
NAV-482-TEMP) in your main repo with the history of the changes made to the subtree.Push the newly created branch to the subtree repository.
The
git subtree splitessentially extracts the history of a subfolder (in your case,nav.dll) and puts it into a new branch. The--ignore-joinsand--rejoinoptions help in cleaning and maintaining the correct history.If some of these operations might not be available or straightforward in the SourceTree UI, particularly the specific options of
git subtree. You might need to use the command line for these operations.As noted by Olegs Jasjko in the comments, you can add a squash option:
With this command, all the changes in the
NAV-482-DLLsubtree will be squashed into a single commit on the newNAV-482-TEMPbranch. This means theNAV-482-TEMPbranch will have a simplified history, with one commit representing the entire history of changes from the subtree.This approach is particularly useful when you want to maintain a cleaner, more concise history in the branch that is being created. It reduces the number of commits and makes it easier to understand the overall changes made in the subtree over time.
I suppose a
git reflog show --all | grep 4fb3fa1d8661a6294e798912d39f3ffbbe60a9ddwould return nothing...If recreating the missing data is not feasible or necessary, you might need to consider methods to bypass this commit in their operations. That could involve adjusting the subtree split to exclude the range involving the missing commit.
Determine the range of commits that are necessary for the subtree split, excluding the missing commit. That involves identifying the commit just before the missing one and the commit just after (or a later commit that is present in the repository).
Generate a series of patches for the commits that you want to include in the subtree. That can be done using
git format-patch. Apply these patches to a new branch, effectively recreating the history without the missing commit.Alternatively, you can cherry-pick individual commits from the range you identified, again excluding the missing commit. That method is more manual but offers more control over which commits are included.