gitbutlerapp/gitbutler · warning

This will be replaced with GitButler's 'but' command

Error message

This will be replaced with GitButler's 'but' command

What it means

Companion warning in the same block as the 'Found existing but symlink' message (install_macos.rs:156): the installer explicitly states that the custom, non-GitButler symlink will be replaced by GitButler's 'but' command during the atomic swap. Together with the following info line it tells you the original target is not a GitButler installation and will not be preserved (unlike the regular-file case, which gets a but.backup.<timestamp> copy). There is no prompt and no rollback for this specific action; the target path is only recorded in the log output.

Source

Thrown at crates/but-installer/src/install_macos.rs:156

        ));
    } else if but_symlink.is_symlink() {
        let existing_target = fs::read_link(&but_symlink)?;
        let existing_target_str = existing_target.to_string_lossy();

        // Detect channel switching
        let previous_channel = if existing_target_str.contains("Nightly") {
            Some(Channel::Nightly)
        } else if existing_target_str.contains("/GitButler.app/") {
            Some(Channel::Release)
        } else {
            None
        };

        if previous_channel.is_none() {
            warn(&format!(
                "Found existing 'but' symlink pointing to: {existing_target_str}"
            ));
            warn("This will be replaced with GitButler's 'but' command");
            info(
                "Note: Your custom symlink setup will be overwritten. The original target is not a GitButler installation.",
            );
        }
    }

    // Create temporary symlink to test the new installation
    let new_app_macos_dir = install_app_new.join("Contents/MacOS/gitbutler-tauri");
    let _ = fs::remove_file(&but_new);

    unix_fs::symlink(&new_app_macos_dir, &but_new)?;

    // Verify the new installation works
    let verify_status = Command::new(&but_new)
        .arg("--version")
        .stdout(Stdio::null())
        .stderr(Stdio::null())
        .status();

View on GitHub (pinned to caf1f223d3)

Solutions

  1. Before installing, record the current target if you care about it: readlink ~/.local/bin/but > ~/but-symlink.bak
  2. If the target was a wrapper or custom build, re-create it under a distinct name after install (ln -sfn /path/to/custom ~/.local/bin/but-custom)
  3. Remove the custom symlink pre-install (rm ~/.local/bin/but) to get a clean, warning-free install
  4. Verify the replacement: but --version should report the GitButler app-bundled CLI

Example fix

# before
rm ~/.local/bin/but              # avoid the overwrite warning entirely

# after install
readlink ~/.local/bin/but
/Users/me/Applications/GitButler.app/Contents/MacOS/gitbutler-tauri
Defensive patterns

Strategy: validation

Validate before calling

# Pre-install check for a custom (non-GitButler) symlink target:
if [ -L ~/.local/bin/but ]; then
  t=$(readlink ~/.local/bin/but)
  case "$t" in *GitButler.app*|*Nightly*) ;; *) rm ~/.local/bin/but;; esac
fi

Prevention

When it happens

Trigger: Same condition as the preceding warn: ~/.local/bin/but is a symlink whose target contains neither 'Nightly' nor '/GitButler.app/', e.g. a hand-made link to ~/.cargo/bin/but or a third-party binary. The swap at install_macos.rs:227-230 then removes the old link (fs::remove_file) and symlinks to the new app bundle.

Common situations: Users who manage their own bin symlinks; migrating from manual CLI installs to the desktop app; discovering post-install that a custom wrapper script target is gone because only the symlink text was logged, not saved.

Related errors


AI-assisted analysis of gitbutlerapp/gitbutler@caf1f223d3 (2026-08-20). Data as JSON: /api/errors/e5cce79e35e09cd7. Report an issue: GitHub.