git筆記(廖雪峯git教程)及自己總結Q&A

集中式和分佈式的區別:svn和git

先說集中式版本控制系統,版本庫是集中存放在中央服務器的,而幹活的時候,用的都是自己的電腦,所以要先從中央服務器取得最新的版本,然後開始幹活,幹完活了,再把自己的活推送給中央服務器。中央服務器就好比是一個圖書館,你要改一本書,必須先從圖書館借出來,然後回到家自己改,改完了,再放回圖書館。

集中式的弊端:必須聯網,而且在互聯網的情況下,網速會很慢。

和集中式版本控制系統相比,分佈式版本控制系統的安全性要高很多,因爲每個人電腦裏都完整的版本庫,某一個人的電腦壞掉了不要緊,隨便從其他人那裏複製一個就可以了。而集中式版本控制系統的中央服務器要是出了問題,所有人都沒法幹活了。

在實際使用分佈式版本控制系統的時候,其實很少在兩人之間的電腦上推送版本庫的修改,因爲可能你們倆不在一個局域網內,兩臺電腦互相訪問不了,也可能今天你的同事病了,他的電腦壓根沒有開機。因此,分佈式版本控制系統通常也有一臺充當“中央服務器”的電腦,但這個服務器的作用僅僅是用來方便“交換”大家的修改,沒有它大家也一樣幹活,只是交換修改不方便而已。

 

 

下載版本,創建版本庫:

安裝成功後:

下載安裝包鏈接:https://git-scm.com/download/win

安裝目錄是:E:\Program Files\PortableGit

安裝完成後,在開始菜單裏找到“Git”->“Git Bash”,蹦出一個類似命令行窗口的東西,就說明Git安裝成功!

做配置:

$ git config --global user.name "fang"

$ git config --global user.email "[email protected]"

注意git config命令的--global參數,用了這個參數,表示你這臺機器上所有的Git倉庫都會使用這個配置,當然也可以對某個倉庫指定不同的用戶名和Email地址。

git上:創建版本庫:如果你使用Windows系統,爲了避免遇到各種莫名其妙的問題,請確保目錄名(包括父目錄)不包含中文。

cd : change directory的簡寫,改變目錄的意思,就是切換到哪個目錄下, 如 cd e:\fff  切換 E 盤下面的fff 目錄。

 

新建一個版本庫的目錄:

mkdir learngit

cd learngit

 

git init 進行初始化;

E:\git_df\learngit\.git目錄不要隨意改動目錄下的文件,否則會把Git倉庫給破壞了。

 

 

把文件添加到版本庫:

使用Windows的童鞋要特別注意:

千萬不要使用Windows自帶的記事本編輯任何文本文件。

建議你下載Notepad++代替記事本,不但功能強大,而且免費!記得把Notepad++的默認編碼設置爲UTF-8 without BOM即可。---設置---UTF-8

書寫一個readme.txt,上傳到倉庫中:

簡單解釋一下git commit命令,-m後面輸入的是本次提交的說明,可以輸入任意內容,當然最好是有意義的,這樣你就能從歷史記錄裏方便地找到改動記錄。-m的信息最好不要省略。

git commit命令執行成功後會告訴你,1 file changed:1個文件被改動(我們新添加的readme.txt文件);2 insertions:插入了兩行內容(readme.txt有兩行內容)。

爲什麼Git添加文件需要add,commit一共兩步呢?因爲commit可以一次提交很多文件,所以你可以多次add不同的文件,比如:

總結:

現在總結一下今天學的兩點內容:

初始化一個Git倉庫,使用git init命令。

添加文件到Git倉庫,分兩步:

  1.  使用命令git add <file>,注意,可反覆多次使用,添加多個文件;
  2. 使用命令git commit -m <message>,完成。

Git時光穿梭機:回退版本

總結;

要隨時掌握工作區的狀態,使用git status命令。 如果git status告訴你有文件被修改過,用git diff可以查看修改內容。

 

版本回退:

git log命令顯示從最近到最遠的提交日誌,我們可以看到3次提交,最近的一次是append GPL,上一次是add distributed,最早的一次是wrote a readme file。

