一、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\remote.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-master\environment.c
enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED;
git-master\builtin\push.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命令就是只推送當前工作分支的內容到遠端版本庫中。