[BUG] Git push sends too much data unnecessarily
From: Rajiv Sharma <hidden>
Date: 2026-01-14 12:41:23
Thank you for filling out a Git bug report! Please answer the following questions to help us understand your issue. What did you do before the bug happened? (Steps to reproduce your issue) I tried to create a new branch pointing to the commit which was the ancestor of the current branch (i.e. HEAD~1) and pushing it to the remote. Since the commit was already known to the server, I expected the push to be kind of no-op since it's simply creating a new pointer. However the push ended up taking 10+ minutes. Since I was running with the `--verbose` flag, I realised that the push ended up sending multiple GBs worth of data just for creating a new branch on an existing commit already known to the remote. After some experimentation, I managed to find an easy repro for this issue: Clone a non-empty repo from some remote (e.g. git clone https://SERVER_HOSTNAME/repo_name.git) in two locations, `primary` and `secondary` and ensure that both have the same branch checked out. Navigate to the `primary` location and create a local commit for repo `repo_name`. Push this commit C1 to the remote server Navigate to the `secondary` location and try to create a new branch by running `git push origin HEAD:refs/heads/shiny_new_branch --verbose` (or by checking out that branch and pushing it). Note that `HEAD` here refers to the `HEAD` commit as seen by `secondary` which in reality is `HEAD~1` compared to the remote If the repo had some commits on the checked out branch, you will notice the verbose output highlighting objects being sent to the server where there was no need to do so To understand more about exactly how much data is sent, I ran a few more experiments and came to the conclusion that the git client sends HEAD commit + all ancestors of HEAD commit except the commits which are also ancestors of some other branch / ref known to Git. Pictorially, it can be represented as: B1 B2 <-- HEAD * * (sent) | | * * (sent) | | * * (sent) | / | / * (NOT sent) | * (NOT sent) This explains the multi GB push in my case because I was working on a long standing branch with lots of commits. Initially I assumed this was a server problem but then realised that in the push path the server just advertises refs and where they point and it's the client that does the negotiation. I think the bug exists somewhere in the negotiation logic but I am not sure. What did you expect to happen? (Expected behavior) I would have expected the push to be extremely lightweight without sending any objects to the server. What happened instead? (Actual behavior) Already detailed in the first section above. What's different between what you expected and what actually happened? The git client sends loads of data to the server when it shouldn't have had to send anything at all. Anything else you want to add: Note that there are workarounds for this problem. If I do a `git pull` and get the latest state of the repo before performing any push, this problem doesn't occur. Nevertheless, I think it might be worthwhile to fix this. I managed to repro this across OS (Linux, MacOS) and across versions. [System Info] git version: git version 2.47.3 cpu: x86_64 no commit associated with this build sizeof-long: 8 sizeof-size_t: 8 shell-path: /bin/sh libcurl: 7.76.1 OpenSSL: OpenSSL 3.5.1 1 Jul 2025 zlib: 1.2.11 uname: Linux 6.9.0-0_fbk12_0_g28f2d09ad102 #1 SMP Thu Nov 6 08:05:52 PST 2025 x86_64 compiler info: gnuc: 11.5 libc info: glibc: 2.34 $SHELL (typically, interactive shell): /bin/bash [Enabled Hooks]