Git Rev News Edition 134 (April 30th, 2026)

17 min read Original article ↗

Welcome to the 134th edition of Git Rev News, a digest of all things Git. For our goals, the archives, the way we work, and how to contribute or to subscribe, see the Git Rev News page on git.github.io.

This edition covers what happened during the months of March and April 2026.

  • [PATCH 0/4] line-log: route -L output through the standard diff pipeline

    git log -L lets users follow the history of a specified line range inside a file, for example by passing -L:funcname:file.c to track the evolution of a function. Since the feature was introduced, however, its diff output has been generated by a hand-rolled helper called dump_diff_hacky() rather than by Git’s standard diff pipeline, with a NEEDSWORK comment in line-log.c openly admitting:

    /*
     * NEEDSWORK: manually building a diff here is not the Right
     * Thing(tm).  log -L should be built into the diff pipeline.
     */
    

    The practical consequence is that almost every diff formatting option that users have come to rely on (--word-diff, --color-moved, the -w/-b whitespace options, --no-prefix, --src-prefix/--dst-prefix, --full-index, --abbrev, -R, --output-indicator-*, the pickaxe options -S/-G, and so on) is silently ignored when combined with -L. The hand-rolled output also omits the index lines, new file mode headers, and funcname context in @@ hunk headers that the standard pipeline produces.

    Michael Montalbo opened the discussion by sending a four-patch series that finally addressed this long-standing limitation. The series explicitly replaced an earlier attempt of him, “line-log: fix -L with pickaxe options”, which had taken the opposite approach of rejecting -S/-G when combined with -L; the new direction is to make those options work instead. Patch 1 carries over a crash fix from that previous attempt unchanged, patch 2 contains the core change, patch 3 adds an extensive set of tests for the newly-working options, and patch 4 updates the documentation.

    In detail, patch 1 fixes a real assertion failure that could be triggered by combining -L with pickaxe options across a merge that contains a rename, an issue originally reported by Matthew Hughes. Inside queue_diffs(), the caller’s diff_options was being reused for rename detection, which meant that any user-specified pickaxe state (-G, -S, or --find-object) would run inside diffcore_std() and silently discard diff pairs that the rename machinery still needed. The fix builds a private diff_options for the rename-detection path, mirroring the pattern already used in git blame’s find_rename(), and isolates the rename machinery from unrelated user options.

    Patch 2 is where the heavy lifting happens. Instead of formatting output by hand, -L now feeds its filepairs through builtin_diff() and fn_out_consume(), the same path used by git diff and git log -p. The mechanism is a pair of callback wrappers that sit between xdi_diff_outf() and fn_out_consume(), filtering xdiff’s output down to only the tracked line ranges. To make sure xdiff actually emits every line within each tracked range as context, the context length is inflated to span the largest range. The tracked line ranges themselves are now carried on struct diff_filepair as a borrowed pointer, so that each file’s ranges travel with its filepair through the rest of the pipeline. As a side effect, line_log_print() shrinks down to little more than a diffcore_std() call followed by diff_flush(), the “-L implies --patch” default is wired up in revision setup rather than forced at output time, and diff_filepair_dup() is switched from xmalloc to xcalloc so that newly added fields (including the line_ranges) are zero-initialized.

    Because diffcore_std() now actually runs at output time, options such as -S, -G, --orderfile, and --diff-filter come along for the ride and start working with -L for the first time. Michael also notes in the commit message that the context-length inflation means xdiff might process more output than strictly needed for very wide ranges, but his benchmarks on files up to 7800 lines showed no measurable regression.

    There is, of course, a user-visible output change: -L output now includes index lines, new file mode headers, and funcname context in @@ hunk headers that were previously absent. Tools that parse -L output may need to handle these additional lines. The cover letter is upfront about this, and also lists two limitations that are deliberately left for follow-up work: line_log_print() still calling show_log() and diff_flush() directly rather than going through log_tree_diff_flush(), and the non-patch diff formats (--raw, --numstat, --stat, etc.) remaining unimplemented for -L.

    Junio Hamano, the Git maintainer, replied to the cover letter the same day with a single word: “Exciting.” He approved the deliberate incremental scope, observing that since “previously all the output routines were hand-rolled, but this reduces the extent of deviation — as long as we are moving in the right direction, it is a good idea to find a good place to stop and leave the rest for later.” On the note about non-patch diff formats, Junio remarked that “it would not hurt if these are omitted”, which led to a small back-and-forth where Michael initially thought he was being asked to do something extra in a follow-up; Junio clarified that the series was already omitting them (“You are already omitting, no? I took ‘remain unimplemented’ to mean exactly that”), and that simply mentioning the omission, as the cover letter already did, was the right thing to do.

    Junio also pointed out that the “Michael Montalbo (4): … block in the cover letter looked like a reflowed duplicate of the proper commit list right below” it. Michael acknowledged that as a mistake in crafting the cover letter and offered to add a few names from git shortlog --no-merges -s -n line-log.[ch] to the Cc list to attract more reviewers.

    On the documentation patch (4/4), Kristoffer Haugsbakk caught a subtle AsciiDoc problem: by indenting the new paragraph with tabs, Michael had inadvertently turned the new prose into a code block. Kristoffer recommended dropping the indentation in favour of a plain list-continuation marker so the text would render as regular paragraph text, that is, “flush to the left.” Michael thanked him and folded the fix into his next iteration.

    For readers less familiar with the relevant pieces of the diff stack, a few words of context may help.

    git log -L is itself a relatively unusual citizen in Git’s command zoo: most git log machinery walks commits and emits whatever its configured formatters dictate, but -L additionally carries a set of line ranges per file, narrowing the history to commits that touch those ranges. Mapping that range-aware view onto the standard diff output machinery is non-trivial because xdiff itself does not know anything about the user’s tracked ranges; it just produces a unified diff for two blobs. The new callback wrappers introduced in patch 2 bridge that gap by intercepting xdiff’s output as it is generated and discarding hunks that fall outside the requested ranges.

    The diffcore_std() function is the standard point at which Git applies a number of cross-cutting transformations to a queued set of diff pairs: rename detection, the pickaxe filters (-S, -G, --find-object), the orderfile sort, and the --diff-filter filter, among others. Once -L actually feeds its pairs through this function, all of those features become available essentially “for free.” That is also why patch 1 has to be careful: rename detection performed during the line-history walk must not let a user’s pickaxe filter inadvertently throw away the very pairs the rename machinery needs to do its job.

    After the initial round of review, Michael sent version 2 of the series. The only structural change from v1 is that patch 4 now uses a list-continuation marker instead of indentation in Documentation/line-range-options.adoc, addressing Kristoffer’s review feedback so the new paragraph renders correctly. The crash-fix patch (1/4) also gained an explanatory comment in its test file about commit-level filtering with pickaxe still being a known limitation: show_log() prints the commit header before diffcore_std() runs, so commits cannot yet be suppressed even when no diff pairs survive filtering. Fixing that would require deferring show_log() until after diffcore_std(), which is again a larger log-tree restructuring that v2 explicitly leaves for later.

    Junio reviewed v2 patch 2 again and was generally positive. He noted that “huge diff to the test material mostly comes from the addition of the diff headers like the index line, etc., which makes this patch scary but is very welcome addition”, and on the new field line_ranges carried on struct diff_filepair, simply replied “OK.” On the rewrite of line_log_print() itself, which now queues a duplicated filepair per range, attaches the borrowed line_ranges, and calls diffcore_std() followed by diff_flush(), he wrote: “Very welcome change.”

    Some weeks later, after no further substantive review arrived, Junio came back to the v2 cover letter and wrote, in a slightly resigned but encouraging tone: “The central part of the series (i.e., patch #2) looked quite sensible. I haven’t read the tests very carefully, though. I was hoping that we will see another set of eyes or two to help review this series, but nothing has happened in the past few weeks, so let’s mark the topic for ‘next’.” The series was later merged into ‘master’ and these improvements have been released as part of Git v2.54.0.

    This is an example of long-standing technical debt finally being paid down. A NEEDSWORK comment that has lived in line-log.c for many years is finally retired; an entire family of diff options (formatting, whitespace, pickaxe, output-indicator, prefix, color-moved, and more) becomes available with -L for the first time; and a real assertion failure involving merges, renames, and pickaxe filters is fixed along the way.

  • Editor’s note: This edition features a retrospective interview with a contributor who contributed to Git through a mentoring program. We hope the reflections shared by the GSoC contributor will provide an insightful perspective that benefits the community. As always, we welcome your thoughts and feedback!

  • Who are you and what do you do?

    I’m Meet, a final-year Computer Engineering student from Ahmedabad, India. I’ve done GSoC twice - first with the Python Software Foundation working on cve-bin-tool, and then with Git working on the git-refs command. I also did an LFX Mentorship with Microcks under CNCF between the two GSoCs. Currently I’m doing an internship at an early-stage stealth startup alongside finishing up my degree.

  • How did you initially become interested in contributing to Git, and what motivated you to choose it as your GSoC project?

    Back in 2021, a friend showed me a video about GSoC, and it seemed completely out of reach at the time. Fast forward to late 2023, the same friend suggested we finally give it a real shot. We both spent about 4 months contributing to open-source projects to build up experience. Both of us got selected for GSoC 2024. I got into the Python Software Foundation. After finishing GSoC with PSF, I loved the experience so much that I wanted to do it again. I decided to try Git for GSoC 2025. I started by sending some small patches to get familiar with the codebase and the mailing list workflow, reviewed patches from other prospective GSoC students, and eventually proposed the git-refs consolidation project.

  • Is there any aspect of Git that you now see differently after having contributed to it?

    Before contributing, I only really knew about Git’s porcelain commands - push, pull, fetch, rebase, checkout, the stuff you use every day. I had no idea how much was happening underneath. Once I started reading the Git Internals chapters from the Pro Git book and diving into the source code, I discovered this whole world of plumbing commands - cat-file, hash-object, update-index, for-each-ref, update-ref, rev-parse, ls-tree, write-tree - there are way more of them than the porcelain commands most people interact with.

    I learned that Git is fundamentally a content-addressable filesystem with a VCS interface built on top. Everything is an object - blobs hold file contents, trees represent directories, commits are snapshots pointing to trees, and refs are just pointers into this object graph. The objects are addressed by their SHA-1 hashes, and everything you do through the familiar commands is just a thin layer operating on this object database. Understanding all of this completely changed how I think about version control. When something goes wrong in Git, I no longer feel lost - I can reason about what’s actually happening at the object level.

  • How do you balance your contributions with other responsibilities like work or school?

    During GSoC, I was mostly focused on Git full-time. My university schedule was flexible enough that I could dedicate most of my working hours to the project. That said, there were stretches where college reviews and submissions piled up at the same time as a patch series needed revisions, and that got a little hectic. I ended up working on weekends sometimes to make up for lost time and stay on track with the project timeline. The trickier part was the mailing list workflow itself - reviews could come at any time given the global nature of the community, so I had to stay responsive even during busy college weeks.

  • Can you share how GSoC helped enhance your technical and non-technical skills (like communication, project management, etc.)?

    On the technical side, working on Git taught me a lot about writing C code that has to be clean enough for others to maintain long after you’re gone. The Git codebase has strict coding standards and the review process enforces them. I got much better at designing modular code, writing meaningful commit messages, and structuring patch series so that each patch tells a clear story.

    On the non-technical side, the mailing list workflow was probably the biggest growth area. All communication is public, asynchronous, and text-based. There’s no hiding behind a quick Slack message - you have to articulate your design decisions clearly in writing. I also learned how to take feedback without taking it personally. Early on, getting a review that asked me to rethink my approach felt discouraging. Over time I realized that the reviewers were investing their time in making my code better, and that changed my perspective entirely.

  • What was your biggest takeaway or learning from GSoC that you now apply regularly in your work?

    Community consensus matters more than being technically correct. In Git, you can write perfectly functional code, but if the community doesn’t agree with the design direction, it won’t get merged. My project depended heavily on consensus around how the git-refs command should behave and what it should consolidate. I spent a fair amount of time not just writing code, but defending design choices and sometimes accepting that a different approach was better [ patch series ]. That taught me to separate my ego from my code. I try to apply that everywhere now - when someone pushes back on something I wrote, my first reaction is to understand why, not to defend.

  • What was the biggest challenge you faced during your contributions to Git, and how did you overcome it?

    The mailing list workflow. Before Git, all of my open-source contributions were made on GitHub through pull requests. Git uses email-based patches, which was a completely different process - formatting patches with git send-email, making sure the threading is correct, handling version updates to a patch series. The first few times I felt like I was fighting the tooling more than the actual code.

    But it got easier. After a few rounds, it started to feel like second nature. The bigger challenge was the review process itself. Git’s mailing list reviews are thorough. Reviewers will question your variable naming, your commit message wording, your design rationale - everything. Having to defend code changes and push features to near-perfection was time consuming, but it made me a much better programmer. I overcame it by just sticking with it and treating every review comment as a learning opportunity rather than criticism.

  • Have you thought about mentoring new GSoC / Outreachy students?

    Yes, I’d love to. After my GSoC 2024 with PSF, a lot of students reached out to me for guidance on open source and GSoC applications. I helped several of them with finding the right organizations, reviewing proposals, and getting started with contributions. Three of them got selected for GSoC 2025, which I’m really proud of.

    For Git specifically, I’d like to mentor in the future, but I want to be in a position where I can give it the time it deserves. Right now I’m occupied with finishing my degree, an internship at a startup, and job hunting, so it wouldn’t be fair to a mentee if I signed up and couldn’t be fully present. But it’s definitely something I want to do - the mentorship I received from Patrick Steinhardt and Jialuo She was really valuable, and I’d like to pay that forward.

  • What upcoming features or changes in Git are you particularly excited about?

    The introduction of Rust into the Git codebase. Git 2.52 was the first release to optionally include Rust code, starting with variable-width integer encoding. Rust will become mandatory for Git 3.0. As someone who’s written C code for Git, I find this really interesting - Rust brings memory safety guarantees that could prevent entire classes of bugs.

  • What is your toolbox for interacting with the mailing list and for development of Git?

    For writing code, I use AstroNvim as my editor. For sending patches, I use git send-email configured with Gmail’s SMTP. For reading and replying to mailing list threads, I just use Gmail’s web interface - it works well enough for following discussions and replying inline. I develop and test on Linux, which I’ve been using as my daily driver since 2020.

  • What is your advice for people who want to start Git development? Where and how should they start?

    Read the Pro Git book first, especially the Git Internals chapters. It gives you a mental model of how Git actually works underneath, which makes reading the source code much less intimidating.

    Then, start small. Subscribe to the mailing list and just read for a week or two. Look at what kind of patches are being sent, how reviews work, how people structure their patch series. The Git project has a document called “MyFirstContribution” in the Documentation folder that walks you through the entire process of submitting your first patch.

    For your first contribution, look for something small - a documentation fix, a test improvement, a minor bug fix. The goal isn’t to make a big impact right away. The goal is to get comfortable with the workflow: formatting patches, sending them via email, responding to reviews. Once you’ve done that once or twice, everything else gets easier.

    And don’t be afraid of the mailing list. It looks intimidating from the outside, but the community is genuinely helpful. Reviewers invest real time into helping newcomers improve their patches. Take that feedback seriously and you’ll grow fast.

  • Would you recommend other students or contributors to participate in the GSoC, Outreachy or other mentoring programs, working on Git? Why? Do you have advice for them?

    Absolutely. GSoC with Git was one of the best experiences I’ve had. The community is welcoming, the mentors are invested in your success, and the codebase is one of the most widely used pieces of software in the world. There’s something special about knowing that the code you wrote is running on millions of machines.

    My advice: start contributing early, well before the application period. Don’t just pick Git because it looks good on a resume - pick it because you’re genuinely curious about how it works. The people reviewing your patches can tell the difference. Also, get comfortable with the mailing list workflow before GSoC starts. It’s the single biggest adjustment for most newcomers, and if you spend your GSoC period still figuring out git send-email, you’ll lose valuable time.

    And finally, be patient with yourself. The Git codebase is large and the standards are high. Your first patches will probably need multiple revisions. That’s normal. Every contributor who came before you went through the same thing.