git-branchless
git-branchless copied to clipboard
Implement some form of interactive rebase
Unlike git rebase -i
, it should be possible to manipulate the tree structure, rather than a linear sequence of commits. Depends on #176.
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.
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.
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
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
- We basically have two optional columns, how do we disambiguate them?
- A commit can have multiple branches, how do we handle that?
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.
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.
I modeled git stack
s 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
-
co main
asSwitchCommit
-
co abc123
asSwitchMark
where the hash is a placeholder for whatever the new hash will be for commitabc123
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
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.
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>
There might be some interesting ideas to consider regarding rebase scripting from git-assembler
: https://www.thregr.org/~wavexx/software/git-assembler/