學(xué)Git,為自己

劉小澤寫于18.12.18-19

了解到Git其實(shí)就是因?yàn)楹芗t的Github,但Git包含的東西比Github多多了。Git的魔力一直吸引著我,但目前還是只看到了Git的冰山一角,再次接觸希望有新收獲。

關(guān)于設(shè)定

開始使用git,先要設(shè)置使用者的email和名稱,比如在終端中輸入

 git config --global user.name "Bioplanet"
 git config --global user.email "Bioplanet520@outlook.com"

可以用git config --list查看當(dāng)前的設(shè)定

當(dāng)然使用--global是針對(duì)整個(gè)環(huán)境來(lái)講,如果想要根據(jù)不同的項(xiàng)目設(shè)定不同作者,就可以在項(xiàng)目目錄下替換為--local設(shè)定

我們都知道,工程師的美德之一就是懶惰,拋棄重復(fù)性工作,因此可以設(shè)置一些快捷方式幫助git更快處理

  • 與文本編輯器無(wú)縫連接
    我們都希望git可以直接在終端中打開編輯器如Sublime或者VS code,進(jìn)行代碼編寫,然后直接上傳到github備份。于是可以找到sublime的安裝目錄,在它的bin 目錄下有一個(gè)subl ,然后編輯bash_profile 【針對(duì)mac環(huán)境】,添加export PATH=$PATH:/Applications/Sublime\ Text.app/Contents/SharedSupport/bin 就好。之后就可以利用subl FILE 在terminal中直接用Sublime打開相應(yīng)的代碼了

  • 少打重復(fù)的字或者少打錯(cuò)字
    設(shè)置縮寫是比較不錯(cuò)的選擇,例如:

    git config --global alias.co checkout
    git config --global alias.br branch
    git config --global alias.st status
    git config --global alias.l "log --oneline --graph"
    

    當(dāng)然,這些都可以在~/.gitconfig中進(jìn)行修改


全新的開始

第一次使用最重要的就是git init ,想對(duì)哪個(gè)目錄進(jìn)行版本控制(簡(jiǎn)稱“版控”),就在哪個(gè)目錄下進(jìn)行該操作,結(jié)果就是在該目錄下生成了.git的隱藏目錄。

別看我們平時(shí)看不到它,它可儲(chǔ)存了整個(gè)Git的精華(也許正因如此,才讓目錄隱藏,避免用戶刪除)。因此,如果有一天,我們不想對(duì)這個(gè)目錄進(jìn)行版控了,那么只需要移除.git目錄就好

豆知識(shí) Doodle Tip:針對(duì)mac系統(tǒng),建議練習(xí)文件都放在一個(gè)名為/tmp的目錄下進(jìn)行,這個(gè)目錄有個(gè)最大的好處:在電腦重啟后里面的東西都會(huì)被清空,不需要手動(dòng)清理。但是,切記,重要內(nèi)容不要放在這個(gè)目錄下


文件放心交給Git吧

以下內(nèi)容都是作為新手的我踩過(guò)的坑,并且不止一次踩過(guò),以至于多個(gè)文件丟失,好在不是什么重要的。后來(lái)結(jié)合搜索的知識(shí)總結(jié)了一些重點(diǎn),感覺(jué)還是很有用的

先把文件添加進(jìn)暫存區(qū)

首先看看git status這個(gè)命令,它是用來(lái)查詢目錄當(dāng)前的狀態(tài),如果是一個(gè)新的目錄執(zhí)行這個(gè)指令,會(huì)返回nothing to commit 表示當(dāng)前沒(méi)有什么東西可以提交;
但是如果新建了一個(gè)文件,那么就會(huì)提示Untraced files,就是說(shuō)這個(gè)文件還沒(méi)有被加入Git版控系統(tǒng)中,并沒(méi)有被Git正式追蹤,僅僅是檢查到有這個(gè)東西;

我們有了Untracked文件,下面就是把新建的文件交給Git,讓它來(lái)管理、追蹤,也就是使用git add + 文件名稱或整個(gè)目錄,隨后不會(huì)提示任何信息,但是可以再次使用git status來(lái)查看當(dāng)前狀態(tài)。

只要git add后,文件的狀態(tài)就會(huì)變成new file,而不再是Untracked,表示此時(shí)文件被放在了暫存區(qū)(Staging Area),隨后看看有沒(méi)有一起做伴的,去到儲(chǔ)存庫(kù)中。

豆問(wèn)題1: 如果在git add之后,我們又修改了文件的內(nèi)容,會(huì)發(fā)生什么?

【例如:我們之前新增一個(gè)文件叫a.txt,然后我們使用git add a.txt將文件添加到暫存區(qū),突然想起來(lái)有個(gè)地方需要修改,于是又在終端中修改了a.txt

