Preparing for Git 3.0: What Changes, What Goes, What to Do Today
We separate the official status of Git 3.0 (BreakingChanges.adoc: no date yet) from the plan reported by GitLab and LWN. We try the main, SHA-256 and reftable defaults, safe.bareRepository, mandatory Rust, the commands being removed and why git checkout stays on Git 2.54, and end with a preparation checklist.
Version note: This post is about preparing for Git 3.0; Git 3.0 has not been released yet. The commands were tested with Git 2.54, and the information is current as of 5 November 2026.
Guess First
An old blog post recommends this command to see which files a commit touched. You run it in the bookstore repo on Git 2.54. What happens: do you get a list of commits, a list with a warning, or neither?
$ git whatchanged -1
The answer:
$ git whatchanged -1
'git whatchanged' is nominated for removal.
hint: You can replace 'git whatchanged <opts>' with:
hint: git log <opts> --raw --no-merges
hint: Or make an alias:
hint: git config set --global alias.whatchanged 'log --raw --no-merges'
If you still use this command, here's what you can do:
- read https://git-scm.com/docs/BreakingChanges.html
- check if anyone has discussed this on the mailing
list and if they came up with something that can
help you: https://lore.kernel.org/git/?q=git%20whatchanged
- send an email to <git@vger.kernel.org> to let us
know that you still use this command and were unable
to determine a suitable replacement
fatal: refusing to run without --i-still-use-this
Neither. The command is still inside Git, but it refuses to run unless you say --i-still-use-this. This is how Git prepares for 3.0: first a warning, then making it harder to use, and finally removal. This post is the last link of the series. We look at what will change in Git 3.0, what will be removed, what will stay, and what you can do today.
Official Status and the Reported Plan
Let's draw the line clearly first, because the two get mixed up a lot online.
The official status is this: Git 3.0 has not been released, and there is no tag starting with v3. The Documentation/BreakingChanges.adoc document in Git's own repository lists what will change in 3.0, and it is explicit about the date: "There is no planned release date for this breaking version yet." The document promises one more thing: the last release before 3.0 will be a long-term support (LTS) release, getting bug fixes for at least four release cycles and security fixes for six. The version number changed too: the current release is 2.56, but the "Git 2.98" cycle has started on the master branch, and the draft release notes describe 2.98 as the third-from-last release preparing for 3.0.
The reported plan is this: GitLab's "What's new in Git 2.56.0" post from 28 September 2026 and LWN's article from 18 September 2026 write that 2.98 is planned for December 2026, with 2.99 and 3.0 released together in spring 2027. According to that plan, 2.99 will be the LTS release and its only difference from 3.0 is that the breaking-changes switch is not turned on. LWN also notes that the schedule was discussed at the Git Contributor Summit and that maintainer Junio Hamano had not yet announced it on the mailing list. So these dates are a plan, not an announcement. When you put them in your calendar, write "around".
Every breaking change sits behind a build switch called WITH_BREAKING_CHANGES. If you build Git with that switch you see the 3.0 behaviour today; the project tests that build regularly in CI. In the Git you normally install, the switch is off.
Defaults That Will Change: main, SHA-256, reftable
Three defaults are changing, and we have seen all three earlier in the series. The first is the branch name. On a machine without settings, the hint from git init already says so:
$ git init fresh
hint: Using 'master' as the name for the initial branch. This default branch name
hint: will change to "main" in Git 3.0. To configure the initial branch name
...
That decision was formally declared in 2.52. The second is the object hash for new repos moving from SHA-1 to SHA-256, and the third is the ref store moving from "files" to reftable. The document makes SHA-256 conditional on libraries and hosting platforms being ready, and reftable on JGit, libgit2 and Gitoxide being ready. SHA-1 will not be deprecated; your existing repos keep working as they are. Only the default for newly created repos changes.
You can choose all three explicitly today:
$ git config set --global init.defaultRefFormat reftable
$ git init -q --object-format=sha256 b3
$ cd b3
$ git repo info object.format references.format
object.format=sha256
references.format=reftable
$ git branch --show-current
main
$ git commit -m "Add README"
[main (root-commit) c380a48] Add README
1 file changed, 3 insertions(+)
create mode 100644 README.md
$ git push ../bookstore.git main:sha256-test
fatal: the receiving end does not support this repository's hash algorithm
The last line shows why SHA-256 is still at the "try it locally" stage: you can't push to a SHA-1 remote, and there is no conversion between the two formats. reftable, on the other hand, is safe to try today; the ref format is local and does not concern the remote.
Security: safe.bareRepository
An attacker can put a bare repo inside their repo as plain files. When you clone that repo and cd into that folder, Git discovers the folder you are in as a bare repo and reads its config. If the config defines a command to run, even an ordinary git status can trigger it. In 3.0 the default of safe.bareRepository moves from all to explicit: Git will refuse to work in bare repos it discovers on its own. Let's turn it on today and look at the effect:
$ git config set --global safe.bareRepository explicit
$ cd bookstore.git
$ git log --oneline -1
fatal: cannot use bare repository '.../bookstore.git' (safe.bareRepository is 'explicit')
$ git --git-dir=. log --oneline -1
4734313 Add cart total
$ cd ..
$ git -C bookstore ls-remote ../bookstore.git main
47343131d946a43f3c701a7499a1ffc49e1734a3 refs/heads/main
While moving around inside a bare repo you now have to say it explicitly with --git-dir. Using it as a remote is not affected: push, fetch and ls-remote keep working because they already give the path explicitly. What will be affected are scripts and server maintenance jobs that go into a bare repo folder and run commands there directly.
Rust Becomes Mandatory
Git has so far been written in C and could be built on any platform with a C compiler. Rust came in step by step: 2.49 brought an interface for Rust, 2.52 added the first optional Rust component, and 2.55 turned Rust on by default in both build systems. In 3.0 the option to turn it off goes away, meaning you will need a Rust compiler to build Git.
For you this most likely has no practical meaning; if you install Git from a package manager or the official installer, building it is the packager's business. Old or exotic platforms without Rust support are the ones affected. 2.99 being an LTS release is planned with exactly these platforms in mind. The document also says the Rust requirement may slip past 3.0 if the impact on distributions turns out too large.
What Will Be Removed
whatchanged from the opening is not the only command on the list. git pack-redundant gets the same treatment; since 2023 it has not run without --i-still-use-this. name-rev --stdin has been running with a warning since 2.40:
$ git log --raw --no-merges -1
commit 47343131d946a43f3c701a7499a1ffc49e1734a3
Author: Ada Lovelace <ada@example.com>
Date: Sat Nov 7 10:02:00 2026 +0300
Add cart total
:000000 100644 0000000 aee2863 A src/cart.js
$ git log --format=%H -1 | git name-rev --stdin
warning: --stdin is deprecated. Please use --annotate-stdin instead, which is functionally equivalent.
This option will be removed in a future release.
47343131d946a43f3c701a7499a1ffc49e1734a3 (main)
$ git log --format=%H -1 | git name-rev --annotate-stdin
47343131d946a43f3c701a7499a1ffc49e1734a3 (main)
The replacement for whatchanged is git log --raw --no-merges, and for name-rev --stdin it is --annotate-stdin. What else is on the list? The .git/info/grafts file, used to "patch" history locally, goes; git replace took its place long ago. The .git/branches/ and .git/remotes/ folders, the prehistoric ways of defining remotes, go; today everyone uses the [remote] sections in config. The core.commentChar=auto and core.commentString=auto values deprecated in 2.52, and writing symbolic refs as symlinks (core.preferSymlinkRefs=true), are removed too; reading support stays, writing goes.
What Stays: git checkout Is Not Removed
In the first post of Block B we talked about why switch and restore are safer. That does not mean git checkout is going away:
$ git checkout -q -b try-checkout; git branch --show-current
try-checkout
The BreakingChanges document has a separate section for superseded features that will not be deprecated, and git checkout is in it. The reasoning is simple: it is very widely used, and removing it would break countless scripts, tutorials and habits. The three commands will keep living side by side. If you see a headline saying "Git 3.0 removes checkout", it is wrong.
Preparing Today: A Checklist
One: put init.defaultBranch main in your global config. Nothing changes when 3.0 arrives, and you get rid of the hint today. If your old repos use master, don't rush; the default only affects new repos.
Two: check with a grep whether whatchanged, pack-redundant or name-rev --stdin appear in your scripts and aliases. If some very old automation uses .git/branches or .git/info/grafts, add it to the list too.
Three: turn code that reads ref files directly into Git commands, and migrate a test repo with git refs migrate --ref-format=reftable. See whether your IDE and CI tools can open it.
Four: turn on safe.bareRepository explicit on your own machine. If something breaks, you will have found out before 3.0 arrives.
Five: try SHA-256 only in a local repo; don't choose it for a team repo until you see that your hosting platform and tools support it.
Six: note the Git versions on your CI images and servers. If 2.99 is going to be LTS and you have a platform that can't move to 3.0, you will want to know where it will stay.
Common Pitfalls
The first is taking the reported schedule for a fixed date. Spring 2027 is a plan; the official document still says "no date". Don't lock a project's roadmap to it.
The second is the "SHA-1 is going away" panic. Existing SHA-1 repos will keep working in 3.0; what changes is the default for new repos. Trying to convert all your repos now creates more problems than it solves at this point.
The third is treating --i-still-use-this as a permanent fix. The flag means "give me a bit more time"; with 3.0 the command itself goes away. If you added the flag to a script, leave a note next to it and move to the replacement command.
The fourth is rewriting every script that uses checkout in a panic. There is no need; preferring switch and restore in what you write from now on is enough.
A Small Experiment
★☆☆ Is init.defaultBranch in the output of git config list --show-scope on your machine? If not, add it and watch the git init hint disappear.
★★☆ Find the places in your own dotfiles and project scripts where whatchanged, name-rev --stdin, .git/refs/heads and git config --get appear. How many did you find? Separate the ones that will break in 3.0 from the ones that are only deprecated.
★★★ Migrate a test repo to reftable, turn on safe.bareRepository explicit and do your daily work that way for a week. At the end, note which tools caused trouble.
With this post we have reached the end of the series for now: from the first commit to hooks, from checkout to git history. But Git does not stand still. The series will continue with new Git releases: when 2.98 comes out, when 3.0 arrives and after that, we will add new posts in the same "this is how we used to do it, this is how we do it now" style.