如果嫌輸出信息太多,看得眼花繚亂的,可以試試加上--pretty=oneline參數:

commit id(版本號)而是一個SHA1計算出來的一個非常大的數字,用十六進制表示,是唯一的,因爲Git是分佈式的版本控制系統,後面我們還要研究多人在同一個版本庫裏工作,如果大家都用1,2,3……作爲版本號,那肯定就衝突了。

回退版本:

首先,Git必須知道當前版本是哪個版本,在Git中,用HEAD表示當前版本,也就是最新的提交1094adb...(注意我的提交ID和你的肯定不一樣),上一個版本就是HEAD^,上上一個版本就是HEAD^^,當然往上100個版本寫100個^比較容易數不過來,所以寫成HEAD~100。

git reset --hard HEAD^  回退到倒數第一個版本

git reset --hard HEAD^^ 回退到倒數第二個版本

git reset --hard 1094a   ---回退到指定的版本:1094a(是commit id的前幾個)

回退之後,還想知道曾經最新的版本,可以用命令:git reflog(記錄每一步操作)

總結:

HEAD指向的版本就是當前版本,因此,Git允許我們在版本的歷史之間穿梭,使用命令git reset --hard commit_id。

穿梭前,用git log可以查看提交歷史,以便確定要回退到哪個版本。

要重返未來,用git reflog查看命令歷史,以便確定要回到未來的哪個版本

 

暫存區:Git和其他版本控制系統如SVN的一個不同之處就是有暫存區的概念

 

工作區:就是你在電腦裏能看到的目錄,比如我的learngit文件夾就是一個工作區:

版本庫(Repository):工作區一個隱藏目錄.git,這個不算工作區,而是Git的版本庫。Git的版本庫裏存了很多東西,其中最重要的就是稱爲stage(或者叫index)的暫存區,還有Git爲我們自動創建的第一個分支master,以及指向master的一個指針叫HEAD。

你可以簡單理解爲,需要提交的文件修改通通放到暫存區,然後,一次性提交暫存區的所有修改。

git add  file1-n :是把文件1-n都放在暫存區,git  commit  是一次性把暫存區的所有修改都提交到master分支中。

暫存區是Git非常重要的概念,弄明白了暫存區,就弄明白了Git的很多操作到底幹了什麼。

管理修改

爲什麼Git比其他版本控制系統設計得優秀,因爲Git跟蹤並管理的是修改,而非文件。

第一次修改 -> git add -> 第二次修改 -> git add -> git commit

現在,你又理解了Git是如何跟蹤修改的,每次修改,如果不用git add到暫存區,那就不會加入到commit中。

撤銷修改

git checkout -- file可以丟棄工作區的修改:

git checkout -- file命令中的--很重要,沒有--,就變成了“切換到另一個分支”的命令,我們在後面的分支管理中會再次遇到git checkout命令。

git reset HEAD <file>可以把暫存區的修改撤銷掉(unstage),重新放回工作區:

小結:

場景1:當你改亂了工作區某個文件的內容,想直接丟棄工作區的修改時,用命令git checkout -- file。

場景2:當你不但改亂了工作區某個文件的內容,還添加到了暫存區時,想丟棄修改,分兩步,第一步用命令git reset HEAD <file>,就回到了場景1,第二步按場景1操作。

場景3:已經提交了不合適的修改到版本庫時,想要撤銷本次提交,參考版本回退一節,不過前提是沒有推送到遠程庫。

刪除文件

另一種情況是刪錯了,因爲版本庫裏還有呢,所以可以很輕鬆地把誤刪的文件恢復到最新版本:git checkout其實是用版本庫裏的版本替換工作區的版本,無論工作區是修改還是刪除,都可以“一鍵還原”。

命令git rm用於刪除一個文件。如果一個文件已經被提交到版本庫,那麼你永遠不用擔心誤刪,但是要小心,你只能恢復文件到最新版本,你會丟失最近一次提交後你修改的內容

Git分支管理

