0.使用GitHub
0.1 添加到遠程庫
0.2 從遠程庫克隆
0.3 GitHub使用1.創建版本庫
2.時光穿梭機
2.1 版本回退
2.2 工作區和暫存區
2.3 管理修改
2.4 撤銷修改
2.5 刪除文件3.分支管理
3.1 創建與合并分支
3.2 解決沖突
3.3 分支管理策略
3.4 Bug分支
3.5 Feature分支
3.6 多人協作4.標簽管理
4.1 創建標簽
4.2 操作標簽5.自定義Git
5.1 忽略特殊文件
5.2 配置別名
5.3 搭建Git服務器6.擴展
6.1 rebase的使用
0.使用GitHub
生成SSH key,如果沒有key的話,在用戶主目錄下面,執行下面語句:
ssh-keygen -t rsa -C "youremail@example.com"
該語句在用戶主目錄下面生成.ssh文件夾,文件夾中有兩個文件,分別是id_rsa和id_rsa.pub,前者是私鎖,不能告訴別人,后者是公鎖,可以告訴別人,需要將后者即是id_rsa.pub中內容添加到GitHub的賬戶中,因為Git支持SSH協議,SSH key是GitHub用來識別代碼是該用戶提交過來的。
0.1 添加到遠程庫
git remote add origin https://github.com/Jayzen/demo_for_test.git
#遠程庫的名字叫做origin,是默認的遠程庫的名稱,其中demo_for_test是用戶自定義的倉庫名稱
git push -u origin master
#第一次推送master分支時,加上了-u參數,Git不但會把本地的master分支內容推送的遠程新的master分支,還會把本地的master分支和遠程的master分支關聯起來,在以后的推送或者拉取時就可以簡化命令
git push origin master #第二次之后遠程庫的代碼提交(對比第一次提交少了-u 參數)
0.2 從遠程庫克隆
git clone https://github.com/Jayzen/gitskill.git #自己的電腦這個可行
git clone git@github.com:Jayzen/gitskill.git
0.3 GitHub使用
如果要修改一個開源庫,步驟如下:
fork #fork一個項目,相當于在自己的github上面復制了一個相同的項目
git clone XX #在用戶的本地復制該代碼
git push #用戶本地修改代碼之后,推送到GiHub中用戶本身的目錄下面
pull request #發起這個pull request,看作者是否接受
具體示意圖見如:
1.創建版本庫
git init #初始化一個倉庫
git add <file> #添加到倉庫
git commit -m "some descriptions" #提交到倉庫,其中后面顯示的-m是對本次提交的一次說明
2.時光穿梭機
git status #查看用戶的狀態
#如果只是對代碼進行了修改,之后沒有做任何改動,則會顯Changes not staged for commit
#如果是在當前文件夾內添加了一個文件,之后沒有做任何動作,則會顯示untracked files
#如果對文件進行了修改,執行了add,沒有執行commit,則會顯示Changes to be committed
#如果代碼全部提交到倉庫中,則會顯示nothing to commit, working directory clean
git diff #查看代碼做了哪些修改,這種狀態修改的說明只能是該文件沒有執行git add之前才能看到
2.1 版本回退
git log #顯示從近到遠的提交日志
git log --pretty=oneline #將這些日志按照行顯示
git reset --hard HEAD^ #將版本退回到上一次提交,其中HEAD^表示上一個版本,HEAD^^表示上上一個版本
git reset --hard commit_id #其中commit_id是commit過程中生成的id值
git reflog #記錄head指向的每一次命令
head指向append GPL
改為head指向add distributed
2.2 工作區和暫存區
工作區其實就是git當前工作的文件夾。
把文件往Git版本庫里添加的時候,是分兩步執行的:
第一步是用git add把文件添加進去,實際上就是把文件修改添加到暫存區;
第二步是用git commit提交更改,實際上就是把暫存區的所有內容提交到當前分支。
與此同時,在工作區中修改readme.txt文件和添加LICENSE,并且兩次使用add命令,結果如下所示:
以上的結果可以看出,兩次add方法是將文件添加到暫存區中,執行git commit -m "fourth commit",得到以下的結果,暫存區是干凈的。
2.3 管理修改
Git跟蹤的是修改,而不是文件。
git commit 提交給是是暫存區的內容,如果修改了文件,沒有執行commit add,那么git commit對修改的文件內容無效。
git diff HEAD -- readme.txt #查看工作區和版本庫里面最新版本的區別
2.4 撤銷修改
第一種情況:在工作區中修改,當時沒有提交到暫存區
git checkout --file
命令git checkout -- readme.txt意思就是,把readme.txt文件在工作區的修改全部撤銷,這里有兩種情況:
一種是readme.txt自修改后還沒有被放到暫存區,現在,撤銷修改就回到和版本庫一模一樣的狀態;
一種是readme.txt已經添加到暫存區后,又作了修改,現在,撤銷修改就回到添加到暫存區后的狀態。
第二種情況:已經提交到暫存區
git reset HEAD file #可以把暫存區的修改撤銷掉,重新放回工作區
git checkout --file #重復第一種情況
其中
git reset #命令既可以回退版本,也可以把暫存區的修改回退到工作區。當我們用HEAD時,表示最新的版本。
2.5 刪除文件
當前工作區內有兩個文件,分別是demo.rb和test.rb,其中在工作區中刪除文件test.rb,則下面有兩種情況:
#第一種:確實要刪除該文件
git rm test.rb
git commit -m "remove test.rb"
自己測試了下,下面的代碼也可以實現刪除功能,因為版本控制跟蹤的修改,而不是文件。
git add .
git commit -m "remove test.rb"
#第二種:
刪除文件出現錯誤,因此相當于撤銷修改
git checkout --test.rb #git checkout其實是用版本庫里的版本替換工作區的版本,無論工作區是修改還是刪除,都可以“一鍵還原”。
3.1 創建和合并分支
git branch #查看分支
git branch <name> #創建分支
git checkout <name> #切換分支
git checkout -b <name> #創建+切換分支
git merge <name> #合并某分支到當前分支
git branch -d <name> #刪除分支
一開始的時候,master分支是一條線,Git用master指向最新的提交,再用HEAD指向master,就能確定當前分支,以及當前分支的提交點,每次提交,master分支都會向前移動一步,這樣,隨著你不斷提交,master分支的線也越來越長:
當我們創建新的分支,例如dev時,Git新建了一個指針叫dev,指向master相同的提交,再把HEAD指向dev,就表示當前分支在dev上:
Git創建一個分支很快,因為除了增加一個dev指針,改改HEAD的指向,工作區的文件都沒有任何變化!不過,從現在開始,對工作區的修改和提交就是針對dev分支了,比如新提交一次后,dev指針往前移動一步,而master指針不變:
假如我們在dev上的工作完成了,就可以把dev合并到master上。Git怎么合并呢?最簡單的方法,就是直接把master指向dev的當前提交,就完成了合并:
合并完分支后,甚至可以刪除dev分支。刪除dev分支就是把dev指針給刪掉,刪掉后,我們就剩下了一條master分支:
3.2 解決沖突
當主分支和從分支在同一個地方進行修改了,并且進行合并之后,出現了沖突。
#生成另外一個分支,對這個分支進行修改,然后提交
git checkout -b feature
修改demo.rb中的內容
git add demo.rb
git commit -m "commit feature"
#回到master分支,對master分支進行修改,然后提交
git checkout master
修改demo.rb中的內容,并且和上一個部分修改同一個地方
git add demo.rb
git commit -m "commit master"
#對兩個分支進行合并
git merge feature #出現了conflict
#修改conflict的內容,重新進行提交
git add demo.rb
git commit -m "final commit"
#上面的內容對conflict內容進行了修改,并且在master分支上進行了合并成功
#刪除分支
git branch -d feature
#用圖像形式顯示合并
git log --graph --pretty=oneline --abbrev-commit
3.3 分支管理策略
每個人不應該在master分支上建立分支,而應該在dev分支上建立分支,每次提交應該針對dev分支,當發布版本時應該從dev分支上提交到master分支
如果按照上文的合并方式(fast forward)進行的話,如果刪除了分支,就會丟失分支信息,因此這里可以采用禁用Fast forward模式,Git就會在merge時生成一個新的commit。
git checkout -b dev
修改demo.rb文件內容
git add demo.rb
git commit -m "commit dev"
#切換到master分支,禁止fast forward模式
git checkout master
git merge --no-ff -m "merge with no-ff" dev
#查看log,可以看到分支信息
git log --graph --pretty=oneline --abbrev-commit
下面圖片顯示分支信息:
3.4 Bug分支
Bug分支的策略是把當前的分支存儲起來,然后建立bug分支,修復好之后再對當前分支進行恢復。
git status #當前分支下的內容
git stash #對當前分支進行存儲
git status #當對當前分支進行存儲之后,發現當前分支的status是空的
#對bug分支進行修復
git checkout master
git checkout -b bug-issue
對demo.rb文件內容進行修改
git add demo.rb
git commit -m "bug commit"
git checkout master
git merge --no-ff -m "merge bug commit" bug-issue
git status #查看工作目錄是空的
git slash list #查看slash
git slash apply #恢復后,stash內容并不刪除,你需要用git stash drop來刪除
git stash apply stash@{0} #恢復指定的slash
git slash pop #恢復的同時把stash內容也刪了
git slash list #恢復后查看slash的內容也沒有了
3.5 Feature分支
如果是開發新功能,最好是新建一個分支,如果這個分支已經被合并,那么刪除這個分支使用:
git branch -d feature
如果這個分支沒有被合并,刪除這個分支,需要用到下面的語句:
git branch -D feature
3.6 多人協作
從遠程克隆倉庫也是分多種情況,第一種情況是只有一個master分支的情況下:
git clone XX #遠程倉庫克隆時,實際上Git自動把本地的master分支和遠程的master分支對應起來了,并且,遠程倉庫的默認名稱是origin
git remote #origin 此代碼是查看遠程庫的信息,遠程庫的默認信息是origin
git remote -v #使用-v查看遠程庫更為詳細的信息
origin git@github.com:michaelliao/learngit.git (fetch)
origin git@github.com:michaelliao/learngit.git (push)
git push origin master #推送master分支
git push origin dev #推送dev分支
第二種情況是當遠程庫存在多個分支時候,使用git clone語句克隆代碼,使用git branch語句只能查看master分支,為了顯示其他分支,需要創建遠程的origin的dev分支到本地:
git clone XX
git branch #master
#實際上被克隆的代碼庫有很多分支,而這里只能顯示master分支
git checkout -b dev origin/dev
#使用上面的語句在本地建立dev分支,和遠程庫的dev分支對象起來,同時獲得遠程庫的分支信息代碼
#在dev分支上修改代碼
git commit -m "add the dev"
git push origin dev #將代碼推送到遠程庫dev分支中
第三情況是處理沖突:兩個人同時寫作同一個代碼庫,比如在feature分支上面,一個人已經作為修改,另外一個人在此人修改之前已經git clone到本地,并且在feature同一個地方做了修改,因此會出現conflict。
#已經有其他用戶在feature分支上面建立test.rb文件
#下面的代碼都是在本地的feature分支上進行
git add test.rb
git commit -m "add the test.rb"
git push origin feature
上面的代碼出現錯誤,根據提示可以知道,是因為出現了代碼沖突,根據提示使用git pull。
git pull #如果存在no tracking information,說明本地分支和遠程分支之間的鏈接關系沒有建立
git branch --set-upstream-to=origin/feature feature #設置feature和origin/feature的鏈接
git pull #出現沖突及沖突提示
#沖突解決好之后重新提交
git commit -m "conflict commit"
git push origin feature
4.標簽管理
標簽是版本庫的一個快照,若給版本庫打了一個標簽,就相當于在某個時候獲取一個特定時間的版本庫,標簽和分支不同,分支可以移動,標簽不能移動。
4.1 創建標簽
git checkout master #切換到最新的master分支上
git tag v1.0 #給最新的分支貼上標簽
git tag #查看所有標簽
默認情況下標簽是打在最新的提交的commit上,如果需要打在之前提交的commit上,需要如下的語句
git log --pretty=oneline --abbrev-commit #顯示commit id log
git tag v0.9 1234234 #其中1234234是commit id值,即將標簽打在這個commit id中。
git show v1.0 #查看某個版本的標簽
git tag -a v0.1 -m "version 0.1 released" 3628164
#創建帶有說明的標簽,用-a指定標簽名,-m指定說明文字
4.2 操作標簽
git tag -d v0.9 #刪除標簽
git push origin v0.9 #因為標簽都是在本地的,此代碼是推送標簽到遠程
git push origin --tags #一次性推送全部尚未推送到遠程的本地標簽
#如果標簽已經推送到遠程,要刪除遠程標簽就麻煩一點,先從本地刪除:
#然后,從遠程刪除。刪除命令也是push
git tag -d v0.9
git push origin :refs/tags/v0.9
5.自定義Git
git config --global color.ui true #設置顏色
5.1 忽略特殊文件
在工作區建立 .gitignore
ruby的示例文件可以在這里找到
5.2 配置別名
配置別名就是在將Git的命令用其他名字來表示,示例代碼如下所示:
git config --global alias.co checkout
git config --global alias.ci commit
git config --global alias.br branch
#--global參數是全局參數,也就是這些命令在這臺電腦的所有Git倉庫下都有用。
每個倉庫的Git配置文件都放在.git/config文件中,其中別名就在[alias]后面,要刪除別名,直接把對應的行刪掉即可。
[core]
repositoryformatversion = 0
filemode = true bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
[remote "origin"]
url = git@github.com:michaelliao/learngit.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
[alias]
last = log -1
而當前用戶的Git配置文件放在用戶主目錄下的一個隱藏文件.gitconfig
中:
[alias]
co = checkout
ci = commit
br = branch
st = status
[user]
name = Your Name
email = your@email.com
5.3 搭建Git服務器
見這里
6.擴展
6.1 rebase的使用
相關文檔
在master分支上簡歷mywork分支,示意圖如下所示:
在mywork分支上提交兩次代碼,同時其他用戶在master分支上提交了兩次代碼,示意圖如下所示:
在這里,你可以用"pull"命令把"origin"分支上的修改拉下來并且和你的修改合并; 結果看起來就像一個新的"合并的提交",示意圖如下所示:
但是,如果你想讓"mywork"分支歷史看起來像沒有經過任何合并一樣,可以用git rebase,代碼如下所示:
git checkout mywork
git rebase origin
這些命令會把你的"mywork"分支里的每個提交(commit)取消掉,并且把它們臨時 保存為補丁(patch)(這些補丁放到".git/rebase"目錄中),然后把"mywork"分支更新 到最新的"origin"分支,最后把保存的這些補丁應用到"mywork"分支上。
當'mywork'分支更新之后,它會指向這些新創建的提交(commit),而那些老的提交會被丟棄。 如果運行垃圾收集命令(pruning garbage collection), 這些被丟棄的提交就會刪除。
現在我們可以看一下用合并(merge)和用rebase所產生的歷史的區別:
6.2 修改最近一次的提交 commit --amend
該功能會修改最近一次的提交,使用commit --amend
比如最開始是這樣的:
需要對添加add的講解進行修改,使用下面代碼:
git add .
git commit --amend
上面的代碼會跳出一個編輯頁面,可以修改添加add的講解的值,修改為添加add和commit的講解,并且進行保存,使用git log操作,可以得到如下的結果:
6.3 取消最新一次的提交 git revert head
下面的代碼可以取消最近一次的提交
git revert HEAD
原本最初的提交branch如下所示:
執行git revert HEAD之后,變為如下的結果
就是說針對“添加pull的講解”所變化的內容消失了。
6.4 使用reset來刪除前面的幾個提交
代碼如下所示:
git reset --hard HEAD~~ #這是刪除最前面的兩個提交
git reset --hard HEAD~ #這是刪除了最前面的一個提交
git reset --hard ORGI_HEAD #如果之前的reset出錯了,該代碼會返回最開始進行reset的位置
圖片演示如下:
6.5 **使用cherry-pick將其他分支中的內容添加到主分支中 **
如下圖所示:
0.使用GitHub
0.1 添加到遠程庫
0.2 從遠程庫克隆
0.3 GitHub使用1.創建版本庫
2.時光穿梭機
2.1 版本回退
2.2 工作區和暫存區
2.3 管理修改
2.4 撤銷修改
2.5 刪除文件3.分支管理
3.1 創建與合并分支
3.2 解決沖突
3.3 分支管理策略
3.4 Bug分支
3.5 Feature分支
3.6 多人協作4.標簽管理
4.1 創建標簽
4.2 操作標簽5.自定義Git
5.1 忽略特殊文件
5.2 配置別名
5.3 搭建Git服務器6.擴展
6.1 rebase的使用
0.使用GitHub
生成SSH key,如果沒有key的話,在用戶主目錄下面,執行下面語句:
ssh-keygen -t rsa -C "youremail@example.com"
該語句在用戶主目錄下面生成.ssh文件夾,文件夾中有兩個文件,分別是id_rsa和id_rsa.pub,前者是私鎖,不能告訴別人,后者是公鎖,可以告訴別人,需要將后者即是id_rsa.pub中內容添加到GitHub的賬戶中,因為Git支持SSH協議,SSH key是GitHub用來識別代碼是該用戶提交過來的。
0.1 添加到遠程庫
git remote add origin https://github.com/Jayzen/demo_for_test.git
#遠程庫的名字叫做origin,是默認的遠程庫的名稱,其中demo_for_test是用戶自定義的倉庫名稱
git push -u origin master
#第一次推送master分支時,加上了-u參數,Git不但會把本地的master分支內容推送的遠程新的master分支,還會把本地的master分支和遠程的master分支關聯起來,在以后的推送或者拉取時就可以簡化命令
git push origin master #第二次之后遠程庫的代碼提交(對比第一次提交少了-u 參數)
0.2 從遠程庫克隆
git clone https://github.com/Jayzen/gitskill.git #自己的電腦這個可行
git clone git@github.com:Jayzen/gitskill.git
0.3 GitHub使用
如果要修改一個開源庫,步驟如下:
fork #fork一個項目,相當于在自己的github上面復制了一個相同的項目
git clone XX #在用戶的本地復制該代碼
git push #用戶本地修改代碼之后,推送到GiHub中用戶本身的目錄下面
pull request #發起這個pull request,看作者是否接受
具體示意圖見如:
1.創建版本庫
git init #初始化一個倉庫
git add <file> #添加到倉庫
git commit -m "some descriptions" #提交到倉庫,其中后面顯示的-m是對本次提交的一次說明
2.時光穿梭機
git status #查看用戶的狀態
#如果只是對代碼進行了修改,之后沒有做任何改動,則會顯Changes not staged for commit
#如果是在當前文件夾內添加了一個文件,之后沒有做任何動作,則會顯示untracked files
#如果對文件進行了修改,執行了add,沒有執行commit,則會顯示Changes to be committed
#如果代碼全部提交到倉庫中,則會顯示nothing to commit, working directory clean
git diff #查看代碼做了哪些修改,這種狀態修改的說明只能是該文件沒有執行git add之前才能看到
2.1 版本回退
git log #顯示從近到遠的提交日志
git log --pretty=oneline #將這些日志按照行顯示
git reset --hard HEAD^ #將版本退回到上一次提交,其中HEAD^表示上一個版本,HEAD^^表示上上一個版本
git reset --hard commit_id #其中commit_id是commit過程中生成的id值
git reflog #記錄head指向的每一次命令
head指向append GPL
改為head指向add distributed
2.2 工作區和暫存區
工作區其實就是git當前工作的文件夾。
把文件往Git版本庫里添加的時候,是分兩步執行的:
第一步是用git add把文件添加進去,實際上就是把文件修改添加到暫存區;
第二步是用git commit提交更改,實際上就是把暫存區的所有內容提交到當前分支。
與此同時,在工作區中修改readme.txt文件和添加LICENSE,并且兩次使用add命令,結果如下所示:
以上的結果可以看出,兩次add方法是將文件添加到暫存區中,執行git commit -m "fourth commit",得到以下的結果,暫存區是干凈的。
2.3 管理修改
Git跟蹤的是修改,而不是文件。
git commit 提交給是是暫存區的內容,如果修改了文件,沒有執行commit add,那么git commit對修改的文件內容無效。
git diff HEAD -- readme.txt #查看工作區和版本庫里面最新版本的區別
2.4 撤銷修改
第一種情況:在工作區中修改,當時沒有提交到暫存區
git checkout --file
命令git checkout -- readme.txt意思就是,把readme.txt文件在工作區的修改全部撤銷,這里有兩種情況:
一種是readme.txt自修改后還沒有被放到暫存區,現在,撤銷修改就回到和版本庫一模一樣的狀態;
一種是readme.txt已經添加到暫存區后,又作了修改,現在,撤銷修改就回到添加到暫存區后的狀態。
第二種情況:已經提交到暫存區
git reset HEAD file #可以把暫存區的修改撤銷掉,重新放回工作區
git checkout --file #重復第一種情況
其中
git reset #命令既可以回退版本,也可以把暫存區的修改回退到工作區。當我們用HEAD時,表示最新的版本。
2.5 刪除文件
當前工作區內有兩個文件,分別是demo.rb和test.rb,其中在工作區中刪除文件test.rb,則下面有兩種情況:
#第一種:確實要刪除該文件
git rm test.rb
git commit -m "remove test.rb"
自己測試了下,下面的代碼也可以實現刪除功能,因為版本控制跟蹤的修改,而不是文件。
git add .
git commit -m "remove test.rb"
#第二種:
刪除文件出現錯誤,因此相當于撤銷修改
git checkout --test.rb #git checkout其實是用版本庫里的版本替換工作區的版本,無論工作區是修改還是刪除,都可以“一鍵還原”。
3.1 創建和合并分支
git branch #查看分支
git branch <name> #創建分支
git checkout <name> #切換分支
git checkout -b <name> #創建+切換分支
git merge <name> #合并某分支到當前分支
git branch -d <name> #刪除分支
一開始的時候,master分支是一條線,Git用master指向最新的提交,再用HEAD指向master,就能確定當前分支,以及當前分支的提交點,每次提交,master分支都會向前移動一步,這樣,隨著你不斷提交,master分支的線也越來越長:
當我們創建新的分支,例如dev時,Git新建了一個指針叫dev,指向master相同的提交,再把HEAD指向dev,就表示當前分支在dev上:
Git創建一個分支很快,因為除了增加一個dev指針,改改HEAD的指向,工作區的文件都沒有任何變化!不過,從現在開始,對工作區的修改和提交就是針對dev分支了,比如新提交一次后,dev指針往前移動一步,而master指針不變:
假如我們在dev上的工作完成了,就可以把dev合并到master上。Git怎么合并呢?最簡單的方法,就是直接把master指向dev的當前提交,就完成了合并:
合并完分支后,甚至可以刪除dev分支。刪除dev分支就是把dev指針給刪掉,刪掉后,我們就剩下了一條master分支:
3.2 解決沖突
當主分支和從分支在同一個地方進行修改了,并且進行合并之后,出現了沖突。
#生成另外一個分支,對這個分支進行修改,然后提交
git checkout -b feature
修改demo.rb中的內容
git add demo.rb
git commit -m "commit feature"
#回到master分支,對master分支進行修改,然后提交
git checkout master
修改demo.rb中的內容,并且和上一個部分修改同一個地方
git add demo.rb
git commit -m "commit master"
#對兩個分支進行合并
git merge feature #出現了conflict
#修改conflict的內容,重新進行提交
git add demo.rb
git commit -m "final commit"
#上面的內容對conflict內容進行了修改,并且在master分支上進行了合并成功
#刪除分支
git branch -d feature
#用圖像形式顯示合并
git log --graph --pretty=oneline --abbrev-commit
3.3 分支管理策略
每個人不應該在master分支上建立分支,而應該在dev分支上建立分支,每次提交應該針對dev分支,當發布版本時應該從dev分支上提交到master分支
如果按照上文的合并方式(fast forward)進行的話,如果刪除了分支,就會丟失分支信息,因此這里可以采用禁用Fast forward模式,Git就會在merge時生成一個新的commit。
git checkout -b dev
修改demo.rb文件內容
git add demo.rb
git commit -m "commit dev"
#切換到master分支,禁止fast forward模式
git checkout master
git merge --no-ff -m "merge with no-ff" dev
#查看log,可以看到分支信息
git log --graph --pretty=oneline --abbrev-commit
下面圖片顯示分支信息:
3.4 Bug分支
Bug分支的策略是把當前的分支存儲起來,然后建立bug分支,修復好之后再對當前分支進行恢復。
git status #當前分支下的內容
git stash #對當前分支進行存儲
git status #當對當前分支進行存儲之后,發現當前分支的status是空的
#對bug分支進行修復
git checkout master
git checkout -b bug-issue
對demo.rb文件內容進行修改
git add demo.rb
git commit -m "bug commit"
git checkout master
git merge --no-ff -m "merge bug commit" bug-issue
git status #查看工作目錄是空的
git slash list #查看slash
git slash apply #恢復后,stash內容并不刪除,你需要用git stash drop來刪除
git stash apply stash@{0} #恢復指定的slash
git slash pop #恢復的同時把stash內容也刪了
git slash list #恢復后查看slash的內容也沒有了
3.5 Feature分支
如果是開發新功能,最好是新建一個分支,如果這個分支已經被合并,那么刪除這個分支使用:
git branch -d feature
如果這個分支沒有被合并,刪除這個分支,需要用到下面的語句:
git branch -D feature
3.6 多人協作
從遠程克隆倉庫也是分多種情況,第一種情況是只有一個master分支的情況下:
git clone XX #遠程倉庫克隆時,實際上Git自動把本地的master分支和遠程的master分支對應起來了,并且,遠程倉庫的默認名稱是origin
git remote #origin 此代碼是查看遠程庫的信息,遠程庫的默認信息是origin
git remote -v #使用-v查看遠程庫更為詳細的信息
origin git@github.com:michaelliao/learngit.git (fetch)
origin git@github.com:michaelliao/learngit.git (push)
git push origin master #推送master分支
git push origin dev #推送dev分支
第二種情況是當遠程庫存在多個分支時候,使用git clone語句克隆代碼,使用git branch語句只能查看master分支,為了顯示其他分支,需要創建遠程的origin的dev分支到本地:
git clone XX
git branch #master
#實際上被克隆的代碼庫有很多分支,而這里只能顯示master分支
git checkout -b dev origin/dev
#使用上面的語句在本地建立dev分支,和遠程庫的dev分支對象起來,同時獲得遠程庫的分支信息代碼
#在dev分支上修改代碼
git commit -m "add the dev"
git push origin dev #將代碼推送到遠程庫dev分支中
第三情況是處理沖突:兩個人同時寫作同一個代碼庫,比如在feature分支上面,一個人已經作為修改,另外一個人在此人修改之前已經git clone到本地,并且在feature同一個地方做了修改,因此會出現conflict。
#已經有其他用戶在feature分支上面建立test.rb文件
#下面的代碼都是在本地的feature分支上進行
git add test.rb
git commit -m "add the test.rb"
git push origin feature
上面的代碼出現錯誤,根據提示可以知道,是因為出現了代碼沖突,根據提示使用git pull。
git pull #如果存在no tracking information,說明本地分支和遠程分支之間的鏈接關系沒有建立
git branch --set-upstream-to=origin/feature feature #設置feature和origin/feature的鏈接
git pull #出現沖突及沖突提示
#沖突解決好之后重新提交
git commit -m "conflict commit"
git push origin feature
4.標簽管理
標簽是版本庫的一個快照,若給版本庫打了一個標簽,就相當于在某個時候獲取一個特定時間的版本庫,標簽和分支不同,分支可以移動,標簽不能移動。
4.1 創建標簽
git checkout master #切換到最新的master分支上
git tag v1.0 #給最新的分支貼上標簽
git tag #查看所有標簽
默認情況下標簽是打在最新的提交的commit上,如果需要打在之前提交的commit上,需要如下的語句
git log --pretty=oneline --abbrev-commit #顯示commit id log
git tag v0.9 1234234 #其中1234234是commit id值,即將標簽打在這個commit id中。
git show v1.0 #查看某個版本的標簽
git tag -a v0.1 -m "version 0.1 released" 3628164
#創建帶有說明的標簽,用-a指定標簽名,-m指定說明文字
4.2 操作標簽
git tag -d v0.9 #刪除標簽
git push origin v0.9 #因為標簽都是在本地的,此代碼是推送標簽到遠程
git push origin --tags #一次性推送全部尚未推送到遠程的本地標簽
#如果標簽已經推送到遠程,要刪除遠程標簽就麻煩一點,先從本地刪除:
#然后,從遠程刪除。刪除命令也是push
git tag -d v0.9
git push origin :refs/tags/v0.9
5.自定義Git
git config --global color.ui true #設置顏色
5.1 忽略特殊文件
在工作區建立 .gitignore
ruby的示例文件可以在這里找到
5.2 配置別名
配置別名就是在將Git的命令用其他名字來表示,示例代碼如下所示:
git config --global alias.co checkout
git config --global alias.ci commit
git config --global alias.br branch
#--global參數是全局參數,也就是這些命令在這臺電腦的所有Git倉庫下都有用。
每個倉庫的Git配置文件都放在.git/config文件中,其中別名就在[alias]后面,要刪除別名,直接把對應的行刪掉即可。
[core]
repositoryformatversion = 0
filemode = true bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
[remote "origin"]
url = git@github.com:michaelliao/learngit.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
[alias]
last = log -1
而當前用戶的Git配置文件放在用戶主目錄下的一個隱藏文件.gitconfig
中:
[alias]
co = checkout
ci = commit
br = branch
st = status
[user]
name = Your Name
email = your@email.com
5.3 搭建Git服務器
見這里
6.擴展
6.1 rebase的使用
相關文檔
在master分支上簡歷mywork分支,示意圖如下所示:
在mywork分支上提交兩次代碼,同時其他用戶在master分支上提交了兩次代碼,示意圖如下所示:
在這里,你可以用"pull"命令把"origin"分支上的修改拉下來并且和你的修改合并; 結果看起來就像一個新的"合并的提交",示意圖如下所示:
但是,如果你想讓"mywork"分支歷史看起來像沒有經過任何合并一樣,可以用git rebase,代碼如下所示:
git checkout mywork
git rebase origin
這些命令會把你的"mywork"分支里的每個提交(commit)取消掉,并且把它們臨時 保存為補丁(patch)(這些補丁放到".git/rebase"目錄中),然后把"mywork"分支更新 到最新的"origin"分支,最后把保存的這些補丁應用到"mywork"分支上。
當'mywork'分支更新之后,它會指向這些新創建的提交(commit),而那些老的提交會被丟棄。 如果運行垃圾收集命令(pruning garbage collection), 這些被丟棄的提交就會刪除。
現在我們可以看一下用合并(merge)和用rebase所產生的歷史的區別:
6.2 修改最近一次的提交 commit --amend
該功能會修改最近一次的提交,使用commit --amend
比如最開始是這樣的:
需要對添加add的講解進行修改,使用下面代碼:
git add .
git commit --amend
上面的代碼會跳出一個編輯頁面,可以修改添加add的講解的值,修改為添加add和commit的講解,并且進行保存,使用git log操作,可以得到如下的結果:
6.3 取消最新一次的提交 git revert head
下面的代碼可以取消最近一次的提交
git revert HEAD
原本最初的提交branch如下所示:
執行git revert HEAD之后,變為如下的結果
就是說針對“添加pull的講解”所變化的內容消失了。
6.4 使用reset來刪除前面的幾個提交
代碼如下所示:
git reset --hard HEAD~~ #這是刪除最前面的兩個提交
git reset --hard HEAD~ #這是刪除了最前面的一個提交
git reset --hard ORGI_HEAD #如果之前的reset出錯了,該代碼會返回最開始進行reset的位置
圖片演示如下:
6.5 **使用cherry-pick將其他分支中的內容添加到主分支中 **
如下圖所示:
將添加commit的講解添加到master分支中,代碼如下所示:
git checkout master
git cherry-pick 99daed2
#下面的提示代碼是正常現象,說明提交成功
error: could not apply 99daed2... commit
hint: after resolving the conflicts, mark the corrected paths
hint: with 'git add <paths>' or 'git rm <paths>'
hint: and commit the result with 'git commit'
#但是如果出現沖突的話,需要添加如下的進行如下的操作
git add filename
git commit
6.6 **使用rebase -i 匯合提交 **
這是做的事情是講master上面最近的兩次進行合并,匯合為一次提交,使用的代碼如下:
git rebase -i HEAD~~
#上面的代碼執行之后,會有下面的代碼界面出現,將第二行的pick改為squash
pick 9a54fd4 添加commit的說明
pick 0d4a808 添加pull的說明
# Rebase 326fc9f..0d4a808 onto d286baa
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#編輯保存退出,然后出現了編輯界面,編輯里面的值,該值將成為合并commit的說明
示意圖如下所示:
就是將添加commit的講解和添加pull的講解進行合并,成為一個commit。示意圖如下所示:
6.7 用rebase -i 修改提交
在這里修改添加commit的講解
代碼修改如下所示:
git rebase -i HEAD~~
將第一行的pick改為eidt,保存之后退出
pick 9a54fd4 添加commit的說明
pick 0d4a808 添加pull的說明
# Rebase 326fc9f..0d4a808 onto d286baa
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#
#打開sample.txt,適當地修改“commit的講解”部分
git add sample.txt
git commit --amend
#已經commit,但是rebase操作還沒結束。若要通知這個提交的操作已經結束,請指定 --continue選項執行rebase。
git rebase --continue
6.8 把分支內容合并成一個提交,并導入到master分支
示意圖如下所示:
把下面的一個分支合并成一個提交,并導入的master分支中,具體的代碼如下所示:
git checkout master
git merge --squash issue1
#出現了下面的提示,說明提交成功
Squash commit -- not updating HEAD
Automatic merge went well; stopped before committing as requested
#出現下面的提示,則說明提交失敗,出現了沖突
Auto-merging sample.txt
CONFLICT (content): Merge conflict in sample.txt
Squash commit -- not updating HEAD
Automatic merge failed;
fix conflicts and then commit the result.
#說明發生了沖突,修改之后進行提交
git add sample.txt
git commit
6.9使用二分法查找bug
二分法的原理
代碼演示如下:
git bisect start master commit_id #master是bad點,commit_id是最開始提交點
git bisect run make test #進行了自動化測試,此代碼可以測試出錯誤點