'does git pull atomically write files

I can't find anything in the documentation. If I do a git pull, am I guaranteed that the underlying file, resulting of the merge, is atomically written?

Some more context about what I am trying to achieve: I have some scripts that periodically do a git pull and I need to know if I can rely on the state of the files being valid during a pull.

We are basically using git as a deployment tool. We never have merge conflicts by design. On the remote end, a job constantly pulls every x seconds, and other jobs read the files. What could happen is that we open a file while it's being pulled by git, and the contents of the file are not what we are expecting. This is unless git is smart enough to use some atomic swap on the underlying OS (RedHat in this case)



Solution 1:[1]

The short answer is no.

It's worth considering that git pull isn't about files at all, it's about commits. Files are just a side effect. :-) The pull operation is just git fetch (obtain commits) followed by a second Git command, usually git merge. The merge step merges commits. This has a side effect of merging files as well, if the operation is not a fast-forward instead of a merge; and then when the merge or fast-forward is complete, Git does a git checkout of the resulting commit.

So this really boils down to: Is git checkout atomic at the OS level? The answer is a very loud no: it's not atomic in any way. Individual files written in the work-tree are written one at a time, using OS-level write calls, which are not atomic. Files that need to be created or deleted are done one at a time. Git does use the index, which indexes (i.e., keeps tabs on) the work-tree, to minimize the number of files removed, created, or rewritten-in-place. Git also locks against other Git operations, and makes the Git-level transaction appear atomic—but anything working outside Git, that does not cooperate with Git's locking system, will be able to see the changes as they occur.

Solution 2:[2]

On the git checkout part of git pull, see torek's answer.

On the git fetch part of git pull, there is an --atomic flag, Git 2.36 (Q2 2022) clarifies it.

"git fetch"(man) can make two separate fetches, but ref updates coming from them were in two separate ref transactions under "--atomic", which has been corrected with Git 2.36 (Q2 2022).

See commit 583bc41, commit b3a8046, commit 4f2ba2d, commit 62091b4, commit 2983cec, commit efbade0, commit 2a0cafd (17 Feb 2022) by Patrick Steinhardt (pks-t).
(Merged by Junio C Hamano -- gitster -- in commit 851d2f0, 13 Mar 2022)

fetch: increase test coverage of fetches

Signed-off-by: Patrick Steinhardt

When using git fetch with the --atomic flag, the expectation is that either all of the references are updated, or alternatively none are in case the fetch fails.

While we already have tests for this, we do not have any tests which exercise atomicity either when pruning deleted refs or when backfilling tags.
This gap in test coverage hides that we indeed don't handle atomicity correctly for both of these cases.

Add test cases which cover these testing gaps to demonstrate the broken behaviour.


Warning:

With Git 2.36 (Q2 2022), revert the "deletion of a ref should not trigger transaction events for loose and packed ref backends separately" that regresses the behaviour when a ref is not modified since it was packed.

See commit 4315986, commit 347cc1b, commit c6da34a (13 Apr 2022) by Junio C Hamano (gitster).
(Merged by Junio C Hamano -- gitster -- in commit 4027e30, 14 Apr 2022)

4027e30c53:Merge branch 'jc/revert-ref-transaction-hook-changes'

Revert "fetch: increase test coverage of fetches"
Revert "Merge branch 'ps/avoid-unnecessary-hook-invocation-with-packed-refs'"

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 torek
Solution 2