但Git的分支是與衆不同的,無論創建、切換和刪除分支,Git在1秒鐘之內就能完成!無論你的版本庫是1個文件還是1萬個文件。

創建和合並分支

head指針指向誰,就是這個分支。

head指向master,就是master分支,

指向dev,就是dev分支;

切換到git的目錄E:\git_df\learngit\.git,再執行git命令:

Git鼓勵大量使用分支:

查看分支:git branch

創建分支:git branch <name>

切換分支:git checkout <name>

創建+切換分支:git checkout -b <name>

合併某分支到當前分支:git merge <name>

刪除分支:git branch -d <name>

解決衝突:

當Git無法自動合併分支時,就必須首先解決衝突。解決衝突後,再提交,合併完成。

解決衝突就是把Git合併失敗的文件手動編輯爲我們希望的內容,再提交。

用git log --graph命令可以看到分支合併圖。

git log --graph --pretty=oneline --abbrev-commit  查看分支合併細節

分支管理策略:

通常,合併分支時,如果可能,Git會用Fast forward模式,但這種模式下,刪除分支後,會丟掉分支信息。

如果要強制禁用Fast forward模式,Git就會在merge時生成一個新的commit,這樣,從分支歷史上就可以看出分支信息。

下面我們實戰一下--no-ff方式的git merge:

首先,仍然創建並切換dev分支:

$ git checkout -b dev

Switched to a new branch 'dev'

修改readme.txt文件,並提交一個新的commit:

$ git add readme.txt

$ git commit -m "add merge"

[dev f52c633] add merge

 1 file changed, 1 insertion(+)

 

現在,我們切換回master:

$ git checkout master

Switched to branch 'master'

準備合併dev分支,請注意--no-ff參數,表示禁用Fast forward:

$ git merge --no-ff -m "merge with no-ff" dev

Merge made by the 'recursive' strategy.

 readme.txt | 1 +

 1 file changed, 1 insertion(+)

因爲本次合併要創建一個新的commit,所以加上-m參數,把commit描述寫進去。

合併後,我們用git log看看分支歷史:

$ git log --graph --pretty=oneline --abbrev-commit

*   e1e9c68 (HEAD -> master) merge with no-ff

|\ 

| * f52c633 (dev) add merge

|/ 

*   cf810e4 conflict fixed

...

 

可以看到,不使用Fast forward模式,merge後就像這樣:

 

分支策略

在實際開發中,我們應該按照幾個基本原則進行分支管理:

首先,master分支應該是非常穩定的,也就是僅用來發布新版本,平時不能在上面幹活;

那在哪幹活呢?幹活都在dev分支上,也就是說,dev分支是不穩定的,到某個時候,比如1.0版本發佈時,再把dev分支合併到master上,在master分支發佈1.0版本;

你和你的小夥伴們每個人都在dev分支上幹活,每個人都有自己的分支,時不時地往dev分支上合併就可以了。

所以,團隊合作的分支看起來就像這樣:

 

小結

Git分支十分強大,在團隊開發中應該充分應用。

合併分支時,加上--no-ff參數就可以用普通模式合併,合併後的歷史有分支,能看出來曾經做過合併,而fast forward合併就看不出來曾經做過合併。

 

 

修改bug時:

幸好,Git還提供了一個stash功能,可以把當前工作現場“儲藏”起來,等以後恢復現場後繼續工作:

把工作區的內容保存:

git stash :把工作區的內容保存

git stash  list:查看工作區的內容

git stash pop:恢復的同時把stash內容也刪了

git stash apply恢復,但是恢復後,stash內容並不刪除,你需要用git stash drop來刪除;

 

修復bug時,我們會通過創建新的bug分支進行修復,然後合併,最後刪除;

當手頭工作沒完成時,先把工作現場git stash一下,然後去修復bug,修復後,再git stash pop,回到工作現場。

 

開發一個新feature,最好新建一個分支;

如果要丟棄一個沒有被合併過的分支,可以通過git branch -D <name>強行刪除。

 

但是,並不是一定要把本地分支往遠程推送,那麼,哪些分支需要推送,哪些不需要呢?

master分支是主分支,因此要時刻與遠程同步;

