1. 程式人生 > >git命令詳解( 七 )

git命令詳解( 七 )

兩條命令 技術 但是 靈活 用法 開發 分享 還記得 們的

此為git命令詳解的第七篇

這章我們可以來逐漸揭開 git push、fetch 和 pull 的神秘面紗了。我們會逐個介紹這幾個命令,它們在理念上是非常相似的。

   git push的參數

  git fetch 的參數

git push:

首先來看 git push。在遠程跟蹤課程中,你已經學到了 Git 是通過當前檢出分支的屬性來確定遠程倉庫以及要 push 的目的地的。這是未指定參數時的行為,我們可以為 push 指定參數,語法是:

git push <remote> <place>

<place> 參數是什麽意思呢?我們稍後會深入其中的細節, 先看看例子, 這個命令是:

git push origin master

把這個命令翻譯過來就是:

切到本地倉庫中的“master”分支,獲取所有的提交,再到遠程倉庫“origin”中找到“master”分支,將遠程倉庫中沒有的提交記錄都添加上去,搞定之後告訴我。

我們通過“place”參數來告訴 Git 提交記錄來自於 master, 要推送到遠程倉庫中的 master。它實際就是要同步的兩個倉庫的位置。

需要註意的是,因為我們通過指定參數告訴了 Git 所有它需要的信息, 所以它就忽略了我們所檢出的分支的屬性!

我們來看看指定參數的例子,註意下我們當前檢出的位置

技術分享圖片

執行命令:git checkout C0

     git push origin master

技術分享圖片

好了! 通過指定參數, 遠程倉庫中的 master 分支得到了更新。

如果不指定參數會發生什麽呢?

技術分享圖片

執行命令:git checkout C0

     git push

技術分享圖片

命令失敗了(正如你看到的,什麽也沒有發生)! 因為我們所檢出的 HEAD 沒有跟蹤任何分支

<place>參數詳解

還記得之前課程說的吧,當為 git push 指定 place 參數為 master 時,我們同時指定了提交記錄的來源和去向。

你可能想問 —— 如果來源和去向分支的名稱不同呢?比如你想把本地的 foo 分支推送到遠程倉庫中的 bar 分支。

哎,很遺憾 Git 做不到…… 開個玩笑,別當真!當然是可以的啦 :) Git 擁有超強的靈活性(有點過於靈活了)

接下來咱們看看是怎麽做的……

要同時為源和目的地指定 <place> 的話,只需要用冒號 : 將二者連起來就可以了:

git push origin <source>:<destination>

這個參數實際的值是個 refspec,“refspec” 是一個自造的詞,意思是 Git 能識別的位置(比如分支 foo 或者 HEAD~1

一旦你指定了獨立的來源和目的地,就可以組織出言簡意賅的遠程操作命令了,讓我們看看演示!

記住,source 可以是任何 Git 能識別的位置:

技術分享圖片

執行命令:git push origin foo^:master

技術分享圖片

這是個另人困惑的命令,但是它確實是可以運行的 —— Git 將 foo^ 解析為一個位置,上傳所有未被包含到遠程倉庫裏 master 分支中的提交記錄。

如果你要推送到的目的分支不存在會怎麽樣呢?沒問題!Git 會在遠程倉庫中根據你提供的名稱幫你創建這個分支!

技術分享圖片

執行命令:git push origin master:newBranch

技術分享圖片

Git fetch 的參數

我們剛學習了 git push 的參數,很酷的 <place> 參數,還有用冒號分隔的 refspecs(<source>:<destination>)。 這些參數可以用於 git fetch 嗎?

你猜中了!git fetch 的參數和 git push 極其相似。他們的概念是相同的,只是方向相反罷了(因為現在你是下載,而非上傳)

讓我們逐個討論下這些概念……

<place> 參數

如果你像如下命令這樣為 git fetch 設置 <place> 的話:

git fetch origin foo

Git 會到遠程倉庫的 foo 分支上,然後獲取所有本地不存在的提交,放到本地的 o/foo 上。

來看個例子(還是前面的例子,只是命令不同了)

技術分享圖片

執行命令:git fetch origin foo

技術分享圖片

你可能會好奇 —— 為何 Git 會將新提交放到 o/foo 而不是放到我本地的 foo 分支呢?之前不是說這樣的 <place> 參數就是同時應用於本地和遠程的位置嗎?

好吧, 本例中 Git 做了一些特殊處理,因為你可能在 foo 分支上的工作還未完成,你也不想弄亂它。還記得在 git fetch 課程裏我們講到的嗎 —— 它不會更新你的本地的非遠程分支, 只是下載提交記錄(這樣, 你就可以對遠程分支進行檢查或者合並了)。

“如果我們指定 <source>:<destination> 會發生什麽呢?”

如果你覺得直接更新本地分支很爽,那你就用冒號分隔的 refspec 吧。不過,你不能在當前檢出的分支上幹這個事,但是其它分支是可以的。

這裏有一點是需要註意的 —— source 現在指的是遠程倉庫中的位置,而 <destination> 才是要放置提交的本地倉庫的位置。它與 git push 剛好相反,這是可以講的通的,因為我們在往相反的方向傳送數據。

理論上雖然行的通,但開發人員很少這麽做。我在這裏介紹它主要是為了從概念上說明 fetchpush 的相似性,只是方向相反罷了。

來看個瘋狂的例子:

技術分享圖片

執行命令:git fetch origin foo:bar

技術分享圖片

哇! 看見了吧, Git 將 foo~1 解析成一個 origin 倉庫的位置,然後將那些提交記錄下載到了本地的 bar 分支(一個本地分支)上。註意由於我們指定了目標分支,fooo/foo 都沒有被更新。

如果執行命令前目標分支不存在會怎樣呢?我們看一下上個對話框中沒有 bar 分支的情況。

技術分享圖片

執行命令:git fetch origin foo:bar

技術分享圖片

看見了吧,跟 git push 一樣,Git 會在 fetch 前自己創建立本地分支, 就像是 Git 在 push 時,如果遠程倉庫中不存在目標分支,會自己在建立一樣。

沒有參數呢?

如果 git fetch 沒有參數,它會下載所有的提交記錄到各個遠程分支……

技術分享圖片

執行:git fetch

技術分享圖片

古怪的 <source>

Git 有兩種關於 <source> 的用法是比較詭異的,即你可以在 git push 或 git fetch 時不指定任何 source,方法就是僅保留冒號和 destination 部分,source 部分留空。

  • git push origin :side
  • git fetch origin :bugFix

我們分別來看一下這兩條命令的作用……

如果 push 空 <source> 到遠程倉庫會如何呢?它會刪除遠程倉庫中的分支! 例子: 技術分享圖片

執行命令:git push origin :foo

技術分享圖片

就是這樣子, 我們通過給 push 傳空值 source,成功刪除了遠程倉庫中的 foo 分支, 這真有意思...(所以我們以後要慎用這個,萬一搞丟了分支還得麻煩)

如果 fetch 空 <source> 到本地,會在本地創建一個新分支。

技術分享圖片

執行命令:git fetch origin :bar

技術分享圖片

很神奇吧!但無論怎麽說, 這就是 Git!

git命令詳解( 七 )