arxanas / git-branchless

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

Implement some form of interactive rebase #177

Open arxanas opened 2 years ago

arxanas commented 2 years ago

Unlike git rebase -i, it should be possible to manipulate the tree structure, rather than a linear sequence of commits. Depends on #176.

epage commented 2 years ago

I'm also interested in interactive rebase for git-stack (see my issue). I wonder if our requirements align enough to allow a common edit format. The more we can standardize it, the more likely it is to get editor support, among other reasons.

arxanas commented 2 years ago

My envisioning is that it would be like git rebase -i, but with indentation to indicate child commits:

pick abc123 some root commit
  pick abc456 first child
    pick def456 first grandchild
  pick abc789 second child (topologically unorderable wrt first child)

Let me know if you have any other interface ideas.

epage commented 2 years ago

So a typical linear rebase would be

pick abc123 some root commit
  pick abc456 first child
    pick def456 first grandchild
        ...

That seems pretty indentation heavy and I would be worried it'd run counter to how people think (since they are used to seeing parent/children in a series), whether git rebase -i, git log, or git sl

I had been considering flattening it as much as possible and have any additional children be sections that list their base commit in a new column.

So it'd be something like

main     pick abc123 some root commit
             pick abc456 first child
             pick def456 first grandchild

abc123 pick abc789 second child (topologically unorderable wrt first child)

(seriously, gitlab, your code fences mess up rendering?)

In thinking about both approaches, this one also optimizes for re-parenting because its just changing lines or changing bases rather than also having to change indentation of entire hierarchies of commits

epage commented 2 years ago

Another feature I've been considering (more important for git-stack than git-branchless) is modifying branch refs. This, combined with my parent commit idea, gets a little tricky in syntax

Maybe something like

main     [] pick abc123 some root commit
             [] pick abc456 first child
             [branch1, new-branch] pick def456 first grandchild

abc123 [branch2] pick abc789 second child (topologically unorderable wrt first child)

Its ugly. Unsure how much its worth cramming all of these features in.

arxanas commented 2 years ago

That seems pretty indentation heavy and I would be worried it'd run counter to how people think (since they are used to seeing parent/children in a series), whether git rebase -i, git log, or git sl

That's a good point. The git sl approach is to linearize one set of children and then indent the rest, but I don't know if that would be intuitive for users.

epage commented 2 years ago

I modeled git stacks core after git rebase -i, with two different levels (the higher level graph, the lower level list of instructions).

In considering this, another model I thought of is

co main Merge #299
pick abc123 some root commit
pick abc456 first child
pick def456 first grandchild

co abc123 some root commit
pick abc789 second child (topologically unorderable wrt first child)

Internally, I refer to

Recognizing commits vs marks and ordering arbitrarily created sequences will take some figuring out.

Maybe branches can be another command / directive

co main Merge #299
pick abc123 some root commit
pick abc456 first child
pick def456 first grandchild
branch branch1 new-branch

co abc123 some root commit
pick abc789 second child (topologically unorderable wrt first child)
branch branch2
arxanas commented 2 years ago

On the Graphite Slack, user Bilal Quadri (@bilalq?) says this:

One major point of friction for me is the interop between git and gt. I always create commits without pre-planning my PR breakdown. I usually decide on that separation after the fact. In fact, a lot of my commits are temporary and get squashed away or reordered before I ever submit a PR. It'd be really nice if there was an interactive rebase where I could just have a bunch of commits created on top of main or whatever my target branch is and run gt stack fix --interactive. I'd imagine this opening $EDITOR similar to how git rebase -i works. In there, I would be able to define stack points. This would also remove the need to re-learn all my existing habits/workflows. A user can use git as they normally would, but using graphite becomes as simple as running gt sf -i to create the stack. I added a request for this here: https://app.graphite.dev/changes-requested#request-Ao06hhkGqWaeBU7upXbc Personally, this is my #1 valued feature request. Asking every engineer to relearn or adapt their workflows around the gt tool is a little heavy right now.

This would indicate that they would very much value the ability to set branches as part of interactive rebase.

bilalq commented 2 years ago

Yeah, this would be huge for me.

Even something to either extend the interactive rebase in git to add a preprocessing step to it could work.

Let's say I have a dag looking like this:

* cc8788ba - (HEAD -> main) Implement signin with Facebook (12 hours ago) <Bilal Quadri>
* a5cb48c7 - Implement signin with Apple (12 hours ago) <Bilal Quadri>
* bf1c8c7a - Implement signin with Google (12 hours ago) <Bilal Quadri>
* ee139214 - Integrate with AWS Cognito user pool (12 hours ago) <Bilal Quadri>
* cde12345 - Setup auth event handlers (12 hours ago) <Bilal Quadri>
* abc123ef - Create UI for auth (14 hours ago) <Bilal Quadri>
* af34cca1 - (origin/main) Configure code coverage reports (16 hours ago) <Bilal Quadri>

The normal git rebase prompt would open with:

pick abc123ef Create UI for auth
pick cde12345 Setup auth event handlers
pick ee139214 Integrate with AWS Cognito user pool
pick bf1c8c7a Implement signin with Google
pick a5cb48c7 Implement signin with Apple
pick cc8788ba Implement signin with Facebook

Ideally, I'd like to edit it to something like:

-- feat/create-auth-ui
pick abc123ef Create UI for auth
-- feat/integrate-auth-ui-with-auth-service
pick cde12345 Setup auth event handlers
pick ee139214 Integrate with AWS Cognito user pool
-- feat/support-social-logins
pick bf1c8c7a Implement signin with Google
pick a5cb48c7 Implement signin with Apple
pick cc8788ba Implement signin with Facebook

But have that be treated as:

pick abc123ef Create UI for auth
pick cde12345 Setup auth event handlers
exec git checkout -b feat/create-auth-ui && git checkout -
pick ee139214 Integrate with AWS Cognito user pool
exec git checkout -b feat/integrate-auth-ui-with-auth-service && git checkout -
pick bf1c8c7a Implement signin with Google
pick a5cb48c7 Implement signin with Apple
pick cc8788ba Implement signin with Facebook
exec git checkout -b feat/support-social-logins && git checkout -
exec gt stack fix --regen

To ultimately end up with a dag like:

* cc8788ba - (HEAD -> feat/support-social-logins, main) Implement signin with Facebook (10 hours ago) <Bilal Quadri>
* a5cb48c7 - Implement signin with Apple (12 hours ago) <Bilal Quadri>
* bf1c8c7a - Implement signin with Google (12 hours ago) <Bilal Quadri>
* ee139214 - (feat/integrate-auth-ui-with-auth-service) Integrate with AWS Cognito user pool (12 hours ago) <Bilal Quadri>
* cde12345 - Setup auth event handlers (12 hours ago) <Bilal Quadri>
* abc123ef - (feat/create-auth-ui) Create UI for auth (14 hours ago) <Bilal Quadri>
* af34cca1 - (origin/main) Configure code coverage reports (16 hours ago) <Bilal Quadri>
arxanas commented 2 years ago

There might be some interesting ideas to consider regarding rebase scripting from git-assembler: https://www.thregr.org/~wavexx/software/git-assembler/