# gittutorial
> 原文: [https://git-scm.com/docs/gittutorial](https://git-scm.com/docs/gittutorial)
## 名稱
gittutorial - Git的教程介紹
## 概要
```
git *
```
## 描述
本教程將介紹如何將新項目導入Git,對其進行更改以及與其他開發人員共享更改。
如果您主要對使用Git獲取項目感興趣,例如,測試最新版本,您可能更喜歡從 [Git用戶手冊](user-manual.html)的前兩章開始。
首先,請注意您可以獲取`git log --graph`等命令的文檔:
```
$ man git-log
```
要么:
```
$ git help log
```
使用后者,您可以使用您選擇的手動查看器;有關詳細信息,請參閱 [git-help [1]](https://git-scm.com/docs/git-help) 。
在進行任何操作之前,最好使用您的姓名和公共電子郵件地址向Git介紹自己。最簡單的方法是:
```
$ git config --global user.name "Your Name Comes Here"
$ git config --global user.email you@yourdomain.example.com
```
## 導入新項目
假設您有初始工作的tarball project.tar.gz。您可以將它放在Git版本控制下,如下所示。
```
$ tar xzf project.tar.gz
$ cd project
$ git init
```
Git會回復
```
Initialized empty Git repository in .git/
```
您現在已經初始化了工作目錄 - 您可能會注意到創建了一個名為“.git”的新目錄。
接下來,告訴Git使用 _git add_ 拍攝當前目錄下所有文件內容的快照(注意_。_):
```
$ git add .
```
此快照現在存儲在Git稱為“索引”的臨時暫存區域中。您可以使用 _git commit_ 將索引的內容永久存儲在存儲庫中:
```
$ git commit
```
這將提示您提交提交消息。您現在已經在Git中存儲了項目的第一個版本。
## 做出改變
修改一些文件,然后將更新的內容添加到索引:
```
$ git add file1 file2 file3
```
你現在準備好了。您可以使用帶有--cached選項的 _git diff_ 查看即將提交的內容:
```
$ git diff --cached
```
(沒有--cached, _git diff_ 會顯示你已經做過但尚未添加到索引中的任何更改。)您還可以通過 _git status [ _git status獲得有關情況的簡短摘要_:_
```
$ git status
On branch master
Changes to be committed:
Your branch is up to date with 'origin/master'.
(use "git reset HEAD <file>..." to unstage)
modified: file1
modified: file2
modified: file3
```
如果您需要進行任何進一步調整,請立即執行此操作,然后將任何新修改的內容添加到索引中。最后,提交您的更改:
```
$ git commit
```
這將再次提示您輸入描述更改的消息,然后記錄項目的新版本。
或者,您可以使用,而不是預先運行 _git add_
```
$ git commit -a
```
它會自動注意任何修改過的(但不是新的)文件,將它們添加到索引中,然后一步一步地提交。
關于提交消息的注意事項:雖然不是必需的,但最好以一個簡短(小于50個字符)的行來概括更改開始提交消息,然后是空白行,然后是更全面的描述。提交消息中第一個空白行的文本被視為提交標題,并且該標題在整個Git中使用。例如, [git-format-patch [1]](https://git-scm.com/docs/git-format-patch) 將提交轉換為電子郵件,它使用主題行上的標題和正文中的其余提交。
## Git跟蹤內容而不是文件
許多修訂控制系統提供`add`命令,告訴系統開始跟蹤對新文件的更改。 Git的`add`命令執行更簡單和更強大的功能: _git add_ 用于新修改的文??件和新修改的文??件,在這兩種情況下,它都會獲取給定文件的快照,并在索引中顯示內容,準備好包含在下一次提交中。
## 查看項目歷史記錄
您可以隨時查看更改的歷史記錄
```
$ git log
```
如果您還希望在每個步驟中看到完整的差異,請使用
```
$ git log -p
```
通常,變更概述對于了解每個步驟非常有用
```
$ git log --stat --summary
```
## 管理分支機構
單個Git存儲庫可以維護多個開發分支。要創建名為“experimental”的新分支,請使用
```
$ git branch experimental
```
如果你現在跑
```
$ git branch
```
您將獲得所有現有分支的列表:
```
experimental
* master
```
“experimental”分支是您剛創建的分支,“master”分支是自動為您創建的默認分支。星號標記您當前所在的分支;類型
```
$ git checkout experimental
```
切換到實驗分支。現在編輯文件,提交更改,然后切換回主分支:
```
(edit file)
$ git commit -a
$ git checkout master
```
檢查您所做的更改是否已不再可見,因為它是在實驗分支上進行的,您將返回主分支。
您可以在主分支上進行不同的更改:
```
(edit file)
$ git commit -a
```
在這一點上,兩個分支已經分歧,每個分支都有不同的變化。要將實驗中所做的更改合并到master中,請運行
```
$ git merge experimental
```
如果變化沒有沖突,那么你就完成了。如果存在沖突,標記將留在顯示沖突的有問題的文件中;
```
$ git diff
```
會表明這一點。一旦編輯了文件以解決沖突,
```
$ git commit -a
```
將提交合并的結果。最后,
```
$ gitk
```
將顯示生成的歷史記錄的精美圖形表示。
此時,您可以刪除實驗分支
```
$ git branch -d experimental
```
此命令可確保實驗分支中的更改已在當前分支中。
如果你在一個分支瘋狂的想法上發展,那么后悔它,你總是可以刪除分支
```
$ git branch -D crazy-idea
```
分支機構既便宜又簡單,所以這是嘗試一些東西的好方法。
## 使用Git進行協作
假設Alice已經在/ home / alice / project中啟動了一個帶有Git存儲庫的新項目,并且在同一臺機器上有一個主目錄的Bob想要貢獻。
鮑勃開頭:
```
bob$ git clone /home/alice/project myrepo
```
這將創建一個新目錄“myrepo”,其中包含Alice的存儲庫的副本。克隆與原始項目處于同等地位,擁有自己原始項目歷史的副本。
鮑勃然后進行一些更改并提交它們:
```
(edit files)
bob$ git commit -a
(repeat as necessary)
```
當他準備好時,他告訴Alice從/ home / bob / myrepo的存儲庫中取出更改。她這樣做:
```
alice$ cd /home/alice/project
alice$ git pull /home/bob/myrepo master
```
這將Bob的“主”分支的更改合并到Alice的當前分支中。如果Alice在此期間進行了自己的更改,那么她可能需要手動修復任何沖突。
因此,“pull”命令執行兩個操作:它從遠程分支獲取更改,然后將它們合并到當前分支中。
請注意,一般情況下,Alice會在啟動此“拉動”之前希望提交本地更改。如果Bob的工作與Alice自其歷史分歧后所做的工作沖突,Alice將使用她的工作樹和索引來解決沖突,現有的本地更改將干擾沖突解決過程(Git仍將執行獲取,但將拒絕合并 - - 愛麗絲將不得不以某種方式擺脫她的局部變化,并在發生這種情況時再次拉動)。
Alice可以使用“fetch”命令查看Bob在沒有合并的情況下做了什么。這允許Alice使用特殊符號“FETCH_HEAD”來檢查Bob做了什么,以確定他是否有任何值得拉動的東西,如下所示:
```
alice$ git fetch /home/bob/myrepo master
alice$ git log -p HEAD..FETCH_HEAD
```
即使Alice有未提交的本地更改,此操作也是安全的。范圍符號“HEAD..FETCH_HEAD”表示“顯示可從FETCH_HEAD到達的所有內容,但排除可從HEAD訪問的任何內容”。 Alice已經知道了導致她當前狀態(HEAD)的所有內容,并且回顧了Bob在他的狀態(FETCH_HEAD)中沒有看到的這個命令。
如果Alice想要想象自從他們的歷史分叉后Bob做了什么,她可以發出以下命令:
```
$ gitk HEAD..FETCH_HEAD
```
這使用了我們之前在 _git log_ 中看到的相同的雙點范圍表示法。
Alice可能想要查看他們分叉后他們做了什么。她可以使用三點形式而不是兩點形式:
```
$ gitk HEAD...FETCH_HEAD
```
這意味著“顯示從任何一個都可以訪問的所有內容,但排除可以從它們中訪問的任何內容”。
請注意,這些范圍表示法可以與gitk和“git log”一起使用。
在檢查Bob做了什么之后,如果沒有緊急情況,Alice可能會決定繼續工作而不會從Bob那里撤離。如果Bob的歷史確實有Alice會立即需要的東西,那么Alice可以選擇先將她的工作藏匿在一起,做一個“拉動”,然后在最終的歷史記錄之上最終取消正在進行的工作。
當您在一個小型緊密結合的小組中工作時,一遍又一遍地與同一個存儲庫進行交互并不罕見。通過定義_遠程_存儲庫速記,您可以更輕松:
```
alice$ git remote add bob /home/bob/myrepo
```
有了這個,Alice可以使用 _git fetch_ 命令單獨執行“pull”操作的第一部分,而無需將它們與自己的分支合并,使用:
```
alice$ git fetch bob
```
與簡寫形式不同,當Alice使用 _git remote_ 設置的遠程存儲庫速記從Bob獲取時,所獲取的內容存儲在遠程跟蹤分支中,在本例中為`bob/master`。所以在此之后:
```
alice$ git log -p master..bob/master
```
顯示了Bob從Alice的主分支分支后所做的所有更改的列表。
檢查完這些更改后,Alice可以將更改合并到她的主分支中:
```
alice$ git merge bob/master
```
這`merge`也可以通過_從她自己的遠程跟蹤分支_拉出來完成,如下所示:
```
alice$ git pull . remotes/bob/master
```
請注意,無論命令行上給出了什么,git pull總是合并到當前分支中。
之后,Bob可以使用Alice的最新更改來更新他的回購
```
bob$ git pull
```
請注意,他不需要提供Alice的存儲庫的路徑;當Bob克隆了Alice的存儲庫時,Git將她的存儲庫的位置存儲在存儲庫配置中,該位置用于拉取:
```
bob$ git config --get remote.origin.url
/home/alice/project
```
( _git clone_ 創建的完整配置使用`git config -l`可見, [git-config [1]](https://git-scm.com/docs/git-config) 手冊頁解釋了每個選項的含義。)
Git還以“origin / master”的名義保留了Alice的主分支的原始副本:
```
bob$ git branch -r
origin/master
```
如果Bob后來決定在不同的主機上工作,他仍然可以使用ssh協議執行克隆和拉取:
```
bob$ git clone alice.org:/home/alice/project myrepo
```
或者,Git有一個原生協議,或者可以使用http;有關詳細信息,請參閱 [git-pull [1]](https://git-scm.com/docs/git-pull) 。
Git也可以用于類似CVS的模式,具有各種用戶推送更改的中央存儲庫;見 [git-push [1]](https://git-scm.com/docs/git-push) 和 [gitcvs-migration [7]](https://git-scm.com/docs/gitcvs-migration) 。
## 探索歷史
Git歷史表示為一系列相互關聯的提交。我們已經看到 _git log_ 命令可以列出這些提交。請注意,每個git日志條目的第一行也提供了提交的名稱:
```
$ git log
commit c82a22c39cbc32576f64f5c6b3f24b99ea8149c7
Author: Junio C Hamano <junkio@cox.net>
Date: Tue May 16 17:18:22 2006 -0700
merge-base: Clarify the comments on post processing.
```
我們可以將此名稱賦予 _git show_ 以查看有關此提交的詳細信息。
```
$ git show c82a22c39cbc32576f64f5c6b3f24b99ea8149c7
```
但還有其他方法可以引用提交。您可以使用足夠長的名稱的任何初始部分來唯一標識提交:
```
$ git show c82a22c39c # the first few characters of the name are
# usually enough
$ git show HEAD # the tip of the current branch
$ git show experimental # the tip of the "experimental" branch
```
每個提交通常都有一個“父”提交,指向項目的先前狀態:
```
$ git show HEAD^ # to see the parent of HEAD
$ git show HEAD^^ # to see the grandparent of HEAD
$ git show HEAD~4 # to see the great-great grandparent of HEAD
```
請注意,合并提交可能包含多個父級:
```
$ git show HEAD^1 # show the first parent of HEAD (same as HEAD^)
$ git show HEAD^2 # show the second parent of HEAD
```
您也可以提交自己的提交名稱;跑完之后
```
$ git tag v2.5 1b2e1d63ff
```
您可以通過名稱“v2.5”來引用1b2e1d63ff。如果您打算與其他人共享此名稱(例如,識別發布版本),您應該創建一個“標記”對象,并可能簽名;有關詳細信息,請參閱 [git-tag [1]](https://git-scm.com/docs/git-tag) 。
任何需要知道提交的Git命令都可以使用任何這些名稱。例如:
```
$ git diff v2.5 HEAD # compare the current HEAD to v2.5
$ git branch stable v2.5 # start a new branch named "stable" based
# at v2.5
$ git reset --hard HEAD^ # reset your current branch and working
# directory to its state at HEAD^
```
小心最后一個命令:除了丟失工作目錄中的任何更改外,它還將刪除此分支的所有后續提交。如果此分支是包含這些提交的唯一分支,則它們將丟失。此外,不要在其他開發人員從中公開可見的分支上使用 _git reset_ ,因為它會迫使其他開發人員進行不必要的合并以清理歷史記錄。如果您需要撤消已推送的更改,請改用 _git revert_ 。
_git grep_ 命令可以在項目的任何版本中搜索字符串,所以
```
$ git grep "hello" v2.5
```
在v2.5中搜索所有出現的“hello”。
如果省略提交名稱, _git grep_ 將搜索它在當前目錄中管理的任何文件。所以
```
$ git grep "hello"
```
是一種快速搜索Git跟蹤的文件的方法。
許多Git命令也采用提交集,可以通過多種方式指定。以下是 _git log_ 的一些示例:
```
$ git log v2.5..v2.6 # commits between v2.5 and v2.6
$ git log v2.5.. # commits since v2.5
$ git log --since="2 weeks ago" # commits from the last 2 weeks
$ git log v2.5.. Makefile # commits since v2.5 which modify
# Makefile
```
你也可以給 _git log_ 一個“范圍”的提交,其中第一個不一定是第二個的祖先;例如,如果分支“穩定”和“主”的提示在一段時間之前偏離了共同的提交,那么
```
$ git log stable..master
```
將列出在主分支中但不在穩定分支中進行的提交
```
$ git log master..stable
```
將顯示在穩定分支上但不在主分支上進行的提交列表。
_git log_ 命令有一個缺點:它必須在列表中顯示提交。當歷史中的發展線分散并然后合并在一起時, _git log_ 呈現這些提交的順序是沒有意義的。
大多數具有多個貢獻者的項目(例如Linux內核或Git本身)經常合并,而 _gitk_ 在可視化其歷史方面做得更好。例如,
```
$ gitk --since="2 weeks ago" drivers/
```
允許您瀏覽在“drivers”目錄下修改文件的過去2周內提交的任何提交。 (注意:您可以在按下“ - ”或“+”的同時按住控制鍵來調整gitk的字體。)
最后,大多數采用文件名的命令都可以選擇允許您通過提交在任何文件名之前,以指定文件的特定版本:
```
$ git diff v2.5:Makefile HEAD:Makefile.in
```
您也可以使用 _git show_ 查看任何此類文件:
```
$ git show v2.5:Makefile
```
## 下一步
本教程應足以為您的項目執行基本的分布式版本控制。但是,要完全理解Git的深度和強大功能,您需要了解它所基于的兩個簡單想法:
* 對象數據庫是一個相當優雅的系統,用于存儲項目文件,目錄和提交的歷史記錄。
* 索引文件是目錄樹狀態的緩存,用于創建提交,檢出工作目錄,以及保存合并中涉及的各種樹。
本教程的第二部分解釋了對象數據庫,索引文件以及充分利用Git所需的其他一些可能性和結果。你可以在 [gittutorial-2 [7]](https://git-scm.com/docs/gittutorial-2) 找到它。
如果你不想馬上繼續這樣做,那么在這一點上可能有趣的一些其他離題是:
* [git-format-patch [1]](https://git-scm.com/docs/git-format-patch) , [git-am [1]](https://git-scm.com/docs/git-am) :這些將git提交系列轉換成電子郵件補丁,反之亦然,對Linux內核等項目很有用它嚴重依賴于電子郵件補丁。
* [git-bisect [1]](https://git-scm.com/docs/git-bisect) :當項目中存在回歸時,追蹤錯誤的一種方法是搜索歷史記錄以查找應該歸咎于的確切提交。 Git bisect可以幫助您對該提交執行二進制搜索。即使在具有大量合并分支的復雜非線性歷史的情況下,它也足夠智能地執行接近最優的搜索。
* [gitworkflows [7]](https://git-scm.com/docs/gitworkflows) :概述推薦的工作流程。
* [giteveryday [7]](https://git-scm.com/docs/giteveryday) :每天Git有20個命令或者所以。
* [gitcvs-migration [7]](https://git-scm.com/docs/gitcvs-migration) :適用于CVS用戶的Git。
## 也可以看看
[gittutorial-2 [7]](https://git-scm.com/docs/gittutorial-2) , [gitcvs-migration [7]](https://git-scm.com/docs/gitcvs-migration) , [gitcore-tutorial [7]](https://git-scm.com/docs/gitcore-tutorial) , [gitglossary [7]](https://git-scm.com/docs/gitglossary) , [git-help [1]](https://git-scm.com/docs/git-help) , [gitworkflows [7]](https://git-scm.com/docs/gitworkflows) , [giteveryday [7]](https://git-scm.com/docs/giteveryday) , [Git用戶手冊](user-manual.html)
## GIT
部分 [git [1]](https://git-scm.com/docs/git) 套件
- git
- git-config
- git-help
- git-init
- git-clone
- git-add
- git-status
- git-diff
- git-commit
- git-reset
- git-rm
- git-mv
- git-branch
- git-checkout
- git-merge
- git-mergetool
- git-log
- git-stash
- git-tag
- git-worktree
- git-fetch
- git-pull
- git-push
- git-remote
- git-submodule
- git-show
- git-log
- git-shortlog
- git-describe
- git-apply
- git-cherry-pick
- git-rebase
- git-revert
- git-bisect
- git-blame
- git-grep
- gitattributes
- giteveryday
- gitglossary
- githooks
- gitignore
- gitmodules
- gitrevisions
- gittutorial
- gitworkflows
- git-am
- git-format-patch
- git-send-email
- git-request-pull
- git-svn
- git-fast-import
- git-clean
- git-gc
- git-fsck
- git-reflog
- git-filter-branch
- git-instaweb
- git-archive
- git-bundle
- git-daemon
- git-update-server-info
- git-cat-file
- git-check-ignore
- git-checkout-index
- git-commit-tree
- git-count-objects
- git-diff-index
- git-for-each-ref
- git-hash-object
- git-ls-files
- git-merge-base
- git-read-tree
- git-rev-list
- git-rev-parse
- git-show-ref
- git-symbolic-ref
- git-update-index
- git-update-ref
- git-verify-pack
- git-write-tree