作爲程序員如果你還不知道 Git 和 GitHub,說不過去吧,趕緊來學習一波。
一、認識GitHub
Git 是個版本控制系統,說明白點就是進行代碼的各種管理,比如你寫錯代碼進行回滾啊、追尋 Bug 是哪個傢伙造成的啊(邪惡臉)、合併別人代碼等等,達到協同進行軟件的開發工作。
其中版本管理控制系統分爲「集中式版本控制系統」和「分佈式版本控制系統」,很多人可能用過 SVN,就是屬於集中式版本控制系統,但 Git 屬於分佈式版本控制系統。關於兩者區別自行搜索資料瞭解下。當然學習起來,Git 相對算更難上手些。
如果說單純學習 Git,其實和 GitHub 也無關,但我覺得結合 GitHub 來學習是很好的。說到這,或許還有人不知道 GitHub 是什麼,沒關係,簡單講就是一個開源社區網站(也被大家叫爲「同性戀社區」,因爲活躍着基本都是程序員呀,而這個羣體基本又都是 ♂ 捂臉.jpg),裏面囊及了全球很多程序大牛,包括 Linux 之父 Linus 也在的,並且其 Linux 系統的代碼也是放(即開源)在這個網站,任何人都可以查看整個源代碼。對於這樣一個社區網站,如果只是人人可以把代碼開源在上面以讓其他人也可以閱讀進行學習這樣一個單一功能,這也太單一了吧。其實 GitHub 功能很多,包括允許用戶追蹤其他用戶、組織、軟件庫的動態,對軟件代碼的改動和 Bug 提出評論等。
社羣功能再多,但最重要的還是版本控制,比如 A 開源了某個項目代碼,B、C 等人可以克隆(即下載)下來進行閱讀、修改,等修改了好的功能,可以發起 PR 提交 A,A 若是覺得代碼寫的沒問題,可以同意請求進行代碼合併,這樣通過多人寫作,這個項目代碼將會越來越好。其過程必定離不開 Git 操作。雖然有 GUI 客戶端軟件操作,但是一開始學會學習使用命令行 Git 操作,這樣能更好達到對 Git 的深層學習,也有助於更好的理解。
在這裏補充點內容,對於如何爲別人的開源的項目貢獻代碼,其大概流程如下:
- 先點擊 A 的項目倉庫站點的“fork”的按鈕,這樣的你的 GitHub 賬戶下也會有一個相同的倉庫;
- 然後把你這個 fork 過來的倉庫代碼 Clone 檢出,然後就可以進行你對該項目代碼的修改了,覺得修改 ok,最後 push (即加入)到你該遠程倉庫,最後通過內建的“pull request”機制向項目負責人申請代碼合併;
- A 覺得你修改的代碼寫的很好,就可以進行同意了,同意之後,就能把你修改的代碼合併到該項目,這樣你也算是爲該項目貢獻了力量。
不過相信還是存在部分人可能還只聽過 GitHub,網站甚至沒登錄過,更別說網站全英文,容易失去信心。這裏還是摘入網上一些文章和資料先自己瞭解和學習吧:
系列文章:stormzhang - 從0開始學習 GitHub 系列 推薦看完該系列文章。
如何創建項目:
關於 GitHub 網站:
二、Git命令
2.1 認識Git
簡單講講我的認識:首先 Git 屬於「分佈式版本控制系統」,先要好好理解這個分佈式與集中式的不同。
集中式的如 SVN,是有一臺中央服務器(其實就是某臺電腦安裝了 SVN 軟件),所有開發人員從自己電腦(比如 Eclipse 下安裝 SVN 插件)檢出項目代碼,任何一人修改了代碼就可以提交至中央服務器,然後其他人檢出(即更新、合併了代碼),這樣反覆重複的過程,其中包括衝突的解決等,這所有的代碼操作都記錄在中央服務器 SVN 中的。從中可以看出這臺中央服務器的作用和重要性吧,說一個很明顯的問題:萬一中央服務器宕機了,你就不能提交,也不能更新代碼了。
分佈式的如 Git,是每個人本地維護一個版本控制管理信息,那怎麼做到的呢?首先你本地需要安裝 Git ,這個軟件安裝完畢,新建目錄並在該目錄下執行 git init
就會有一個 .git
隱藏文件夾及內容,這個文件夾下內容維護着該目錄下的項目代碼情況。但怎麼就分佈式呢?——大概是這樣的,GitHub (其實就可以理解爲某臺電腦/服務器)上有別人提交上去的項目代碼,然後你 Clone (克隆/下載)來,你本地這份項目代碼就包含 .git
文件夾,裏面就有這個項目代碼的所有的版本信息,類似的,其他任何人也可以同樣 Clone 下來,也是有這樣一份這個項目代碼的所有的版本信息,然後你們都可以基於自己 Clone 下來的項目代碼進行代碼的修改了,本地會記錄你的修改、提交、回滾等等代碼操作信息,就算 GitHub 網站掛了也沒事,你們本地都有保持着這個項目代碼的所有版本控制信息。 大概意思大家再體會下。
然後這裏可以涉及到很多關於 Git 的操作,還有一些概念,比如分支。我簡單說下分支,以某個 Android 項目爲例,比如該項目有個主分支 master 是專門用來對外發布上線的代碼,但是開發過程中某個節點遇到某個 Bug 需要修復,則可以在此開發節點新建一個比如 hotfix 分支來進行代碼的修復,修復好了再合併到主分支 master 上,然後可以刪除掉 hotfix 分支。
可以看出 Git 命令是學習的重點,要學的深刻,最好懂得原理和本質,但本文只是個人筆記記錄,我把常用的命令整理了下,方便以後查找。
2.2 操作本地庫常用Git命令
-
git init
: 初始化一個目錄,其實初始化完畢然後本地多出了一個.git
的隱藏目錄,這個目錄管理着一個代碼庫的版本信息。 -
git add
: 把一個文件從untracked
(未被追蹤)狀態轉爲到staged
狀態,直白的講,就是把文件提交到暫緩區
,這個時候還沒真正意義上的代碼提交。格式爲:git add .
提交所有改動,git add hello.txt
提交指定文件的改動。 -
git commit
: 這步纔是真正的代碼提交到倉庫,格式爲:git commit
或者加參數git commit -m “這次的提交說明信息”
,前者會進入一個頁面,輸入 i 可以進入編輯界面,再寫上這次的提交的註釋說明信息(一般用來記錄本次提交的主要意圖),然後按 ESC 鍵退出編輯返回到命令模式,然後連續輸入兩個大寫的 “Z”(用 Shift 鍵或 Capslock 鍵都可以),就保存並退出了;後者的話直接可以寫上提交的註釋說明信息。如果在提交的時候出現提示設置郵箱和用戶名,是爲了保證提交的準確性,在提交的時候 user.name 和 user.email 會進入日誌,這些信息,是追蹤代碼變更的關鍵,比如是誰修改的。以後會隨更新內容一起被永久納入歷史記錄。
PS:在設置用戶名的時候,可以使用任意的字符。Git 實際上是使用 email 進行關聯每次提交的,只不過使用 username 作爲標示符來進行顯示。當你的 email 地址和 github上的 email 地址一致時,則會使用 Github 上面的 name 來進行顯示。
如果工作中只涉及一個 git 服務器,用一個全局配置就可以了。
全局配置:
git config --global user.name "strivebo" git config --global user.email "[email protected]"
非全局配置,某個項目下的配置:(去掉
--global
)git config user.name "strivebo" git config user.email "[email protected]"
可以使用命令來查看修改後的配置:
git config --global user.name 或 git config user.name git config --global user.email 或 git config user.email
取消全局配置:
git config --global --unset user.name git config --global --unset user.email git config --global user.name #(查看)全局配置賬戶是否已經移除 git config --global user.email #(查看)全局配置郵箱是否已經移除
-
git reset --hard
: 版本回退操作,比如我想把當前的版本回退到上一個版本,要使用什麼命令呢?可以使用如下 2 種命令,第一種是:git reset --hard HEAD^
。那麼如果要回退到上上個版本只需把HEAD^
改成HEAD^^
以此類推。那如果要回退到前100個版本的話,使用上面的方法肯定不方便,我們可以使用下面的簡便命令操作:git reset --hard HEAD~100
即可。假設: 我進行了兩次修改,第一次 readme.txt 文件添加了 2222,第二次添加了 3333,我已經使用回退操作回到了第一次的修改,即現在文本內容爲 2222,但我其實又想回到第二次的修改,該怎麼辦呢(如何恢復 3333 內容呢)?可以這樣:
通過如下命令即可獲取到版本號:
git reflog
,可以看到增加內容 3333 的版本號是多少比如爲 6fcfc89,我們現在可以命令:git reset --hard 6fcfc89
來恢復了。 -
git status
: 查看倉庫文件狀態。可以加參數 -s,即git status -s
,加個 -s 用簡潔模式查看當前修改和倉庫裏面差別多少,可以看到有多少文件被新增了,多少被修改了,多少被刪除了。 -
git log
: 查看提交歷史記錄,即版本歷史信息,比如誰提交的,什麼時間啊。 -
git diff
: (不加選項參數)可以顯示工作目錄和暫存區之間的不同。換句話說,這條指令可以讓你看到「如果你現在把所有文件都 add,你會向暫存區中增加哪些內容」。比如git diff develop
,查看當前版本和 develop 分支的差異。 -
git diff –cached
: 查看已經暫存起來的文件和上次提交的版本之間的差異。git diff –cached filename
查看已經暫存起來的某個文件和上次提交的版本之間的差異。 -
git diff --staged
: 使用git diff --staged
可以顯示暫存區和上一條提交之間的不同。換句話說,這條指令可以讓你看到「如果你立即輸入 git commit,你將會提交什麼」。 -
git branch
: 查看有哪些分支,並且能看到當前處於哪個分支上。PS:初始化倉庫後默認有 master 這個主分支,一般情況下不會輕易在該主分支操作。新建分支可以使用git branch <newBranch>
格式,如git branch dev
新建分支 dev,其內容和和主分支一模一樣。git branch -a
:查看本地和遠程所有分支git branch -r
:查看遠程所有分支git branch -v
:查看遠程分支詳細信息
-
git checkout a
: 切換到 a 分支。 -
git checkout -b a
: 有人就說了,我要先新建再切換,未免有點麻煩,有沒有一步到位的,有的:git checkout -b a
表示新建分支 a 並同時切換到分支 a。 -
git merge
: 合併分支代碼,比如合併 dev 分代碼,需要先切換到 master 分支,再git merge dev
即可合併 dev 分支代碼。 -
git merge -- about
: 會嘗試恢復到你運行合併前的狀態。 但當運行命令前,在工作目錄中有未儲藏、未提交的修改時它不能完美處理,除此之外它都工作地很好。由於現在 Git 倉庫處於衝突待解決的中間狀態,所以如果你最終決定放棄這次 merge,也需要執行一次 merge --abort 來手動取消它。輸入這行代碼,你的 Git 倉庫就會回到 merge 前的狀態。 -
git branch -d
: 刪除分支。 假如這個分支新建錯了,或者a分支的代碼已經順利合併到 master 分支來了,那麼 a 分支沒用了,需要刪除,這個時候執行git branch -d a
就可以把a分支刪除了。 -
git branch -D
: 強制刪除。有些時候可能會刪除失敗,比如如果 a 分支的代碼還沒有合併到 master,你執行git branch -d a
是刪除不了的,它會智能的提示你 a 分支還有未合併的代碼,但是如果你非要刪除,那就執行git branch -D a
就可以強制刪除 a 分支。 -
git tag
: 新建標籤。我們在客戶端開發的時候經常有版本的概念,比如 v1.0、v1.1 之類的,不同的版本肯定對應不同的代碼,所以我一般要給我們的代碼加上標籤(即把某次提交標記爲某個 tags,如 v1.0),這樣假設 v1.1 版本出了一個新 bug,但是又不曉得 v1.0 是不是有這個 bug,有了標籤就可以順利切換到 v1.0 的代碼,重新打個包測試了。所以如果想要新建一個標籤很簡單,比如git tag v1.0
就代表我在當前代碼狀態下新建了一個 v1.0 的標籤,輸入 git tag 可以查看歷史 tag 記錄。 想要切換到某個 tag,執行:git checkout v1.0
,就可以切換到 v1.0 的代碼狀態。
2.3 操作遠程庫相關Git命令
-
git clone
: 遠程 clone 即複製/克隆一個完整的 repository (倉庫,即項目代碼)到本地,克隆倉庫時所使用的遠程主機自動被 Git 命名爲origin
,如果想用其他的主機名,需要用git clone
命令的-o
選項指定。格式爲:git clone -o jQuery https://github.com/jquery/jquery.git
,然後git remote
命令查看,可以看到名字爲遠程主機名 jQuery。這裏要特別說下,這裏克隆可以有兩種方式,一種 https 方式,一種 ssh 。
①如果是 https 方式,複製倉庫 https 地址進行 clone 操作,如:
git clone https://github.com/strivebo/git-practice.git
這樣克隆下來的項目倉庫,注意觀察
.git
文件夾下的config
中的文件 url:[remote "origin"] url = https://github.com/strivebo/git-practice.git fetch = +refs/heads/*:refs/remotes/origin/* [branch "master"] remote = origin merge = refs/heads/master
②如果是 ssh 方式,複製倉庫的 ssh 地址進行 clone 操作,如:
git clone [email protected]:strivebo/git-practice.git
這樣克隆下來的項目倉庫,注意觀察
.git
文件夾下的config
中的文件 url:[remote "origin"] url = [email protected]:strivebo/git-practice.git fetch = +refs/heads/*:refs/remotes/origin/* [branch "master"] remote = origin merge = refs/heads/master
注1: 可以看到,https 方式下 url 爲 「https 地址」,ssh 方式下 url 爲「ssh 地址」(我就這麼任性表達了,反正意思明白就行),所以假設你採用的 https 方式 clone 下來的項目可以通過修改這個 url 爲「ssh 地址」,這樣本地倉庫就相當於是使用了 「ssh 方式 clone 下來的」。
**注2:**兩者的區別有,若採用的 https 方式,則每次提交代碼至 GitHub 時,都要求輸入 GitHub 賬號和密碼才能提交,若 ssh 方式,則不需要每次的輸入。但當然這前提是你已經添加 ssh 。
關於 SSH 協議的歷史,可以看看這篇文章:SSH 協議(Secure Shell 協議)。
這裏引用我看到的網上資料關於 https 和 SSH 的區別說下:
- 前者可以隨意克隆 github上的項目,而不管是誰的;而後者則是你必須是你要克隆的項目的擁有者或管理員,且需要先添加 SSH key ,否則無法克隆。
- https url 在 push 的時候是需要驗證用戶名和密碼的;而 SSH 在 push 的時候,是不需要輸入用戶名的,如果配置 SSH key 的時候設置了密碼,則需要輸入密碼的,否則直接是不需要輸入密碼的。
關於如何添加 ssh 下面是步驟:
-
Linux 與 Mac 都是默認安裝了 SSH ,而 Windows 系統安裝了 Git Bash(即安裝了 Git 就有這個) 應該也是帶了 SSH 的,在終端輸入
ssh
命令可以查看是否安裝了 ssh; -
緊接着輸入
ssh-keygen -t rsa
或者ssh-keygen -t rsa -C "註釋"
格式 ,就是指定 rsa 算法生成密鑰,接着連續三個回車鍵(不需要輸入密碼)然後就會生成兩個文件 id_rsa 和 id_rsa.pub ,而 id_rsa 是密鑰,id_rsa.pub 就是公鑰。這兩文件默認分別在如下目錄裏生成: Linux/Mac 系統 在~/.ssh
下,win系統在/c/Documents and Settings/username/.ssh
下, 都是隱藏目錄,大家應該能找到的;PS: 其實在連續安回車鍵中會提示輸入一個密碼以及確認密碼,這個密碼會在你提交項目時使用,如果爲
空
的話(即直接按回車鍵,也即未設置密碼)提交項目代碼時則不用輸入密碼; -
接下來要做的是把 id_rsa.pub 的內容添加到 GitHub 上(PS:如何添加自行網上搜下,就不多說了),這樣你本地的 id_rsa 密鑰跟 GitHub 上的 id_rsa.pub 公鑰進行配對,授權成功,這樣就可以不用像 https 方式每次輸入賬號和密碼進行驗證身份才能提交了。(你就理解爲,SSH 就好比進行了身份驗證的這種理解。)
-
SSH key 添加成功之後,輸入
ssh -T [email protected]
進行測試,如果出現以下提示,再輸入 yes 出現如下圖則證明添加成功了。(圖我就不截了,我覺得問題應該不大)
補充:對於命令
ssh-keygen
添加不同參數的含義—— ssh-keygen參數說明。 -
git remote
: 列出所有的遠程倉庫。從別處 clone 來的,默認都會有一個別名”origin”的倉庫。帶上 -v 可以看到具體 URL。 -
git remote add
: 添加遠程倉庫地址。其實這些操作都是在本地,並沒有實際牽涉到遠程。另外 github 裏面fork 過來的,默認叫”upstream”。該命令完整格式爲:git remote add <主機名> <網址>
,如git remote add orgin [email protected]:strivebo/git-practice.git
-
git remote rw
: 刪除遠程倉庫地址。格式爲:git remote rm <主機名>
-
git remote rename
: 用於遠程主機的改名。完整格式爲:git remote rename <原主機名> <新主機名>
-
git fetch
: 一旦遠程主機的版本庫有了更新(Git 術語叫做 commit),需要將這些更新取回本地,這時就要用到git fetch
命令。格式爲:git fetch <遠程主機名>
,默認情況下,git fetch
取回所有分支(branch)的更新。- 如果只想取回特定分支的更新,可以指定分支名,格式爲:
git fetch <遠程主機名> <分支名>
, 另外,所取回的更新,在本地主機上要用"遠程主機名/分支名"的形式讀取,比如origin
主機的master
,就要用origin/master
讀取。 - 取回遠程主機的更新以後,可以在它的基礎上,使用
git checkout
命令創建一個新的分支,git checkout -b newBrach origin/master
,該命令表示,在origin/master
的基礎上,創建一個新分支。此外,也可以使用git merge
命令或者git rebase
命令,在本地分支上合併遠程分支。
- 如果只想取回特定分支的更新,可以指定分支名,格式爲:
-
git pull
:git pull
命令的作用是,取回遠程主機某個分支的更新,再與本地的指定分支合併。相當於 fetch後,再進行 merge。其完整格式爲:git pull <遠程主機名> <遠程分支名>:<本地分支名>
,如取回origin
主機的next
分支,與本地的master
分支合併,可以這樣寫:git pull origin next:master
- 如果遠程分支是與當前分支合併,則冒號後面的部分可以省略,即
git pull origin next
,該命令表示,取回origin/next
分支,再與當前分支合併。實質上,這等同於先做git fetch
,再做git merge
在某些場合,Git會自動在本地分支與遠程分支之間,建立一種追蹤關係(tracking)。比如,在
git clone
的時候,所有本地分支默認與遠程主機的同名分支,建立追蹤關係,也就是說,本地的master
分支自動"追蹤"origin/master
分支。 Git也允許手動建立追蹤關係。-
git branch --set-upstream master origin/next
該命令指定master
分支追蹤origin/next
分支 -
如果當前分支與遠程分支存在追蹤關係,
git pull
就可以省略遠程分支名。git pull origin
該命令表示,本地的當前分支自動與對應的origin
主機"追蹤分支"(remote-tracking branch)進行合併 -
如果當前分支只有一個追蹤分支,連遠程主機名都可以省略,
git pull
該命令表示,當前分支自動與唯一一個追蹤分支進行合併 -
合併需要採用rebase模式,可以使用
--rebase
選項。git pull --rebase <遠程主機名> <遠程分支名>:<本地分支名>
-
如果遠程主機刪除了某個分支,默認情況下,
git pull
不會在拉取遠程分支的時候,刪除對應的本地分支。這是爲了防止,由於其他人操作了遠程主機,導致git pull
不知不覺刪除了本地分支。但是,你可以改變這個行爲,加上參數-p
就會在本地刪除遠程已經刪除的分支。git pull -p
該命令等同於:git fetch --prune origin git fetch -p
- 如果遠程分支是與當前分支合併,則冒號後面的部分可以省略,即
-
git push
:git push
命令用於將本地分支的更新,推送到遠程主機。它的格式與git pull
命令相仿。其完整格式爲:git push <遠程主機名> <本地分支名>:<遠程分支名>
- 如果省略遠程分支名,則表示將本地分支推送與之存在"追蹤關係"的遠程分支(通常兩者同名),如果該遠程分支不存在,則會被新建。
git push origin master
該命令表示,將本地的master
分支推送到origin
主機的master
分支。如果後者不存在,則會被新建。 - 如果省略本地分支名,則表示刪除指定的遠程分支,因爲這等同於推送一個空的本地分支到遠程分支。
git push origin :master
等同於git push origin --delete master
該命令表示刪除origin
主機的master
分支。 - 如果當前分支與遠程分支之間存在追蹤關係,則本地分支和遠程分支都可以省略。
git push origin
該命令表示,將當前分支推送到origin
主機的對應分支。 - 如果當前分支只有一個追蹤分支,那麼主機名都可以省略。
git push
- 如果當前分支與多個主機存在追蹤關係,則可以使用
-u
選項指定一個默認主機,這樣後面就可以不加任何參數使用git push
。git push -u origin master
該命令將本地的master
分支推送到origin
主機,同時指定origin
爲默認主機,後面就可以不加任何參數使用git push
了。
注:不帶任何參數的
git push
,默認只推送當前分支,這叫做 simple 方式。此外,還有一種matching 方式,會推送所有有對應的遠程分支的本地分支。Git 2.0 版本之前,默認採用 matching 方法,現在改爲默認採用 simple 方式。如果要修改這個設置,可以採用git config
命令。$ git config --global push.default matching # 或者 $ git config --global push.default simple
還有一種情況,就是不管是否存在對應的遠程分支,將本地的所有分支都推送到遠程主機,這時需要使用
--all
選項。$ git push --all origin
上面命令表示,將所有本地分支都推送到
origin
主機。如果遠程主機的版本比本地版本更新,推送時Git會報錯,要求先在本地做
git pull
合併差異,然後再推送到遠程主機。這時,如果你一定要推送,可以使用--force
選項。git push --force origin
上面命令使用
--force
選項,結果導致遠程主機上更新的版本被覆蓋。除非你很確定要這樣做,否則應該儘量避免使用--force
選項。最後,
git push
不會推送標籤(tag),除非使用--tags
選項。git push origin --tags
- 如果省略遠程分支名,則表示將本地分支推送與之存在"追蹤關係"的遠程分支(通常兩者同名),如果該遠程分支不存在,則會被新建。
2.4 參考資料
推薦資料:
- stormzhang:從0開始學習 GitHub 系列
- 阮一峯網絡日誌:Git遠程操作詳解
- 拋物線:Git 原理詳解及實用指南 - 掘金小冊
其他:
三、實戰學習
3.1 代碼提交到 GitHub 上
(1) 兩種克隆方式
- 採用 HTTPS 方式克隆 GitHub 上倉庫(項目):
git clone https://github.com/strivebo/git-practice.git
- 採用 SSH 方式克隆:
git clone [email protected]:strivebo/git-practice.git
- 如果想要在克隆至本地時指定別的目錄名稱,可以在後面加個參數,如:
git clone https://github.com/strivebo/git-practice.git git-practice-another
,手動指定本地倉庫的根目錄名稱爲 git-practice-another。
GitHub 中的 SSH 和 HTTPS 提交區別:
從 GitHub 上 Clone 一個項目到本地的時候,有 use https 和 use ssh 兩種方式,這兩種主要是在 push 項到 GitHub 上時有所不同。完成一個 push 操作,需要對其內容進行安全管理,這裏提供了 ssh 和 https 兩種方式。而在 Clone 項目到本地時,做出選擇後,就已經決定了 push 的方式。
SSH 使用了 RSA,即非對稱加密的方式,存在一個公鑰和私鑰。可以生成一個本地的一組祕鑰,然後將公鑰複製到 GitHub 的 settings/profile 下。使用 https 方式,每次需要驗證用戶身份信息。
(2) 採用https方式克隆
在使用 git status
命令查看倉庫狀態若是看到: your branch is ahead of 'origin/master' by 2 commits.
,解釋下:
- Git 提示你的當前 branch 已經領先於( “ahead of” )‘origin/master’ 兩個提交了
- origin/master 的中的 origin 是遠端倉庫的名稱,是你在用 Clone 指令初始化本地倉庫時 Git 自動幫你起的默認名稱;master 是 origin 上的分支名稱。
可以暫時把 origin/master 簡單理解爲「中央倉庫」,也就是說,這句話是告訴你,你的本地倉庫已經領先中央倉庫兩個提交了。然後可以使用 git push
提交發布至中央服務器(這裏即指 GitHub)。
因爲採用的是 https 方式克隆,所以在這個過程 GitHub 會向你索要賬戶和密碼。填入正確的賬戶和密碼,push 操作就完成了。這時你再去你的 GitHub 倉庫頁面可以看到提交記錄。說明你已經成功把本地倉庫的提交推送到了服務器了。
PS:如果覺得一遍遍地輸入密碼很煩,可以按照 這個頁面 提供的方案來把密碼保存起來。另外還有一個更簡單但安全性低一些的方案。執行這行代碼:git config credential.helper store
,在這之後你只需要再輸入一次密碼, Git 就會把你的密碼保存下來,這之後就再也不用輸入了。說它「安全性低」,是因爲這條指令會讓 Git 把你的密碼以明文形式保存在你的電腦上。具體這兩種保存密碼的方案選擇哪個,看你自己了。
總結下:
- 從 GitHub 把中央倉庫 Clone 到本地把寫完的代碼提交。即先使用命令:
git clone
,再用git add 文件名
把文件添加到暫存區,再用git commit
提交; - 在這個過程中,可以使用
git status
來隨時查看工作目錄的狀態。每個文件有 “changed / unstaged”(已修改), “staged”(已修改並暫存), “commited”(已提交) 三種狀態,以及一種特殊狀態 “untracked”(未跟蹤); - 提交一次或多次之後,把本地提交 push 到中央倉庫(命令:
git push
)。
(3) 採用ssh方式克隆
在擁有了一個 GitHub 賬號之後,就可以自由的 Clone 或者下載其他項目,也可以創建自己的項目,但是你沒法提交代碼。仔細想想也知道,肯定不可能隨意就能提交代碼的,如果隨意可以提交代碼,那麼 GitHub 上的項目豈不亂了套了,所以提交代碼之前一定是需要某種授權的,而 GitHub 上一般都是基於 SSH 授權的。那麼什麼是 SSH 呢? 簡單點說,SSH 是一種網絡協議,用於計算機之間的加密登錄。目前是每一臺 Linux 電腦的標準配置。而大多數 Git 服務器都會選擇使用 SSH 公鑰來進行授權,所以想要在 GitHub 提交代碼的第一步就是要先添加 SSH key 配置。
添加 SSH 步驟:
- Git Bash下輸入
ssh
查看電腦是否安裝了 ssh; - 緊接着輸入
ssh-keygen -t rsa
,什麼意思呢?就是指定 rsa 算法生成密鑰,接着連續三個回
車鍵(不需要輸入密碼) ,然後就會生成兩個文件id_rsa
和id_rsa.pub
,而 id_rsa 是密鑰,id_rsa.pub 就是公鑰。這兩文件默認分別在如下目錄裏生成: Linux/Mac 系統 在 ~/.ssh 下,Windows 系統在 /c/Documents and Settings/username/.ssh 下, 都是隱藏文件。 - 接下來要做的是把 id_rsa.pub 的內容添加到 GitHub 上,這樣你本地的 id_rsa 密鑰跟 GitHub 上的 id_rsa.pub 公鑰進行配對,授權成功纔可以提交代碼。
- SSH key 添加成功之後,輸入
ssh -T [email protected]
進行測試。
最後就是 push、pull 的操作了。添加 SSH key 成功之後,我們就有權限向 GitHub 上我們自己的項目提交代碼了。執行:git push origin master
進行代碼提交。
實踐: 假設我們本地有個 test2 的項目,我們需要的是在 GitHub 上建一個 test 的項目,然後把本地 test2 上的所有代碼 commit 記錄提交到 GitHub 上的 test 項目。
-
第一步就是在 GitHub 上建一個 test 倉庫,具體怎麼操作我就不多說了吧;
-
第二步切換到 test2 目錄,打開 Git Bash,把本地 test2 項目與 GitHub 上的 test 項目進行關聯:
git remote add origin [email protected]:strivebo/test.git
;什麼意思呢?就是添加一個遠程倉庫,地址是
[email protected]:strivebo/test.git
,而 origin 是給這個項目的遠程倉庫起的名字,是的,名字你可以隨便取,只不過大家公認的只有一個遠程倉庫時名字就是 origin ,爲什麼要給遠程倉庫取名字?因爲我們可能一個項目有多個遠程倉庫?比如 GitHub 一個,比如公司一個,這樣的話提交到不同的遠程倉庫就需要指定不同的倉庫名字了。
PS:查看我們當前項目有哪些遠程倉庫可以執行如下命令: git remote -v
,接下來,我們本地的倉庫就可以向遠程倉庫進行代碼提交了:git push origin master
,就是默認向 GitHub 上的 test 倉庫提交了代碼,而這個代碼是在 master 分支,當然你可以提交到指定的分支。
再次強調: Git 使用 https 協議,每次 pull,push 都要輸入密碼,相當的煩。使用 Git 協議,然後使用 ssh 密鑰,這樣可以省去每次都輸密碼。
四、問題和筆記
4.1 問題
問題 1:fatal the current branch master has no upstream branch
對於前面這個「假設我們本地有個 test2 的項目,我們需要的是在 GitHub 上建一個 test 的項目,然後把本地 test2 上的所有代碼 commit 記錄提交到 GitHub 上的 test 項目。」實踐練習有出現了問題,報錯是:fatal the current branch master has no upstream branch.
參考網上資料:
我的總結:如果沒有添加 ssh,沒采用 ssh 方式克隆,那採用 https 方式克隆,如:git remote add origin https://github.com/strivebo/test.git
,然後,下面是引用的網上一個人的解決方式:
此時如果 origin 的 master 分支上有一些本地沒有的提交,push 會失敗。所以解決的辦法是,首先設定本地 master 的上游分支:
git branch --set-upstream-to=origin/master
,然後 pull:git pull --rebase
,最後再 push:git push
。
問題2:官網下載的 Git 與 TortoiseGit 客戶端的關係
Git 自帶GUI界面。使用 git gui
命令可以打開它。在這個界面中可以完成 commit、merge、push、pull 等等常用操作。
…
TortoiseGit 沒有集成 Git。在 TortoiseGit 官方網站可以下載到它。有 32bit 和 64bit 版本,同時也有中文語言包(但我不建議你安裝)。安裝完畢之後,如果你沒有安裝過 Git,那麼還需要去下載 msysGit 來安裝。因爲 TortoiseGit 其實只是一個殼,它需要調用 Git 命令行才能發揮作用。(現在你知道我爲什麼推薦你用命令行了麼?)
爲什麼 TortoiseGit 不像 TortoiseSVN 一樣,把 SVN 命令行工具集成在安裝包中呢?我猜想是以下幾點原因:
- Git 官方從未出過 Windows 版本二進制包;
- msysGit 和 TortoiseGit 是兩個不同的團隊開發的;
- msysGit 和 TortoiseGit 的更新週期差異較大;
- TortoiseGit 團隊希望安裝包更小;
- TortoiseGit 團隊給用戶更靈活的選擇 Git 版本的權利。
問題3:Git 如何 Clone 非 master 分支代碼
問題描述:在從 GitHub 上 Clone 項目下來的時候,如 https 方式克隆某個具有多個分支的項目:git clone https://github.com/TeamNewPipe/NewPipe.git
注:該分支默認分支爲 dev 分支,其他分支有 master 、multyservice 分支。
出現的問題是:克隆完畢,使用 git branch
查看本地分支,只能看到 dev 分支。如果想要是查看或是說克隆非默認分支代碼,如何操作呢?以下兩種解決方式供參考:
①第一種:
新的解決方法:先 git branch -a
列出本地和遠程所有分支,比如某個遠程分支爲 origin/daily/1.4.1,然後再直接使用 git checkout origin/daily/1.4.1
舊的解決方法:1、先在本地建立與遠程分支同名分支名稱;2、切換到該本地分支;3、建立上游分支,即 git branch --set-upstream-to=origin/daily/1.4.1 daily/1.4.1
,這樣完成與上游分支的關聯,然後 pull 就好了。
參考:Git 如何 clone 非 master 分支的代碼
②第二種:
Git 默認只顯示默認分支的數據,需要手動切換到我們需要的分支並顯示出來。
git branch
git checkout -b <本地分支名字> origin/<遠程分支名字>
這樣大功告成。
親測第二種方式是可以的。
問題4:git pull 和 git fetch 有什麼區別?
首先,你的每一個操作都是要指明【來源】和【目標】的,而對於 pull 來說,【目標】就是當前分支;
其次,你得清楚 Git 是有 tracking 的概念的,所謂 tracking 就是把【來源】和【目標】綁定在一起,節省一些操作是需要輸入的參數。
那麼,假設你的 master 和 develop 都是 tracking 了的,於是:
- 當你在 master 下,
git pull
等於 fetch origin,然後 merge origin/master - 當你在 develop 下,
git pull
等於 fetch origin,然後 merge origin/develop
參考:git pull 和 git fetch 有什麼區別?
4.2 筆記
筆記 1:在本地倉庫初始化後,不進行 commit 提交,則新建不了分支;進行了commit提交,則真正建立了 master 分支
在某些場合,Git 會自動在本地分支與遠程分支之間,建立一種追蹤關係(tracking)。比如,在 git clone 的時候,所有本地分支默認與遠程主機的同名分支,建立追蹤關係,也就是說,本地的 master分支自動"追蹤" origin/master 分支。Git 也允許手動建立追蹤關係:git branch --set-upstream master origin/next
該命令指定 master 分支追蹤 origin/next 分支。
——來自阮一峯老師的 Git 文章。
筆記 2:重命名本地和遠程分支名稱
在 Git 中重命名遠程分支,其實就是先刪除遠程分支,然後重命名本地分支,再重新提交一個遠程分支。
- 刪除分支的命令是:在 Git1.7 之後可以使用這個命令
git push origin --delete <遠程分支名稱>
,否則用這個也可以:git push origin :<遠程分支名稱>
表示推送一個空分支到遠程分支,其實就相當於刪除遠程分支; - 重命名本地分支:
git branch -m <舊名稱> <新名稱>
; - 重新提交:
git push origin <新名稱>:<新名稱>
。
五、Git圖形化客戶端—SourceTree
SourceTree 是 Windows 和 Mac OS X 下免費的 Git 和 Hg 客戶端,擁有可視化界面,容易上手操作。同時它也是 Mercurial 和 Subversion 版本控制系統工具。支持創建、提交、clone、push、pull 和 merge 等操作。SourceTree 官方下載:傳送門。
Sourcetree 可簡化您與 Mercurial 和 Git 存儲庫的交互,讓您集中精力編寫代碼。通過 Sourcetree 簡單的 Git 圖形用戶界面查看和管理您的存儲庫。
- 非常簡單,適合初學者:告別命令行 - 通過 Git 客戶端簡化分發版本的控制,快速爲每個人提供最新信息。
- 讓專家如虎添翼:非常適合用於提高高級用戶的工作效率。查看分支之間的變更集、stash、cherry-pick 等等。
- 可視化代碼:眼見真的爲實。單擊一次即可獲取有關所有分支或提交的信息。
- 桌面上的 Git 和 Hg:功能完善的圖形用戶界面,開箱即用,可提供高效、一致的開發流程。可與 Git 和 Mercurial 搭配使用。
網上資料:
六、其他內容
Git命令補充
git branch -vv
:查看本地分支關聯(跟蹤)的遠程分支之間的對應關係,本地分支對應哪個遠程分支。git push origin v0.1.2
:表示將 v0.1.2 標籤提交到 Git 服務器(通常的git push
不會將標籤對象提交到 Git 服務器,我們需要進行該顯式操作);如果將本地所有標籤一次性提交到 Git 服務器,可以git push origin –tags
刪除遠程分支和tag
- 刪除遠程分支:
git push origin --delete <branchName>
,否則,可以使用這種語法,推送一個空分支到遠程分支,其實就相當於刪除遠程分支:git push origin :<branchName>
- 刪除tag:
git push origin --delete tag <tagname>
,這也是刪除 tag 的方法,推送一個空 tag 到遠程tag:git tag -d <tagname>
、git push origin :refs/tags/<tagname>
合併多次 commit(參考)
總結:
git rebase -i HEAD~4 #可以看到最近 4 次的 commits,然後修改 commit 前面的爲 squash,改完後保存,後繼也會出現可以填寫該次的 message
git add .
git rebase --continue
git push -f # -f 強制推送到遠程服務器
參考:
修改未push和已經push的註釋信息
修改還未 push 的註釋:git commit --amend
,修改後保存退出。剛剛 push 到遠端還沒有人其他人下載或改動的:
git commit --amend
進入修改頁面修改註釋信息,修改後 :wq 保存退出。 再使用git push --force-with-lease origin master
。如果其他人已經下載或改動:
git fetch origin
git reset --hard origin/master
update:2018-01-28 v1.2
update:2019-02-12 標題由「Git個人學習筆記及心得」改爲「Git學習記錄(不斷更新)」;修改了某些文字的表達,並增加了「六、其他內容」這節內容。