diff --git a/content/docs/features/virtual-branches/branch-lanes.mdx b/content/docs/features/virtual-branches/branch-lanes.mdx index 2361e21..2f38a79 100644 --- a/content/docs/features/virtual-branches/branch-lanes.mdx +++ b/content/docs/features/virtual-branches/branch-lanes.mdx @@ -6,7 +6,7 @@ import ImageSection from "@/components/ImageSection" How do you manage your virtual branches? -The main interface for Virtual Branches are a series of branch lanes. Each lane represents a scope of work that is different than what your current base branch (ie, `origin/master`) looks like. Work that is not yet in production. +The main interface for Virtual Branches are a series of branch lanes. Each lane represents a scope of work that is different than what your current target branch (ie, `origin/master`) looks like. Work that is not yet in production. This could be a local virtual branch that you're working on, or it could be a virtual branch that was created from a remote branch. @@ -27,17 +27,17 @@ An example of working on two branches at the same time, while pending upstream c The sidebar on the left shows you the stashed virtual branches that you have and the "other" branches that you have available (legacy git branches, remote branches and PRs). All of these branches can be converted into virtual branches by clicking them and then clicking the "Apply" button on the branch view. -### Trunk +### Target -The "Trunk" is the view of the base branch that you've set. It will show you essentially a `git log` of `origin/master` or whatever you set as your base branch, and it will show you if there are any commits upstream that you have not integrated locally yet. We will automatically check for new upstream changes every few minutes, but you can also click the update button to check immediately. +The "Target" is the view of the target branch that you've set. It will show you essentially a `git log` of `origin/master` or whatever you set as your target branch, and it will show you if there are any commits upstream that you have not integrated locally yet. We will automatically check for new upstream changes every few minutes, but you can also click the update button to check immediately. ### Workspace @@ -72,7 +72,7 @@ You can inspect any file change by clicking on the file path. GitButler will exp subtitle="Inspecting our file change" /> -Once you have committed work, you will see it at the bottom as a list of commits under a tag that indicates that they are local. If you hit the "Push" button, it will attempt to push these commits to the same remote server that your base branch is on. +Once you have committed work, you will see it at the bottom as a list of commits under a tag that indicates that they are local. If you hit the "Push" button, it will attempt to push these commits to the same remote server that your target branch is on. If you have authenticated to GitHub, you also have the option to create a Pull Request for that branch automatically. diff --git a/content/docs/features/virtual-branches/butler-flow.mdx b/content/docs/features/virtual-branches/butler-flow.mdx index 9ec8c32..4703b08 100644 --- a/content/docs/features/virtual-branches/butler-flow.mdx +++ b/content/docs/features/virtual-branches/butler-flow.mdx @@ -13,22 +13,22 @@ However, a decade later, and with a new and more powerful branching toolset, we' ## Overview - In a nutshell, the basic development cycle is very simple. -- All work is based off a "base branch", which is a representation of released production code. +- All work is based off a "target branch", which is a representation of released production code. - All work immediately exists in a branch. - Work can be shared with teammates for review as early as possible. - All branches that are close to merging can be applied locally for integration testing. - Branches can be reviewed independently and merged after final review. - Integrated branches are automatically removed from developer context. -### The Base Branch +### The Target Branch In stock Git tooling, there is nothing specified as the production branch, no special "trunk". It is only by convention that this is enforced. -In GitButler, virtual branches will not work without the specification of a special "base branch". Everything exists in relation to this special branch, everything that differs from it must be accounted for by being owned by some other branch, until those changes are integrated. +In GitButler, virtual branches will not work without the specification of a special "target branch". Everything exists in relation to this special branch, everything that differs from it must be accounted for by being owned by some other branch, until those changes are integrated. ### Virtual Branches -Once you choose a base branch, everything that is in your working directory and not ignored by the Git ignore specification must be owned by a virtual branch. If you don't have one active, GitButler will automatically create one for you. +Once you choose a target branch, everything that is in your working directory and not ignored by the Git ignore specification must be owned by a virtual branch. If you don't have one active, GitButler will automatically create one for you. All subsequent changes to your working directory, either by applying other branches or directly modifying files, must be owned by a virtual branch. @@ -46,4 +46,4 @@ Merge conflicts are known almost as soon as they occur and can be communicated a ### Maintenance -Virtual branches can remain applied locally until they are merged into your upstream base branch. Once integrated by any fashion (squash merge, rebase, merge), the virtual branch is automatically disposed of, keeping cruft and overhead low. +Virtual branches can remain applied locally until they are merged into your upstream target branch. Once integrated by any fashion (squash merge, rebase, merge), the virtual branch is automatically disposed of, keeping cruft and overhead low. diff --git a/content/docs/features/virtual-branches/commits.mdx b/content/docs/features/virtual-branches/commits.mdx index 006ee4a..9c26067 100644 --- a/content/docs/features/virtual-branches/commits.mdx +++ b/content/docs/features/virtual-branches/commits.mdx @@ -134,3 +134,22 @@ You can also arbitrarily change the order of your commits by dragging and droppi alt="Moving Commits" src="/img/docs/commits-09.gif" /> + +## Edit Mode + +The other way that you can modify a commit is to go into "Edit Mode". When you click on a commit, there is a button that says "Edit patch". If you click this, GitButler will check out that commit by itself into your working directory (automatically stashing everything else temporarily). + +The screen will go into "Edit mode", indicating that you're in a special state where you're focusing on this one commit. + + + +Then you can change whatever you want and when you click "Save and exit", it will amend the commit you were editing and rebase anything on top of it. + +This is useful for things like getting feedback on a series and being able to go into the appropriate commit, make the changes and continue, as opposed to squashing work. \ No newline at end of file diff --git a/content/docs/features/virtual-branches/merging.mdx b/content/docs/features/virtual-branches/merging.mdx index ca27cf7..be276f9 100644 --- a/content/docs/features/virtual-branches/merging.mdx +++ b/content/docs/features/virtual-branches/merging.mdx @@ -1,47 +1,46 @@ --- -title: Merging +title: Rebasing and Conflicts --- import ImageSection from "@/components/ImageSection" -Conflicts happen sometimes, what to do when we get there? +By default, GitButler rebases the work on your virtual branches when you update your target branch (upstream) work. -So, let's talk a little bit more about merging. Merging in GitButler is a little different than in Git because by default, all applied virtual branches are actually merged in your working directory, as though you had run a `git merge` or `git pull` command. +Often this works just fine and the commits are simply rebased. Occasionally, you will have conflicts with upstream work. -However, it doesn't need to actually make the merge commit and tie those contexts together forever. It can simply do the merge, give you the result and keep track of what you do to it. This allows you to unmerge and remerge at will, as long as the branches merge cleanly. +In this case, GitButler will not do what Git normally does, which is to stop at each conflicted commit and make you fix it before moving on. Instead, it will apply the changes that it can and store the commit as a "conflicted" commit and continue the rebasing process. -The other interesting thing is that you cannot get two branches into a conflicting state while they are both applied, because all code in your working directory has to be owned by something. If you come across a part that overlaps, you have to choose which branch owns it or else unapply one of them. - -## Merge Conflicts - -You also cannot (currently) apply two virtual branches that conflict with each other. That means that the only way to merge two branches that have conflicts is to land one upstream in your base branch first, then integrate that so that it's your base and then pull those conflicting changes into your working directory and solve them. - -In other words, branches can only conflict with upstream changes and you can only resolve one upstream conflicted branch at a time. This is something we will work on changing, but it is a limitation currently. - -When you do have an upstream conflicting branch, you can choose to apply it, which will unapply all other branches and apply this one with conflict markers into your files. Your only branch lane will look something like this: +When you go to update from upstream, GitButler will show you all the branches that it will rebase and will let you know if any of them will have conflicts: -While the branch is in this state, you cannot apply other branches or unapply this one. (We are working on a way to abort this state, but right now you cannot). +In this case, when you perform the rebase, that branch will then contain "conflicted" commits. They will be marked in the UI as conflicted and you can click on them to get a "resolve conflict" button to start the resolution process. -You need to resolve each issue, then hit the "Resolve" button next to each file once they are resolved. This is similar to running `git add` on resolved files in a conflicted merge state in stock Git. + -Once all the files are marked as resolved, you need to commit the resolved merge. This will write a merge commit with both parents so that you have an updated merge base. +When you click that, GitButler will remove the other virtual branches and other work from your working directory and check out just this commit with it's conflict markers. It will show you a special "edit mode" screen, where you are directly editing this commit. -Once the resolution is committed, you can unapply and apply branches again. +If you want to cancel this conflict resolution, you can just hit 'Cancel' and it will go back to your normal state. If you have fixed all the issues, you can click "Save and Exit" and it will commit the conflict resolution and if needed, rebase any further commits on that branch on top of your new work. \ No newline at end of file diff --git a/content/docs/features/virtual-branches/overview.mdx b/content/docs/features/virtual-branches/overview.mdx index 1302666..2d307c2 100644 --- a/content/docs/features/virtual-branches/overview.mdx +++ b/content/docs/features/virtual-branches/overview.mdx @@ -28,20 +28,20 @@ An example of working on two branches at the same time, while pending upstream c You cannot use both GitButler virtual branches and normal Git branching commands at the same time, you will have to "commit" to one approach or the other. -The reason is that stock Git can only handle one branch at a time, it does not have tooling to use or understand multiple, so most commands having to do with the index or HEAD or branching (commit, branch, checkout, etc) may behave unexpectedly. Most importantly, do not use normal Git commit tooling or other GUIs. +The reason is that stock Git can only handle one branch at a time, it does not have tooling to use or understand multiple, so most commands having to do with the index or HEAD or branching (commit, branch, checkout, etc) may behave unexpectedly. To understand why and how to get out of this, please read our [integration branch](/features/virtual-branches/integration-branch) docs. -## Base Branch +## Target Branch With virtual branches, you are not working off of local main or master branches. Everything that you do is on a virtual branch, automatically. -Similar to GitHub, where you specify a default branch to use to merge your Pull Requests into by default, GitButler requires a "Base Branch". This is understood to be whatever your concept of "production" is. Typically what represents deployed, production code that cannot or should not be rolled back. Generally this would be something like origin/master or origin/main. +Similar to GitHub, where you specify a default branch to use to merge your Pull Requests into by default, GitButler requires a "Target Branch". This is understood to be whatever your concept of "production" is. Typically what represents deployed, production code that cannot or should not be rolled back. Generally this would be something like `origin/master` or `origin/main`. -Once a base branch is specified, everything in your working directory that differs from it is branched code and must belong to a virtual branch. +Once a target branch is specified, everything in your working directory that differs from it is branched code and must belong to a virtual branch. -This means that you don't have to create a new branch when you want to start working, you simply start working and then change the branch name later. There is no local "main" or "master" because it doesn't make sense. Everything is a branch, with work that is meant to eventually be integrated into your base branch. +This means that you don't have to create a new branch when you want to start working, you simply start working and then change the branch name later. There is no local "main" or "master" because it doesn't make sense. Everything is a branch, with work that is meant to eventually be integrated into your target branch. ## Virtual Branches You can easily work in a single branch at a time, but GitButler can handle several virtual branches at the same time. If you have 3 different changes in one file, you can drag each of the changes to a different virtual branch lane and commit and push them independently. @@ -53,41 +53,47 @@ Each time you commit on a virtual branch, GitButler calculates what that branch ## Applying and Unapplying Branches Since there isn't just a single branch you can be on, you don't "switch" branches, which implies replacement. You simply "apply" branches, which takes whatever changes they represent and adds them to your working directory. If you don't want those changes in your working directory anymore, you can "unapply" them, which removes only those changes. -Each of these actions is as simple as checking or unchecking a box next to the branch name. - -Click "unapply" for any branch to stash it and remove it's changes from the working directory To delete a virtual branch, you simply unapply it, then left click on it and choose "delete". ## Merging Upstream -Eventually you will have work merged into the branch you chose as your base branch, which will need to be reconciled with all your virtual branches to keep them up to date with where they will eventually need to merge into. +Eventually you will have work merged into the branch you chose as your target branch, which will need to be reconciled with all your virtual branches to keep them up to date with where they will eventually need to merge to. - + -Click "Merge into common base" to integrate upstream changes into your virtual branches. -Upstream work will automatically be shown in your sidebar in the "Trunk" section. When you click "Merge into common base" (or the "Update" button next to your "Applied Branches" section), we will attempt to integrate that work with your existing virtual branches. Each branch, applied or unapplied, will try to be updated with the new work. +Upstream work will automatically be shown in your sidebar in the "Target" section. When you click "Merge into common base" (or the "Update" button next to your "Workspace" section), we will attempt to integrate that work with your existing virtual branches. Each branch, applied or unapplied, will try to be updated with the new work. - -We will attempt to rebase any commits in your virtual branches on top of new work (similar to running a git pull --rebase on each branch). However, if you already have commits in your branch, we have to create a merge commit to get them up to date. - + -If we cannot update a branch because of merge conflicts, we will unapply the branch automatically and leave it in an unmerged state. You can identify these branches with the blue dot next to them in your branch listing. +For each virtual branch you have, we will show you if the incoming upstream work has conflicts with each branch. If there are conflicts, you can choose to stash the branch or go ahead and rebase with conflicts, which you can fix later. If a virtual branch is entirely integrated into upstream, it will be removed and deleted when those changes are integrated. So you can just keep a virtual branch applied locally until it is integrated and it will go away automatically. ## Conflicting Branches -You cannot have conflicting branches applied at the same time. Any virtual branch that conflicts with branches that are currently applied will be noted you cannot apply them until you have unapplied the branch or branches they conflict with. - -## Merge Conflicts -If a virtual branch does have a conflict with your upstream branch and is in a blue dot state, you can fix it by applying it. Applying a conflicting branch will first un-apply all existing virtual branches, then put the merge conflict markers into your working directory and mark conflicted files for you. +If you do rebase work that has conflicts, the commit will be marked as being in a conflicted state and you can check it out and fix it whenever you wish. + - +This is different from how you might have dealt with conflicts in Git before. If there is conflicting work in a commit, GitButler will ignore the parts that conflict and keep rebasing. In other words, rebases _always_ work. Then you can focus resolving each conflicted commit, one at a time. -You will need to resolve each file that is marked, then click "Resolve" under each one. Once all files are resolved, you need to commit to create the merge commit that resolves it. Now it is up to date and can be unapplied or applied again easily. + -While you are in a conflicted state, you cannot apply or unapply any other branches. +This will check out the conflicts into your working directory and you can let us know when you're done resolving it and we'll rebase everything above it. ## The End That is our general overview of how Virtual Branches works. We've found that it's way easier and faster than constantly switching back and forth between branches, managing branches all the time, and all the other overhead that comes with branching in Git, while still being able to easily create pull requests and integrate features. diff --git a/content/docs/features/virtual-branches/pushing-and-fetching.mdx b/content/docs/features/virtual-branches/pushing-and-fetching.mdx index ae50a99..af8d45b 100644 --- a/content/docs/features/virtual-branches/pushing-and-fetching.mdx +++ b/content/docs/features/virtual-branches/pushing-and-fetching.mdx @@ -6,7 +6,7 @@ import ImageSection from "@/components/ImageSection" GitButler can authenticate with an upstream Git server in several different ways. - You can just tell us to use the system Git executable, which you can setup however you want. You can use our built in SSH protocol with either your own SSH key or a key we automatically generate for you (this does not require you to have Git installed), or you can use the default [Git credentials helper](https://git-scm.com/doc/credential-helpers). + You can just tell us to use the system Git executable, which you can setup however you want. You can use our built in SSH protocol with your own SSH key (this does not require you to have Git installed), or you can use the default [Git credentials helper](https://git-scm.com/doc/credential-helpers). You can set your preference (and test if it works) in your project's "Git authentication" section: @@ -15,23 +15,7 @@ You can set your preference (and test if it works) in your project's "Git authen height={600} className="mx-auto" alt="Git Authentication Settings" - src="/img/docs/pushing-01.avif" -/> - -## GitButler's Key - -In case that you don't have an SSH key or authentication method set up, you can always use the SSH key that we automatically generate. - -If you go to your Account area (click on the link in the top right corner of your window), you should see the public version of this key under the "Git Stuff" area. Copy that (there is a button to copy it to your clipboard) and upload it as an authorized ssh key for your Git server. - -In GitHub, you can do that [here](https://github.com/settings/ssh/new). In GitLab, it's [here](https://gitlab.com/-/profile/keys). If you're running something else, it should be a similar process, but it has to be SSH and able to handle Ed25519 keys. - - Once that's done, GitButler will be able to automatically fetch upstream work and push new branches to your upstream server. diff --git a/public/img/docs/conflicts-commits.png b/public/img/docs/conflicts-commits.png new file mode 100644 index 0000000..0a6dcf1 Binary files /dev/null and b/public/img/docs/conflicts-commits.png differ diff --git a/public/img/docs/conflicts-conflicted.png b/public/img/docs/conflicts-conflicted.png new file mode 100644 index 0000000..5439b49 Binary files /dev/null and b/public/img/docs/conflicts-conflicted.png differ diff --git a/public/img/docs/conflicts-edit-mode.png b/public/img/docs/conflicts-edit-mode.png new file mode 100644 index 0000000..1cd15b8 Binary files /dev/null and b/public/img/docs/conflicts-edit-mode.png differ diff --git a/public/img/docs/conflicts-edit.png b/public/img/docs/conflicts-edit.png new file mode 100644 index 0000000..5e6041f Binary files /dev/null and b/public/img/docs/conflicts-edit.png differ diff --git a/public/img/docs/conflicts-incoming.png b/public/img/docs/conflicts-incoming.png new file mode 100644 index 0000000..cbc8fad Binary files /dev/null and b/public/img/docs/conflicts-incoming.png differ diff --git a/public/img/docs/conflicts-resolve.png b/public/img/docs/conflicts-resolve.png new file mode 100644 index 0000000..b3c13be Binary files /dev/null and b/public/img/docs/conflicts-resolve.png differ diff --git a/public/img/docs/merge-upstream-incoming.png b/public/img/docs/merge-upstream-incoming.png new file mode 100644 index 0000000..a748a37 Binary files /dev/null and b/public/img/docs/merge-upstream-incoming.png differ diff --git a/public/img/docs/merge-upstream.png b/public/img/docs/merge-upstream.png new file mode 100644 index 0000000..45977fe Binary files /dev/null and b/public/img/docs/merge-upstream.png differ diff --git a/public/img/docs/pushing.png b/public/img/docs/pushing.png new file mode 100644 index 0000000..2e1da59 Binary files /dev/null and b/public/img/docs/pushing.png differ