作為剛接觸Git的我們,一般會(huì)在修改完直接Commmit提交,把剛做的修改保存下來(lái)(因?yàn)槟J(rèn)commit命令是時(shí)刻跟隨我們的腳步的,我們修改到哪里,它就幫我們保存到哪里。其實(shí)并不是,它并沒(méi)有這么智能,還是需要我們的指令)

回到上面??的問(wèn)題,我們對(duì)文件做了修改,再git status一下(這里是不是就發(fā)現(xiàn)了:最常用的是status命令,我們是需要時(shí)刻提醒的,自己做到了哪一步)。得到的結(jié)果就變成了兩個(gè)a.txt文件了,一個(gè)new file: a.txt,一個(gè)modified: a.txt 。

這里的原因就是:我們?cè)诘诙教砑游募綍捍鎱^(qū)是沒(méi)錯(cuò)的,Git也幫我們記錄下來(lái)了;但是問(wèn)題出現(xiàn)在重新編輯后,這里編輯的內(nèi)容其實(shí)并沒(méi)有再次被加入暫存區(qū)。因此,實(shí)際上暫存區(qū)的內(nèi)容還是我們剛才第二步加入的原始內(nèi)容

當(dāng)然,也不是不能保存修改。如果確認(rèn)無(wú)誤,可以再次使用git add a.txt,將修改后的文件添加到暫存區(qū)

豆問(wèn)題2:在添加文件時(shí),如果想全部添加,是使用git add .還是git add -all呢?

這二者在git 2.0以上版本中確實(shí)都表示全部文件;但是還有有其他的差別,例如在git主目錄下有這幾個(gè)目錄,其中main.css和index.html都做了改動(dòng)。如果在根目錄下執(zhí)行git add .,那么這兩個(gè)改動(dòng)的文件都會(huì)被放如暫存區(qū);但是如果在css目錄下執(zhí)行git add.,那么就只有mian.css會(huì)被放入暫存區(qū)。

但是,我們用git add -all就不用擔(dān)心這個(gè)問(wèn)題,因?yàn)榧幢闶窃赾ss目錄下執(zhí)行這個(gè)操作,還是會(huì)把兩個(gè)修改文件都加入

再?gòu)臅捍鎱^(qū)提交到倉(cāng)庫(kù)中

上面的一大段文字都是在描述:如何將文件加入暫存區(qū),但是僅僅這樣是不夠的。暫存暫存,顧名思義它不會(huì)長(zhǎng)久。如果想讓暫存區(qū)的東西永久保存下來(lái),我們還需要用到git commit

一般用法就是:git commit -m "first commit" ,其中的-m以及后面的字符都是在說(shuō)明:你在這次commit的操作中干了啥。比如第一次提交這個(gè)文件就可以用first commit,簡(jiǎn)單清楚,讓別人和自己都能看懂就行,不限中英文。

這個(gè)操作結(jié)束后,Git就把暫存區(qū)的東西儲(chǔ)存到了倉(cāng)庫(kù)(Repository)中,也就是說(shuō):我Git完成了一個(gè)文件的存檔/備份,也就是做了第一份的版本建立。

直到Commit結(jié)束,才算完成了整個(gè)流程!

關(guān)于commit,還有一點(diǎn)知識(shí)需要了解:

  • Commit到底做了啥?

    其實(shí)它就是負(fù)責(zé)了暫存區(qū)的東西,也就是說(shuō),我們?cè)趫?zhí)行git commit的時(shí)候,那些沒(méi)有添加到暫存區(qū)中的檔案,就不會(huì)被Commit到倉(cāng)庫(kù)中

  • 另外,可不可以不加-m以及后面的啰嗦話?

    答案是:不能!因?yàn)闆](méi)有這個(gè)看似啰嗦,實(shí)際非常有用的語(yǔ)句,Git是不會(huì)允許你完成Commit的操作的。并且添加的話,那些模糊的話就不用加了,比如trouble shooting,我們就是想看shoot了什么trouble,這個(gè)重要的問(wèn)題需要指出,例如可以#12 bug fixed ,表示改正了12號(hào)錯(cuò)誤

  • Commit可不可以提交“空”?

    因?yàn)樵赗里,空也是被當(dāng)成字符來(lái)處理的(雖然很繞,它為空,應(yīng)該沒(méi)東西,但卻還占據(jù)著位置)。那么Commit其實(shí)也是可以的,但是除了作演示Git的合并以外一般沒(méi)啥用,可以使用git commit --allow-empty -m "empty" 提交一個(gè)“空”文檔,然后描述就是“empty”


三大重要空間

Git中的三大重要空間就是:工作區(qū)(Working directory)、暫存區(qū)(Staging area)、倉(cāng)庫(kù)(Repository),它們的關(guān)系是:

那么就有一個(gè)問(wèn)題:難道所有的流程都要通過(guò)add、commit后才能完成嗎?能不能簡(jiǎn)化流程?

其實(shí)可以在commit的時(shí)候加上一個(gè)參數(shù),如: git commit -a -m "update",但是這個(gè)參數(shù)只對(duì)已經(jīng)在倉(cāng)庫(kù)中的文件有效,對(duì)新加入的文件(即Untracked)的文件無(wú)效

其實(shí)用分段式管理還是不麻煩的,并且對(duì)所有文件通用:可以想象有個(gè)倉(cāng)庫(kù),倉(cāng)庫(kù)門口是個(gè)中轉(zhuǎn)站,中轉(zhuǎn)站上有貨物有進(jìn)有出,要存放到倉(cāng)庫(kù)的貨物可以先放到中轉(zhuǎn)站(git add),然后等待貨物達(dá)到一定數(shù)量了,就打開倉(cāng)庫(kù)門,把中轉(zhuǎn)站的貨物一起運(yùn)進(jìn)倉(cāng)庫(kù)(git commit),并且對(duì)每一批貨物都做好記錄(干嘛的、誰(shuí)送的)

為什么要攢一段時(shí)間再開一次倉(cāng)庫(kù)門呢?

其實(shí)來(lái)一件貨物開一次門是可以的,但是問(wèn)題就是記錄次數(shù)太多,讓Commit記錄變得太零散,如果讓別人看的時(shí)候,大家希望看到一個(gè)比較完整的內(nèi)容,而不是一個(gè)Commit接著一個(gè)看

因此,問(wèn)題又來(lái)了:什么時(shí)候選擇進(jìn)行Commit比較好?

沒(méi)什么硬性規(guī)定,當(dāng)完成一個(gè)任務(wù)時(shí)或者一天緊張的工作學(xué)習(xí)時(shí)光結(jié)束時(shí),可以備份也作為記錄


保持看記錄的習(xí)慣

回顧一般的操作流程:

touch a.txt                             # 建立文件 a.txt   
git add a.txt                           # 把 a.txt  加進(jìn)暫存區(qū)
git commit -m "first submit"            # 進(jìn)行 Commit

查看之前的記錄是用git log ,其中會(huì)包含幾項(xiàng)重要信息

  • Commit作者是誰(shuí)
  • 什么時(shí)候進(jìn)行的commit
  • 每次Commit都做了什么

另外,還會(huì)看到commit cc797cdb7c7a337824a25075e0dbe0bc7c703a1e 這種信息,看似亂碼,其實(shí)是非常關(guān)鍵的內(nèi)容:它其實(shí)是SHA-1 (Secure Hash Algorithm 1)演算得到的結(jié)果,特點(diǎn)就是重復(fù)率極低,因此可以當(dāng)做Commit的ID號(hào)【一般使用6-8位就足以區(qū)分不同的Commit了】

當(dāng)然,如果在git log后加上--oneline --graph,結(jié)果就會(huì)變得更精簡(jiǎn),一次顯示的結(jié)果更多

利用log信息,我們可以做的事情可以包括:

  • 查找某個(gè)人的Commit(團(tuán)隊(duì)協(xié)作中很重要)
    git log --oneline --author="doodle"
  • 查找包括某個(gè)字符的
    git log --oneline --grep="btw"
  • 還可以對(duì)Commit的文件進(jìn)行查找,比如想找提到“生信星球”的文件
    git log -S "生信星球"
  • 查詢歷史資料時(shí),可以限定時(shí)間
    git log --oneline --since="9am" --until="5pm" --after="2018-12"

不可避免的修改

在Git中,不管是刪除文件還是重命名,對(duì)Git都是一種 【修改】

關(guān)于修改的部分,比較零散,我在前面都加了編號(hào),表示不同的操作

1 刪除文件

方案一 自己刪除自己提交

可以把原來(lái)文件直接rm a.txt刪除,看下狀態(tài),就會(huì)提示deleted: a.txt。但這只是第一步,只是說(shuō)明我們做了更改,并不是本地刪除Git存檔中就刪除。但是還是要繼續(xù)往下走

# 還是先將做的修改加到暫存區(qū)
git add a.txt
# 看一下狀態(tài)
git status

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    deleted:    a.txt
# 說(shuō)明現(xiàn)在已經(jīng)加入了暫存區(qū),下面就要commit就可以了
方案二 Git幫忙刪

使用git rm a.txt可以省去add的步驟,然后直接commit就好了

2 只想把文件打入冷宮?

上面兩種辦法都是直接刪除文件(直接kill掉),萬(wàn)一我們只是想把文件從Git中移出來(lái),打入冷宮,并不kill它呢?

