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