dev分支是開發分支,團隊所有成員都需要在上面工作,所以也需要與遠程同步;

bug分支只用於在本地修復bug,就沒必要推到遠程了,除非老闆要看看你每週到底修復了幾個bug;

 feature分支是否推到遠程,取決於你是否和你的小夥伴合作在上面開發。

總之,就是在Git中,分支完全可以在本地自己藏着玩,是否推送,視你的心情而定!

 

小結:

查看遠程庫信息,使用git remote -v;

本地新建的分支如果不推送到遠程,對其他人就是不可見的;

從本地推送分支,使用git push origin branch-name,如果推送失敗,先用git pull抓取遠程的新提交;

在本地創建和遠程分支對應的分支,使用git checkout -b branch-name origin/branch-name,本地和遠程分支的名稱最好一致;

建立本地分支和遠程分支的關聯,使用git branch --set-upstream branch-name origin/branch-name; 從遠程抓取分支,使用git pull,如果有衝突,要先處理衝突。

 

 

Git賬號、無密碼登錄、克隆倉庫

GitHub的神奇的網站,顧名思義,該網站就是提供Git倉庫託管服務的,所以,只要註冊一個GitHub賬號,就可以免費獲得Git遠程倉庫。

在繼續閱讀後續內容前,請自行註冊GitHub賬號。由於你的本地Git倉庫和GitHub倉庫之間的傳輸是通過SSH加密的,所以,需要一點設置:

github的用戶名和密碼:

Sunnyfang3

https://github.com/Sunnyfang3/learngit.git

在繼續閱讀後續內容前,請自行註冊GitHub賬號。由於你的本地Git倉庫和GitHub倉庫之間的傳輸是通過SSH加密的,所以,需要一點設置:

ssh-keygen -t rsa -C "[email protected]"
你需要把郵件地址換成你自己的郵件地址,然後一路回車,使用默認值即可,由於這個Key也不是用於軍事目的,所以也無需設置密碼。

如果一切順利的話,可以在用戶主目錄裏找到.ssh目錄,裏面有id_rsa和id_rsa.pub兩個文件,這兩個就是SSH Key的祕鑰對,id_rsa是私鑰,不能泄露出去,id_rsa.pub是公鑰,可以放心地告訴任何人。
第2步:登陸GitHub,打開“Account settings”,“SSH Keys”頁面:
然後,點“Add SSH Key”,填上任意Title,在Key文本框裏粘貼id_rsa.pub文件的內容:
點“Add Key”,你就應該看到已經添加的Key:

生成ssh祕鑰:

C:\Users\zhanglei\.ssh

 

往github上添加本地的倉庫,保證本地倉庫和github上的庫保持一致:

git remote add origin [email protected]:Sunnyfang3/learngit.git

下一步,就可以把本地庫的所有內容推送到遠程庫上:

git push -u origin master  ---第一次推時,就添加-u這個參數

 

把本地庫的內容推送到遠程,用git push命令,實際上是把當前分支master推送到遠程。

以後再將本地的庫內容

$ git push origin master  

遇到小問題:當連接暫時無法建立時,要選擇yes,進行重試;(估計跟本地網絡問題有關。)

 

 

 

總結:

 

要關聯一個遠程庫,使用命令git remote add origin git@server-name:path/repo-name.git;

關聯後,使用命令git push -u origin master第一次推送master分支的所有內容;

此後,每次本地提交後,只要必要,就可以使用命令git push origin master推送最新修改;

分佈式版本系統的最大好處之一是在本地工作完全不需要考慮遠程庫的存在,也就是有沒有聯網都可以正常工作,而SVN在沒有聯網的時候是拒絕幹活的!當有網絡的時候,再把本地提交推送一下就完成了同步,真是太方便了!

 

如果克隆一個庫:

要克隆一個倉庫,首先必須知道倉庫的地址,然後使用git clone命令克隆。例如在本地:

git clone [email protected]:michaelliao/gitskills.git

Git支持多種協議,包括https,但通過ssh支持的原生git協議速度最快。

 

 

標籤管理:

