github-api-push: When Git Push Becomes a Set of API Calls

A single-file Node script that reads local Git state, uploads tracked files through the GitHub Contents API, and gets through networks that block normal Git transport.

7 min read • View on GitHub • More from slavingia

A locked corporate gate blocks a heavy Git packfile crate on one side while a small courier slips through a side door labeled as the GitHub REST API on the other. It explains the repo's central trick: route file updates through web-friendly API traffic when Git transport is blocked.
The project does not try to make Git faster. It tries to make push possible when the normal path is closed.
Key Takeaways

Most Git tools try to make push faster. This one tries to make push possible. The trick is simple and a little rude: let local Git describe the repo, then move the files through GitHub's web-facing API instead of the transport that corporate proxies and brittle network appliances often break.

Why the Git protocol fails where web APIs still work

That distinction matters because not every network treats traffic the same way. SSH can be blocked outright. HTTPS Git remotes can be inspected, throttled, or interrupted by proxies that dislike long-lived, stateful protocol sessions. Plain REST calls often fit the approved shape of web traffic better, which is why a Contents API request can succeed where a normal push dies.

A split scene shows one giant compressed packfile crate crashing into a locked Git tunnel on the left, while many small file envelopes move one by one through a web-friendly corridor on the right. It visualizes the trade-off between Git's efficient transport and the slower but more accessible API route.
Normal Git is a freight train. github-api-push is a parcel service that can use the roads Git cannot.

Git's memory, API's transport

The clever part is that the script does not reimplement Git. It asks the installed Git client for the current branch, the origin remote, and the tracked file list. That means it inherits the local repo's understanding of what belongs in the push, including ignored files staying ignored. Once it has that map, it can construct a sequence of authenticated requests to GitHub.

The repo's core move is to separate what Git knows from how the bytes move.

const branch = execSync('git rev-parse --abbrev-ref HEAD').toString().trim();
const remote = execSync('git remote get-url origin').toString().trim();
const files = execSync('git ls-files').toString().trim().split('\n');

const fetch = await createFetcher();

for (const file of files) {
  const content = fs.readFileSync(file, 'base64');
  await fetch(`https://api.github.com/repos/${owner}/${repo}/contents/${file}`, {
    method: 'PUT',
    headers: {
      'Authorization': `token ${token}`,
      'User-Agent': 'github-api-push',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      message: `Update ${file}`,
      content,
      branch
    })
  });
}

The real trade-off: efficiency versus reach

A normal push wins on engineering elegance. Git sends compressed deltas and packfiles, which is exactly what you want when the Git transport is available. github-api-push gives that up. It uploads files individually through a web API, which is less efficient but easier to route through locked-down networks.

ApproachHow it moves dataNetwork fitTrade-off
git pushSends packfiles and deltas through the Git protocolBest when Git transport is openFast and faithful
github-api-pushUploads tracked files through GitHub REST callsUseful when web APIs pass but Git is blockedSlower, but reaches places Git cannot
Browser or manual editsEdits files in the GitHub UIUsually works anywhere a browser worksPainful beyond tiny fixes

That is why the tool reads like an emergency kit. It is not a better Git. It is a different route out of a bad network, built for the moment when the normal path is closed and a web request is the only thing that gets through.

Who this is for, and who should ignore it

If you work behind proxy rules that block SSH, break HTTPS Git, or make remote operations unreliable, this is a useful escape hatch. If your network is normal, ignore it. The project is at its most interesting when treated as a reminder that transport choice is part of product design, even in developer tools.