Skip to content

Commit

Permalink
fix: Push git refs atomically
Browse files Browse the repository at this point in the history
Several times I've run into an issue where:

* My main has diverged from upstream main.
* I use `cargo release` to push both main and a tag.

In this situation, the tag push succeeds while the push to main fails.
This isn't desired and in my case breaks automation, which expects
the tag to be an ancestor of main.

Use an atomic push to avoid this issue. The man page says:

```
--[no-]atomic
Use an atomic transaction on the remote side if available. Either all
refs are updated, or on error, no refs are updated. If the server does
not support atomic pushes the push will fail.
```

I was a bit worried about the "push will fail" bit, but
https://github.blog/2015-04-30-git-2-4-atomic-pushes-push-to-deploy-and-more/
says that atomic pushes were added in 2015. I can't imagine anyone
running a 7 year old Git on a server at this point, especially since
there have been multiple security vulns in Git since then.
  • Loading branch information
sunshowers committed Nov 5, 2022
1 parent 867ee3f commit 1acc9fd
Showing 1 changed file with 3 additions and 1 deletion.
4 changes: 3 additions & 1 deletion src/ops/git.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,9 @@ pub fn push<'s>(
options: impl IntoIterator<Item = &'s str>,
dry_run: bool,
) -> CargoResult<bool> {
let mut command = vec!["git", "push"];
// Use an atomic push to ensure that e.g. if main and a tag are pushed together, and the local
// main diverges from the remote main, that the push fails entirely.
let mut command = vec!["git", "push", "--atomic"];

for option in options {
command.push("--push-option");
Expand Down

0 comments on commit 1acc9fd

Please sign in to comment.