使用--cached參數(shù)即可

例如:git rm a.txt --cached ,提示信息會(huì)顯示:rm a.txt。實(shí)際上,并不是真的把文件刪了,而是把文件從Git中剔除,如果此時(shí)再查看一下狀態(tài),就會(huì)發(fā)現(xiàn)變成了Untracked

3 想變個(gè)名字時(shí)尚一下?

例如想把a.txt改為b.txt,也是可以用兩種方案:

方案一 自己改名

mv a.txt b.txt ,注意:雖然只有一個(gè)更改的動(dòng)作,但是Git完成了兩個(gè):一個(gè)是刪除a.txt文件,另一個(gè)是新建了b.txt文件。因此最后的狀態(tài)變成了Untracked。接下來(lái),只需要用git add --all,就會(huì)發(fā)現(xiàn)現(xiàn)在的狀態(tài)變成了renamed: a.txt -> b.txt

方案二 Git改名

利用git mv a.txt b.txt,也是想刪除操作一樣,可以少一步操作直接變成renamed狀態(tài)

事實(shí)上,Git并不在乎你取什么名字,它是根據(jù)文件內(nèi)容計(jì)算得到SHA-1值,然后當(dāng)我們更改文件名時(shí),Git的第一步只是指向了原來(lái)的文件,當(dāng)文件名改變后,Git才又為它重新生成一個(gè)新的編號(hào)/名稱

4 想修改Commit記錄?

如果有時(shí)因?yàn)榍榫w向Commit中摻雜了個(gè)人情感,事后感到后悔想修改下,一般有這幾種方法(嚴(yán)重性從大到小排列):

  • 整個(gè)刪除.git
  • 使用git rebase修改
  • 先用git reset拆除commit,整理后再重新commit
  • 利用--amend參數(shù)修改最后一次Commit
修修補(bǔ)補(bǔ)最后一次Commit amend

加入原來(lái)的log中有一句:

$ git log --oneline
3879515 GUN
5dbc437 add a.txt
357fce7 add container
adb4f43 update index 

現(xiàn)在感覺(jué)第一句不太恰當(dāng),想要做下修改,于是可以

$ git commit --amend -m "Good Ur Night"
[master 414a91c] Good Ur Night

當(dāng)然,如果不加-m參數(shù),就會(huì)彈出VIM窗口,讓你從里面編輯

想要修改更早的Commit =》 Rebase

amend只能修改最后一次的記錄,但是Rebase可以修改更早的

切記: 上面的例子可以看到,雖然我們只是改了下語(yǔ)言,但是最后的SHA-1值就發(fā)生了變化,于是就相當(dāng)于改變了時(shí)間線【看過(guò)”閃電俠”或者“蝴蝶效應(yīng)”的朋友都知道改變時(shí)間線的后果】。因此,盡量不要在push后重新修改

想要撤銷Commit =》Reset

例如現(xiàn)在的log包含了以下信息

$ git log --oneline
f12d8ef (HEAD -> master) add c.txt
83e7e30 add b.txt
687fce7 add a.txt

現(xiàn)在想要撤銷最后一次的Commit,就可以用git reset f12d8ef^【其中這個(gè)^表示前一次的Commit,如果是要到前兩次就^^,次數(shù)再多就直接f12d8ef~5 表示5次】。但是如果是返回HEAD這個(gè)Commit的話,還有種簡(jiǎn)單的方法可以表示:就是git reset master^或者git reset HEAD^

因此,如果想回到687fce7,就可以:git reset 687fce7、git reset HEAD~3git reset master~3 。第一種就像絕對(duì)路徑,而后兩種有點(diǎn)相對(duì)路徑的意思。

另外,reset還有三個(gè)參數(shù),它們還是有一些不同的,主要區(qū)別就是對(duì)從Commit中撤銷回來(lái)的文件怎么處理

模式 --mixed(默認(rèn)) --soft --hard
從Commit撤銷的文件去向 丟回工作目錄 丟回暫存區(qū) 直接丟棄

雖然我們知道,reset的英文含義是“重置”,但是在Git中更像“become”或者“go to”的意思,表示“去到哪里”。因此即便用了reset也不要有什么心理壓力,既然表示“去到哪里/變成什么樣子”,那我們也可以撤回,都不是事。不要認(rèn)為用了reset就和恢復(fù)出廠一樣的嚴(yán)重

例如:這里如果使用—hard參數(shù)從f12d8ef退回到687fce7,git reset HEAD~2 --hard ,那么暫時(shí)的結(jié)果就是只保留了687fce7的文件,其余全部消失。如果想恢復(fù)到reset之前的狀態(tài),把所有的文件再重新恢復(fù),可以看一下Git中的git reflog(里面存放了對(duì)HEAD的每一次改動(dòng)信息),看看之前的SHA-1值是多少,查到是f12d8ef,于是就可以用git reset f12d8ef --hard 把剛才reset的文件都撿回來(lái)

