Git --force-with-lease with + in branch (refspec)

匿名 (未验证) 提交于 2019-12-03 08:48:34

问题:

On current Git, is there a material difference between git push --force-with-lease origin +somebranch, git push --force-with-lease origin somebranch and git push origin +somebranch (without a plus)? All three seem to do the same thing.

I tried to look for documentation. I tried to look at refspec in documentation, but I don't know if there is a difference and if so, which would one should prefer by default when I like to pull to work branch via git pull --rebase origin master, for instance.

回答1:

This is a good question; the documentation is a bit ambiguous, and the source is very confusing (the actual application of force flags is widely scattered).

One answer is clear enough. Here is what the git push documentation says, with my boldface added:

--[no-]force-with-lease
--force-with-lease=<refname>
--force-with-lease=<refname>:<expect>

all remote refs that are going to be updated by requiring their current value to be the same as the remote-tracking branch we have for them.

the named ref (alone), if it is going to be updated, by requiring its current value to be the same as the remote-tracking branch we have for it.

the named ref (alone), if it is going to be updated, by requiring its current value to be the same as the specified value (which is allowed to be different from the remote-tracking branch we have for the refname, or we do not even have to have such a remote-tracking branch when this form is used).

all the previous --force-with-lease on the command line.

Hence, if the compare-and-swap option1 is supported by the transport, and you have written --force-with-lease and not --no-force-with-lease, then all updates, forced or not, use the lease mode.

The --no-force-with-lease, however, clears out stored-up push_cas_option structure, and it's not immediately obvious to me when those stored-up value are applied to each refspec.

Using an explicit <refname> also clearly protects only the one reference, regardless of any force flag set for it.

Precisely what happens when the underlying transport lacks support for compare-and-swap is also not clear to me. Fortunately GitHub's Git servers support it, making this just a distraction if you're specifically referring to GitHub.


1Internally, the Git source code uses the macro CAS_OPT_NAME: the function of force-with-lease is inspired by modern CPUs' compare-and-swap instructions, which atomically test whether some variable2 is set to a predicted value, replacing it with a new value if so, and also returning, in some form, the actual value found in the variable.

This may set condition codes, if the CPU architecture uses condition codes, but in most if not all cases you get the old value so that you can retry the compare-and-swap if appropriate. For instance, to implement atomic add-one, you can loop with: load r1,(r0); label: add r1,1,r2; cas r1,r2,(r0); bne label; to implement atomic-test-and-set of bit 2: load r1,(r0); label: or r1,4,r2; cas r1,r2,(r0); bne label; and so on. This method is used on Intel Pentium and SPARC systems, for instance.

Some CPUs use the cache machinery instead. If the closest-to-CPU cache has shared vs exclusive modes (e.g., MESI or MOESI) we can use a "load linked" or "load locked" instruction followed by a "store conditional" instruction. The conditional store succeeds only if the cache line is still exclusively owned by the current CPU. In this case, we must re-do the initial locked-load of the variable, and our loops look more like: label: ll r1,(r0); add 1,r1; sc (r0),r1; bne label. This is used on PowerPC and MIPS architectures.

2Typically the variable in question is a memory location, often with alignment constraints, even on CPUs that nominally support unaligned memory. For instance, on the Intel Haswell, a compare-and-swap-8-byte instruction will run to completion on a 4-byte boundary, but it will not actually be atomic. I discovered this the hard way when a colleague's memory allocator provided only 4-byte alignment. :-)



回答2:

which would one should prefer by default when I like to pull to work branch via git pull --rebase origin master?

I reported on force-with-lease in 2013 for git 1.8.5, and March 2016 for git 2.8".

I would say... none of them.
A pull --rebase is done to avoid having to force push (with or without lease) anything.

I simply set (since git 2.6)

git config pull.rebase true git config rebase.autoStash true 

That allows me do do some simple git pull, followed by simple git push (no forced push involved)



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!