git教程筆記
Git是什麽
Git能解決什麽問題
Git能解決什麽問題?答曰:版本控制。
經常寫文檔的同學應該比較清楚,對某個文檔修改了一點以後,又不想直接覆蓋,這樣的話,後面發現寫錯了,就恢復不回來。所以就復制出很多文件名不一樣,但是內容差不多的文件。
這樣也不是不可以,但是問題在於,Copy了很多份,太消耗空間。同時查找恢復也並不方便。
所以我們希望有這樣一種軟件,它可以
- 自動記錄文件的改動
- 可以團隊協作編輯
比如這樣
版本 | 文件名 | 用戶 | 說明 | 日期 |
---|---|---|---|---|
1 | service.doc | 張三 | 刪除了軟件服務條款5 | 7/12 10:38 |
2 | service.doc | 張三 | 增加了License人數限制 | 7/12 18:09 |
3 | service.doc | 李四 | 財務部門調整了合同金額 | 7/13 9:51 |
4 | service.doc | 張三 | 延長了免費升級周期 | 7/14 15:17 |
其實僅僅是對Word文檔進行版本控制,我覺得有道雲協作就可以了,但是它需要使用外網,而且不是利用Windows自帶的目錄,感覺還是不太方便。
分布式版本控制平臺
其實版本控制器還有很多,比如CVS和SVN,但是它們都是集中式的控制系統。
所謂集中式,自然有個Master級別的角色,它可以保存所有的版本庫。大家需要先從版本庫裏面獲得最新的版本,修改以後再上傳。這樣Master自然就有了所有分支最新的版本了。
缺點是必須聯網
那分布式版本控制系統有啥區別呢?分布式系統沒有Master這個角色,所有的終端一視同仁,每個人都有一個完整的版本庫。那怎麽協作呢?只需要互相通信,互相推送就可以了。
分布式系統的優點在於安全,一個人的電腦壞了,還有其他人的電腦作為備份嘛。
當然在實際應用的時候,一般不會有兩個人互相推送,還是會引入一個中央服務器,但是它就類似於一個交換機,只是用來交互數據,沒有它大家也可以在本地幹活。
而且Git還有強大的分支管理功能,還是免費的。現在最快、最簡單也最流行的就是Git了。
安裝Git
Linux上安裝
sudo apt-get install git
Windows上安裝
參考【使用教程】CMDer,Window下CMD的替代者
安裝Cmder即可,裏面就自帶了git功能。
配置
首先要進行全局設置:
$ git config --global user.name "Your Name"
$ git config --global user.email "[email protected]"
提交版本
創建版本庫
什麽是版本庫?就是倉庫,respository,可以理解為一個目錄,裏面的所有文件可以被Git管理起來,裏面的文件修改、刪除都跟跟蹤到。
下面來創建版本庫,
在需要創建版本庫的地方裏面打開cmder,輸入
git init
當前目錄下多了一個.git的目錄,這個目錄是Git來跟蹤管理版本庫的
某些文件不提交
有些時候需要把某些文件放到目錄中,但是又不能提交它。可以在Git工作區建立一個.gitignore
文件,裏面填充要忽略的文件名
我們可以通過.gitignore網站查看各種配置文件,組合一下即可用。
一般需要忽略那些文件呢?
- 操作系統自動生成的文件或者編譯生成的文件。
- 忽略敏感信息,比如密碼
比如Python裏面,
# Windows:
Thumbs.db
ehthumbs.db
Desktop.ini
# Python:
*.py[cod]
*.so
*.egg
*.egg-info
dist
build
# My configurations:
db.ini
deploy_key_rsa
有的時候,想添加一個文件到Git,發現添加不了,多半是被忽略了。可以使用
git add -f <文件>
也可以看是哪條規則限制了這個文件的上傳
git check-ignore -v <文件>
將文件提交到版本庫裏面
所有的版本控制系統都只能跟蹤文本文件的改動,比如TXT文件、代碼等。
對於圖片、視頻、Word等都是二進制文件,雖然仍然可以由版本控制系統管理,但是沒有辦法對比文件系統的變化。也就是說通過Cmder無法對比兩個版本之間的差別。
所以使用Git主要還是針對於代碼文件、TXT文件等進行版本控制,需要註意的是
使用windows進行編碼的時候,建議使用Notepad++將默認編碼設置為UTF-8 without BOM
添加文件到Git倉庫,分兩步:
第一步,使用命令
git add .
,註意,可反復多次使用,添加多個文件;
要隨時掌握工作區的狀態,使用git status
命令。
如果git status告訴你有文件被修改過,用git diff readme.txt
可以查看修改內容。
git diff HEAD -- readme.txt
可以看查看工作區和版本庫裏面最新版本的區別第二步,使用命令
git commit -m "備註"
進行正式提交。
實際上每次執行git commit -m
就保存了一次快照
,類似於打遊戲的時候存一次檔。如果我們想回退的話,可以通過快照來進行恢復rollback
可以使用git log --pretty=oneline
命令顯示從最近到最遠的提交日誌,以時間軸的形式顯示日誌提交。
版本回退
上面一章我們講了,可以使用git commit
進行提交,然後使用git log --pretty=oneline
查看有提交的版本。
$ git log --pretty=oneline
3628164fb26d48395383f8f31179f24e0882e1e0 append GPL
ea34578d5496d7dd233c827ed32a8cd576c5ee85 add distributed
cb926e7ea50ad11b8f9e909c05226233bf755030 wrote a readme file
其中類似3628164...882e1e0的是commit id(版本號),為了保證多人提交的環境下,commit id不同,所以Git使用了SHA1計算出來的一個非常大的數字,用十六進制表示,這樣就可以避免沖突了。
Git就會把每個版本自動串成一條時間線
如何進行版本回退
首先,Git必須知道當前版本是哪個版本,
- 用
HEAD
表示當前版本, - 上一個版本就是
HEAD^
- 上上一個版本就是
HEAD^^
, - 當然往上100個版本寫成
HEAD~100
然後使用git reset
開始回退
git reset --hard HEAD^
如果發現回退錯了,所以想回到最開始的版本。
- 如果命令行窗口還沒有被關掉,可以順著往上找直到找到那個版本的ID是3628164...,於是就可以指定回到未來的某個版本:
$ git reset --hard 3628164
- 如果命令行窗口關閉了,可以使用
git reflog
來查看執行commit命令時候的commit id。然後使用git reset
總結一下:
現在總結一下:
HEAD指向的版本就是當前版本,因此,Git允許我們在版本的歷史之間穿梭,使用命令
git reset --hard commit_id
。穿梭前,用
git log
可以查看提交歷史,以便確定要回退到哪個版本。要重返未來,用
git reflog
查看命令歷史,以便確定要回到未來的哪個版本。
幾個概念
首先解釋幾個名詞:
- 工作區:指的是建立了git的目錄,也就是平時我們進行代碼編輯的地方
- 版本庫:工作區有一個隱藏目錄.git,是Git的版本庫。
版本庫裏面有暫存區(Stage)
、分支(Master)以及指向分支的指針HEAD
其中Git區別於其他的版本控制系統的一個不同之處就是有了暫存區
git add
命令實際上就是把要提交的所有修改放到暫存區(Stage),然後,執行git commit
就可以一次性把暫存區的所有修改提交到分支。
理解了這個,我們來可如下的過程
第一次修改 -> git add -> 第二次修改 -> git commit
可以發現第二次修改以後並沒有git add
,也就是第二次修改的內容沒有放到暫存區,所以git commit不會把第第二次的修改提交了。
這就是Git比其他版本控制系統優秀的地方,因為Git跟蹤管理的是修改,而不是文件
沒有提交到分支之前的撤銷
之前我們說到了如果已經git commit
到分支以後,要進行版本回退應該怎麽做。
但是如果我們只是添加到了暫存區,甚至還沒提交到暫存區,此時應該如何撤銷呢?
只是修改,沒有add到暫存區:
使用這個命令還可以把誤刪的文件恢復回來git checkout -- file
- 已經add到暫存區,但是沒有commit
- 首先使用
git reset HEAD file
回退到工作區。 - 然後使用
git checkout -- file
把工作區的修改撤銷了。
- 首先使用
總之,記住一點:git checkout -- 文件
命令,撤銷的是工作中文件的修改,而git reset HEAD -- 文件
命令,撤銷的是暫存區中文件的修改。
撤銷本地所有修改
git checkout . #本地所有修改的。沒有的提交的,都返回到原來的狀態
git stash #把所有沒有提交的修改暫存到stash裏面。可用git stash pop回復。
git reset --hard HEAD #返回到某個節點,不保留修改。
分支
分支有什麽用?每個人可以創建自己的分支,想提交就提交,直到完成所有的功能以後,一次性合並到原來的分支上,這樣可以不影響別人工作。
Git好就好在切換分支只需要不到1s,比SVN等快很多。
創建分支
Git默認有一條主分支,即master
分支,而HEAD
指針實際上指向當前分支的,此時就是master
當創建新的分支後,Git新建了一個指針dev
,HEAD
指向dev
,切換到了dev
上了。然後後面的修改都是在dev
上了,master
指針不變。
當我們在dev
上把工作完成了,就可以合並分支。方法就是直接把master
指向dev
當前的提交。
下面是具體用命令怎麽做
創建dev分支並切換
$ git branch dev $ git checkout dev#切換分支
- 正常提交
- 切換到master分支上
合並指定分支dev到當前
master
分支
此時有可能兩個分支都有提交,所以無法自動合並,需要手動解決沖突,再提交git merge dev
刪除分支
$ git branch -d dev
分支策略
在實際團隊協作的時候,應該保證master
非常穩定,只 是用來發布新的版本,平臺應該不在上面修改。
每個人可以經常生成一些dev分支, 在上面進行修改,當有必要的時候,再合並到主分支上即可。
場景一:Bug分支
每個bug都可以通過一個新的臨時分支來修復,修復後,合並分支,然後將臨時分支刪除。
當你接到一個修復一個代號101的bug的任務時,可以創建一個分支issue-101來修復它,但是dev上的工作只進行到一半,還沒法提交,怎麽辦?
可以使用stash功能把現場存儲起來,之後可以恢復
git stash
- 然後創建Bug分支,進行修復
- 切換到master上,合並,刪除分支
- 現在應該回到dev分支繼續幹活了。恢復現場
git stash apply
:恢復以後stash內容不刪除,需要再使用git stash drop
git stash pop
:恢復的時候同時把stash的內容也刪除了。
因為可能多次保存現場,所以可以先使用git stash list
查看,然後恢復指定的stash
$ git stash apply stash@{0}
場景二:Feature分支
開發一個新feature,最好新建一個分支,但是還沒開發完的時候,收到通知取消此特性。
此時當然直接刪除就好,不過問題就在於分支還沒有被合並,如果刪除可以通過git branch -D <name>
強行刪除。
使用標簽
發布一個版本的時候,可以先在版本庫裏面打一個tag。標簽其實就是版本庫的一個快照
既然有commit,為什麽還要tag呢?
比如要將上周一的版本打包發布,我們知道commit id是一堆亂七八糟的數字,並不好查找,如果加上一個tag v1.2
,就有了實際意義,可以與某個commit綁在一起,更好查找。
如何打標簽
- 首先,切換到打標簽的分支上
git branch
- 使用
git tag v1.l0
創建一個標簽,使用git tag
可以查看所有標簽,標簽不是按照時間排序,而是按照字母排序 如果要綁定歷史的 commit,可以怎能先使用
git log
找到commit idgit tag v0.9 commit id
可以創建帶有說明的標簽
git tag -a v0.1 -m "version 0.1 released" 32321332
可以使用
git show v0.1
查看說明。
如果標簽打錯了,能改嗎?當然能。刪除即可。
$ git tag -d v0.1
因為創建的標簽都只存儲在本地,不會自動推送到遠程。所以,打錯的標簽可以在本地安全刪除。
遠程倉庫
到現在為止我們已經學會了如何在自己的電腦上進行工作,本章則將講解如何把代碼托管到Gitee遠程倉庫來進行管理,這樣就可以進行協作以及代碼的備份呢。
之前我們只是在自己的電腦上搭一個Git倉庫,實際上也可以分布到不同的機器上,別的機器只要復制原始版本就好了,這樣就可以保證大家都一樣。
所以完全可以搭一個Git服務器,然後所有的人都從服務器裏面復制一份到自己這邊,再把各自的提交推送到倉庫裏面,實現協作。
最著名的Git服務器當屬GitHub
,不過在國內比較的慢,所以我們使用中國版的GitHub
——碼雲(gitee.com)
上傳公鑰
本地Git倉庫和GitHub倉庫之間的傳輸是通過SSH加密的,所以需要先上傳公鑰,想知道原理可以點擊HTTPS
首先創建SSH Key
打開CMDer,輸入
然後一路回車ssh-keygen -t rsa -C "[email protected]"#需要把郵件地址換成你自己的郵件地址
可以通過everything
搜索一下id_rsa.pub
這個公鑰在那裏,然後使用Notepad++打開,復制所有的內容。
在Gitee的設置裏面粘貼公鑰的內容。
為什麽要SSH Key呢?
因為碼雲要識別這個推送確實是你本人幹的。
當然碼雲支持多個Key,如果有多個電腦,可以建立多個Key
將代碼推送到遠端
如果要把代碼推送到遠端,有兩種場景,一是現在已經在本地建立了倉庫了,現在想在Gitee上同樣建立一個,然後合並即可。
另一種是現在啥都沒幹,直接從Gitee上建一個,然後clone到本地即可。
首先在Gitee上建立一個新倉庫名字是articlespider
- 如果已經在本地建立了倉庫
- 首先關聯遠程庫:
git remote add origin git@server-name:path/repo-name.git
- 使用命令
git push -u origin master
第一次推送master分支的所有內容; - 此後的提交只需要使用
git push origin master
- 首先關聯遠程庫:
cd existing_git_repo
git remote add origin https://gitee.com/***/articlespider.git
git push -u origin master
如果在新建遠程倉庫的時候加上了README.MD
,但是這個Readme.md
又不在本地庫裏面,所以會報錯。可以
$ git pull --rebase origin master
當然也可以在本地根目錄新建一個Readme.md
如果現在還沒有建立倉庫,可以使用
git clone
復制一個版本下來。git clone [email protected]:****/articlespider.git
多人協作
創建了遠程倉庫以後,可以進行多人協作。可以將本地的分支推送到遠端,也可以從遠端拉取
推送分支
遠程倉庫默認名稱是origin
可以使用git push進行推送。
git push origin 分支
拉取分支
現在另一個人需要在dev分支上做開發,首先應該先clone一份到本地。
git clone [email protected]:****/articlespider.git
當從遠程倉庫克隆的時候,Git自動把master與遠程的master對應起來。
查看遠程庫的信息:git remote -v
此時只能看到master
分支,如果也要在分支dev
上開發的話,必須創建遠程origin的dev分支到本地,
git checkout -b dev origin/dev
然後就可以繼續開發了。
那麽我們怎麽與之協作呢?
- 首先可以使用
git push origin <branch>
推送自己的修改 如果推送失敗,則遠程分支比本地的更新,需要先用
git pull
合並。
如果提示no tracking information
,說明鏈接關系沒有建立起來。使用git branch --set-upstream <branch> origin/<branch>
- 如果合並有沖突,則解決沖突,並在本地提交
沖突解決之後,再用
git push origin <branch>
推送標簽
因為創建的標簽都只存儲在本地,不會自動推送到遠程
如果要推送某個標簽到遠程,使用命令git push origin <tagname>
或者,一次性推送全部尚未推送到遠程的本地標簽:
$ git push origin --tags
如果要刪除的話,首先需要先刪除本地的。
$ git tag -d v0.9
然後,從遠程刪除。
$ git push origin :refs/tags/v0.9
修改遠程庫的名字
我們可能同時進行多個項目,他們都需要推送到遠端。比如learngit項目,現在要與遠程庫關聯
git remote add origin [email protected]:<your name>/learngit.git
如果報錯fatal: remote origin already exists.
說明本地庫已經關聯了一個名叫origin的遠程庫
可以先刪除
git remote rm origin
再關聯一個遠程庫gitee
git remote add gitee [email protected]:<gitee name>/learngit.git
此時遠程庫的名稱叫gitee,不叫origin。
如果要推送:
git push gitee master
配置別名
所謂配置別名其實就是配置命令的簡寫,比如使用git st表示git status等。
$ git config --global alias.st status#查看工作區狀態
$ git config --global alias.co checkout#切換分支,撤銷修改
$ git config --global alias.ci commit#提交
$ git config --global alias.br branch#分支
$ git config --global alias.unstage ‘reset HEAD‘#回退
$ git config --global alias.last ‘log -1‘#查看log
$git config --global alias.lg "log --color --graph --pretty=format:‘%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset‘ --abbrev-commit"
加上--global是針對當前用戶起作用的
搭建Git服務器
搭建服務器
需要準備一臺運行Ubuntu的機器
- 安裝git :
sudo apt-get install git
- 創建git 用戶,用來運行git服務:
sudo adduser git
- 創建證書登錄
收集所有需要登錄的用戶的公鑰,就是他們自己的id_rsa.pub文件,把所有公鑰導入到/home/git/.ssh/authorized_keys文件裏,一行一個。 初始化git倉庫
選定一個目錄作為Git倉庫,假定是/srv/sample.git,在/srv目錄下輸入命令:$ sudo git init --bare sample.git
這樣就會創建一個沒有工作區的裸倉庫,把所有者改為
git
sudo chown -R git:git sample.git
禁用shell登錄
編輯/etc/passwd文件完成。找到類似下面的一行:git:x:1001:1001:,,,:/home/git:/bin/bash
改為:
這樣,git用戶可以正常通過ssh使用git,但無法登錄shell,因為我們為git用戶指定的git-shell每次一登錄就自動退出。git:x:1001:1001:,,,:/home/git:/usr/bin/git-shell
克隆遠程倉庫:
$ git clone git@server:/srv/sample.git
總結
最後把所有的命令總結成一個表格
一級 | 二級 | 命令 |
---|---|---|
提交代碼 | 新建倉庫 | git init |
提交到暫存區 | git add . | |
提交到分支 | git commit -m "" | |
查看 | 查看狀態 | git status |
查看提交記錄 | git log --pretty=oneline | |
查看命令歷史 | git reflog | |
對比 | git diff HEAD -- readme.txt | |
標簽 | git tag | |
遠端倉庫 | git remote -v | |
版本控制 | 未提交到暫存區 | git checkout . |
已提交到暫存區 | git reset HEAD file | |
已經提交到分支 | git reset --hard | |
分支 | 創建分支 | git branch dev |
切換分支 | git checkout dev | |
合並 | git merge dev | |
刪除分支 | git branch -d dev | |
強行刪除 | git branch -D dev | |
存儲現場 | git stash | |
恢復現場 | git stash pop | |
標簽 | 創建標簽 | git tag v0.9 |
刪除標簽 | git tag -d v0.8 | |
推送遠程標簽 | git push origin --tags | |
刪除遠程標簽 | git push origin :refs/tags/v0.9 | |
遠程倉庫 | 上傳公鑰 | ssh-keygen -t rsa -C "[email protected]" |
關聯遠程庫 | git remote add origin https://gitee.com/***/articlespider.git | |
刪除遠程庫 | git remote rm origin | |
第一次提交 | git push -u origin master | |
普通提交 | git push origin | |
拉取 | git pull origin | |
多人協作 | 復制 | git clone [email protected]:****/articlespider.git |
創建遠端分支到本地 | git checkout -b dev origin/dev | |
創建鏈接關系 | git branch --set-upstream origin/ | |
別名 | 查看log | $git config --global alias.lg "log --color --graph --pretty=format:‘%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue) |
參考
本文主要是根據Git教程整理得到的,目的是幫助Git學習。
git教程筆記