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