I have been trying to use the relatively new --atomic
option for git push
, but it has not worked for me, i.e., it still lets some refs change even though others failed.
It seems from the diff here that there needs to be something on the remote server that will accept the atomic flag as well. While this makes sense, it seems that the default is to use it.
I am pushing to a BitBucket server instance with http protocol. The current version of Git on the server is "git version 2.8.1".
Is there something that I need to configure on the server to enable this to work?
Edit:
Below is an example which can reproduced.
Configuration on server:
$ git --version
git version 2.8.1
$ git config --get-all --show-origin receive.advertiseatomic
file:/home/bitbucket/.gitconfig 1
On the client:
$ git --version
git version 2.8.2.windows.1
$ git push <local-path>/.git HEAD:refs/heads/wwww HEAD:refs/heads/zzz --force-with-lease=zzz --atomic
error: atomic push failed for ref refs/heads/zzz. status: 7
fatal: The remote end hung up unexpectedly
To <local-path>/.git
! [rejected] HEAD -> wwww (atomic push failed)
! [rejected] HEAD -> zzz (stale info)
error: failed to push some refs to '<local-path>/.git'
$ git push origin HEAD:refs/heads/wwww HEAD:refs/heads/zzz --force-with-lease=zzz --atomic
Total 0 (delta 0), reused 0 (delta 0)
remote:
remote:
To http://[email protected]/scm/proj/repo.git
* [new branch] HEAD -> wwww
! [rejected] HEAD -> zzz (stale info)
error: failed to push some refs to 'http://[email protected]/scm/proj/repo.git'
I'm one of the Bitbucket Server developers. Apologies for such a late response to this question but I only just noticed it.
This appears to be just how Git works. If you re-test your git push --atomic
with GitHub via HTTPS, for example, you'll see identical behavior.
Looking at the Git source code, remote-curl.c
, which provides main
for git-remote-http
and git-remote-https
, does not pass --atomic
when it invokes git send-pack
to send a pack file. (See how the send-pack
command line is constructed here) So when using git push --atomic
with an HTTP(S) remote, the --atomic
is simply ignored and the push runs as normal. That's why you see the branch being created.
Note that this isn't a server-side behavior at all. There's nothing Bitbucket Server, or any other hosting provider, can do in this situation. If you use GIT_TRACE_PACKET=1
to trace what the client and server send to each other, you'll see a conversation like this:
22:16:06.562939 pkt-line.c:46 packet: git< #
service=git-receive-pack
22:16:06.562990 pkt-line.c:46 packet: git< 0000
22:16:06.562994 pkt-line.c:46 packet: git<
1b9c21b7aeb6ad03957cc8a023b2406d3ccee319
refs/heads/branch-1\0report-status delete-refs side-band-64k quiet
atomic ofs-delta agent=git/github-g4f6c801f9475
22:16:06.563013 pkt-line.c:46 packet: git<
1b9c21b7aeb6ad03957cc8a023b2406d3ccee319 refs/heads/branch-2
22:16:06.563016 pkt-line.c:46 packet: git<
1b9c21b7aeb6ad03957cc8a023b2406d3ccee319 refs/heads/branch-3
22:16:06.563019 pkt-line.c:46 packet: git<
fe86a3eae65e18787040499c17a567096159b9ce refs/heads/master
22:16:06.563024 pkt-line.c:46 packet: git< 0000
22:16:06.563329 pkt-line.c:46 packet: git>
HEAD:refs/heads/branch-4
22:16:06.563346 pkt-line.c:46 packet: git> 0000
22:16:06.563357 run-command.c:347 trace: run_command:
'send-pack' '--stateless-rpc' '--helper-status' '--thin' '--progress'
'https://github.com/bturner/atomic-pushes.git/' '--stdin'
22:16:06.563765 exec_cmd.c:129 trace: exec: 'git' 'send-pack'
'--stateless-rpc' '--helper-status' '--thin' '--progress'
'https://github.com/bturner/atomic-pushes.git/' '--stdin'
22:16:06.564691 git.c:348 trace: built-in: git
'send-pack' '--stateless-rpc' '--helper-status' '--thin' '--progress'
'https://github.com/bturner/atomic-pushes.git/' '--stdin'
22:16:06.564788 pkt-line.c:46 packet: git<
HEAD:refs/heads/branch-4
22:16:06.564793 pkt-line.c:46 packet: git< 0000
22:16:06.564797 pkt-line.c:46 packet: git<
1b9c21b7aeb6ad03957cc8a023b2406d3ccee319
refs/heads/branch-1\0report-status delete-refs side-band-64k quiet
atomic ofs-delta agent=git/github-g4f6c801f9475
22:16:06.564805 pkt-line.c:46 packet: git<
1b9c21b7aeb6ad03957cc8a023b2406d3ccee319 refs/heads/branch-2
22:16:06.564826 pkt-line.c:46 packet: git<
1b9c21b7aeb6ad03957cc8a023b2406d3ccee319 refs/heads/branch-3
22:16:06.564830 pkt-line.c:46 packet: git<
fe86a3eae65e18787040499c17a567096159b9ce refs/heads/master
22:16:06.564834 pkt-line.c:46 packet: git< 0000
22:16:06.564970 pkt-line.c:46 packet: git>
0000000000000000000000000000000000000000
6925c65344e87c65e5cd2b56d392cd06ef96ca71 refs/heads/branch-4\0
report-status side-band-64k agent=git/2.4.0
22:16:06.564989 pkt-line.c:46 packet: git> 0000
22:16:06.565027 pkt-line.c:46 packet: git<
00960000000000000000000000000000000000000000
6925c65344e87c65e5cd2b56d392cd06ef96ca71 refs/heads/branch-4\0
report-status side-band-64k agent=git/2.4.00000
In this output, I've run git push --atomic https://github.com/... non-fast-forward:refs/heads/master non-fast-forward:refs/heads/branch-4
. Notice that when git send-pack
is run, there's no --atomic
option set (but git send-pack
does support it being set). That means the atomic handling in send-pack.c
is never triggered.
You can see that in action from the "conversation" that follows. "git<" lines are things the server said to the client, so you can see the ref advertisement is sent. "git>" lines are things the client said to the server. Notice that there's a "git>" line sending "refs/heads/branch-4", but there is no similar line for "refs/heads/master". The client never even tries to send the "master" update to the server at all, because, using the server's ref advertisement, it already knows that update is non-fast-forward and, since --force
wasn't used, that that update is going to fail.
SSH's wire protocol output is even more simple:
22:56:08.609608 pkt-line.c:46 packet: push<
1b9c21b7aeb6ad03957cc8a023b2406d3ccee319
refs/heads/branch-1\0report-status delete-refs side-band-64k quiet
atomic ofs-delta agent=git/github-g4f6c801f9475
22:56:08.609774 pkt-line.c:46 packet: push<
1b9c21b7aeb6ad03957cc8a023b2406d3ccee319 refs/heads/branch-2
22:56:08.609798 pkt-line.c:46 packet: push<
1b9c21b7aeb6ad03957cc8a023b2406d3ccee319 refs/heads/branch-3
22:56:08.609801 pkt-line.c:46 packet: push<
6925c65344e87c65e5cd2b56d392cd06ef96ca71 refs/heads/branch-4
22:56:08.609825 pkt-line.c:46 packet: push<
fe86a3eae65e18787040499c17a567096159b9ce refs/heads/master
22:56:08.609831 pkt-line.c:46 packet: push< 0000
Similar to HTTPS, "push<" lines are what the server said to the client. As you can see, the server sends a ref advertisement, and then the client simply aborts--it never writes a single packet to the server.
So in neither of these cases was the --atomic
handled by the server at all. That's not to say it never can be, but for these simple examples, where the client can detect at least one update is sure to fail, --atomic
is handled (or not handled) entirely locally.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With