5 已經(jīng)Commit完,卻發(fā)現(xiàn)還有一個(gè)文件忘了加

一般會(huì)碰到多個(gè)文件一起Commit,但完成后發(fā)現(xiàn)忘了一個(gè),這時(shí)情況就比較尷尬:不想花一份同樣的時(shí)間卻只為了一個(gè)孤零零的文件;但是這個(gè)文件不添加又怕后來(lái)忘記。于是可以。。。

  • 使用git reset撤掉最后一次的Commit,加入新文件后重新Commit

  • 使用--amend進(jìn)行Commit

    例如:文件c.txt是被落下的,可以先git add c.txt,然后用git commit --amend --no-edit 就可以吧c.txt并入最后一次Commit【--no-edit表示我不想編輯Commit信息,所以也不要跳出來(lái)VIM編輯器了】

還是一樣,push前需要檢查清楚,盡量不在push后重新修改

6 可以只Commit文件的一部分嗎

git add時(shí)可以就加上-p參數(shù),然后Git就問(wèn)你需不需要把這個(gè)區(qū)塊(hunk)加入暫存區(qū),接下來(lái)選擇y就表示將整個(gè)檔案加入;選擇e就彈出編輯器,讓你自己刪除那些不想添加的區(qū)域,保存后離開,這部分就被加到暫存區(qū)了

7 Git對(duì)空目錄是不認(rèn)識(shí)的

比如新建一個(gè)目錄,想要Commit,但是git status 始終顯示工作目錄沒(méi)有發(fā)生任何修改,這是因?yàn)镚it是針對(duì)文件內(nèi)容進(jìn)行計(jì)算的,只有空目錄沒(méi)有內(nèi)容,它感受不到目錄存在。解決辦法就是:touch DIR/.keep 在新目錄下新建一個(gè)隱藏的文件就好,然后就繼續(xù)add +commit 就可以

8 誤刪了文件怎么辦?

很多情況下(尤其精神不好的時(shí)候),容易沖動(dòng)用rm搞砸一切,假入不小心刪除了Git目錄下的一些文件,此時(shí)的狀態(tài)都應(yīng)該是deleted。通過(guò)git checkout c.txt 可以救活一個(gè),想全部救活就用git checkout .

上面的操作全都是恢復(fù)到上一次commit操作,如果想恢復(fù)更遠(yuǎn)(例如兩個(gè)版本以前),就可以加個(gè)參數(shù):git checkout HEAD~2 c.txt

9 Git中經(jīng)常見到的HEAD是什么東西

在Git的邏輯中,HEAD相當(dāng)于一個(gè)風(fēng)向標(biāo),指向某個(gè)分支,而分支只想某個(gè)Commit。一般可以認(rèn)為HEAD是“目前所在的分支” 。HEAD信息存放在.git目錄下 ,cat .git/HEAD得到ref: refs/heads/master 信息。其中可以看到,目前HEAD指向master分支,看一下master分支中都有什么:cat .git/refs/heads/master ,結(jié)果就是這樣的字符:ecdfbac9f5fe463e078fb4f737ce39773895e121

因此,如果我們有多個(gè)分支(例如有master、doudou、huahau),想切換的話,可以用git checkout 。在變動(dòng)的時(shí)候,隨之改變的還有.git/HEAD文件和Reflog文件

10 修改歷史信息

感覺(jué)就像坐著時(shí)光機(jī)穿越似的,利用rebase這個(gè)時(shí)光機(jī)可以回到過(guò)去,修改多個(gè)歷史的Commit信息

先看看當(dāng)前的記錄:git log --oneline ,然后選擇一個(gè)時(shí)間節(jié)點(diǎn)git rebase -i bc08d2 (其中-i是互動(dòng)模式),之后會(huì)打開一個(gè)編輯器,其中開頭的pick 意思是保留Commit,不做修改。找到想改的Commit行,把pick改成reword,保存離開。接著就會(huì)跳到我們要改的那個(gè)Commit的編輯器中,更改完信息后,保存退出;進(jìn)行下一個(gè)...【需要注意的是:在互動(dòng)模式中,文件從上到下是由舊到新,正好與log記錄中相反】

如果改著改著,中途不小心退出了,不用擔(dān)心。其實(shí)Git是為你保留了記錄的,接下來(lái)選擇git rebase --continue就是繼續(xù),選擇--abort 就是徹底退出之前的編輯。

我們改完后,如果想回到修改之前,需要用到git reset ORIG_HEAD --hard

11 合并臃腫的Commit信息

