ingydotnet / git-subrepo

MIT License
3.18k stars 263 forks source link

Stuck on push after pushed to another remote url: "There are new changes upstream, you need to pull first." #598

Open jcalfee opened 9 months ago

jcalfee commented 9 months ago

I recently successfully pushed this subrepo to a different remote url ("$prod"). Now I'm trying to come back to the original URL ("$origin") and push there to update that repository as well.

# This is what I need to do:
$ git subrepo push --remote=$origin $repo
git-subrepo: There are new changes upstream, you need to pull first.

# Just to show the details:
$ git subrepo pull --remote=$origin $repo
git-subrepo: Local repository does not contain de7e6f8f329b649a1049c8578cf89bee3744bbc1. Try to 'git subrepo fetch $repo' or add the '-F' flag to always fetch the latest content.

# Because the last push was $prod, the local repo **does** contain the commit changes, but the hash is different.
# In other words: $origin does not have this hash, but $prod does.  So, attempting to pull from $prod seams to work:
$ git subrepo pull --remote=$prod $repo
Subrepo '$repo' is up to date.
$ git subrepo fetch --remote=$prod $repo
Fetched '$repo' from '$prod' (master).

# Just for good measure:
$ git subrepo pull --remote=$origin $repo
git-subrepo: Local repository does not contain de7e6f8f329b649a1049c8578cf89bee3744bbc1. Try to 'git subrepo fetch $repo' or add the '-F' flag to always fetch the latest content.
$ git subrepo fetch --remote=$origin $repo
Fetched '$repo' from '$origin' (master).

# And I'll retry the desired command:
$ git subrepo push --remote=$origin $repo
git-subrepo: There are new changes upstream, you need to pull first.

I did push to a different remote and now I'm coming back to the original upstream. The default method is rebase. Possibly related https://github.com/ingydotnet/git-subrepo/issues/541#issuecomment-890279004, but I did not do any cherry picking or force push and clean did not change anything.

jcalfee commented 9 months ago

I already tried the -F above (fetch). Why does force push not disable this check? ("Local repository does not contain de7e6f8")

$ git subrepo push $repo -r "$origin" --force
git-subrepo: Local repository does not contain de7e6f8f329b649a1049c8578cf89bee3744bbc1. Try to 'git subrepo fetch $repo' or add the '-F' flag to always fetch the latest content.

If I can't save it, I believe I recall correctly: I can delete $repo/.gitrepo, commit that delete, then use git subrepo init to recreate the repo and push it to the correct place, then not try this again.

admorgan commented 9 months ago

The create a commit on push is feeling more like an anit-feature to me. The reason it behaves that way makes sense, it makes future operations faster, but I use a lot of services such as Gerrit where the pushed patch doesn't just go into a repo, it gets reviewed and updated so it doesn't contain the same SHA. This breaks the interaction. Also doing a git subrepo pull after a push would accomplish the same goal. I have been sitting on it because it is a big change to how things work. I think your use case makes my case stronger. I will make a patch for removing the push commit to the next released version.

mathrick commented 1 month ago

Any news on this, or better yet, a workaround for now? I ran into the same issue, and I'm 100% stuck with no way forward that I can see. My use-case is the following:

Now where the wheels came off the cart seems to be some combination of me pushing to my fork's github URL first, before creating an intermediary local repo and pushing/pulling from there, together with some of the branch manipulation it seems. I don't know exactly when it got hosed, but the end result is that I'm now completely stuck with subrepo.commit pointing to a commit that's not in the ancestry chain, which breaks all the commands I try, and no way forward, because it looks at subrepo.commit SHA as it existed back in the listed subrepo.parent, rather than as it exists in the current HEAD, so I have no way to try to convince it to use a commit that actually does exist in the ancestry.

The only way I can see is to rewrite my published history on the main project to fixup the original subrepo.parent to point to the replacement subprepo.commit SHA, then change the value of subrepo.parent SHA in the HEAD to let it resolve stuff. But that's many commits back in history, that history has been pushed already, it feels awful that I have to compromise main's history to unhose the subrepo, and I'm not even sure it won't get me into another circular pickle by rebasing the ancestry and potentially invalidating the replacement subrepo.commit SHA in the process. All in all, not a great experience.

mathrick commented 1 month ago

Also, I'd like to point out that the message it gives is terribly unhelpful and not at all what the issue is. The line in question checks for ancestry, but no amount of fetching from the remote will change the ancestry, unless I'm missing something very fundamental about how git subrepo operates. So suggesting git subrepo fetch or -F is only making things more confusing.