惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

C
Check Point Blog
GbyAI
GbyAI
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
U
Unit 42
美团技术团队
NISL@THU
NISL@THU
C
Cisco Blogs
SecWiki News
SecWiki News
N
Netflix TechBlog - Medium
Forbes - Security
Forbes - Security
Cloudbric
Cloudbric
雷峰网
雷峰网
T
Tailwind CSS Blog
博客园 - 司徒正美
The Register - Security
The Register - Security
L
LangChain Blog
S
Security Affairs
Hacker News - Newest:
Hacker News - Newest: "LLM"
B
Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
T
Threat Research - Cisco Blogs
I
InfoQ
S
Schneier on Security
L
Lohrmann on Cybersecurity
量子位
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Martin Fowler
Martin Fowler
Schneier on Security
Schneier on Security
F
Fortinet All Blogs
TaoSecurity Blog
TaoSecurity Blog
K
Kaspersky official blog
Google DeepMind News
Google DeepMind News
Cisco Talos Blog
Cisco Talos Blog
PCI Perspectives
PCI Perspectives
Attack and Defense Labs
Attack and Defense Labs
WordPress大学
WordPress大学
Microsoft Azure Blog
Microsoft Azure Blog
H
Help Net Security
Project Zero
Project Zero
The GitHub Blog
The GitHub Blog
D
Docker
N
News | PayPal Newsroom
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
H
Hacker News: Front Page
云风的 BLOG
云风的 BLOG
Microsoft Security Blog
Microsoft Security Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园 - 聂微东
Webroot Blog
Webroot Blog
MongoDB | Blog
MongoDB | Blog

Butler's Log

Agentic Version Control Benchmarks Grit: rewriting Git in Rust with agents Git Merge 2026 Agent-safe Git with GitButler We’ve raised $17M to build what comes after Git Announcing the GitButler CLI for Linux The Great CSS Expansion A couple of git nits Simplifying Git by Using GitButler Introducing the GitButler CLI GitButler 0.19 - "Commander Keen" But Head: Crafting a Custom Font MCP vs RAG: Two Very Different Ways to Gain Context Getting Started With GitButler Agents Using the GitButler MCP Server to Build Better AI-Driven Git Workflows Using GitButler With Multiple GitHub Accounts Advent of Code! Upcoming GitButler Events Use GitButler for your Gerrit workflow Integrating GitButler and GitHub Enterprise Butler Flow: shipping code faster (but less like Alfred, more like CI on steroids) - Part 3 Butler Flow: shipping code faster (but less like Alfred, more like CI on steroids) - Part 2 Butler Flow: shipping code faster (but less like Alfred, more like CI on steroids) - Part 1 Grid Happens: Because Flexbox Wasn’t Enough Using Cursor Hooks for automatic version control Deep Dive into the new Cursor Hooks A Responsive Item Counter with CSS only GitButler 0.16 - "Sweet Sixteen" GitButler's Claude Code tab GitButler's Annual Open Source Pledge Report Git Mini Summit 2025 Videos Automate Your AI Workflows with Claude Code Hooks Managing Multiple Claude Code Sessions Without Worktrees GitButler 0.15 - "Quirky Quinceañera" 20 years of Git. Still weird, still wonderful. GitButler's new patch based Code Review (Beta) Going down the rabbit hole of Git's new bundle-uri How to do patch-based review with git range-diff How Core Git Developers Configure Git Why is Git Autocorrect too fast for Formula One drivers? Stacked Branches with GitButler Git Merge 2024 Talks are Up GitButler 0.13 - "Lucky Baseball" Git Merge 2024 Why GitHub Actually Won GitButler is joining the Open Source Pledge The New Era of Town Hall Chat The Future of Open Source GitButler is now Fair Source Git Merge 2024 GitButler 0.12 - "Stingy Baker" The Birth of THE MERGE GitButler for Windows Fixing up Git with Autosquash The Git Zeitgeist Git Worktrees and GitButler DevWorld Git Slides Git Tips and Tricks Git Tips 1: Oldies but Goodies Git Tips 2: New Stuff in Git Git Tips 3: Really Large Repositories FOSDEM Git Talk Opening Up GitButler Debugging Tauri in VS Code Advent of GitButler Code Signing Commits in Git, Explained Virtual Branches Alpha Our We Are Developers Adventure Building Virtual Branches DevDays in Vilnius The Future of Software and Open Source Introducing GitButler
Fearless Rebasing
Scott Chacon · 2024-10-23 · via Butler's Log