有時(shí)候,我們?cè)谔峤籆ommit信息時(shí),難免有些復(fù)雜,比如一個(gè)文件寫add doodle 1 ,另一個(gè)又寫add doodle 2 ,一個(gè)Commit的利用率不高(這里的一個(gè)Commit只對(duì)一個(gè)文件有效,造成了最后log文件的繁瑣)。如果可以將多個(gè)相似的Commit進(jìn)行合并,是不是能清爽一些?

像上面一樣,還是先git log --oneline ,再git rebase -i bc08d2 ,只不過(guò)對(duì)于要合并的Commit的信息將pick改成squash ,最后在彈出的編輯器中進(jìn)行編輯,保存就結(jié)束了

12 撤銷三兄弟

  • Reset : 改變歷史記錄【把目前狀態(tài)設(shè)成某個(gè)指定的Commit狀態(tài),一般用于未push的Commit】
  • Rebase: 改變歷史記錄【新增、修改、刪除Commit都很方便,一般用于未push的Commit】
  • Revert:不改變歷史記錄【新增一個(gè)Commit來(lái)對(duì)之前的Commit做反轉(zhuǎn),當(dāng)然原來(lái)的Commit還是會(huì)留在歷史記錄中,一般用于push過(guò)的Commit】

13 打個(gè)Tag

一般當(dāng)我們認(rèn)為自己的代碼完成了里程碑式的發(fā)展時(shí),比如開發(fā)版本1.0.0或者beta發(fā)布,一般會(huì)打個(gè)tag

分為輕量標(biāo)簽(lightweight tag)和附注標(biāo)簽(annotated tag)

官方說(shuō)明:Annotated tags are meant for release while lightweight tags are meant for private or temporary object labels

  • 輕量標(biāo)簽:相當(dāng)于一個(gè)貼紙,直接粘上就完事,例如git tag douhua 347dfe
  • 附注標(biāo)簽:含有的信息會(huì)多一些,像一個(gè)簡(jiǎn)短的介紹,例如git tag douhua 347dfe -a -m "Doudou and Huahua" (-a 表示 annotation;-m 和Commit中的一個(gè)意思)

刪除標(biāo)簽使用-d參數(shù),例如git tag -d douhua

既然標(biāo)簽和分支都充當(dāng)風(fēng)向標(biāo),那么有什么不同嗎?

當(dāng)Commit修改時(shí),分支是隨之移動(dòng)的,而標(biāo)簽還在原地,牢牢貼在那里


分支?分身?

假入你有一個(gè)分身,你要讓他干嘛呢?

答:幫你嚇退敵人;幫你學(xué)生信;幫你寫作業(yè);幫你做實(shí)驗(yàn)。。。這些確實(shí)都是不錯(cuò)的選擇,但是分身有個(gè)最大的作用就是:一旦任務(wù)執(zhí)行失敗,本體并不受影響

如果我們的任務(wù)比較復(fù)雜,尤其一個(gè)package需要多個(gè)人共同完成時(shí),就不能隨便Commit。我們可以在另一個(gè)分支中來(lái)測(cè)試某些新功能或者修復(fù)某些bug,當(dāng)效果滿意時(shí)我們可以選擇合并到主線;即便效果不好,也不會(huì)對(duì)主線造成影響

新接觸一個(gè)分支

查看分支很簡(jiǎn)單,直接git branch就好,預(yù)先設(shè)置的都是master分支,當(dāng)前分支前面有*標(biāo)明

想要增加一個(gè)分支,可以直接加上名字git branch doodle ,這樣就增加了一個(gè)doodle的分支

分支名字不夠霸氣?改!例如有一個(gè)分支叫紫薯,我們完全可以用git branch -m 紫薯 紫薯俠 ,即便是預(yù)先安裝的master也可以改

刪除分支也是可以的:使用git branch -d test ,但是這里如果test分支還沒(méi)有合并到主線,刪除時(shí)會(huì)提醒你。如果真的不想要他了,并且不要合并,可以用-D強(qiáng)制刪除。因此,所有的分支都能刪,包括master,只不過(guò)不能刪當(dāng)前的分支(就像conda刪除環(huán)境一樣,不能刪除當(dāng)前所在的)

想要切換分支? 直接git checkout doodle ,隨后星號(hào)就移到了doodle上面

什么?切換分支文件丟失!

加入我們?cè)赿oodle分支下新建了兩個(gè)文件,并且add+commit 后也確實(shí)看到文件在列表中;但是如果切回原來(lái)的master分支,發(fā)現(xiàn)新建的兩個(gè)文件沒(méi)了,其實(shí)不用擔(dān)心,文件還在,只不過(guò)在當(dāng)前分支顯示不出來(lái)。我們只需要切換回原來(lái)的doodle分支就好了

切換到不存在的分支可以么?

