gitbutler
gitbutler copied to clipboard
Better switching between Git and GitButler
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 pointingHEAD
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).
- Whenever you make changes to any files, do commits, move files between virtual branches - we update the commit that
- 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 normalgit 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 togitbutler/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 thewd
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:
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
related: https://github.com/gitbutlerapp/gitbutler/pull/3044
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.