發佈一個版本時,我們通常先在版本庫中打一個標籤(tag),這樣,就唯一確定了打標籤時刻的版本。將來無論什麼時候,取某個標籤的版本,就是把那個打標籤的時刻的歷史版本取出來。所以,標籤也是版本庫的一個快照。

 

所以,tag就是一個讓人容易記住的有意義的名字,它跟某個commit綁在一起。

 

創建標籤:

git tag <name>就可以打一個新標籤:默認標籤是打在最新提交的commit上的。

git tag查看所有標籤:

 

git tag v0.9 f52c633  對某個commit id對象的版本打tag。方便對歷史版本進行打tag‘

git show <tagname>查看標籤信息:

git tag不是按照打tag的時間排序的,是按照字母排序的。

git tag -a v0.1 -m "version 0.1 released" 1094adb:還可以創建帶說明的標籤,用-a指定標籤名,-m指定說明文字

注意:標籤總是和某個commit掛鉤。如果這個commit既出現在master分支,又出現在dev分支,那麼在這兩個分支上都可以看到這個標籤。

 

 

 

git  tag  -d  tagname      刪除一個標籤:git tag -d v0.1;因爲創建的標籤都只存儲在本地,不會自動推送到遠程。所以,打錯的標籤可以在本地安全刪除。

git push origin <tagname> :如果要推送某個標籤到遠程

git push origin --tags或者,一次性推送全部尚未推送到遠程的本地標籤:

 

如果標籤已經推到遠程了,要先刪除本地的標籤,然後再推送到遠程即可;

git tag -d v0.9

git push origin :refs/tags/v0.9

要看看是否真的從遠程庫刪除了標籤,可以登陸GitHub查看。

小結:

命令git push origin <tagname>可以推送一個本地標籤;

命令git push origin --tags可以推送全部未推送過的本地標籤;

命令git tag -d <tagname>可以刪除一個本地標籤;

命令git push origin :refs/tags/<tagname>可以刪除一個遠程標籤

 

小結:

在GitHub上,可以任意Fork開源倉庫;

 

 自己擁有Fork後的倉庫的讀寫權限;

 

 可以推送pull request給官方倉庫來貢獻代碼。

 

 

https://www.liaoxuefeng.com/wiki/1016959663602400/1017318207388128

列表生成式:

[x * x for x in range(1, 11)]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

[x * x for x in range(1, 11) if x % 2 == 0]
[4, 16, 36, 64, 100]

 [m + n for m in 'ABC' for n in 'XYZ']
['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']


>>> import os # 導入os模塊,模塊的概念後面講到
>>> [d for d in os.listdir('.')] # os.listdir可以列出文件和目錄
['.emacs.d', '.ssh', '.Trash', 'Adlm', 'Applications', 'Desktop', 'Documents', 'Downloads', 'Library', 'Movies', 'Music', 'Pictures', 'Public', 'VirtualBox VMs', 'Workspace', 'XCode']

字典
>>> d = {'x': 'A', 'y': 'B', 'z': 'C' }
>>> for k, v in d.items():
...     print(k, '=', v)
...
y = B
x = A
z = C

>>> d = {'x': 'A', 'y': 'B', 'z': 'C' }
>>> [k + '=' + v for k, v in d.items()]
['y=B', 'x=A', 'z=C']

生成器generator

要創建一個generator,有很多種方法。第一種方法很簡單,只要把一個列表生成式的[]改成(),就創建了一個generator:d

>>> L = [x * x for x in range(10)]
>>> L
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> g = (x * x for x in range(10))
>>> g
調用g中的元素的方法是:next(g),
直到調取到最後一個元素,之後就報錯StopIteration;
此外還有一次性展示生成器內的所有元素的方法,例如for循環:
>>> g=(x * x for x in range(10))
>>> for i in g:
...     print(i)
... 
0
1
4
9
16
25
36
49
64
81

另外一種生成生成器的方法:一個函數中如果含有yield說明該函數是一個生成器:

def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b
        a, b = b, a + b
        n = n + 1
    return 'done'