一般來(lái)說(shuō),我們都要先建立一個(gè)分支,然后再切換。但是如果想切換到一個(gè)之前沒(méi)有建立過(guò)的分支,有一個(gè)快速的辦法就是git checkout -b 新分支名字 【-b參數(shù)的作用就是:如果切換的分支存在,就直接切換;如果不存在,就新建一個(gè)分支,然后切換過(guò)去】

或者可以利用這個(gè)命令,在之前的某個(gè)Commit來(lái)新建一個(gè)分支,感覺(jué)就好像 ”回到年輕時(shí),做點(diǎn)不一樣的事“,例如之前有一個(gè)Commit 347dfe4值,我們想回到這里新建一個(gè)huahau的分支:git branch huahau 347dfe4

分支合并

如果我們之前新建了分支doodle,并且在doodle中Commit了兩個(gè)文件,然后想要回到master分支,把doodle中的文件合并過(guò)來(lái),可以用:git checkout master + git merge doodle ,這時(shí)master中就會(huì)出現(xiàn)doodle中的兩個(gè)文件。

那么合并完的分支還要繼續(xù)留著么?

其實(shí)按道理講,主線master已經(jīng)擁有了doodle的一切,那么doodle就沒(méi)有作用了。但是如果不想讓自己對(duì)親分身有”過(guò)河拆橋“的愧疚的話??,留著也不是不行。完全看自己

沒(méi)有合并的分支不小心被砍掉,怎么辦?

合并完的我們可以隨心意,但是如果使用了git branch -D強(qiáng)行刪除沒(méi)有合并的分支,就會(huì)給你一個(gè)信息(Deleted branch doodle (was c274a5a).),其中那串Commit字符SHA-1值很重要,就是你的”后悔藥“。我們知道,分支只是一個(gè)指向某一Commit的風(fēng)向標(biāo),刪除這個(gè)風(fēng)向標(biāo)并不會(huì)導(dǎo)致Commit消失

于是想要恢復(fù)分支,可以利用原來(lái)的Commit SHA-1值,用git branch new_doodle c274a5a 來(lái)迎接老朋友【還是那句話,SHA-1值不需要刻意記憶,需要去到Reflog中查詢】

只要某個(gè)分支的某幾個(gè)Commit

使用cherry-pick 加上想要的Commit號(hào),就把那個(gè)Commit內(nèi)容復(fù)制過(guò)來(lái),于是在當(dāng)前的分支上就多了一個(gè)commit。加多個(gè)Commit就在命令后多寫幾個(gè)Commit號(hào)。

默認(rèn)情況是復(fù)制過(guò)來(lái)就合并到當(dāng)前分支的,如果不想合并只放在暫存區(qū),就用git cherry-pick --no-commit


什么?記錄到一半,又有新任務(wù)?

我們的學(xué)習(xí)過(guò)程都是并行的,可能同時(shí)手頭有多個(gè)任務(wù),如果自己在做一項(xiàng),同時(shí)又有新任務(wù)來(lái),并且很緊急,那么就需要切換到重要級(jí)優(yōu)先的任務(wù)中去。

先不管那么多,先保存目前的所有修改git add -all ,然后Commitgit commit -m "not finish yet" ,接下來(lái)就可以切換到其他分支去工作,做完后再切換回之前的分支,最后Reset一下git reset HEAD^


了解了Git,那GitHub呢?

首先說(shuō)GitHub的G和H是大寫哦,它是一個(gè)商業(yè)網(wǎng)站,目前是全球最大的Git Server。為什么這么多人在用,并且代碼都放上面?因?yàn)樵贕itHub上造假是非常麻煩的事情,而且我們知道,開發(fā)者都有懶惰的美德。因此,自己做過(guò)什么貢獻(xiàn),開發(fā)過(guò)什么項(xiàng)目一目了然,可以說(shuō),GitHub是開發(fā)者最好的簡(jiǎn)歷。

讓本地與遠(yuǎn)端保持同步

有時(shí)我們會(huì)在網(wǎng)站上直接更改,如果本地想保持最新,可以用git pull --rebase 。我們知道,這也算是一個(gè)合并的任務(wù),因此也會(huì)在本地默認(rèn)加上Commit,加上rebase的目的就是不要加這個(gè)關(guān)于合并的Commit

本地推不上去什么鬼?

有時(shí)本地push會(huì)報(bào)錯(cuò)

$ git push
To https://github.com/eddiekao/dummy-git.git
 ! [rejected]        master -> master (fetch first)

這是因?yàn)檫h(yuǎn)端比本地的版本還新,Git不想這么做,解決辦法如下:

先拉再推,就是先從遠(yuǎn)端pull到最新版git pull --rebase ,如果合并沒(méi)有沖突,再往上推

