[TOC]
## git config
初次運行 Git 前的配置——`git config`
`git config` 工具來幫助設置控制 Git 外觀和行為的配置變量。 這些變量存儲在三個不同的位置:
1. `etc/gitconfig` 文件:包含系統上每一個用戶及他們倉庫的通用配置。 如果使用帶有 --system 選項的 git config 時,它會從此文件讀寫配置變量。
2. `~/.gitconfig` 或 `~/.config/git/config` 文件:只針對當前用戶。 可以傳遞 --global 選項讓 Git 讀寫此文件。
3. `.git/config`文件:當前使用倉庫的 Git 目錄中的 config 文件,針對該倉庫有效。
每一個級別覆蓋上一級別的配置,所以 `.git/config` 的配置變量會覆蓋 `/etc/gitconfig` 中的配置變量。
在 Windows 系統中,Git 會查找 $HOME 目錄下(一般情況下是 C:\Users\$USER)的.gitconfig 文件。 Git 同樣也會尋找 /etc/gitconfig 文件,但只限于 MSys 的根目錄下,即安裝 Git 時所選的目標位置。
### 用戶信息
當安裝完 Git 應該做的第一件事就是設置你的用戶名稱與郵件地址。 這樣做很重要,因為每一個 Git 的提交都會使用這些信息,并且它會寫入到你的每一次提交中,不可更改:
~~~bash
$ git config --global user.name "John Doe"
$ git config --global user.email johndoe@example.com
~~~
>[warning] 如果使用了 --global 選項,那么該命令只需要運行一次,因為之后無論你在該系統上做任何事情, Git 都會使用那些信息。
>當你想針對特定項目使用不同的用戶名稱與郵件地址時,可以在那個項目目錄下運行沒有 --global 選項的命令來配置。
### 文本編輯器
Git 會使用操作系統默認的文本編輯器,通常是 Vim(Linux)。 如果你想使用不同的文本編輯器,例如 Emacs(Mac),可以這樣做:
~~~bash
$ git config --global core.editor emacs
~~~
### 檢查配置信息
使用 `git config --list` 命令來列出所有 Git 當時能找到的配置。
~~~bash
$ git config --list
user.name=John Doe
user.email=johndoe@example.com
color.status=auto
color.branch=auto
color.interactive=auto
color.diff=auto
~~~
可能會看到重復的變量名,因為 Git 會從不同的文件中讀取同一個配置(例如:`/etc/gitconfig` 與 `~/.gitconfig`)。 這種情況下,Git 會使用它找到的每一個變量的最后一個配置。
可以通過輸入 `git config <key>`: 來檢查 Git 的某一項配置
~~~bash
$ git config user.name
John Doe
~~~
## git help
獲取幫助
若你使用 Git 時需要獲取幫助,有三種方法可以找到 Git 命令的使用手冊:
~~~bash
$ git help <verb>
$ git <verb> --help
$ man git-<verb>
~~~
例如,要想獲得 config 命令的手冊,執行
~~~bash
$ git help config
~~~
這些命令很棒,因為你隨時隨地可以使用而無需聯網。 如果你覺得手冊或者本書的內容還不夠用,你可以嘗試在 Freenode IRC 服務器( irc.freenode.net )的 #git 或 #github 頻道尋求幫助。 這些頻道經常有上百人在線,他們都精通 Git 并且樂于助人。
## git init
### 在空目錄中初始化倉庫
進入該目錄并輸入:
~~~bash
$ git init
~~~
該命令將創建一個名為` .git` 的子目錄,這個子目錄含有你初始化的 Git 倉庫中所有的必須文件,這些文件是 Git 倉庫的骨干。但是,在這個時候,我們僅僅是做了一個初始化的操作,你的項目里的文件還沒有被跟蹤。
### 在非空目錄中初始化倉庫
通過 `git add` 命令來實現對指定文件的跟蹤,然后執行 `git commit` 提交:
~~~bash
$ git add *.c
$ git add LICENSE
$ git commit -m 'initial project version'
~~~
就得到了一個實際維護(或者說是跟蹤)著若干個文件的 Git 倉庫。
## git clone
獲得一份已經存在了的 Git 倉庫的拷貝,就要用到 `git clone` 命令。
Git 克隆的是該 Git 倉庫服務器上的幾乎所有數據,而不是僅僅復制完成你的工作所需要文件。
執行 `git clone`命令的時候,默認配置下遠程 Git 倉庫中的每一個文件的每一個版本都將被拉取下來。事實上,如果你的服務器的磁盤壞掉了,你通常可以使用任何一個克隆下來的用戶端來重建服務器上的倉庫(雖然可能會丟失某些服務器端的掛鉤設置,但是所有版本的數據仍在)。
克隆倉庫的命令格式是 `git clone [url]` 。比如,要克隆 Git 的可鏈接庫 `libgit2`,可以用下面的命令:
~~~bash
$ git clone https://github.com/libgit2/libgit2
~~~
這會在當前目錄下創建一個名為 “libgit2” 的目錄,并在這個目錄下初始化一個 .git 文件夾,從遠程倉庫拉取下所有數據放入 .git 文件夾,然后從中讀取最新版本的文件的拷貝。
你進入到這個新建的 libgit2 文件夾,所有的項目文件已經在里面了,準備就緒等待后續的開發和使用。如果你想在克隆遠程倉庫的時候,自定義本地倉庫的名字,你可以使用如下命令:
~~~bash
$ git clone https://github.com/libgit2/libgit2 mylibgit
~~~
這將執行與上一個命令相同的操作,不過在本地創建的倉庫名字變為 `mylibgit`。
Git 支持多種數據傳輸協議。上面的例子使用的是 `https://` 協議,不過你也可以使用` git://` 協議或者使用 `SSH` 傳輸協議,比如 `user@server:path/to/repo.git` 。
## git fetch
從遠程倉庫中抓取與拉取`git fetch [remote-name]`
這個命令會訪問遠程倉庫,從中拉取所有你還沒有的數據。執行完成后,你將會擁有那個遠程倉庫中所有分支的引用,可以隨時合并或查看。
如果你使用 `clone` 命令克隆了一個倉庫,命令會自動將其添加為遠程倉庫并默認以 `origin` 為簡寫。所以,`git fetch origin` 會抓取克隆(或上一次抓取)后新推送的所有工作。
`git fetch` 命令會將數據拉取到你的本地倉庫, 它并不會自動合并或修改你當前的工作。當準備好時你必須手動將其合并入你的工作。
## git push
推送到遠程倉庫:`git push [remote-name] [branch-name]`
當你想分享你的項目時,必須將其推送到上游。當你想要將 master 分支推送到 origin 服務器時(克隆時通常Git會自動設置好那兩個名字),那么運行這個命令就可以將你所做的備份到服務器:
~~~bash
$ git push origin master
~~~
只有當你有所克隆服務器的寫入權限,并且之前沒有人推送過時,這條命令才能生效。當你和其他人在同一時間克隆,他們先推送到上游然后你再推送到上游,你的推送就會毫無疑問地被拒絕。你必須先將他們的工作拉取下來并將其合并進你的工作后才能推送。
## git pull
## git status
## git add
## git commit
### 提交時附帶簡短說明。
~~~bash
$ git commit -m "xx"
~~~
xx:即為要附加在本次提交的簡短說明文字。
### 修改最近一次提交的信息
~~~bash
$ git commit --amend
~~~
執行上述命令后,git會啟動安裝時配置的文本編輯器,最近一次提交的信息會在該編輯器中顯示進行修改。
## git rebase
## git log
用于回顧提交歷史的工具是 `git log` 命令。
默認不用任何參數的話,git log 會按提交時間列出所有的更新,最近的更新排在最上面。正如你所看到的,這個命令會列出每個提交的 SHA-1 校驗和、作者的名字和電子郵件地址、提交時間以及提交說明。
~~~bash
$ git log
commit ca82a6dff817ec66f44342007202690a93763949
Author: Scott Chacon <schacon@gee-mail.com>
Date: Mon Mar 17 21:52:11 2008 -0700
changed the version number
commit 085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7
Author: Scott Chacon <schacon@gee-mail.com>
Date: Sat Mar 15 16:40:33 2008 -0700
removed unnecessary test
commit a11bef06a3f659402fe7563abf99ad00de2209e6
Author: Scott Chacon <schacon@gee-mail.com>
Date: Sat Mar 15 10:31:28 2008 -0700
first commit
~~~
### 顯示提交的內容差異
選項`-p`,用來顯示每次提交的內容差異,可以加上 -2 來僅顯示最近兩次提交:
~~~ bash
$ git log -p -2
~~~
該選項除了顯示基本信息之外,還在附帶了每次 commit 的變化。當進行代碼審查,或者快速瀏覽某個搭檔提交的 commit 所帶來的變化的時候,這個參數就非常有用了。
### 看到每次提交的簡略的統計信息
想看到每次提交的簡略的統計信息,你可以使用 `--stat` 選項:
~~~ bash
$ git log --stat
~~~
`--stat` 選項在每次提交的下面列出所有被修改過的文件、有多少文件被修改了以及被修改過的文件的哪些行被移除或是添加了。在每次提交的最后還有一個總結。
### 指定不同于默認格式的方式展示提交歷史
選項`--pretty`,指定使用不同于默認格式的方式展示提交歷史。這個選項有一些內建的子選項。比如用`oneline` 將每個提交放在一行顯示,查看的提交數很大時非常有用。另外還有 `format`,`short`,`full` 和`fuller` 可以用,展示的信息或多或少有些不同。
~~~ bash
$ git log --pretty=oneline
ca82a6dff817ec66f44342007202690a93763949 changed the version number
085bb3bcb608e1e8451d4b2432f8ecbe6306e7e7 removed unnecessary test
a11bef06a3f659402fe7563abf99ad00de2209e6 first commit
~~~
`format`,可以定制要顯示的記錄格式。這樣的輸出對后期提取分析格外有用?—?因輸出的格式不會隨著Git的更新而發生改變:
~~~ bash
$ git log --pretty=format:"%h - %an, %ar : %s"
ca82a6d - Scott Chacon, 6 years ago : changed the version number
085bb3b - Scott Chacon, 6 years ago : removed unnecessary test
a11bef0 - Scott Chacon, 6 years ago : first commit
~~~
Table 2-1. git log --pretty=format 常用的選項
| 選項 | 說明 |
| --- | --- |
| %H | 提交對象(commit)的完整哈希字串 |
| %h | 提交對象的簡短哈希字串 |
| %T | 樹對象(tree)的完整哈希字串 |
| %t | 樹對象的簡短哈希字串 |
| %P | 父對象(parent)的完整哈希字串 |
| %p | 父對象的簡短哈希字串 |
| %an | 作者(author)的名字 |
| %ae | 作者的電子郵件地址 |
| %ad | 作者修訂日期(可以用 --date= 選項定制格式) |
| %ar | 作者修訂日期,按多久以前的方式顯示 |
| %cn | 提交者(committer)的名字 |
| %ce | 提交者的電子郵件地址 |
| %cd | 提交日期 |
| %cr | 提交日期,按多久以前的方式顯示 |
| %s | 提交說明 |
`作者`指的是實際作出修改的人,`提交者`指的是最后將此工作成果提交到倉庫的人。所以,當你為某個項目發布補丁,然后某個核心成員將你的補丁并入項目時,你就是作者,而那個核心成員就是提交者。
當 `oneline` 或 `format` 與另一個 log 選項 `--graph` 結合使用時尤其有用。這個選項添加了一些ASCII字符串來形象地展示你的分支、合并歷史:
~~~ bash
$ git log --pretty=format:"%h %s" --graph
* 2d3acf9 ignore errors from SIGCHLD on trap
* 5e3ee11 Merge branch 'master' of git://github.com/dustin/grit
|\
| * 420eac9 Added a method for getting the current branch.
* | 30e367c timeout code and tests
* | 5a09431 add timeout protection to grit
* | e1193f8 support for heads with slashes in them
|/
* d6016bc require time for xmlschema
* 11d191e Merge branch 'defunkt' into local
~~~
Table 2-2. git log 的常用選項
| 選項 | 說明 |
| --- | --- |
| `-p` | 按補丁格式顯示每個更新之間的差異。 |
| `--stat` | 顯示每次更新的文件修改統計信息。 |
| `--shortstat` | 只顯示 --stat 中最后的行數修改添加移除統計。 |
| `--name-only` | 僅在提交信息后顯示已修改的文件清單。 |
| `--name-status` | 顯示新增、修改、刪除的文件清單。 |
| `--abbrev-commit` | 僅顯示 SHA-1 的前幾個字符,而非所有的 40 個字符。 |
| `--relative-date` | 使用較短的相對時間顯示(比如,“2 weeks ago”)。 |
| `--graph` | 顯示 ASCII 圖形表示的分支合并歷史。 |
| `--pretty` | 使用其他格式顯示歷史提交信息。可用的選項包括 oneline,short,full,fuller 和 format(后跟指定格式)。 |
## git reflog
在任何時候通過執行 `git reflog` 命令來了解你曾經做過什么:
~~~bash
$ git reflog
1a410ef HEAD@{0}: reset: moving to 1a410ef
ab1afef HEAD@{1}: commit: modified repo.rb a bit
484a592 HEAD@{2}: commit: added repo.rb
~~~
這里可以看到我們已經檢出的兩次提交,然而并沒有足夠多的信息。 為了使顯示的信息更加有用,我們可以執行` git log -g`,這個命令會以標準日志的格式輸出引用日志。
~~~bash
$ git log -g
commit 1a410efbd13591db07496601ebc7a059dd55cfe9
Reflog: HEAD@{0} (Scott Chacon <schacon@gmail.com>)
Reflog message: updating HEAD
Author: Scott Chacon <schacon@gmail.com>
Date: Fri May 22 18:22:37 2009 -0700
third commit
commit ab1afef80fac8e34258ff41fc1b867c702daa24b
Reflog: HEAD@{1} (Scott Chacon <schacon@gmail.com>)
Reflog message: updating HEAD
Author: Scott Chacon <schacon@gmail.com>
Date: Fri May 22 18:15:24 2009 -0700
modified repo.rb a bit
~~~
## git branch
本地分支管理
### 創建
當前分支為master
~~~ bash
$ git checkout -b iss53
Switched to a new branch "iss53"
~~~
### 切換
當前分支為master
~~~ bash
$ git checkout iss53
Switched to branch "iss53"
~~~
>[info] 在切換分支時,一定要注意你工作目錄里的文件會被改變。如果是切換到一個較舊的分支,你的工作目錄會恢復到該分支最后一次提交時的樣子。如果 Git 不能干凈利落地完成這個任務,它將禁止切換分支。
### 合并
當前分支為master
~~~ bash
$ git merge hotfix
Updating f42c576..3a0874c
~~~
### 刪除
當前分支為master
~~~ bash
$ git branch -d iss53
~~~
### 所有分支
當前分支為master,列出本地所有分支
~~~ bash
$ git branch -a
~~~
## git remote
**遠程倉庫**:是指托管在因特網或其他網絡中的你的項目的版本庫。
你可以有好幾個遠程倉庫,通常有些倉庫對你只讀,有些則可以讀寫。與他人協作涉及管理遠程倉庫以及根據需要推送或拉取數據。
管理遠程倉庫包括了解如何添加遠程倉庫、移除無效的遠程倉庫、管理不同的遠程分支并定義它們是否被跟蹤等等。
可以運行 `git remote` 命令。它會列出你指定的每一個遠程服務器的簡寫。如果你已經克隆了自己的倉庫,那么至少應該能看到 origin - 這是 Git 給你克隆的倉庫服務器的默認名字:
~~~ bash
$ git remote
origin
~~~
也可以指定選項 -v,會顯示需要讀寫遠程倉庫使用的 Git 保存的簡寫與其對應的 URL。
~~~ bash
$ git remote -v
origin https://github.com/schacon/ticgit (fetch)
origin https://github.com/schacon/ticgit (push)
~~~
如果你的遠程倉庫不止一個,該命令會將它們全部列出。
### 查看遠程倉庫
* `git remote [-v]`命令。
列出你指定的每一個遠程服務器的簡寫。如果你已經克隆了自己的倉庫,那么至少應該能看到 `origin` 這是 Git 給你克隆的倉庫服務器的默認名字:
~~~bash
$ git clone https://github.com/schacon/ticgit
Cloning into 'ticgit'...
remote: Reusing existing pack: 1857, done.
remote: Total 1857 (delta 0), reused 0 (delta 0)
Receiving objects: 100% (1857/1857), 374.35 KiB | 268.00 KiB/s, done.
Resolving deltas: 100% (772/772), done.
Checking connectivity... done.
~~~
~~~bash
$ cd ticgit
$ git remote
origin
~~~
可以指定選項 -v,會顯示需要讀寫遠程倉庫使用的 Git 保存的簡寫與其對應的 URL。
~~~bash
$ git remote -v
origin https://github.com/schacon/ticgit (fetch)
origin https://github.com/schacon/ticgit (push)
~~~
與幾個協作者合作的,擁有多個遠程倉庫的倉庫看起來像下面這樣:
~~~bash
$ git remote -v
bakkdoor https://github.com/bakkdoor/grit (fetch)
bakkdoor https://github.com/bakkdoor/grit (push)
cho45 https://github.com/cho45/grit (fetch)
cho45 https://github.com/cho45/grit (push)
defunkt https://github.com/defunkt/grit (fetch)
defunkt https://github.com/defunkt/grit (push)
koke git://github.com/koke/grit.git (fetch)
koke git://github.com/koke/grit.git (push)
origin git@github.com:mojombo/grit.git (fetch)
origin git@github.com:mojombo/grit.git (push)
~~~
* `git remote show [remote-name] `
如果想要查看某一個遠程倉庫的更多信息,可以使用該命令。
如果想以一個特定的縮寫名運行這個命令,例如 origin,會得到像下面類似的信息:
~~~bash
$ git remote show origin
* remote origin
Fetch URL: https://github.com/schacon/ticgit
Push URL: https://github.com/schacon/ticgit
HEAD branch: master
Remote branches:
master tracked
dev-branch tracked
Local branch configured for 'git pull':
master merges with remote master
Local ref configured for 'git push':
master pushes to master (up to date)
~~~
它同樣會列出遠程倉庫的 URL 與跟蹤分支的信息。還有:
1. 遠程倉庫的 URL
2. 當前正處于 `master` 分支
3. 跟蹤分支:`master`、`dev-branch`。
4. 如果運行` git pull`,就抓取遠程 master 分支的內容,合并到本地 master 分支。
5. 如果運行` git push`,就向遠程 master 分支推送本地 master 分支的內容。
還可以通過` git remote show` 看到更多的信息。
~~~bash
$ git remote show origin
* remote origin
URL: https://github.com/my-org/complex-project
Fetch URL: https://github.com/my-org/complex-project
Push URL: https://github.com/my-org/complex-project
HEAD branch: master
Remote branches:
master tracked
dev-branch tracked
markdown-strip tracked
issue-43 new (next fetch will store in remotes/origin)
issue-45 new (next fetch will store in remotes/origin)
refs/remotes/origin/issue-11 stale (use 'git remote prune' to remove)
Local branches configured for 'git pull':
dev-branch merges with remote dev-branch
master merges with remote master
Local refs configured for 'git push':
dev-branch pushes to dev-branch (up to date)
markdown-strip pushes to markdown-strip (up to date)
master pushes to master (up to date)
~~~
這個命令列出了當你在特定的分支上執行 `git push` 會自動地推送到哪一個遠程分支。它也同樣地列出了哪些遠程分支不在你的本地,哪些遠程分支已經從服務器上移除了,還有當你執行 `git pull` 時哪些分支會自動合并。
### 添加遠程倉庫
運行 `git remote add <shortname> <url>` 添加一個新的遠程 Git 倉庫,同時指定一個你可以輕松引用的簡寫:
~~~bash
$ git remote add pb https://github.com/paulboone/ticgit
$ git remote -v
origin https://github.com/schacon/ticgit (fetch)
origin https://github.com/schacon/ticgit (push)
pb https://github.com/paulboone/ticgit (fetch)
pb https://github.com/paulboone/ticgit (push)
~~~
接下來,在命令行中使用字符串 pb 來代替整個 URL。例如,如果你想拉取 Paul 的倉庫中有但你沒有的信息,可以運行 `git fetch pb`:
~~~bash
$ git fetch pb
remote: Counting objects: 43, done.
remote: Compressing objects: 100% (36/36), done.
remote: Total 43 (delta 10), reused 31 (delta 5)
Unpacking objects: 100% (43/43), done.
From https://github.com/paulboone/ticgit
* [new branch] master -> pb/master
* [new branch] ticgit -> pb/ticgit
~~~
### 遠程倉庫重命名
`git remote rename <nameNow> <nameChangeTo>`
修改一個遠程倉庫的簡寫名。例如,想要將 pb 重命名為 paul,可以用 git remote rename 這樣做:
~~~bash
$ git remote rename pb paul
~~~
~~~bash
$ git remote
origin
paul
~~~
遠程分支名字也會被修改。那些過去引用 `pb/master` 的現在會引用 `paul/master`。
### 遠程倉庫移除
`git remote rm <nameNow>`
如果因為一些原因想要移除一個遠程倉庫 - 你已經從服務器上搬走了或不再想使用某一個特定的鏡像了,又或者某一個貢獻者不再貢獻了 - 可以使用:
~~~bash
$ git remote rm paul
~~~
~~~bash
$ git remote
origin
~~~
### 指定URL所用協議
set your authentication credential to the git Remote URI:
~~~bash
$ git remote set-url origin https://yourusername@github.com/user/repo.git
~~~
Then you'll be asked for a password when trying to `git push`.
Or, set a password too:
~~~bash
$ git remote set-url origin https://youruser:password@github.com/user/repo.git
~~~
But, github password will be stored in plaintext in your .git directory, which is obviously undesirable.
change your repo config on your PC to ssh way:
1. edit `.git/config` file under your repo directory
2. find `url=entry under section [remote "origin"]`
3. change it from `url=https://MichaelDrogalis@github.com/derekerdmann/lunch_call.git` to `url=ssh://git@github.com/derekerdmann/lunch_call.git`. that is, change all the texts before `@` symbol to `ssh://git`
4. Save config file and quit. now you could use `git push origin master` to sync your repo on GitHub
### 從遠程倉庫中抓取與拉取
`$ git fetch [remote-name]`命令。
git會將數據拉取到你的本地倉庫 - 它并不會自動合并或修改你當前的工作。當準備好時你必須手動將其合并入你的工作。
可以使用` git pull` 命令來自動的抓取(git fetch)然后合并(git merge)遠程分支到當前分支。前提是所在本地分支已經設置了跟蹤一個遠程分支。默認情況下,`git clone` 命令會自動設置本地 master 分支跟蹤克隆的遠程倉庫的 master 分支(或不管是什么名字的默認分支)。運行 `git pull` 都會查找當前分支所跟蹤的服務器與分支,從服務器上抓取數據然后嘗試合并該遠程分支。
### 推送到遠程倉庫
`git push [remote-name] [branch-name]`命令。
當你想要將 master 分支推送到 origin 服務器時(再次說明,克隆時通常會自動幫你設置好那兩個名字),那么運行這個命令就可以將你所做的備份到服務器:
~~~ bash
$ git push origin master
~~~
只有當你有所克隆服務器的寫入權限,并且之前沒有人推送過時,這條命令才能生效。當你和其他人在同一時間克隆,他們先推送到上游然后你再推送到上游,你的推送就會被拒絕。你必須先將他們的工作拉取下來并將其合并進你的工作后才能推送。
### 創建遠程分支
`git push origin [branch-name]`命令
遠程分支就是本地分支push到服務器上。比如master就是一個最典型的遠程分支(默認)。
遠程跟蹤分支是遠程分支狀態的引用。它們是你不能移動的本地引用,當你做任何網絡通信操作時,它們會自動移動。遠程跟蹤分支像是你上次連接到遠程倉庫時,那些分支所處狀態的書簽。
它們以 (remote)/(branch) 形式命名。例如,如果你想要看你最后一次與遠程倉庫` origin` 通信時 `master` 分支的狀態,你可以查看 `origin/master` 分支。你與同事合作解決一個問題并且他們推送了一個 `iss53` 分支,你可能有自己的本地 iss53 分支;但是在服務器上的分支會指向 `origin/iss53` 的提交。
> 遠程倉庫名字 “origin” 與分支名字 “master” 一樣,在 Git 中并沒有任何特別的含義一樣。同時 “master” 是當你運行 git init 時默認的起始分支名字,原因僅僅是它的廣泛使用,“origin” 是當你運行 git clone 時默認的遠程倉庫名字。如果你運行 git clone -o booyah,那么你默認的遠程分支名字將會是 booyah/master。
只要你不與 origin 服務器連接,你的 origin/master 指針就不會移動。如果要同步你的工作,運行 `git fetch origin` 命令。這個命令查找 “origin” 是哪一個服務器(在本例中,它是 git.ourcompany.com),從中抓取本地沒有的數據,并且更新本地數據庫,移動 origin/master 指針指向新的、更新后的位置。
當抓取到新的遠程跟蹤分支時,本地不會自動生成一份可編輯的副本(拷貝)。換一句話說,這種情況下,不會有一個新的 `serverfix` 分支 - 只有一個不可以修改的 `origin/serverfix` 指針。
這時可以運行 `git merge origin/serverfix `將這些工作合并到當前所在的分支。如果想要在自己的 serverfix 分支上工作,可以將其建立在遠程跟蹤分支之上:
~~~ bash
$ git checkout -b serverfix origin/serverfix
Branch serverfix set up to track remote branch serverfix from origin.
Switched to a new branch 'serverfix'
~~~
這會產生一個本地分支`serverfix`,起點位于 `origin/serverfix`。
### 跟蹤分支
`git checkout -b [branch] [remotename]/[branch]`命令
上述的本地分支`serverfix`也被稱為“跟蹤分支”,是與遠程分支有直接關系的本地分支。如果在一個跟蹤分支上輸入 git pull,Git 能自動地識別去哪個服務器上抓取、合并到哪個分支。
當克隆一個倉庫時,它通常會自動地創建一個跟蹤 origin/master 的 master 分支。然而,也可以設置其他的跟蹤分支 - 其他遠程倉庫上的跟蹤分支,或者不跟蹤 master 分支。最簡單的就是之前看到的例子。另外, Git 提供了 --track 快捷方式:
~~~ bash
$ git checkout --track origin/serverfix
Branch serverfix set up to track remote branch serverfix from origin.
Switched to a new branch 'serverfix'
~~~
設置已有的本地分支跟蹤一個剛剛拉取下來的遠程分支,或者想要修改正在跟蹤的上游分支,你可以在任意時間使用 -u 或 --set-upstream-to 選項運行 git branch 來顯式地設置。
~~~ bash
$ git branch -u origin/serverfix
Branch serverfix set up to track remote branch serverfix from origin.
~~~
>當設置好跟蹤分支后,可以通過 @{upstream} 或 @{u} 快捷方式來引用它。所以在 master 分支時并且它正在跟蹤 origin/master ,可以使用 git merge @{u} 來取代 git merge origin/master。
### 查看設置的所有跟蹤分支
`git branch` 的 `-vv` 選項。這會將所有的本地分支列出來并且包含更多的信息,如每一個分支正在跟蹤哪個遠程分支與本地分支是否是領先、落后或是都有。
例如:
~~~ bash
$ git branch -vv
iss53 7e424c3 [origin/iss53: ahead 2] forgot the brackets
master 1ae2a45 [origin/master] deploying index fix
* serverfix f8674d9 [teamone/server-fix-good: ahead 3, behind 1] this should do it
testing 5ea463a trying something new
~~~
上述代碼表示:
* ` iss53` 分支正在跟蹤 `origin/iss53` 并且 “ahead” 是 2,意味著本地有兩個提交還沒有推送到服務器上。
* `master` 分支正在跟蹤 `origin/master` 分支并且是最新的。
* `serverfix` 分支正在跟蹤 `teamone` 服務器上的 `server-fix-good` 分支并且領先 2 落后 1,意味著服務器上有一次提交還沒有合并入同時本地有三次提交還沒有推送。
* `testing` 分支并沒有跟蹤任何遠程分支。
上述數字的值來自于最后一次從每個服務器上抓取的數據。這個命令并沒有連接服務器,它只會告訴你關于本地緩存的服務器數據。如果想要統計最新的領先與落后數字,需要在運行此命令前抓取所有的遠程倉庫。可以像這樣做:
`$ git fetch --all; git branch -vv`
### 刪除遠程分支
運行帶有` --delete` 選項的 `git push` 命令來刪除一個遠程分支。如果想要從服務器上刪除 serverfix 分支,運行下面的命令:
~~~ bash
$ git push origin --delete serverfix
To https://github.com/schacon/simplegit
- [deleted] serverfix
~~~
基本上這個命令做的只是從服務器上移除這個指針。Git 服務器通常會保留數據一段時間直到垃圾回收運行,所以如果不小心刪除掉了,通常是很容易恢復的。
### 刪除本地的遠程跟蹤分支
`$ git remote prune [-n | --dry-run]<name> `命令。
在遠程分支被刪除后,若本地的相應跟蹤分支還存在(用`git branch -avv`命令后,在“remotes/ name”里還有出現),則就用這個prune命令進行刪去。
--dry-run,只是報告并不進行刪除。
~~~ bash
$ git remote prune origin
~~~
## git tag
`git tag` 命令用來為代碼歷史記錄中的某一個點指定一個永久的書簽。 一般來說它用于發布相關事項。
### 列出標簽
~~~ bash
$ git tag
~~~
這個命令以字母順序列出標簽;但是它們出現的順序并不重要。
### 查找標簽
例如,Git 自身的源代碼倉庫包含標簽的數量超過 500 個。如果只對 1.8.5 系列感興趣,可以運行:
~~~ bash
$ git tag -l 'v1.8.5*'
v1.8.5
v1.8.5-rc0
v1.8.5-rc1
v1.8.5-rc2
v1.8.5-rc3
v1.8.5.1
v1.8.5.2
v1.8.5.3
~~~
### 創建標簽
Git 使用兩種主要類型的標簽:
* 輕量標簽(lightweight)
* 附注標簽(annotated)
一個輕量標簽很像一個不會改變的分支 - 它只是一個特定提交的引用。
附注標簽是存儲在 Git 數據庫中的一個完整對象。它們是可以被校驗的;其中包含打標簽者的名字、電子郵件地址、日期時間;還有一個標簽信息;并且可以使用 GNU Privacy Guard (GPG)簽名與驗證。通常建議創建附注標簽,這樣你可以擁有以上所有信息;但是如果你只是想用一個臨時的標簽,或者因為某些原因不想要保存那些信息,輕量標簽也是可用的。
#### 創建輕量標簽
輕量標簽本質上是將提交校驗和存儲到一個文件中 - 沒有保存任何其他信息。給最新的提交創建輕量標簽,不需要使用 -a、-s 或 -m 選項,只需要提供標簽名字:
~~~ bash
$ git tag v1.4-lw
$ git tag
v0.1
v1.3
v1.4
v1.4-lw
v1.5
~~~
這時,如果在標簽上運行`git show`,你不會看到額外的標簽信息。命令只會顯示出提交信息:
~~~ bash
$ git show v1.4-lw
commit ca82a6dff817ec66f44342007202690a93763949
Author: Scott Chacon <schacon@gee-mail.com>
Date: Mon Mar 17 21:52:11 2008 -0700
changed the version number
~~~
#### 創建標注標簽
給最新的提交創建標注標簽,在運行 `tag` 命令時指定 -a 選項:
~~~ bash
$ git tag -a v1.4 -m 'my version 1.4'
$ git tag
v0.1
v1.3
v1.4
~~~
-m 選項指定了一條將會存儲在標簽中的信息。如果沒有為附注標簽指定一條信息,Git 會運行編輯器要求你輸入信息。
通過使用 git show 命令可以看到標簽信息與對應的提交信息:
~~~ bash
$ git show v1.4
tag v1.4
Tagger: Ben Straub <ben@straub.cc>
Date: Sat May 3 20:19:12 2014 -0700
my version 1.4
commit ca82a6dff817ec66f44342007202690a93763949
Author: Scott Chacon <schacon@gee-mail.com>
Date: Mon Mar 17 21:52:11 2008 -0700
changed the version number
~~~
輸出顯示了打標簽者的信息、打標簽的日期時間、附注信息,然后顯示具體的提交信息。
### 刪除標簽
~~~ bash
$ git tag -d XXX 或
$ git tag XXX -d
~~~
### 后期打標簽
你也可以對過去的提交打標簽。假設提交歷史是這樣的:
~~~ bash
$ git log --pretty=oneline
15027957951b64cf874c3557a0f3547bd83b3ff6 Merge branch 'experiment'
a6b4c97498bd301d84096da251c98a07c7723e65 beginning write support
0d52aaab4479697da7686c15f77a3d64d9165190 one more thing
6d52a271eda8725415634dd79daabbc4d9b6008e Merge branch 'experiment'
0b7434d86859cc7b8c3d5e1dddfed66ff742fcbc added a commit function
4682c3261057305bdd616e23b64b0857d832627b added a todo file
166ae0c4d3f420721acbb115cc33848dfcc2121a started write support
9fceb02d0ae598e95dc970b74767f19372d61af8 updated rakefile
964f16d36dfccde844893cac5b347e7b3d44abbc commit the todo
8a5cbc430f1a9c3d00faaeffd07798508422908a updated readme
~~~
現在,假設在 v1.2 時你忘記給項目打標簽,也就是在 “updated rakefile” 提交。你可以在之后補上標簽。要在那個提交上打標簽,你需要在命令的末尾指定提交的校驗和(或部分校驗和):
~~~ bash
$ git tag -a v1.2 9fceb02
~~~
可以看到你已經在那次提交上打上標簽了:
~~~ bash
$ git tag
v0.1
v1.2
v1.3
v1.4
v1.4-lw
v1.5
$ git show v1.2
tag v1.2
Tagger: Scott Chacon <schacon@gee-mail.com>
Date: Mon Feb 9 15:32:16 2009 -0800
version 1.2
commit 9fceb02d0ae598e95dc970b74767f19372d61af8
Author: Magnus Chacon <mchacon@gee-mail.com>
Date: Sun Apr 27 20:43:35 2008 -0700
updated rakefile
...
~~~
### 共享標簽
默認情況下,`git push` 命令并不會傳送標簽到遠程倉庫服務器上。在創建完標簽后你必須顯式地推送標簽到共享服務器上。這個過程就像共享遠程分支一樣 - 你可以運行 `git push origin [tagname]`。
~~~bash
$ git push origin v1.5
Counting objects: 14, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (12/12), done.
Writing objects: 100% (14/14), 2.05 KiB | 0 bytes/s, done.
Total 14 (delta 3), reused 0 (delta 0)
To git@github.com:schacon/simplegit.git
* [new tag] v1.5 -> v1.5
~~~
如果想要一次性推送很多標簽,也可以使用帶有` --tags` 選項的` git push` 命令。這將會把所有不在遠程倉庫服務器上的標簽全部傳送到那里。
~~~ bash
$ git push origin --tags
Counting objects: 1, done.
Writing objects: 100% (1/1), 160 bytes | 0 bytes/s, done.
Total 1 (delta 0), reused 0 (delta 0)
To git@github.com:schacon/simplegit.git
* [new tag] v1.4 -> v1.4
* [new tag] v1.4-lw -> v1.4-lw
~~~
現在,當其他人從倉庫中克隆或拉取,他們也能得到你的那些標簽。
### 檢出標簽
在 Git 中你并不能真的檢出一個標簽,因為它們并不能像分支一樣來回移動。如果你想要工作目錄與倉庫中特定的標簽版本完全一樣,可以使用` git checkout -b [branchname] [tagname] `在特定的標簽上創建一個新分支:
~~~ bash
$ git checkout -b version2 v2.0.0
Switched to a new branch 'version2'
~~~
當然,如果在這之后又進行了一次提交,version2 分支會因為改動向前移動了,那么 version2 分支就會和 v2.0.0 標簽稍微有些不同,這時就應該當心了。
### 為發布打標簽
作為一個維護者,如果你決定要為標簽簽名的話,打標簽的過程應該是這樣子的:
~~~ bash
$ git tag -s v1.5 -m 'my signed 1.5 tag'
You need a passphrase to unlock the secret key for
user: "Scott Chacon <schacon@gmail.com>"
1024-bit DSA key, ID F721C45A, created 2009-02-09
~~~
### 生成一個構建號
Git 中不存在隨每次提交遞增的“v123”之類的數字序列,如果你想要為提交附上一個可讀的名稱,可以對其運行` git describe` 命令。Git 將會給出一個字符串,它由最近的標簽名、自該標簽之后的提交數目和你所描述的提交的部分 SHA-1 值構成:
~~~ bash
$ git describe master
v1.6.2-rc1-20-g8c5b85c
~~~
這樣你在導出一個快照或構建時,可以給出一個便于人們理解的命名。實際上,如果你的 Git 是從 Git 自己的版本庫克隆下來并構建的,那么 git --version 命令給出的結果是與此類似的。如果你所描述的提交自身就有一個標簽,那么它將只會輸出標簽名,沒有后面兩項信息。
注意 `git describe` 命令只適用于有注解的標簽(即使用 -a 或 -s 選項創建的標簽),所以如果你在使用 git describe 命令的話,為了確保能為標簽生成合適的名稱,打發布標簽時都應該采用加注解的方式。你也可以使用這個字符串來調用 checkout 或 show 命令,但是這依賴于其末尾的簡短 SHA-1 值,因此不一定一直有效。比如,最近 Linux 內核為了保證 SHA-1 值對象的唯一性,將其位數由 8 位擴展到了 10 位,導致以前的 git describe 輸出全部失效。
### 準備一次發布
現在你可以發布一個構建了。其中一件事情就是為那些不使用 Git 的可憐包們創建一個最新的快照歸檔。使用 `git archive` 命令完成此工作:
~~~ bash
$ git archive master --prefix='project/' | gzip > `git describe master`.tar.gz
$ ls *.tar.gz
v1.6.2-rc1-20-g8c5b85c.tar.gz
~~~
如果有人將這個壓縮包解壓,他就可以得到你的項目文件夾的最新快照。你也可以以類似的方式創建一個 zip 壓縮包,但此時你應該向 `git archive` 命令傳遞 `--format=zip` 選項:
~~~ bash
$ git archive master --prefix='project/' --format=zip > `git describe master`.zip
~~~
現在你有了本次發布的一個 tar 包和一個 zip 包,可以將其上傳到網站或以電子郵件的形式發送給人們。
### 制作提交簡報
現在是時候通知郵件列表里那些好奇你的項目發生了什么的人了。使用` git shortlog` 命令可以快速生成一份包含從上次發布之后項目新增內容的修改日志(changelog)類文檔。它會對你給定范圍內的所有提交進行總結;比如,你的上一次發布名稱是 v1.0.1,那么下面的命令可以給出上次發布以來所有提交的總結:
~~~ bash
$ git shortlog --no-merges master --not v1.0.1
Chris Wanstrath (8):
Add support for annotated tags to Grit::Tag
Add packed-refs annotated tag support.
Add Grit::Commit#to_patch
Update version and History.txt
Remove stray `puts`
Make ls_tree ignore nils
Tom Preston-Werner (4):
fix dates in history
dynamic version method
Version bump to 1.0.2
Regenerated gemspec for version 1.0.2
~~~
這份整潔的總結包括了自 v1.0.1 以來的所有提交,并且已經按照作者分好組,你可以通過電子郵件將其直接發送到列表中。
- WebAPP
- Linux Command
- 入門
- 處理文件
- 查找文件單詞
- 環境
- 聯網
- Linux
- Linux目錄配置標準:FHS
- Linux文件與目錄管理
- Linux賬號管理與ACL權限設置
- Linux系統資源查看
- 軟件包管理
- Bash
- Daemon/Systemd
- ftp
- Apache
- MySQL
- Command
- Replication
- mysqld
- remote access
- remark
- 限制
- PHP
- String
- Array
- Function
- Class
- File
- JAVA
- Protocals
- http
- mqtt
- IDE
- phpDesigner
- eclipse
- vscode
- Notepad++
- WebAPI
- Javasript
- DOM
- BOM
- Event
- Class
- Module
- Ajax
- Fetch
- Promise
- async/await
- Statements and declarations
- Function
- Framwork
- jQurey
- Types
- Promise
- BootStrap
- v4
- ThinkPHP5
- install
- 定時任務
- CodeIgniter
- React.js
- node.js
- npm
- npm-commands
- npm-folder
- package.json
- Docker and private modules
- module
- webpack.js
- install
- configuration
- package.json
- entry
- modules
- plugins
- Code Splitting
- loaders
- libs
- API
- webpack-cli
- Vue.js
- install
- Compile
- VueAPI
- vuex
- vue-router
- vue-devtools
- vue-cli
- vue-loader
- VDOM
- vue-instance
- components
- template
- Single-File Components
- props
- data
- methods
- computed
- watch
- Event-handling
- Render Func
- remark
- 案例學習
- bootstrap-vue
- modal
- fontAwesome
- Hosting Font Awesome Yourself
- using with jquery
- using with Vue.js
- HTML
- CSS
- plugins
- Chart.js
- D3.js
- phpSpreadSheet
- Guzzle
- Cmder
- Git
- git命令
- git流程
- Postman
- Markdown
- Regular Expressions
- PowerDesigner
- 附錄1-學習資源