Better generated branch names with jj

Better generated branch names with jj

使用 jj 优化分支名称生成

The jj version control system generates branch names that leave something to be desired. Here’s my alternative. jj 版本控制系统自动生成的分支名称往往不尽如人意。以下是我的替代方案。

I’ve been using jj (Jujutsu), a Git-compatible version control system recently. I’m pretty happy with it. Today I’m happy with its configurability. 最近我一直在使用 jj (Jujutsu),这是一个兼容 Git 的版本控制系统。我对它非常满意,尤其是今天,我对其高度的可配置性感到惊喜。

For a number of reasons, jj expects and encourages the use of anonymous branches. But if you push to a Git repository, then the anonymous branch needs a name (a “bookmark” in jj, a “branch” in Git). 出于多种原因,jj 期望并鼓励使用匿名分支。但如果你要推送到 Git 仓库,那么这个匿名分支就需要一个名称(在 jj 中称为“书签/bookmark”,在 Git 中称为“分支/branch”)。

The jj command-line interface provides a shorthand to push a given change, generating a name automatically. For example, jj git push --change xyz pushes the revision with the ID xyz to a Git branch named push-xyz. jj 命令行界面提供了一种快捷方式来推送指定的变更,并自动生成名称。例如,jj git push --change xyz 会将 ID 为 xyz 的修订版本推送到名为 push-xyz 的 Git 分支。

As a default, it makes sense to emphasize the change ID, since the jj CLI shows and uses those IDs often. But suppose later on I’m looking at the list of branches on the repository on the GitHub website. What actual work does push-xyz represent? I cannot and will not remember. 默认情况下,强调变更 ID 是合理的,因为 jj 命令行经常显示和使用这些 ID。但假设稍后我在 GitHub 网站上查看仓库的分支列表时,push-xyz 到底代表什么工作?我记不住,也不想去记。

I changed my configuration to fix this. I wrote a new template alias, slugify(), and changed the git_push_bookmark template to use it: 我修改了配置来解决这个问题。我编写了一个新的模板别名 slugify(),并修改了 git_push_bookmark 模板来使用它:

[template-aliases]
"slugify(str)" = '''
  truncate_end(
    65,
    str.first_line()
      .replace(regex:'[^[[:alnum:]].]', '-')
      .replace(regex:'-{2,}', '-')
      .replace(regex:'\.{2,}', '.')
      .replace(regex:'(^-+|-+$)', '')
      .lower()
  )
'''

[templates]
git_push_bookmark = 'slugify(description) ++ "/" ++ change_id.short()'

Now, if I run jj git push --change ozkspkuyzpwu, jj generates a short slug-like name from the change’s description (the commit message, if you’re coming from Git). In this case, it generates add-note-about-jj-bookmark-templates/ozkspkuyzpwu. This is more readable while retaining the link back to the revision IDs that show up in the jj CLI. 现在,如果我运行 jj git push --change ozkspkuyzpwu,jj 会根据变更的描述(如果你来自 Git 背景,即提交信息)生成一个简短的 slug 风格名称。在本例中,它生成了 add-note-about-jj-bookmark-templates/ozkspkuyzpwu。这不仅更具可读性,同时还保留了与 jj 命令行中显示的修订 ID 的关联。

If I were to push to a repo shared with others, then I would change it put my branches into a namespace for myself: 如果我要推送到一个与他人共享的仓库,我会修改配置,将我的分支放入我个人的命名空间中:

[templates]
git_push_bookmark = '"ddbeck/" ++ slugify(description) ++ "/" ++ change_id.short()'

One thing I didn’t do is make sure that the branch names are safe for Git. Git has some awfully complicated rules to determine whether a branch name is valid. I assume that I’ll get an error if my template ever generates an invalid branch name, at which point I’ll have to create a bookmark manually. 我没有做的一件事是确保这些分支名称对 Git 来说绝对安全。Git 对于判断分支名称是否有效有着极其复杂的规则。我假设如果我的模板生成了无效的分支名称,我会收到错误提示,届时我再手动创建书签即可。