I have a confession to make. For most of my Git life, I have been a merger.

I have been asked countless times if it's better to merge or to rebase and while I never want to stir up a hornet's nest, I have always advocated merging over rebasing. Not only that, but I have nearly always done so myself when working on a project.

To me, merging has always been better. It keeps more of the history, there are by definition fewer conflicts since it only has to merge the last tree rather than every intermediate tree, it's easier to see what each series actually was, it's easier to see when it was integrated, etc.

However, let's admit it, rebasing is sexy.

Rebasing versus merging, which is better?

I've always loved the idea of a linear history, of rewriting a series until it's perfect and getting that nice useful blame and bisecting power. Getting rid of that subway map history graph in favor of a nice simple series of patches.

But rebasing is also a pain in the ass.

You run rebase --pull and get conflict after conflict and can't do anything else until you're done. You can't save your progress if you get tired of the exercise halfway through. It's also difficult to keep your series clean anyhow - doing fix-up commits, autosquashing, interactive rebasing. Even those of us fairly used to the tooling mess up or get frustrated sometimes. Now compound that with the need for your entire team to feel comfortable with this tooling. Heavy sigh.

Recently, however, I have completely changed my mind. I am now an official rebaser.

The reason is not because I was convinced by someone that I've been wrong this whole time, nor was it because Git's tooling around rebasing got better. It's because of Fearless Rebasing.

One of the things that GitButler has never been very good at so far is merge conflicts. We just didn't have a good story for it because we weren't sure what a good way was to handle it. What is actually an ideal (or even, not horrible) way to deal with merge conflicts?

When researching other tools, I ran across the Jujutsu project that is being developed at Google.

Jujutsu has a novel concept of "first class conflicts", where it can record conflicted states in it's commit objects. Git can't do this. If Git runs into a conflict when trying to merge, rebase or cherry-pick something, it halts everything and makes you fix it before moving forward. It has no way to save the conflict for later resolution and keep going.

But Jujutsu does, which means that every time you do a rebase operation, it is always successful.

How does this work?

When Jujutsu tries to rebase commits and runs into a conflict, instead of writing the conflict out to the working directory and throwing a bunch of status files into your .git directory, it instead writes a specially formatted commit that lists out the trees it attempted to merge, pretends that this commit was not there and continues with the next commits.

This means that you can end up in a state like this, where you have several conflicted commits and then some commits after them that are not in a conflicted state.

Then to resolve the conflicts, you can edit one of the commits and resolve it, which amends that commit and automatically rebases everything above it again.

We loved this concept so much that we decided to implement an approach that is very similar.

When working with a virtual branch, we want to empower you to think about your changes as a series of patches that you can constantly and easily change, amend, squash, split, edit and rebase.

If you can do all of that fearlessly, knowing that everything is easy to do, simple to undo and much more painless to resolve, then that lets us maintain that beautiful and simple history.

In our 0.13 release of GitButler, we are introducing a very similar workflow to rebasing your commits to what Jujutsu does. If you create a series of commits and then rebase it onto new upstream work and there are conflicts, we will always rebase successfully but mark any problematic commits and only apply the parts of them to your working directory that do not conflict.

So let's say that you have three commits in your branch and rebase and the first two have conflict problems. Now we will partially apply them (whichever hunks do not conflict), write a special commit that has a conflicted header, then try the next one.

Now you can solve these conflicts one by one. Even in any order - you don't have to approach the first one first, you can start with the second one if you prefer.

To solve the conflicts, you can click on a commit that is in a conflicted state and click the "Resolve Conflicts" button, which now checks out just those conflicts into your working directory.

It also changes your GitButler UI to let you know you are in this special state and allows you to either abort the session using the "Cancel" button or save your conflicted state and rebase the remaining commits with the "Save" button.

Now the entire rebasing workflow in Git is massively easier. You can solve conflicts whenever you prefer and you can push off the work until you're ready to work on them, even continuing to make new commits while some of your commits are in a conflicted state.

We believe that fearless rebasing is a much nicer way to deal with conflicts. If you want to try it out, download GitButler and see how it feels. Maybe we'll make a rebaser out of you too.

Scott Chacon

Written by Scott Chacon

Scott Chacon is a co-founder of GitHub and GitButler, where he builds innovative tools for modern version control. He has authored Pro Git and spoken globally on Git and software collaboration.