一、git的push命令
git的commit只是本地修改,不用担心对于远端版本库的影响。当你不需要考虑后果的时候,通常就会比较胆大。对应的,push的修改会在远端生效,所以这个修改就需要小心谨慎一些。最为方便和常用的当然是只推送当前工作分支(branch)的修改,这是比较直观的期望运行效果。但是这个不添加任何参数的git push到底推送的是哪个分支还是需要确认一下的。
从git的man手册中看到对于这一点的描述并不清楚(如果不是看了更加困惑的话),然后网络上的资料看起来也有些莫名其妙。从执行该命令的效果来看,的确是只推送了当前工作分支的内容到远端。但是就像一个语法特性,你在某个编译器下测试通过,并不代表它就是一个标准的语言标准,也有可能只是一个编译器的语法糖。
二、从代码中看
从代码上看,默认推送(push_default)的初始值为PUSH_DEFAULT_UNSPECIFIED,这个选项对应的动作是操作当前分支(也就是HEAD文件中指定的分支)。这也就是说从代码和行为上看,这个push都是将当前工作分支的内容推送到远端版本库中。为什么网上的资料说明需要通过git config设置push.default呢?
static void read_config(void)
{
static int loaded;
int flag;
if (loaded)
return;
loaded = 1;
current_branch = NULL;
if (startup_info->have_repository) {
const char *head_ref = resolve_ref_unsafe("HEAD", 0, NULL, &flag);
if (head_ref && (flag & REF_ISSYMREF) &&
skip_prefix(head_ref, "refs/heads/", &head_ref)) {
current_branch = make_branch(head_ref, strlen(head_ref));
}
}
git_config(handle_config, NULL);
alias_all_urls();
}
git-master
emote.c
struct branch *branch_get(const char *name)
{
struct branch *ret;
read_config();
if (!name || !*name || !strcmp(name, "HEAD"))
ret = current_branch;
else
ret = make_branch(name, strlen(name));
set_merge(ret);
return ret;
}
git-masterenvironment.c
enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED;
git-masteruiltinpush.c
static void setup_default_push_refspecs(struct remote *remote)
{
struct branch *branch = branch_get(NULL);
int triangular = is_workflow_triangular(remote);
switch (push_default) {
default:
case PUSH_DEFAULT_MATCHING:
refspec_append(&rs, ":");
break;
case PUSH_DEFAULT_UNSPECIFIED:
case PUSH_DEFAULT_SIMPLE:
if (triangular)
setup_push_current(remote, branch);
else
setup_push_upstream(remote, branch, triangular, 1);
break;
……
}
三、git版本更新对该行为的修改
1、最早的版本
通过该网页可以知道,在git的2.0版本之前,默认的配置是“matching”,也就是push的是本地目录中所有的、在远端版本库中有对应名字的分支,也即是不添加新分支、不删除已有分支,只更新分支。如果在没有修改改配置的情况下,默认是这个危险的行为。
matching: push all matching branches
All branches having the same name in both ends are considered to be matching.
This used to be the default, but not since Git 2.0 (simple is the new default).
2、git 2.0的修改
在新的版本中,由于修改了默认的推送行为,所以会对用户一个警告提示,从而让用户有所准备。
The warning has been there since version 1.8.0 (Oct 2012), hence we can expect the vast majority of current Git users to have been exposed to it, and most of them have already set push.default explicitly. The switch from 'matching' to 'simple' was planned for 2.0 (May 2014), but actually happened only for 2.3 (Feb 2015).
3、git 2.3版本
在更新的版本中,使用git的可能都是新生代的用户,它们可能根本不知道之前存在过这种默认的行为,所以这个警告看起来更加的莫名其妙,而之前的老用户差不多也都已经知道了这个“坑”的存在,所以这个消息就从新版本中直接删除了。而这个也就是当前大多数人看到的版本。而我现在使用的git是相当新的2.27版本,所以网上的描述和当前的git行为还是有较大差别的。
四、结论
但是无论如果,结论就是在新的版本(至少是2.0之后的)中,不带任何参数的git push命令就是只推送当前工作分支的内容到远端版本库中。