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

推荐订阅源

阮一峰的网络日志
阮一峰的网络日志
IT之家
IT之家
H
Heimdal Security Blog
Jina AI
Jina AI
宝玉的分享
宝玉的分享
博客园 - 【当耐特】
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
爱范儿
爱范儿
T
Tailwind CSS Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Apple Machine Learning Research
Apple Machine Learning Research
有赞技术团队
有赞技术团队
酷 壳 – CoolShell
酷 壳 – CoolShell
WordPress大学
WordPress大学
AWS News Blog
AWS News Blog
C
Cisco Blogs
Cisco Talos Blog
Cisco Talos Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
D
Darknet – Hacking Tools, Hacker News & Cyber Security
The Hacker News
The Hacker News
The Cloudflare Blog
Hugging Face - Blog
Hugging Face - Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
T
Threatpost
S
Securelist
P
Privacy International News Feed
C
CXSECURITY Database RSS Feed - CXSecurity.com
博客园 - 聂微东
博客园 - 叶小钗
J
Java Code Geeks
V
V2EX
博客园 - Franky
Spread Privacy
Spread Privacy
K
Kaspersky official blog
C
Cyber Attacks, Cyber Crime and Cyber Security
Simon Willison's Weblog
Simon Willison's Weblog
Project Zero
Project Zero
大猫的无限游戏
大猫的无限游戏
S
SegmentFault 最新的问题
C
Cybersecurity and Infrastructure Security Agency CISA
C
CERT Recently Published Vulnerability Notes
Latest news
Latest news
NISL@THU
NISL@THU
罗磊的独立博客
W
WeLiveSecurity
Google DeepMind News
Google DeepMind News
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
博客园_首页
V
Visual Studio 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" Fearless Rebasing 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 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
Git Tips 1: Oldies but Goodies
Scott Chacon · 2024-02-08 · via Butler's Log

For the first in our short series of Git tips, I wanted to start with stuff that's been around for a while, but it still seems like a lot of people don't know about or don't know how to use.

None of this is new, but I find them useful and they're arguably a little obscure. I'm just going to cover:

  • Conditional Configs
  • Git Blame and Log with Line Ranges
  • Git Blame with Following
  • Word Diff
  • Resolution Reuse

Let's dig in!

Many of you probably know this, but Git has a cool little key/value store called git config which will check in three places for values to use when it's running various commands.

Every Git user will have probably been told to run something like this when they first set up:

$ git config --global user.name "John Doe"
$ git config --global user.email johndoe@example.com

That adds the user.name value to your ~.gitconfig file. But there is also --system (which probably none of you have used) which writes it to a system-wide config file and --local (the default) that writes it to .git/config in whatever project you're currently in.

When Git looks for a value, it will look in that order - local, global, system - for a definition.

However, there is a secret fourth place that Git can look. If you add to your global config something that looks like this:

[includeIf "gitdir:~/projects/oss"]
    path = ~/.gitconfig-oss

Then Git will look in the ~/.gitconfig-oss files for values only if the project you are currently working in matches ~/projects/oss . So, you could have a "work" directory and have work-specific values there (company email address, gpg signing key, etc) and an "oss" directory with values for your open source projects, etc.

But gitdir is not the only filter you can use. You can also put branch name specific values as a include filter with onbranch or you can only include config files if the project you are currently in has a remote matching a specific URL with hasconfig:remote.*.url . So like if you have GitHub org specific keys or something.

Check out the docs for more.

Git Blame and Log with Line Ranges

There are a couple of interesting options that you can use with git blame that most people don't know about and nearly none of the existing GUIs implement.

One is the line range option, -L. A lot of times, if you're running blame on the command line, you just page the whole file and find the part you're looking for. However, if you want to just display a subsection of your file, you can give it a line range, like git blame -L 28,43 path/to/file

git blame -L

You can also use a semi-strange : syntax to give Git a pattern to find the beginning of a block and only blame that block. So in this same situation, I can get the same result by running git blame -L :'class LocalFile' gitbutler-ui/src/lib/vbranches/types.ts

Typically you can use a function name or something for that string.

The other thing you can do to see similar information in a different way, is to run git log with similar options. This will give you all the commits filtered to those that last touched this region of the file. So for example, git log -L28,43:gitbutler-ui/src/lib/vbranches/types.ts will give you something like this:

So instead of being ordered by lines, it sort of gathers all the commits that are shown in the blame and then shows you those commits with code that modified that block in each commit. Basically the same data, but in a different format, more like a story of how that code was put together.

One thing that is really not great about using blame in GUI tools is that the CLI has much more powerful tooling for finding something closer to the real story behind your code.

There are many scenarios where this is really valuable. The first is ignoring whitespace changes. Some of the GUIs do that, but not all of them. So if you go and implement a prettierrc file, BLAM, now you're the owner of tons of lines of code. The git blame -w option will ignore these types of whitespace changes.

The other great option is -C which will look for code movement between files in a commit. So if you refactor a function from one file to another, the normal git blame will simply show you as the author in the new file, but the -C option will follow that movement and show the last person to actually change those lines of code. Either of these scenarios could be what you're looking for, but I would argue that more often it's the latter.

If you want Git to try even harder (look for movement in multiple commits or in all of your commits) you can pass -C up to three times.

Also, your GUI does not do this (most likely, I can't speak for all of them).

So, let's look at the VS Code GitLens blame output of the previous example:

git blame in GitLens VS Code plugin

Ok, looks good. Kiril wrote most of this code it appears. Let's now look at the same block with git blame -w -C -C -C

git blame -C -C -C

Now we can see that Git has followed this hunk of code from file to file over the course of multiple renames.

Also, Kiril only really owns a few lines of code, Mattias actually wrote big hunks of it. If we want to know about those lines, it's much better to ask Mattias rather than Kiril, as our GUI blame would suggest.

This is incredibly minor, and some GUIs have nice versions of this (I find GitHub's better than what I'm about to show you, since it subtly does both) but if you ARE running git diff on the command line and there is a line change where something small changed within it, you can change Git's default format to word-based rather than line based with the --word-diff option.

normal, line-based git diff

super cool git diff --word-diff

Finally, if you're rebasing or cherry-picking a lot and you've ever run into the same conflict more than once, you can turn on a feature where Git memorizes the conflict and the resolution to it. If it ever sees that same conflict again, it will automatically re-solve it for you.

You can easily turn it on with the config setting rerere.enabled and you can further ask it to automatically stage it for you with rerere.autoUpdate

$ git config --global rerere.enabled true
$ git config --global rerere.autoUpdate true

a conflict... always remembers

Then, the next time you get a merge conflict that it's seen before, magic!

automatically fix it the next time

Again, all of this has been in Git for a while, but if you don't know... now you know.

Next up is New Stuff in Git.