[TOC]
基本概念
-
master
指針:指向最新的提交
資料
http://sfault-image.b0.upaiyun.com/37/92/37923f2478edc5709b36562b26c9e008
全局配置
$ git config --global user.name "kk"
$ git config --global user.email "xxx@gmail.com"
編輯模式查看全局設置:
git config --global -e
列表形式查看全局設置:
git config --global -l
使用GitHub時,在本地創(chuàng)建SSH Key
ssh-keygen -t rsa -C "youremail@example.com"
如果一切順利的話,可以在用戶主目錄里(~/.ssh)找到.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文件的內(nèi)容
遠程倉庫
克隆遠程倉庫到本地
git clone git@github.com:michaelliao/gitskills.git
克隆遠程倉庫某個分支到本地
git clone -b <branch> <remote_repo>
例如:git clone -b 指定的分支名字
給本地倉庫指定遠程倉庫
關聯(lián)GitHub倉庫:
git remote add origin git@github.com:michaelliao/learngit.git
顯示遠程倉庫:
git remote show origin
第一次推送使用:
git push -u origin 分支名稱
之后推送使用:
git push origin maste
查看遠程倉庫地址
git remote -v
取消關聯(lián)遠程倉庫
git remote rm origin
初始化git倉庫
git init
git add .
git commit -m “xxxx"
文件操作
刪除所有文件
git rm * -r
刪除文件夾
git rm filename -r
忽略無需版本控制的文檔
echo “*.txt” > .gitignore
日志
查看commit日志
git reflog
或
git log
分支管理
- 查看當前所在分支
git branch -a
- 切換到某個分支
git checkout 分支名字
- 創(chuàng)建本地分支并切換到創(chuàng)建的分支:
git checkout -b your_branch
- 提交該分支到遠程倉庫
git push origin dev
- 追蹤遠程分支
git branch --track release_2.3.0 origin/HEAD:refs/for/release_2.3.0
- 將本地分支push到遠程分支,(遠程會自動創(chuàng)建your_branch分支),并關聯(lián)本地分支與遠程分支
git push -u origin your_branch
- 刪除遠程分支
git push origin --delete <branchName>
- 刪除本地分支
git branch -d your_branch
本地提交回滾
- 先重置本地在上次提交之后的修改(如果需要的話)
git checkout *.m
- 重置為遠程倉庫的最新版本
soft表示本地的修改還在本地文件中,不加的話那么本地的修改也沒了
git reset HEAD^ --soft
拉取遠程代碼時沖突
- 保存本地修改到暫存區(qū)
git stash
- 拉取遠程代碼
git pull
- 將暫存區(qū)內(nèi)容恢復到本地,有沖突時先解決沖突
git stash pop
git stash 的使用
- 列出所有暫時保存的工作
git stash list
- 恢復某個暫時保存的工作
git stash apply stash@{1}
保存stash時設置stash名稱
git stash save "my_stash"
丟棄最近一次stash的文件
git stash drop
合并某次提交 merge a specific commit in Git
git cherry-pick d42c389f
git merge 后 push 到 Gerrit 失敗,提示 no new changes
- 在
git merge
的時候,加上--no-ff
參數(shù),是為了讓它生成一個新的 commit,這樣就可以提交了~(不過生成的 gerrit change 是看不到改動信息的)
tag 操作
- 查看tag
git tag
- 創(chuàng)建 本地 tag
git tag 1.0.0
或者
git tag -m "first release" 0.1.0
- 推送 本地 tag 到遠程服務器
git push origin 1.0.0
- 或者推送所有tags到遠程服務器
git push --tags
- 刪除本地 tag
git tag -d 1.0.0
- 刪除遠程 tag
- 先刪除本地 tag
git tag -d 1.0.0
- 然后push
git push origin --delete tag 1.0.0
fatal: remote origin already exists.
錯誤解決
- 先刪除遠程 Git 倉庫
git remote rm origin
2 再添加遠程 Git 倉庫
git remote add origin git@github.com:FBing/Java-code-generator
git ignore
- 創(chuàng)建
.gitignore文件
touch .gitignore
忽略規(guī)則示例
# 這是注釋行,將被忽略
*.a # 忽略所有以.a為擴展名的文件
!lib.a # 但是名為lib.a的文件或目錄不要忽略,即使前面設置了對*.a的忽略
/TODO # 只忽略此目錄下的TODO文件,子目錄中的TODO文件不忽略
build/ # 忽略所有build目錄下的文件,但如果是名為build的文件則不忽略
doc/*.txt # 忽略文件如doc/notes.txt,但是文件如doc/server/arch.txt不忽略
例如忽略下圖的GPUImage.framework框架
SystemVedio/GPUImage/GPUImage.framework
只追蹤某幾個文件
#忽略所有文件,注意放在開頭
/*
#除src文件夾外
!/src
#除bin文件夾外
!/bin
#總的效果就是git只跟蹤src和bin兩個文件夾
merge 與 rebase 的區(qū)別
參考:https://www.zhihu.com/question/36509119/answer/131513261
搞清楚這個問題首先要搞清楚merge和rebase背后的含義。
merge:會產(chǎn)生一次合并提交
先看merge,官方文檔給的說明是:
git-merge - Join two or more development histories together
顧名思義,當你想要兩個分支交匯的時候應該使用merge。
根據(jù)官方文檔給的例子,是master merge topic,如圖:
A---B---C topic
/
D---E---F---G---H master
然而在實踐中,在H這個commit上的merge經(jīng)常會出現(xiàn)merge conflict。為了避免解決沖突的時候引入一些不必要的問題,工程中一般都會規(guī)定no conflict merge。比如你在github上發(fā)pull request,如果有conflict就會禁止merge。
所以才會有題主問的問題:在當前的topic分支,想要引入master分支的F、G commit上的內(nèi)容以避免merge conflict,方便最終合并到master。
這種情況下用merge當然是一個選項。用merge代表了topic分支與master分支交匯,并解決了所有合并沖突。然而merge的缺點是引入了一次不必要的history join。如圖:
A--B--C-X topic
/ /
D---E---F---G---H master
其實仔細想一下就會發(fā)現(xiàn),在引入master分支的F、G commit這個問題上,我們并沒有要求兩個分支必須進行交匯(join),我們只是想避免最終的merge conflict而已。
rebase:將其他分支的內(nèi)容整合到當前分支,改變當前分支branch out的位置
rebase是另一個選項。rebase的含義是改變當前分支branch out的位置。這個時候進行rebase其實意味著,將topic分支branch out的位置從E改為G,如圖:
A---B---C topic
/
D---E---F---G master
在這個過程中會解決引入F、G導致的沖突,同時沒有多余的history join。但是rebase的缺點是,改變了當前分支branch out的節(jié)點。如果這個信息對你很重要的話,那么rebase應該不是你想要的。rebase過程中也會有多次解決同一個地方的沖突的問題,不過可以用squash之類的選項解決。個人并不認為這個是rebase的主要問題。
綜上,其實選用merge還是rebase取決于你到底是以什么意圖來避免merge conflict。實踐上個人還是偏愛rebase。一個是因為branch out節(jié)點不能改變的情況實在太少。另外就是頻繁從master merge導致的冗余的history join會提高所有人的認知成本。