Safely Push a Git Ref to an HTTP DAV Repository
You will finish with a controlled way to send a local Git ref to a repository that accepts Git's HTTP/DAV push protocol. The guide uses the installed Git 2.43.0 from git-man 2.43.0. Allow about fifteen minutes, plus time to confirm that the remote server is configured for DAV writes. You need a local repository with the ref you intend to publish, the remote URL, and credentials accepted by that server.
The route
Jump straight to the step you need, or tick off Done means at the end.
This is a transport-level command, not the usual smart HTTP push performed by git push. It sends missing objects and updates remote refs directly through HTTP/DAV. Make sure the server administrator has explicitly provided a URL for this protocol. Do not guess a URL from a normal clone address.
1. Confirm the installed command
Check the version and syntax first. This is ordinary, read-only work and does not need elevated privileges:
$ git --version
git version 2.43.0
$ git http-push -h
usage: git http-push [--all] [--dry-run] [--force] [--verbose] <remote> [<head>...]
The local manpage is for Git 2.43.0. The official upstream page currently describes the same manual as unchanged through Git 2.55.0, but always check the binary on the machine that will perform the push.
Checkpoint: confirm that the command exists and that you are in the intended repository:
$ command -v git
/usr/bin/git
$ git rev-parse --show-toplevel
/path/to/your/repository
2. Inspect the ref before sending anything
List the local refs and select an exact source name. Replace the example branch with the ref you have reviewed:
$ git show-ref --heads
<commit-id> refs/heads/main
$ git rev-parse --verify refs/heads/main^{commit}
<commit-id>
A ref argument can be a single name, which means the same source and destination name, or a pair in the form source:destination. The source must match exactly one local ref. Use full names when the destination matters:
$ git http-push --dry-run https://dav.example.invalid/project.git \
refs/heads/main:refs/heads/main
The URL above is a placeholder and is not expected to connect. Replace it with the DAV URL supplied by your administrator. The destination should normally begin with refs/ when you are creating a remote ref explicitly.
3. Preview the update
Run the real command with --dry-run first. It performs the work except for actually sending the updates, so it is the safest checkpoint before changing the remote:
$ git http-push --dry-run --verbose \
https://dav.example.invalid/project.git \
refs/heads/main:refs/heads/main
With --verbose, Git reports the objects it walks locally and the objects it would send. Exact diagnostics depend on the server and URL. A failed preview is not a reason to add --force; first check the URL, authentication, DAV configuration, ref spelling and network access.
Checkpoint: record the local commit and compare it with the remote ref using an independent read-only method provided by the server. Do not continue if the destination contains commits that your local history does not include.
4. Push a fast-forward ref
Once the preview and remote review are correct, run the same command without --dry-run:
$ git http-push --verbose \
https://dav.example.invalid/project.git \
refs/heads/main:refs/heads/main
<objects walked and sent by Git>
Without --force, the remote ref is updated only when it does not exist or when its current value is an ancestor of the local source. This fast-forward check protects other people's commits. The command sends missing objects before updating the ref, so a successful operation should leave the remote able to resolve the new commit.
If the command reports a non-fast-forward refusal, stop and inspect both histories. Merge or rebase locally according to your project's policy, then preview again. Do not treat a refusal as a prompt to force the update.
5. Map one local ref to another remote name
Use a source and destination pair when the names differ. This example publishes the local branch release as a remote branch named stable:
$ git http-push --dry-run \
https://dav.example.invalid/project.git \
refs/heads/release:refs/heads/stable
The colon belongs to the refspec. It is not valid inside a ref name. If the destination does not match a remote ref, the explicit destination must start with refs/. A bare release is shorthand for release:release, not a request to rename the branch.
6. Handle force and deletion as change controls
Force pushing disables the fast-forward check for every ref in that invocation:
$ git http-push --dry-run --force \
https://dav.example.invalid/project.git \
refs/heads/main:refs/heads/main
This can make the remote lose commits. Treat it as a destructive, security-sensitive change: obtain approval, save the current remote commit ID, check the destination carefully, and arrange a recovery copy before using --force. A leading plus sign can disable the check for only one ref, for example +refs/heads/main:refs/heads/main. The same review rules apply.
The -d and -D forms remove a remote ref. They cannot remove the remote HEAD, and the manpage imposes additional ancestry and object checks. Do not use deletion as a troubleshooting step:
$ git http-push --dry-run -d \
https://dav.example.invalid/project.git \
refs/heads/old-release
Before a real deletion, record the ref's commit ID and confirm that consumers no longer need it. Recovery requires recreating the ref from a known commit, if the remote still retains the objects:
$ git http-push \
https://dav.example.invalid/project.git \
<known-local-ref>:refs/heads/old-release
7. Diagnose the boundaries
--all tells Git not to assume that the remote is complete. It verifies all objects in the entire history of the local ref, which can take longer than an ordinary update:
$ git http-push --dry-run --all --verbose \
https://dav.example.invalid/project.git \
refs/heads/main:refs/heads/main
Use it when the remote may have been copied incompletely or when an administrator specifically requests a full object check. It does not bypass ref safety checks and it does not repair a broken DAV server.
The command is temporarily disabled when libcurl is older than 7.16 because that combination has been reported to fail and sometimes corrupt repositories. Check the linked library package and system logs if Git refuses to run this transport. Do not work around that protection by forcing unrelated options.
For a normal hosted Git service, prefer the service's documented smart HTTP, SSH or other supported transport. If the server does not advertise or document HTTP/DAV writes, stop and ask for the correct push method. This command cannot turn a read-only HTTP endpoint into a writable Git remote.
Done means
- You confirmed Git 2.43.0 or recorded the version on the actual push host.
- You used a documented HTTP/DAV URL and selected an exact local source ref.
- You ran a verbose dry run and checked the destination history.
- Your normal push omitted
--forceand preserved the fast-forward check. - Any force update or deletion had explicit approval, a recorded commit ID and a recovery path.
- You know whether the server supports this legacy transport rather than assuming a clone URL does.