arxanas / git-branchless

High-velocity, monorepo-scale workflow for Git
Apache License 2.0
3.41k stars 83 forks source link

`git sync` while on non-detached `main` causes a `git checkout main` for every stack #1155

Open mlcui-corp opened 8 months ago

mlcui-corp commented 8 months ago

Description of the bug

This causes git syncs to be significantly slower, especially if git checkout main takes a while. This isn't usually the case, unless you're in a huge monorepo.

Good (checked out at a non-main commit, or detached at main): ``` Attempting rebase in-memory... [1/2] Committed as: REDACTED [2/2] Committed as: REDACTED branchless: processing 2 rewritten commits In-memory rebase succeeded. Attempting rebase in-memory... [1/1] Committed as: REDACTED branchless: processing 1 rewritten commit In-memory rebase succeeded. Attempting rebase in-memory... [1/1] Committed as: REDACTED branchless: processing 1 rewritten commit In-memory rebase succeeded. Attempting rebase in-memory... [1/1] Committed as: REDACTED branchless: processing 1 rewritten commit In-memory rebase succeeded. Attempting rebase in-memory... [1/1] Committed as: REDACTED branchless: processing 1 rewritten commit In-memory rebase succeeded. Attempting rebase in-memory... [1/1] Committed as: REDACTED branchless: processing 1 rewritten commit In-memory rebase succeeded. Attempting rebase in-memory... [1/1] Committed as: REDACTED branchless: processing 1 rewritten commit In-memory rebase succeeded. Attempting rebase in-memory... [1/3] Committed as: REDACTED [2/3] Committed as: REDACTED [3/3] Committed as: REDACTED branchless: processing 3 rewritten commits In-memory rebase succeeded. Attempting rebase in-memory... [1/1] Committed as: REDACTED branchless: processing 1 rewritten commit In-memory rebase succeeded. Attempting rebase in-memory... [1/3] Committed as: REDACTED [2/3] Committed as: REDACTED [3/3] Committed as: REDACTED branchless: processing 3 rewritten commits In-memory rebase succeeded. Attempting rebase in-memory... Synced REDACTED... ```
Bad (checked out non-detached main): ``` Attempting rebase in-memory... [1/2] Committed as: REDACTED [2/2] Committed as: REDACTED branchless: processing 2 rewritten commits branchless: creating working copy snapshot branchless: running command: git checkout main Switched to branch 'main' Your branch is up to date with 'origin/main'. branchless: processing checkout In-memory rebase succeeded. Attempting rebase in-memory... [1/1] Committed as: REDACTED branchless: processing 1 rewritten commit branchless: creating working copy snapshot branchless: running command: git checkout main Switched to branch 'main' Your branch is up to date with 'origin/main'. branchless: processing checkout In-memory rebase succeeded. Attempting rebase in-memory... [1/1] Committed as: REDACTED branchless: processing 1 rewritten commit branchless: creating working copy snapshot branchless: running command: git checkout main Switched to branch 'main' Your branch is up to date with 'origin/main'. branchless: processing checkout In-memory rebase succeeded. Attempting rebase in-memory... [1/1] Committed as: REDACTED branchless: processing 1 rewritten commit branchless: creating working copy snapshot branchless: running command: git checkout main Switched to branch 'main' Your branch is up to date with 'origin/main'. branchless: processing checkout In-memory rebase succeeded. Attempting rebase in-memory... [1/1] Committed as: REDACTED branchless: processing 1 rewritten commit branchless: creating working copy snapshot branchless: running command: git checkout main Switched to branch 'main' Your branch is up to date with 'origin/main'. branchless: processing checkout In-memory rebase succeeded. Attempting rebase in-memory... [1/1] Committed as: REDACTED branchless: processing 1 rewritten commit branchless: creating working copy snapshot branchless: running command: git checkout main Switched to branch 'main' Your branch is up to date with 'origin/main'. branchless: processing checkout In-memory rebase succeeded. Attempting rebase in-memory... [1/1] Committed as: REDACTED branchless: processing 1 rewritten commit branchless: creating working copy snapshot branchless: running command: git checkout main Switched to branch 'main' Your branch is up to date with 'origin/main'. branchless: processing checkout In-memory rebase succeeded. Attempting rebase in-memory... [1/3] Committed as: REDACTED [2/3] Committed as: REDACTED [3/3] Committed as: REDACTED branchless: processing 3 rewritten commits branchless: creating working copy snapshot branchless: running command: git checkout main Switched to branch 'main' Your branch is up to date with 'origin/main'. branchless: processing checkout In-memory rebase succeeded. Attempting rebase in-memory... [1/1] Committed as: REDACTED branchless: processing 1 rewritten commit branchless: creating working copy snapshot branchless: running command: git checkout main Switched to branch 'main' Your branch is up to date with 'origin/main'. branchless: processing checkout In-memory rebase succeeded. Attempting rebase in-memory... [1/3] Committed as: REDACTED [2/3] Committed as: REDACTED [3/3] Committed as: REDACTED branchless: processing 3 rewritten commits branchless: creating working copy snapshot branchless: running command: git checkout main Switched to branch 'main' Your branch is up to date with 'origin/main'. branchless: processing checkout In-memory rebase succeeded. Attempting rebase in-memory... Synced REDACTED... ```

I also see working copy snapshots being created - not too sure if that's related.

To work around this, git switch --detach & git sync instead.

Expected behavior

git sync on main is fast in monorepos.

Actual behavior

git sync on main is slow in monorepos.

Version of rustc

No response

Automated bug report

No response

Version of git-branchless

git-branchless-opts 0.7.0 (~/.cargo/git/checkouts shows fbd95855559a73153b83fd0d1e87d75ef2906fee)

Version of git

No response

mlcui-corp commented 8 months ago

This occurs on 35ae2b3a too.

arxanas commented 8 months ago

Maybe it's due to this:

https://github.com/arxanas/git-branchless/blob/81e298dad0bd0335c4d330816c97fab38a24524a/git-branchless-lib/src/core/rewrite/execute.rs#L926-L948

We detach HEAD before moving branches and then check HEAD back out, but that's inefficient in this case. I'm not sure what the best solution is. There might be something better we can do to preserve the index state, or otherwise we could simply add a fast path in check_out_updated_head for the situation that we want to switch to a branch that points to the current commit.