Repository: gitbutlerapp/gitbutler

Issue #3048: Better switching between Git and GitButler
Created: 2024-03-06T12:39:54Z
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:

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

Duplicate issue #3420: Work in progress changes & commits get (optionally) imported during project add
Created: 2024-04-03T18:24:21Z
We used to have the functionality where during the process of adding a repo, if there was work in progress, it was added as a virtual branch, which no longer works.
Lets bring it back in an optional way. If a developer has selected origin/main as their target and they are currently on foo with 2 commits and 3 uncommitted changes, present that and ask the developer if they wish to have that added as a virtual branch.

Closing comment (2024-04-23T19:21:14Z): Probably related to #3048.