Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

jj init --git-repo=. creates divergent branches if local and remote git refs diverge #1862

Open
necauqua opened this issue Jul 13, 2023 · 6 comments

Comments

@necauqua
Copy link
Contributor

Description

Steps to Reproduce the Problem

git init --bare remote
git init local
cd local
git commit --allow-empty -m 'A'
git commit --allow-empty -m 'B'
git branch tmp
git reset --hard HEAD^
git commit --allow-empty -m 'C'
git remote add origin localhost:$PWD/../remote
git push -u origin
git reset --hard tmp
git branch -d tmp

git log --all --decorate --oneline --graph

jj init --git-repo=.

jj log -r 'all()'

Expected Behavior

My expectation was that the branch main would only point to main@git

Actual Behavior

Branch main diverges, pointing to both main@git and main@origin

Specifications

jj 0.7.0-152a0683e25c16f0ef57ee20a723755748b696e3

@necauqua necauqua changed the title jj init --git-repo=. creates divergent branches if local and remote diverge jj init --git-repo=. creates divergent branches if local and remote git refs diverge Jul 13, 2023
@ilyagr
Copy link
Contributor

ilyagr commented Jul 13, 2023

I'm beginning to think that with our current branch model, what jj does here might be, er, a feature (sorry!). We're talking about jj init --git-repo . resulting in something like

main@remote     main@git
   main??        main??
    A            B
     \____   ___/
          \ /
           C

The question is whether main should be conflicted at this point.

The problem is that jj has no way of knowing whether the commit A is the local user's work that they mean to abandon or whether it is somebody else's work that was pushed to the remote and shouldn't be lost. Imagine getting to this situation because a local user did git fetch; jj git init --git-repo ..

If instead of creating a conflict, jj set main definitively at revision B, a subsequent jj git push would succeed and destroy revision A on the remote in this process. Again, this may be what the user wanted on one hand, but on the other A may have been somebody else's commit the local user didn't even notice. So, it might be reasonable to ask the user to specify which version of main they want (B? rebase B on top of A?).

I also had an interesting discussion with @yuja around https://discord.com/channels/968932220549103686/969829516539228222/1128850385256321085 about how this relates to #1734 and how we might want to change the branching model to allow jj to be more intelligent here.

@necauqua
Copy link
Contributor Author

necauqua commented Jul 13, 2023

What I had is a few experimental branches in my work git repo very often divergent with the remote because git-branchless sync rebased them, and I got this when I finally did jj init.

Yeah as I've said in the initial discord comment, when making the repro I kind of understood that from jjs point of view this does actually make some sense, even if slightly unintuitive

So I guess this depends on the branching model change, if it's left unchanged this behavior does make sense - although we may want to document that.

@yuja
Copy link
Contributor

yuja commented Jul 13, 2023

I lean towards considering this is a bug.

Under the current branching model, all remote branches are considered to be kept in sync with the local counterparts. So it's probably better for jj init --git-repo . to take all remote branches as past state:

  1. import git local branches as jj local branches
  2. import git remote branches as jj remote branches
  3. DO NOT import jj remote branches to local branches

If we strictly follow this, missing git local branches become deleted in jj world. This would be too confusing, and the step (3) will need to be adjsted:

  1. import git local branches as jj local branches
  2. import git remote branches as jj remote branches
  3. import jj remote branches to local branches if local_target is none

If we implement some variant of #1734, maybe we can remove the step (3) and leave missing branches as non-tracking:

  1. import git local branches as jj local branches
  2. import git remote branches as jj remote branches, flag as tracking if local counterpart exists

(For non-tracking->tracking transition in #1734, I agree with #1862 (comment).)

@yuja
Copy link
Contributor

yuja commented Jul 13, 2023

  1. import git local branches as jj local branches
  2. import git remote branches as jj remote branches
  3. import jj remote branches to local branches if local_target is none

Wait. git fetch/git pull often leaves local branches behind remotes. There's no clue that local branch is newer than the remote one if these branches are diverged. So the current behavior makes sense.

@chriskrycho
Copy link
Contributor

Forgive me, because it has been a long time, but: what does hg do with named branches and bookmarks respectively in similar situations (i.e. pulling from a remote)?

@yuja
Copy link
Contributor

yuja commented Jul 13, 2023

In hg, branch names are stored in each commit metadata. Bookmarks are close to git refs, but there are no remote-tracking stuff. iirc conflict resolution is manual step (something like divergent bookmark is renamed to name@remote, and user needs to rename/remove it.) The UX was bad.

yuja added a commit to yuja/jj that referenced this issue Nov 25, 2023
If the existing git repo contains local and remote branches of the same name,
one of the remote branches is probably a tracking remote branch. Let's show
a hint how to set up tracking branches. The tracking state could be derived
from .git/config, but doing that automatically might cause another issue like
jj-vcs#1862, which could have been mitigated by git.auto-local-branch = false.
yuja added a commit that referenced this issue Nov 25, 2023
If the existing git repo contains local and remote branches of the same name,
one of the remote branches is probably a tracking remote branch. Let's show
a hint how to set up tracking branches. The tracking state could be derived
from .git/config, but doing that automatically might cause another issue like
#1862, which could have been mitigated by git.auto-local-branch = false.
yuja added a commit to yuja/jj that referenced this issue Dec 16, 2023
As far as I can see in the chat, there's no objection to changing the default,
and git.auto-local-branch = false is generally preferred.

docs/branches.md isn't updated as it would otherwise conflict with jj-vcs#2625. I
think the "Remotes" section will need a non-trivial rewrite.

jj-vcs#1136, jj-vcs#1862
yuja added a commit to yuja/jj that referenced this issue Dec 16, 2023
As far as I can see in the chat, there's no objection to changing the default,
and git.auto-local-branch = false is generally preferred.

docs/branches.md isn't updated as it would otherwise conflict with jj-vcs#2625. I
think the "Remotes" section will need a non-trivial rewrite.

jj-vcs#1136, jj-vcs#1862
yuja added a commit that referenced this issue Dec 16, 2023
As far as I can see in the chat, there's no objection to changing the default,
and git.auto-local-branch = false is generally preferred.

docs/branches.md isn't updated as it would otherwise conflict with #2625. I
think the "Remotes" section will need a non-trivial rewrite.

#1136, #1862
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants