Skip to content

RFC: Extend tracking to new bookmarks #7072

@emilazy

Description

@emilazy

This is a slightly edited and expanded version of my proposal from #4871, intended to replace --allow-new, git.push-new-bookmarks, and git.auto-local-bookmark with a single mechanism that generalizes the existing tracking system and that I hope should be simpler, easier to learn, and more flexible at elegantly adapting to various workflows around remote bookmarks.

I don’t think this solution is perfect because bookmark tracking in general has dodgy semantics, IMO; being used for both the fetch and push end leads to weirdness that @arxanas has pointed out in the past and that we work around with things like trunk() in the default immutable heads. Ideally, it should probably be split into multiple separate concepts for the “direction of travel”. But I feel this proposal would be better than the status quo, the configuration knobs should make it comparably convenient for the important use cases, and hopefully the result would feel less inelegant than the current situation does to me and seemingly many others.

(I’m open to discussion of more fundamental reworks of the tracking system along these lines, but kindly request we do so in another issue, because I feel it’s a can of worms with a lot of UX questions that would need resolving, so I worry about it blocking an incremental improvement.)

Outline

  1. We extend the concept of tracking a bookmark on a remote to apply to ones that don’t yet exist on that remote. jj git push will only push bookmarks that are tracked, whether they are new or pre‐existing. This means that the default behaviour will remain as currently, i.e. no --allow-new by default.

  2. --allow-new is eliminated and replaced by the more orthogonal jj bookmark track ⟨bookmark⟩@⟨remote⟩ before pushing. If you jj git push and the lack of tracking is the only thing preventing a push, it can print a hint to this effct.

  3. It’s fairly likely we’d want to add a --track-on ⟨remote⟩ option to jj bookmark create that sets up the tracking for you.

  4. To make the UX more convenient for cases like the single‐remote one where people are usually creating new bookmarks to push to one obvious remote, we introduce an auto-track-bookmarks option, which takes a (list of) pattern(s) like glob:*@origin, or possibly even a revset. This would affect both fetched bookmarks and newly‐created ones.

  5. git.auto-local-bookmark = true and git.push-new-bookmarks = true can both be deprecated and replaced with something like auto-track-bookmarks = "glob:*@origin" or auto-track-bookmarks = "glob:*@*". I think this matches the semantics people want for a “one‐remote repository”.

    In a shared repository where you only create bookmarks to push your work but you don’t want everyone else’s work to be mutable, you could do auto-track-bookmarks = "glob:emily/*@origin" based on your templates.git_push_bookmark or manual branch naming. In this scenario, if you don’t have a consistent format (everyone just uses the same namespace but only some bookmarks are owned by you), then your options fall back to the more explicit jj bookmark create --track-on or jj bookmark track or jj git push --named. This would be slightly less convenient than the current case where you can set git.push-new-bookmarks = true but git.auto-local-bookmark = false. (However, it behaves more consistently when cloning a new copy of a repository.)

Advantages

  1. This eliminates the weird thing where new local bookmarks “want to be pushed to every remote by default” but are held back by a flag/setting, whereas bookmarks that come down from a remote are associated with it and you need to opt in to syncing them with a local one. I find the current model very strange, and believe the mental model here is much simpler: newly‐created bookmarks are local (…because you’re creating them locally), and tracking is the sole thing that determines whether a local bookmark is synced with a remote on fetch and push.

  2. @senekor’s tutorial can introduce bookmark tracking up front as the way we tell Jujutsu which bookmarks we want to be synced with which remotes, which is important to learn and a common source of confusion for new users. This would still mean telling them to set a configuration setting if he doesn’t want people to have to explicitly specify --track-on origin for new bookmarks, but hopefully the setting makes a lot more sense than the current “disable some safety behaviour to work around (what I see as) an exception to the general tracking model” one.

  3. Automatic tracking of a subset of bookmarks is useful in other cases, too. In Nixpkgs, I often have to push manual merges to staging or staging-next to resolve conflicts. However, we also create versions of these for each stable release, i.e. staging-25.05 and staging-next-25.05. Being able to set auto-track-bookmarks = "glob:staging*@origin" would be handy for this.

  4. This would help pave the way to the request to support tracking multiple bookmarks on different remotes that have the same name but are otherwise unrelated, because the model would be “local bookmarks have a set of remote bookmarks they sync with” and so you could add UI to track a remote bookmark under a different local name.

