文章目錄
前言
最近代碼的版本控制工具由SVN
換成了Git
,只用管理個人項目常用的靈魂三步git add
、git commit
、git push
看來是行不通了,之前雖然也一直在用 Git
,但是用法很有限,主要集中在前面提到的三步,所以爲了更好的工作,我決定還是好好總結一下。
分支在Git
的操作裏有着很重要的地位,代表了不同的開發線路,創建一個分支,也就多了一個索引文件,相比於SVN
分支拷貝全部文件來說來方便的多,所以Git
使得按功能分支的開發模式變得非常簡單,在開發過程中常常需要對分支進行操作。
遠程倉庫
本來就幾個分支,操作上也沒有太麻煩,但是加入了遠程倉庫以後,事情變得複雜起來。有了遠程倉庫一般意味着代碼開發需要多人合作了,這時候常常會產生衝突,分支合併時也變得不那麼容易了。
遠程倉庫其實也很好理解,就是放在遠處用來保存代碼資源的一個倉庫,其實和本地的代碼庫沒有什麼區別,這個遠程倉庫主要是爲了把大家修改的代碼都合併到一起,給大家提供一個統一的目標點。
遠程倉庫究竟有多遠,常見的代碼託管平臺:github
、gitlab
、碼雲都可以提供遠程倉庫,如果你在月球上放置一臺可以聯網的代碼倉庫服務器,那麼距離就是38.4萬千米,但是遠程倉庫也可以很近,你也可以把本機電腦的D盤裏的代碼倉庫作爲E盤的代碼倉庫的遠程倉庫,或許遠程倉庫可能只和你隔了一個文件夾。
由於網絡的原因,github
和 gitlab
訪問常常很慢,所以爲了做練習測試推送,我在碼雲創建了一個倉庫 gitstart
,它的地址大概是這個樣子:[email protected]:myname/gitstart.git
,創建的方法一搜一大把,上面提到的幾個託管平臺,在哪創建都可以,一定要記住地址,因爲後面還要用到。
建立聯繫
本地創建文件夾並進入
albert@homepc MINGW64 /d
$ mkdir gitstart
albert@homepc MINGW64 /d
$ cd gitstart/
albert@homepc MINGW64 /d/gitstart
$
這裏的文件夾名字可以和遠程倉庫不同,但是爲了看起來方便對應,還是取相同的名字好一點。
初始化倉庫
albert@homepc MINGW64 /d/gitstart
$ git init
Initialized empty Git repository in D:/gitstart/.git/
albert@homepc MINGW64 /d/gitstart (master)
$
臨時插播好奇心(不在流程中)
目前這個狀態有點意思,初始化完之後,(master)
這個字符串表示當前是在 master
分支,查一下日誌看看:
albert@homepc MINGW64 /d/gitstart (master)
$ git log
fatal: your current branch 'master' does not have any commits yet
albert@homepc MINGW64 /d/gitstart (master)
$
提示也是正確的,說 master
分支沒有任何提交,但是我們查詢一下分支看看:
albert@homepc MINGW64 /d/gitstart (master)
$ git branch -a
albert@homepc MINGW64 /d/gitstart (master)
$
居然是空的,沒有分支,查詢 .git\HEAD
文件發現裏面有一行 ref: refs/heads/master
,說明當前分支時 master
,但是爲什麼查詢分支沒有結果呢?
打開 .git\refs\heads
目錄,發現這個文件夾下根本沒有 master
文件,其實想想也對,Git
中的分支其實對應着 commit id
,現在什麼都沒有提交,master 也就找不到 commit id
,所以就是有 master
文件,裏面也不知道寫什麼。
查詢遠程倉庫
albert@homepc MINGW64 /d/gitstart (master)
$ git remote -v
albert@homepc MINGW64 /d/gitstart (master)
$
依舊什麼內容都沒有,說明還沒有和遠程倉庫建立聯繫。
與遠程倉庫建立對應關係
albert@homepc MINGW64 /d/gitstart (master)
$ git remote add origin [email protected]:myname/gitstart.git
albert@homepc MINGW64 /d/gitstart (master)
$ git remote -v
origin [email protected]:myname/gitstart.git (fetch)
origin [email protected]:myname/gitstart.git (push)
albert@homepc MINGW64 /d/gitstart (master)
$
這一步需要注意,origin看起來就是一個遠程倉庫的別名,代表着 [email protected]:myname/gitstart.git
這個代碼倉庫,剛剛提到過,這個遠程倉庫也可以是本地的,所以你添加git remote add origin d:/test
也是可以的,就表明 gitstart
的遠程倉庫是本地的 test
倉庫。
第一個分支
剛剛說過,現在本地庫的狀態有些特殊,實際上剛剛在碼雲上創建的 [email protected]:myname/gitstart.git
庫也很特殊,他們都沒有真正的分支,這時只要我們成功提交一次,創建一個commit id
,就相當於初始化了master
分支。
添加README文件
albert@homepc MINGW64 /d/gitstart (master)
$ echo "learn git branch command">README.md
albert@homepc MINGW64 /d/gitstart (master)
$ git add README.md
warning: LF will be replaced by CRLF in README.md.
The file will have its original line endings in your working directory
albert@homepc MINGW64 /d/gitstart (master)
$ git commit -m"add readme file"
[master (root-commit) 3226b63] add readme file
1 file changed, 1 insertion(+)
create mode 100644 README.md
查詢當前分支
albert@homepc MINGW64 /d/gitstart (master)
$ git branch -a
* master
這次可以是出現了,分支爲 master
,前面的 *
表示爲當前分支。
將分支推送到遠程倉庫
albert@homepc MINGW64 /d/gitstart (master)
$ git push -u origin master
Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Writing objects: 100% (3/3), 248 bytes | 248.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
remote: Powered by GITEE.COM [GNK-3.8]
To gitee.com:myname/gitstart.git
* [new branch] master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.
至此,本地倉庫和遠程倉庫就建立了聯繫,下面可以開始學習 Git
分支命令了。
分支操作
新建分支
新建分支可以使用 git branch branch_name
命令,以下就是一個創建名爲 release
分支的命令:
albert@homepc MINGW64 /d/gitstart (master)
$ git branch release
也可以使用 git checkout -b branch_name
來創建一個新分支,創建完會自動切換到新分支:
albert@homepc MINGW64 /d/gitstart (master)
$ git checkout -b dev
Switched to a new branch 'dev'
albert@homepc MINGW64 /d/gitstart (dev)
$
切換分支
這是一個很奇怪的命令,命令格式爲 git checkout branch_name
,總感覺 checkout
子命令包攬了不屬於自己的工作,如果在git branch
的基礎上加一個參數會更合理的一點,但這和切換分支的實際含義可能還有關係,切換分支其實就是修改HEAD文件中的 commit id
,而沒有真正的發生切換。
albert@homepc MINGW64 /d/gitstart (dev)
$ git checkout release
Switched to branch 'release'
albert@homepc MINGW64 /d/gitstart (release)
$ git checkout dev
Switched to branch 'dev'
albert@homepc MINGW64 /d/gitstart (dev)
$
查看本地分支
像剛纔我們創建的 release
分支和 dev
分支都是在本地創建的,這樣的分支通過 git branch
命令就可以查看
albert@homepc MINGW64 /d/gitstart (dev)
$ git branch
* dev
master
release
這樣就列舉了本地的所有分支,在當前分支名字 dev
前面哈還有一個 *
作爲標記
查看遠程分支
只要在上面的命令基礎上加上 -r
參數就行了
albert@homepc MINGW64 /d/gitstart (dev)
$ git branch -r
origin/master
查詢到的分支只有 origin/master
一個,這個分支是一開始我們進行第一次提交產生 master
分支之後,通過 git push -u origin master
推送到遠程倉庫的,所以現在只有一個。
查看所有分支
所有分支包括本地分支和遠程分支,將 -r
參數換成 -a
參數就可以了
albert@homepc MINGW64 /d/gitstart (dev)
$ git branch -a
* dev
master
release
remotes/origin/master
將本地分支推送到遠程倉庫
其實之前已經操作過了,可以試着複習一下,git push -u origin branch_name
,其實這是一個簡寫,-u
可以寫成 --set-upstream
表示設置上游分支,其實就是和遠程倉庫的分支建立聯繫。
branch_name
也是 local_branch_name:remote_branch_name
的一種簡寫,冒號前表示本地分支,冒號後面表示遠程分支,如果只寫一個就表示兩個分支名相同,遠程倉庫中如果沒有這個分支就會新建一個。
也就是說 git push -u origin dev
和 git push--set-upstream origin dev:dev
是一樣的,下面來試一下,然後查看一下分支:
albert@homepc MINGW64 /d/gitstart (dev)
$ git push -u origin dev
Total 0 (delta 0), reused 0 (delta 0)
remote: Powered by GITEE.COM [GNK-3.8]
remote: Create a pull request for 'dev' on Gitee by visiting:
remote: https://gitee.com/myname/gitstart/pull/new/myname:dev...myname:master
To gitee.com:myname/gitstart.git
* [new branch] dev -> dev
Branch 'dev' set up to track remote branch 'dev' from 'origin'.
albert@homepc MINGW64 /d/gitstart (dev)
$ git branch -a
* dev
master
release
remotes/origin/dev
remotes/origin/master
冒號前後的米名字是不是一定相同呢?完全沒有必要,我們可以讓本地的 release
分支對應遠程的 master
分支,只不過這樣怪怪的,但是操作上完全可以的。
albert@homepc MINGW64 /d/gitstart (dev)
$ git checkout release
Switched to branch 'release'
albert@homepc MINGW64 /d/gitstart (release)
$ git push -u origin release:master
Everything up-to-date
Branch 'release' set up to track remote branch 'master' from 'origin'.
查看本地分支與遠程分支對應關係
這個也是剛剛知道的,可以使用 git branch -vv
命令,注意是兩個 v
:
albert@homepc MINGW64 /d/gitstart (release)
$ git branch -vv
dev 3226b63 [origin/dev] add readme file
master 3226b63 [origin/master] add readme file
* release 3226b63 [origin/master] add readme file
執行這個命令之後可以看出,本地的 master
和 release
分支都對應着遠程的 master
分支
刪除本地分支
我們先複習一下新建分支,然後把它推送到遠程倉庫,再使用 git branch -d branch_name
命令進行刪除
albert@homepc MINGW64 /d/gitstart (release)
$ git checkout -b feature_test
Switched to a new branch 'feature_test'
albert@homepc MINGW64 /d/gitstart (feature_test)
$ git push origin feature_test
Total 0 (delta 0), reused 0 (delta 0)
remote: Powered by GITEE.COM [GNK-3.8]
remote: Create a pull request for 'feature_test' on Gitee by visiting:
remote: https://gitee.com/myname/gitstart/pull/new/myname:feature_test...myname:master
To gitee.com:myname/gitstart.git
* [new branch] feature_test -> feature_test
albert@homepc MINGW64 /d/gitstart (feature_test)
$ git branch -a
dev
* feature_test
master
release
remotes/origin/dev
remotes/origin/feature_test
remotes/origin/master
開始刪除分支,刪除之前記得切換到別的分支,否則刪除不成功
albert@homepc MINGW64 /d/gitstart (feature_test)
$ git checkout dev
Switched to branch 'dev'
Your branch is up to date with 'origin/dev'.
albert@homepc MINGW64 /d/gitstart (dev)
$ git branch -d feature_test
Deleted branch feature_test (was 3226b63).
albert@homepc MINGW64 /d/gitstart (dev)
$ git branch -a
* dev
master
release
remotes/origin/dev
remotes/origin/feature_test
remotes/origin/master
刪除遠程分支
通過上面的操作我們發現只刪除了本地的分支,遠程的分支還在,要想刪除遠程分支,需要使用 git push origin --delete branch_name
命令
albert@homepc MINGW64 /d/gitstart (dev)
$ git push origin --delete feature_test
remote: Powered by GITEE.COM [GNK-3.8]
To gitee.com:myname/gitstart.git
- [deleted] feature_test
albert@homepc MINGW64 /d/gitstart (dev)
$ git branch -a
* dev
master
release
remotes/origin/dev
remotes/origin/master
這次再查看時發現遠程分支也被刪掉了。
獲取遠程主分支到本地
其實 Git
的克隆命令默認就是把遠程倉庫的主分支下載到本地,我們可以使用 git clone 遠程地址 本地文件夾
命令來克隆一個倉庫,如果本地文件夾省略,則默認新建一個與倉庫名相同的文件夾:
albert@homepc MINGW64 /d
$ git clone https://gitee.com/myname/gitstart.git gitstartcopy
Cloning into 'gitstartcopy'...
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
albert@homepc MINGW64 /d
$ cd gitstartcopy/
albert@homepc MINGW64 /d/gitstartcopy (master)
$ git branch -a
* master
remotes/origin/HEAD -> origin/master
remotes/origin/dev
remotes/origin/master
獲取遠程其他分支到本地
從上面命令執行後的結果來看,當前本地倉庫中只有 master
分支,其他的分支都是在遠程倉庫上,這時可以用 git checkout branch_name
命令來下載遠程分支:
albert@homepc MINGW64 /d/gitstartcopy (master)
$ git checkout dev
Switched to a new branch 'dev'
Branch 'dev' set up to track remote branch 'dev' from 'origin'.
albert@homepc MINGW64 /d/gitstartcopy (dev)
$ git branch -a
* dev
master
remotes/origin/HEAD -> origin/master
remotes/origin/dev
remotes/origin/master
albert@homepc MINGW64 /d/gitstartcopy (dev)
$ git branch -vv
* dev 3226b63 [origin/dev] add readme file
master 3226b63 [origin/master] add readme file
看到這裏可能會疑惑了,git checkout branch_name
不是切換分支的命令嗎?實際上當 branch_name
分支在本地不存在而遠程倉庫存在時,這個命令與 git checkout -b <branch> --track <remote>/<branch>
含義相同,會在本地新建一個分支,並與遠程分支建立聯繫。
常用集合
- 新建分支:
git checkout -b branch_name
- 切換分支:
git checkout branch_name
- 查看分支:
git branch -a
- 刪除分支:
git branch -d branch_name
- 推送分支到遠程:
git push origin branch_name
- 刪除遠程的分支:
git push origin --delete branch_name
- 拉取遠程分支到本地:
git checkout branch_name
- 查詢分支的對應關係:
git branch -vv
總結
- 以上這些命令都是在本地測試過的,可能考慮的不太全面,不過沒關係,以後的分支操作還會補充到這裏。
- 這些命令在有些特殊的情況下使用可能會遇到問題,如果大家發現了問題請及時指出,我會盡快修改的。