>>> f = fib(6)
>>> f
<generator object fib at 0x104feaaa0>

 

函數是順序執行,遇到return語句或者最後一行函數語句就返回。而變成generator的函數,在每次調用next()的時候執行,遇到yield語句返回,再次執行時從上次返回的yield語句處繼續執行。

舉個簡單的例子,定義一個generator,依次返回數字1,3,5:

def odd():
    print('step 1')
    yield 1
    print('step 2')
    yield(3)
    print('step 3')
    yield(5)

調用該generator時,首先要生成一個generator對象,然後用next()函數不斷獲得下一個返回值:

>>> o = odd()
>>> next(o)
step 1
1
>>> next(o)
step 2
3
>>> next(o)
step 3
5
>>> next(o)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

迭代器

 

 

碼雲:

如果我們希望體驗Git飛一般的速度,可以使用國內的Git託管服務——碼雲(gitee.com)。

 

和GitHub相比,碼雲也提供免費的Git倉庫。此外,還集成了代碼質量檢測、項目演示等功能。對於團隊協作開發,碼雲還提供了項目管理、代碼託管、文檔管理的服務,5人以下小團隊免費。

 

碼雲的免費版本也提供私有庫功能,只是有5人的成員上限。

 

自定義git:

配置別名:配置方法和shell命令中的差不多;

當然還別的命令可以簡寫,很多人都用co表示checkout,ci表示commit,br表示branch:

$ git config --global alias.co checkout
$ git config --global alias.ci commit

$ git config --global alias.br branch

git ci -m "bala bala bala..."

 

配置文件:

配置Git的時候,加上--global是針對當前用戶起作用的,如果不加,那隻針對當前的倉庫起作用。

配置文件放哪了?每個倉庫的Git配置文件都放在.git/config文件中:

給Git配置好別名,就可以輸入命令時偷個懶。我們鼓勵偷懶

 

 

管理git服務器,簡單一看:

 

小結

 

 搭建Git服務器非常簡單,通常10分鐘即可完成;

要方便管理公鑰,用Gitosis;    

要像SVN那樣變態地控制權限,用Gitolite。

 

 

自己項目操作總結

刪除文件的幾種操作:

在git bash上操作,要切換到git倉庫所在的目錄:cd f:,然後切換到待刪除文件的目錄下:cd dir;

git rm test.txt
git commit -m "remove test.txt"

git push

網頁上操作:登錄倉庫,按照路徑,找到文件,點進去,然後點delete按鈕--》確定,就可以刪除文件。

注意:commit之後,是在本地倉庫中已經提交了,但是遠程倉庫還是沒有提交,所以要再push一下才能到遠程倉庫;
再push時,遇到下面的問題:


說明是要更新下代碼;
然後進行git  pull先更新下本地代碼,然後再git push把之前的修改都push上去;

 

git  bash使用

遇到問題:

1、刪除文件時,有下面的報錯:

If no other git process is currently running, this probably means a
git process crashed in this repository earlier. Make sure no other git
process is running and remove the file manually to continue.

 解決方法: 則把倉庫目錄裏的.git/index.lock文件(文件是隱藏的)刪除就可以了。刪除index.lock不會影響Git使用。是說index文件被鎖住了,但是還有一個index文件要進行操作。
一個倉庫配有一個.git文件夾,在這個文件夾裏面生成了一個index.lock文件,導致index文件不能被操作,所以把index.lock刪除就ok

 

2、git bash使用一段時間之後,界面就不是從一行的開頭開始展示 了;而且目錄下內容展示不全面;需要重新打開一個網頁:

暫時沒有找到解決辦法

 

3、git操作:

git上:上傳一個文件的方法步驟:
add  ---commit---push


更改一個文件,然後提交:
pull下來-,然後打開,修改好後,push--》commit即可。

 

4、Git、Github、GitLab三者的區別:
Git - 版本控制工具 。
Github - 一個網站,提供給用戶空間創建git倉儲,保存用戶的一些數據文檔或者代碼等。
GitLab - 基於Git的項目管理軟件。
三者都是基於git的,可以說是git的衍生品。


 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章