Unresolved questions

  1. How exactly should auto-track-bookmarks behave? Some potential options:

    1. The first time we consider a bookmark – whether new locally or fetched from a remote – we store its tracking status according to the current auto-track-bookmarks.
    2. If a bookmark has not been explicitly tracked or untracked, then operations that care about its tracking status check auto-track-bookmarks.
    3. auto-track-bookmarks takes precedence over manual tracking; you cannot manually untrack a bookmark it matches.

    (iii) seems like the most conceptually elegant option, but I’m mostly ambivalent. (i) and (ii) are only distinguished by what happens when you change your auto-track-bookmarks setting. With (ii) you can’t explicitly “forget” having expressed an opinion about whether a bookmark should be tracked, which seems kind of weird.

  2. How exactly should jj bookmark (un)track behave, especially in interaction with auto-track-bookmarks? Do we want the setting to be “timeless” but the command to care about what bookmarks or remotes exist, or should jj bookmark track 'glob:*@*' be equivalent to setting auto-track-bookmarks = "glob:*@*"?

    This basically comes down to what we want the data model to look like, I think. Clearly this proposal is moving in the direction of “local bookmarks have an associated set of remote bookmarks that may or may not yet exist”. Two obvious models:

    1. Store a map from local bookmarks to remote bookmark names; use auto-track-bookmarks as a fallback. This would be compatible with all of the possible auto-track-bookmarks behaviours, I think, but jj bookmark (un)track would behave differently to the setting.
    2. Store a list of every bookmark (un)track command in chronological order; whenever considering a remote operation, start with the assessment of auto-track-bookmarks, then amend it based on each bookmark (un)track in sequence. I believe this is how @senekor was imagining it would work, and it would correspond to the (1.ii) behaviour for auto-track-bookmarks. (Obviously this would be a ridiculous way to actually store it and you’d have some fancy normalized glob intersection structure, but it’s just about the actual end result.)
  3. jj bookmark create --track-on has overlap with jj git push --named; it’s unclear to me whether we’d want to eliminate it in favour of this functionality or if we value having a one‐shot create‐and‐push command that takes custom names and sets up the tracking. If we want to keep it, jj git push --named would presumably set up the tracking according to the remotes you’re pushing the new bookmark to, so jj git push --remote ⟨remote⟩ --named ⟨bookmark⟩=⟨rev⟩ would be short for jj bookmark create --track-on ⟨remote⟩ -r ⟨rev⟩ ⟨bookmark⟩ && jj git push -b ⟨bookmark⟩, which would be short for jj bookmark create -r ⟨rev⟩ ⟨bookmark⟩ && jj bookmark track ⟨bookmark⟩@⟨remote⟩ && jj git push -b ⟨bookmark⟩.

  4. Maybe we’d want to move away from ⟨bookmark⟩@⟨remote⟩ syntax for tracking if people find the idea of tracking a bookmark that doesn’t yet exist on a remote to be confusing (I personally don’t really find it confusing). We would also probably want to adjust it if we start allowing tracking bookmarks under different names.

  5. Is the workflow compromise in (5) of the outline acceptable for the simpler model and increased flexibility? If many people don’t want to track fetched bookmarks, really want all new bookmarks to push with jj bookmark create ⟨bookmark⟩ && jj git push without any additional flags, don’t want to use any of the listed alternatives, and don’t want to define an alias for jj bookmark create --track-on ⟨remote⟩, then this could be a deal‐breaker for the proposal

    I personally think that most use cases for automatic tracking fall under the “single‐person repository, track everything” or “shared repository with a consistent bookmark naming scheme, track only my bookmarks” cases that this proposal handles well, and the available options for this awkward case still seem okay to me. We already make such users pass --allow-new or configure a setting already.

Metadata

Metadata

Assignees

No one assigned

    Labels

    polish🪒🐃Make existing features more convenient and more consistent

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions