<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # 本章內容 讀完本章你就能上手使用 Git 了(注:如果你對Git還不了解,建議從本Git系列****[**Git深入體驗之旅一:Git起步**](http://blog.csdn.net/gtsong/article/details/13997497))。本章將介紹幾個最基本的,也是最常用的 Git 命令,以后絕大多數時間里用到的也就是這幾個命令。讀完本章,你就能初始化一個新的代碼倉庫,做一些適當配置;開始或停止跟蹤某些文件;暫存或提交某些更 新。我們還會展示如何讓 Git 忽略某些文件,或是名稱符合特定模式的文件;如何既快且容易地撤消犯下的小錯誤;如何瀏覽項目的更新歷史,查看某兩次更新之間的差異;以及如何從遠程倉庫 拉數據下來或者推數據上去。 # 2.1?取得項目的 Git 倉庫 有兩種取得 Git 項目倉庫的方法。第一種是在現存的目錄下,通過導入所有文件來創建新的 Git 倉庫。第二種是從已有的 Git 倉庫克隆出一個新的鏡像倉庫來。 ### 在工作目錄中初始化新倉庫 要對現有的某個項目開始用 Git 管理,只需到此項目所在的目錄,執行: ~~~ $ git init ~~~ 初始化后,在當前目錄下會出現一個名為 .git 的目錄,所有 Git 需要的數據和資源都存放在這個目錄中。不過目前,僅僅是按照既有的結構框架初始化好了里邊所有的文件和目錄,但我們還沒有開始跟蹤管理項目中的任何一個文件。(在第九章我們會詳細說明剛才創建的`.git`?目錄中究竟有哪些文件,以及都起些什么作用。) 如果當前目錄下有幾個文件想要納入版本控制,需要先用 git add 命令告訴 Git 開始對這些文件進行跟蹤,然后提交: ~~~ $ git add *.c $ git add README $ git commit -m 'initial project version' ~~~ 稍后我們再逐一解釋每條命令的意思。不過現在,你已經得到了一個實際維護著若干文件的 Git 倉庫。 ### 從現有倉庫克隆 如果想對某個開源項目出一份力,可以先把該項目的 Git 倉庫復制一份出來,這就需要用到 git clone 命令。如果你熟悉其他的 VCS 比如 Subversion,你可能已經注意到這里使用的是 clone 而不是 checkout。這是個非常重要的差別,Git 收取的是項目歷史的所有數據(每一個文件的每一個版本),服務器上有的數據克隆之后本地也都有了。實際上,即便服務器的磁盤發生故障,用任何一個克隆出來 的客戶端都可以重建服務器上的倉庫,回到當初克隆時的狀態(雖然可能會丟失某些服務器端的掛鉤設置,但所有版本的數據仍舊還在,有關細節請參考第四章)。github 克隆倉庫的命令格式為?`git clone [url]`。比如,要克隆 Ruby 語言的 Git 代碼倉庫 Grit,可以用下面的命令: ~~~ $ git clone git://github.com/schacon/grit.git ~~~ 這會在當前目錄下創建一個名為“grit”的目錄,其中包含一個?`.git`?的目錄,用于保存下載下來的所有版本記錄,然后從中取出最新版本的文件拷貝。如果進入這個新建的`grit`?目錄,你會看到項目中的所有文件已經在里邊了,準備好后續的開發和使用。如果希望在克隆的時候,自己定義要新建的項目目錄名稱,可以在上面的命令末尾指定新的名字: ~~~ $ git clone git://github.com/schacon/grit.git mygrit ~~~ 唯一的差別就是,現在新建的目錄成了 mygrit,其他的都和上邊的一樣。 Git 支持許多數據傳輸協議。之前的例子使用的是?`git://`?協議,不過你也可以用?`http(s)://`?或者`user@server:/path.git`表示的 SSH 傳輸協議。我們會在第四章詳細介紹所有這些協議在服務器端該如何配置使用,以及各種方式之間的利弊。 # 2.2?記錄每次更新到倉庫 現在我們手上已經有了一個真實項目的 Git 倉庫,并從這個倉庫中取出了所有文件的工作拷貝。接下來,對這些文件作些修改,在完成了一個階段的目標之后,提交本次更新到倉庫。 請記住,工作目錄下面的所有文件都不外乎這兩種狀態:已跟蹤或未跟蹤。已跟蹤的文件是指本來就被納入版本控制管理的文件,在上次快照中有它們的記 錄,工作一段時間后,它們的狀態可能是未更新,已修改或者已放入暫存區。而所有其他文件都屬于未跟蹤文件。它們既沒有上次更新時的快照,也不在當前的暫存 區域。初次克隆某個倉庫時,工作目錄中的所有文件都屬于已跟蹤文件,且狀態為未修改。 在編輯過某些文件之后,Git 將這些文件標為已修改。我們逐步把這些修改過的文件放到暫存區域,直到最后一次性提交所有這些暫存起來的文件,如此重復。所以使用 Git 時的文件狀態變化周期如圖 2-1 所示。 ![](https://box.kancloud.cn/2016-08-30_57c51ae15d45f.jpg) 圖 2-1. 文件的狀態變化周期 ### 檢查當前文件狀態 要確定哪些文件當前處于什么狀態,可以用 git status 命令。如果在克隆倉庫之后立即執行此命令,會看到類似這樣的輸出: ~~~ $ git status # On branch master nothing to commit (working directory clean) ~~~ 這說明你現在的工作目錄相當干凈。換句話說,當前沒有任何跟蹤著的文件,也沒有任何文件在上次提交后更改過。此外,上面的信息還表明,當前目錄下沒 有出現任何處于未跟蹤的新文件,否則 Git 會在這里列出來。最后,該命令還顯示了當前所在的分支是 master,這是默認的分支名稱,實際是可以修改的,現在先不用考慮。下一章我們就會詳細討論分支和引用。 現在讓我們用 vim 編輯一個新文件 README,保存退出后運行?`git status`?會看到該文件出現在未跟蹤文件列表中: ~~~ $ vim README $ git status # On branch master # Untracked files: # (use "git add ..." to include inwhat will be committed) # # README nothing added to commit but untracked files present (use "git add" to track) ~~~ 就是在“Untracked files”這行下面。Git 不會自動將之納入跟蹤范圍,除非你明明白白地告訴它“我需要跟蹤該文件”,因而不用擔心把臨時文件什么的也歸入版本管理。不過現在的例子中,我們確實想要跟蹤管理 README 這個文件。 ### 跟蹤新文件 使用命令?`git add`?開始跟蹤一個新文件。所以,要跟蹤 README 文件,運行: ~~~ $ git add README ~~~ 此時再運行?`git status`?命令,會看到 README 文件已被跟蹤,并處于暫存狀態: ~~~ $ git status # On branch master # Changes to be committed: # (use "git reset HEAD ..." to unstage) # # new file: README # ~~~ 只要在 “Changes to be committed” 這行下面的,就說明是已暫存狀態。如果此時提交,那么該文件此時此刻的版本將被留存在歷史記錄中。你可能會想起之前我們使用`git init`?后就運行了?`git add`?命令,開始跟蹤當前目錄下的文件。在?`git add`?后面可以指明要跟蹤的文件或目錄路徑。如果是目錄的話,就說明要遞歸跟蹤該目錄下的所有文件。(譯注:其實`git add`?的潛臺詞就是把目標文件快照放入暫存區域,也就是 add file into staged area,同時未曾跟蹤過的文件標記為需要跟蹤。這樣就好理解后續 add 操作的實際意義了。) ### 暫存已修改文件 現在我們修改下之前已跟蹤過的文件?`benchmarks.rb`,然后再次運行?`status`?命令,會看到這樣的狀態報告: ~~~ $ git status # On branch master # Changes to be committed: # (use "git reset HEAD ..." to unstage) # # new file: README # # Changed but not updated: # (use "git add ..." to update what will be committed) # # modified: benchmarks.rb # ~~~ 文件 benchmarks.rb 出現在 “Changed but not updated” 這行下面,說明已跟蹤文件的內容發生了變化,但還沒有放到暫存區。要暫存這次更新,需要運行`git add`?命令(這是個多功能命令,根據目標文件的狀態不同,此命令的效果也不同:可以用它開始跟蹤新文件,或者把已跟蹤的文件放到暫存區,還能用于合并時把有沖突的文件標記為已解決狀態等)。現在讓我們運行`git add`?將 benchmarks.rb 放到暫存區,然后再看看?`git status`?的輸出: ~~~ $ git add benchmarks.rb $ git status # On branch master # Changes to be committed: # (use "git reset HEAD ..." to unstage) # # new file: README # modified: benchmarks.rb # ~~~ 現在兩個文件都已暫存,下次提交時就會一并記錄到倉庫。假設此時,你想要在 benchmarks.rb 里再加條注釋,重新編輯存盤后,準備好提交。不過且慢,再運行`git status`?看看: ~~~ $ vim benchmarks.rb $ git status # On branch master # Changes to be committed: # (use "git reset HEAD ..." to unstage) # # new file: README # modified: benchmarks.rb # # Changed but not updated: # (use "git add ..." to update what will be committed) # # modified: benchmarks.rb # ~~~ 怎么回事?benchmarks.rb 文件出現了兩次!一次算未暫存,一次算已暫存,這怎么可能呢?好吧,實際上 Git 只不過暫存了你運行 git add 命令時的版本,如果現在提交,那么提交的是添加注釋前的版本,而非當前工作目錄中的版本。所以,運行了`git add`?之后又作了修訂的文件,需要重新運行?`git add`?把最新版本重新暫存起來: ~~~ $ git add benchmarks.rb $ git status # On branch master # Changes to be committed: # (use "git reset HEAD ..." to unstage) # # new file: README # modified: benchmarks.rb # ~~~ ### 忽略某些文件 一般我們總會有些文件無需納入 Git 的管理,也不希望它們總出現在未跟蹤文件列表。通常都是些自動生成的文件,比如日志文件,或者編譯過程中創建的臨時文件等。我們可以創建一個名為 .gitignore 的文件,列出要忽略的文件模式。來看一個實際的例子: ~~~ $cat.gitignore *.[oa] *~ ~~~ 第一行告訴 Git 忽略所有以 .o 或 .a 結尾的文件。一般這類對象文件和存檔文件都是編譯過程中出現的,我們用不著跟蹤它們的版本。第二行告訴 Git 忽略所有以波浪符(`~`)結尾的文件,許多文本編輯軟件(比如 Emacs)都用這樣的文件名保存副本。此外,你可能還需要忽略 log,tmp 或者 pid 目錄,以及自動生成的文檔等等。要養成一開始就設置好 .gitignore 文件的習慣,以免將來誤提交這類無用的文件。 文件 .gitignore 的格式規范如下: ● 所有空行或者以注釋符號 # 開頭的行都會被 Git 忽略。 ●?可以使用標準的 glob 模式匹配。 * 匹配模式最后跟反斜杠(`/`)說明要忽略的是目錄。 * 要忽略指定模式以外的文件或目錄,可以在模式前加上驚嘆號(`!`)取反。 所謂的 glob 模式是指 shell 所使用的簡化了的正則表達式。星號(`*`)匹配零個或多個任意字符;`[abc]`?匹配任何一個列在方括號中的字符(這個例子要么匹配一個 a,要么匹配一個 b,要么匹配一個 c);問號(`?`)只匹配一個任意字符;如果在方括號中使用短劃線分隔兩個字符,表示所有在這兩個字符范圍內的都可以匹配(比如`[0-9]`?表示匹配所有 0 到 9 的數字)。 我們再看一個 .gitignore 文件的例子: ~~~ # 此為注釋 – 將被 Git 忽略 *.a # 忽略所有 .a 結尾的文件 !lib.a # 但 lib.a 除外 /TODO # 僅僅忽略項目根目錄下的 TODO 文件,不包括 subdir/TODO build/ # 忽略 build/ 目錄下的所有文件 doc/*.txt# 會忽略 doc/notes.txt 但不包括 doc/server/arch.txt ~~~ ### 查看已暫存和未暫存的更新 實際上?`git status`?的顯示比較簡單,僅僅是列出了修改過的文件,如果要查看具體修改了什么地方,可以用?`git diff`?命令。稍后我們會詳細介紹`git diff`,不過現在,它已經能回答我們的兩個問題了:當前做的哪些更新還沒有暫存?有哪些更新已經暫存起來準備好了下次提交??`git diff`?會使用文件補丁的格式顯示具體添加和刪除的行。 假如再次修改 README 文件后暫存,然后編輯 benchmarks.rb 文件后先別暫存,運行?`status`?命令,會看到: ~~~ $ git status # On branch master # Changes to be committed: # (use "git reset HEAD ..." to unstage) # # new file: README # # Changed but not updated: # (use "git add ..." to update what will be committed) # # modified: benchmarks.rb # ~~~ 要查看尚未暫存的文件更新了哪些部分,不加參數直接輸入?`git diff`: ~~~ $ git diff diff--git a/benchmarks.rb b/benchmarks.rb index 3cb747f..da65585 100644 --- a/benchmarks.rb +++ b/benchmarks.rb @@ -36,6 +36,10 @@ def main @commit.parents[0].parents[0].parents[0] end + run_code(x, 'commits 1')do + git.commits.size + end + run_code(x,'commits 2')do log = git.commits('master', 15) log.size ~~~ 此命令比較的是工作目錄中當前文件和暫存區域快照之間的差異,也就是修改之后還沒有暫存起來的變化內容。 若要看已經暫存起來的文件和上次提交時的快照之間的差異,可以用?`git diff --cached`?命令。(Git 1.6.1 及更高版本還允許使用`git diff --staged`,效果是相同的,但更好記些。)來看看實際的效果: ~~~ $ git diff--cached diff--git a/READMEb/README newfilemode 100644 index 0000000..03902a1 ---/dev/null +++ b/README2 @@ -0,0 +1,5 @@ +grit + by Tom Preston-Werner, Chris Wanstrath + http://github.com/mojombo/grit + +Grit is a Ruby library forextracting information from a Git repository ~~~ 請注意,單單?`git diff`?不過是顯示還沒有暫存起來的改動,而不是這次工作和上次提交之間的差異。所以有時候你一下子暫存了所有更新過的文件后,運行`git diff`?后卻什么也沒有,就是這個原因。 像之前說的,暫存 benchmarks.rb 后再編輯,運行?`git status`?會看到暫存前后的兩個版本: ~~~ $ git add benchmarks.rb $echo'# test line' >> benchmarks.rb $ git status # On branch master # # Changes to be committed: # # modified: benchmarks.rb # # Changed but not updated: # # modified: benchmarks.rb # ~~~ 現在運行?`git diff`?看暫存前后的變化: ~~~ $ git diff diff--git a/benchmarks.rb b/benchmarks.rb index e445e28..86b2f7c 100644 --- a/benchmarks.rb +++ b/benchmarks.rb @@ -127,3 +127,4 @@ end main() ##pp Grit::GitRuby.cache_client.stats +# test line ~~~ 然后用?`git diff --cached`?查看已經暫存起來的變化: ~~~ $ git diff--cached diff--git a/benchmarks.rb b/benchmarks.rb index 3cb747f..e445e28 100644 --- a/benchmarks.rb +++ b/benchmarks.rb @@ -36,6 +36,10 @@ def main @commit.parents[0].parents[0].parents[0] end + run_code(x, 'commits 1')do + git.commits.size + end + run_code(x,'commits 2')do log = git.commits('master', 15) log.size ~~~ ### 提交更新 現在的暫存區域已經準備妥當可以提交了。在此之前,請一定要確認還有什么修改過的或新建的文件還沒有?`git add`?過,否則提交的時候不會記錄這些還沒暫存起來的變化。所以,每次準備提交前,先用`git status`?看下,是不是都已暫存起來了,然后再運行提交命令?`git commit`: ~~~ $ git commit ~~~ 這種方式會啟動文本編輯器以便輸入本次提交的說明。(默認會啟用 shell 的環境變量?`$EDITOR`?所指定的軟件,一般都是 vim 或 emacs。當然也可以按照第一章介紹的方式,使用`git config --global core.editor`?命令設定你喜歡的編輯軟件。) 編輯器會顯示類似下面的文本信息(本例選用 Vim 的屏顯方式展示): ~~~ # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # On branch master # Changes to be committed: # (use "git reset HEAD ..." to unstage) # # new file: README # modified: benchmarks.rb ~ ~ ~ ".git/COMMIT_EDITMSG"10L, 283C ~~~ 可以看到,默認的提交消息包含最后一次運行?`git status`?的輸出,放在注釋行里,另外開頭還有一空行,供你輸入提交說明。你完全可以去掉這些注釋行,不過留著也沒關系,多少能幫你回想起這次更新的內容有哪些。(如果覺得這還不夠,可以用`-v`?選項將修改差異的每一行都包含到注釋中來。)退出編輯器時,Git 會丟掉注釋行,將說明內容和本次更新提交到倉庫。 另外也可以用 -m 參數后跟提交說明的方式,在一行命令中提交更新: ~~~ $ git commit -m "Story 182: Fix benchmarks for speed" [master]: created 463dc4f: "Fix benchmarks for speed" 2 files changed, 3 insertions(+), 0 deletions(-) create mode 100644 README ~~~ 好,現在你已經創建了第一個提交!可以看到,提交后它會告訴你,當前是在哪個分支(master)提交的,本次提交的完整 SHA-1 校驗和是什么(`463dc4f`),以及在本次提交中,有多少文件修訂過,多少行添改和刪改過。 記住,提交時記錄的是放在暫存區域的快照,任何還未暫存的仍然保持已修改狀態,可以在下次提交時納入版本管理。每一次運行提交操作,都是對你項目作一次快照,以后可以回到這個狀態,或者進行比較。 ### 跳過使用暫存區域 盡管使用暫存區域的方式可以精心準備要提交的細節,但有時候這么做略顯繁瑣。Git 提供了一個跳過使用暫存區域的方式,只要在提交的時候,給?`git commit`?加上`-a`?選項,Git 就會自動把所有已經跟蹤過的文件暫存起來一并提交,從而跳過?`git add`?步驟: ~~~ $ git status # On branch master # # Changed but not updated: # # modified: benchmarks.rb # $ git commit -a -m 'added new benchmarks' [master 83e38c7] added new benchmarks 1 files changed, 5 insertions(+), 0 deletions(-) ~~~ 看到了嗎?提交之前不再需要?`git add`?文件 benchmarks.rb 了。 ### 移除文件 要從 Git 中移除某個文件,就必須要從已跟蹤文件清單中移除(確切地說,是從暫存區域移除),然后提交。可以用?`git rm`?命令完成此項工作,并連帶從工作目錄中刪除指定的文件,這樣以后就不會出現在未跟蹤文件清單中了。 如果只是簡單地從工作目錄中手工刪除文件,運行?`git status`?時就會在 “Changed but not updated” 部分(也就是_未暫存_清單)看到: ~~~ $rmgrit.gemspec $ git status # On branch master # # Changed but not updated: # (use "git add/rm ..." to update what will be committed) # # deleted: grit.gemspec # ~~~ 然后再運行?`git rm`?記錄此次移除文件的操作: ~~~ $ git rmgrit.gemspec rm'grit.gemspec' $ git status # On branch master # # Changes to be committed: # (use "git reset HEAD ..." to unstage) # # deleted: grit.gemspec # ~~~ 最后提交的時候,該文件就不再納入版本管理了。如果刪除之前修改過并且已經放到暫存區域的話,則必須要用強制刪除選項?`-f`(譯注:即 force 的首字母),以防誤刪除文件后丟失修改的內容。 另外一種情況是,我們想把文件從 Git 倉庫中刪除(亦即從暫存區域移除),但仍然希望保留在當前工作目錄中。換句話說,僅是從跟蹤清單中刪除。比如一些大型日志文件或者一堆`.a`?編譯文件,不小心納入倉庫后,要移除跟蹤但不刪除文件,以便稍后在?`.gitignore`?文件中補上,用?`--cached`?選項即可: ~~~ $ git rm--cached readme.txt ~~~ 后面可以列出文件或者目錄的名字,也可以使用 glob 模式。比方說: ~~~ $ git rmlog/\*.log ~~~ 注意到星號?`*`?之前的反斜杠?`\`,因為 Git 有它自己的文件模式擴展匹配方式,所以我們不用 shell 來幫忙展開(譯注:實際上不加反斜杠也可以運行,只不過按照 shell 擴展的話,僅僅刪除指定目錄下的文件而不會遞歸匹配。上面的例子本來就指定了目錄,所以效果等同,但下面的例子就會用遞歸方式匹配,所以必須加反斜 杠。)。此命令刪除所有`log/`?目錄下擴展名為?`.log`?的文件。類似的比如: ~~~ $ git rm\*~ ~~~ 會遞歸刪除當前目錄及其子目錄中所有?`~`?結尾的文件。 ### 移動文件 不像其他的 VCS 系統,Git 并不跟蹤文件移動操作。如果在 Git 中重命名了某個文件,倉庫中存儲的元數據并不會體現出這是一次改名操作。不過 Git 非常聰明,它會推斷出究竟發生了什么,至于具體是如何做到的,我們稍后再談。 既然如此,當你看到 Git 的?`mv`?命令時一定會困惑不已。要在 Git 中對文件改名,可以這么做: ~~~ $ git mvfile_from file_to ~~~ 它會恰如預期般正常工作。實際上,即便此時查看狀態信息,也會明白無誤地看到關于重命名操作的說明: ~~~ $ git mvREADME.txt README $ git status # On branch master # Your branch is ahead of 'origin/master' by 1 commit. # # Changes to be committed: # (use "git reset HEAD ..." to unstage) # # renamed: README.txt -> README # ~~~ 其實,運行?`git mv`?就相當于運行了下面三條命令: ~~~ $mvREADME.txt README $ git rmREADME.txt $ git add README ~~~ 如此分開操作,Git 也會意識到這是一次改名,所以不管何種方式都一樣。當然,直接用?`git mv`?輕便得多,不過有時候用其他工具批處理改名的話,要記得在提交前刪除老的文件名,再添加新的文件名。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看