gitbutler icon indicating copy to clipboard operation
gitbutler copied to clipboard

Better switching between Git and GitButler

Open schacon opened this issue 11 months ago • 2 comments

There are some issues when switching between GitButler virtual branches and Git normal branches.

The background to a degree is that GitButler can handle Git branches by converting them to virtual branches. Git cannot handle virtual branches because there are no mechanisms for it's tooling to logically be on more than one branch in the same working directory.

So you have to be in either one "space" or another.

If you are using the GitButler virtual branch space, we do two important things:

  • We change your Git branch to a special "gitbutler/integration" branch (refs/heads/gitbutler/integration) by pointing HEAD at it.
    • Whenever you make changes to any files, do commits, move files between virtual branches - we update the commit that gitbutler/integration is pointing to with instructions. The tree that commit points to is the union of all the commits on all your virtual branches (none of your in-progress, uncommitted work).
  • Any time there are commits (or commit undos or amendments), we make the index file ALSO look like the union of all the virtual branch commit heads, so that a normal git status will properly see the same set of files that you would see in our GUI.
    • That is, we make the staging area always look like the union of everything committed, so any normal Git tools (VS Code for instance) will see your modified files as modifed.

Now, when you switch away from gitbutler/integration by going back to Git and running git checkout branch, GitButler has to assume you're not using it for a while and will not continue to function until you go back to it's branch management space.

There is an issue when clicking the 'go back to gitbutler/integration' button where GitButler will try to take into account the normal Git branch you're currently on.

It should not do this.

What we should do is simply try to get back to exactly the state we were in when you left the GitButler space in the first place. Which should be easy, because we have that state stored in our virtual branch data.

There are three scenarios we need to address when you have switched to a normal Git branch and want to go back to GitButler to return to your GitButler branches state.

Scenario 1: Dirty Working Directory, Press GitButler Button

If you have switched to another branch and have file changes that are not committed, we should not allow you to switch back to gitbutler/integration. The Git CLI would not allow it in most cases anyhow (if something is overwritten), but we should be adamant. If you left our space, you need to be in a clean state to go back. We can suggest to either commit on your branch or stash your work.

Scenario 2: Clean Working Directory, Press GitButler Button

If everything is committed, we should essentially do a normal branch switch. Remove anything unique to the git branch and restore the virtual branch state that the user was in before switching. This would mean:

  • Updating HEAD to point to gitbutler/integration again
  • Update the working directory contents to be the union of all the tree entries of all applied virtual branches (the only actual place we keep this unified tree is in the wd entry of our session data, but we can probably count on the vb data more solidly)

Scenario 3: User runs git checkout gitbutler/integration on the Command Line

This will probably not quite do what you want, because the work in progress (uncommitted) work on those virtual branches will not be restored properly to your working directory. Therefore, we will probably want to intercept this action (FS watcher sees that HEAD changed and looks for this specific change - someone tried to manually go back to gitbutler/integration). Then merge the working directory contents with the tree entries of the applied virtual branches.

This could still have an issue if gitbutler/integration does not have conflicts with the uncommitted content of what they were on but the uncommitted work in the virtual branches does. Therefore, perhaps it's a better idea to simply watch for a switch away from gitbutler/integration and delete it from refs/heads so the user cannot go back to it on the command line. Otherwise, we would simply have to set any conflicting virtual branch trees to 'unapplied' when trying to switch back.

User Interface

In all scenarios, we should have a more clear "You've switched away" page. Currently it looks like this:

CleanShot 2024-03-06 at 14 14 25@2x

What we should add to this is:

  • What git branch they're currently on and if that branch has uncommitted work on it
  • What virtual branches they were on and the refs/gitbutler/X refs (link to doc on how to access/push them)
    • possibly a list of modified files on each of those
  • If there is uncommitted work, that they cannot go back to their GitButler virtual branches until they stash or commit (link to doc)
  • If there is no uncommitted work, a button to switch back to GitButler branches and a summary of what will happen

schacon avatar Mar 06 '24 12:03 schacon

related: https://github.com/gitbutlerapp/gitbutler/pull/3044

krlvi avatar Mar 06 '24 12:03 krlvi

I have decided to stop using GitButler today. I used it for like a month, but its devastating when I accidentally muscle-memory checkout a branch with git CLI. Will watch for the 1.0 release.

bioshazard avatar Apr 24 '24 20:04 bioshazard