甚至還有一種:git push -f使用蠻力往上推,造成的影響就是可能會(huì)把共同開發(fā)者的版本覆蓋掉,導(dǎo)致他們資料丟失【一般不用!

網(wǎng)上發(fā)現(xiàn)某人寫的不錯(cuò),想拷貝到本地看看

使用git clone,可以選擇HTTPS或者SSH,如果clone下來(lái)想保存不同的名稱,可以在命令后面加目錄名

git clone xxx doodle ,于是就把xxx上的整個(gè)內(nèi)容(包括歷史記錄、分支、標(biāo)簽等)復(fù)制到本地一份,保存為doodle

一般來(lái)講,clone命令只需要用一次,并且命好名字,之后想追更新,直接用pull就好

小叉子Fork用起來(lái)

Pull Request (PR)過(guò)程就是一個(gè)相互交流、共同開發(fā)的過(guò)程,事情是這樣的:

  • 先是從GitHub上看到一個(gè)作者寫的東西,自己感興趣,于是自己先Fork一份原作者的文檔到自己的賬戶下
  • 自己擁有所有修改權(quán)限,想怎么動(dòng)就怎么動(dòng)
  • 改完后,push回自己的賬號(hào),然后給原作者發(fā)通知,說(shuō)你幫他搞了一點(diǎn)新功能,請(qǐng)查收
  • 作者如果滿意,就會(huì)把你的工作merge到他的文檔中

想要?jiǎng)h除遠(yuǎn)端的分支

比如本地的分支是master,遠(yuǎn)端服務(wù)器地址是origin表示【如果要本地修改遠(yuǎn)端倉(cāng)庫(kù)名稱,可以用git remote rename; 或者修改遠(yuǎn)端倉(cāng)庫(kù)的URL: git remote set-url origin url

復(fù)習(xí)一下:如果我們要將本地的文件推到遠(yuǎn)端,并且建立遠(yuǎn)端分支doodle,可以用git push -u origin master:doodle 就是說(shuō),將本地的master推上去后,本來(lái)默認(rèn)是在遠(yuǎn)端建立一個(gè)相同名字的分支,但現(xiàn)在指定了叫doodle

這個(gè)origin怎么來(lái)的呢?是利用git remote add得到的,如果我們命名為huahua,那么也可以用huahua表示遠(yuǎn)端服務(wù)器的地址

現(xiàn)在我們有了遠(yuǎn)端分支doodle,那么怎么刪除它?

其實(shí)我們只需要把原來(lái)push操作中的本地分支變成空,就相當(dāng)于刪除了遠(yuǎn)端分支。也就是說(shuō),上傳一個(gè)空的分支到遠(yuǎn)端git push origin :doodle


歡迎關(guān)注我們的公眾號(hào)~_~  
我們是兩個(gè)農(nóng)轉(zhuǎn)生信的小碩,打造生信星球,想讓它成為一個(gè)不拽術(shù)語(yǔ)、通俗易懂的生信知識(shí)平臺(tái)。需要幫助或提出意見請(qǐng)后臺(tái)留言或發(fā)送郵件到Bioplanet520@outlook.com

Welcome to our bioinfoplanet!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Git 基礎(chǔ) 基本原理 客戶端并不是只提取最新版本的文件快照,而是把代碼倉(cāng)庫(kù)完整的鏡像下來(lái)。這樣一來(lái),任何一處協(xié)同...
    __silhouette閱讀 16,221評(píng)論 5 147
  • Git 命令行學(xué)習(xí)筆記 Git 基礎(chǔ) 基本原理 客戶端并不是只提取最新版本的文件快照,而是把代碼倉(cāng)庫(kù)完整的鏡像下來(lái)...
    sunnyghx閱讀 4,165評(píng)論 0 11
  • 2017.8.10晴 作為一個(gè)管理者,想要帶領(lǐng)和管理好自己的團(tuán)隊(duì),最起碼要遵守以下幾個(gè)原則: 1.以身作則 管理好...
    明珠王蕾閱讀 426評(píng)論 0 1
  • 【愛(ài)也有怨氣~家族事件的糾纏】 孩子,一個(gè)永遠(yuǎn)活在良知與愛(ài)的能量之中的個(gè)體,她們無(wú)論何時(shí)何地都在父母賦予的生命中左...
    梵愛(ài)的世界閱讀 413評(píng)論 0 0
  • 午夜 是萬(wàn)物酣暢而眠的時(shí)刻 而我卻在不經(jīng)意中醒來(lái) 當(dāng)我彷徨獨(dú)立 臨窗遠(yuǎn)眺時(shí)—— 我的眼里布滿了夜的顏色 夜空里晶瑩...
    當(dāng)今麥田閱讀 376評(píng)論 1 2

友情鏈接更多精彩內(nèi)容