Git基本使用以及如何向開源項目提交PR
目標
- 非常快速的和fork的源倉庫保持同步
- 修改代碼之後,方便的、快速的提交代碼到fork的倉庫,並向原倉庫提交PR
- 掌握在gitee和GitHub之間快速切換
- 掌握標準的貢獻開源的步驟
Git 基本操作
- GitHub上fork一個項目
- 克隆到本地
git clone [email protected]:jacksparrow414/hello-world.git
- 新建一個名字爲develop的分支,checkout -b 新建分支並切換到該分支
git checkout -b develop
- 在develop分支修改代碼
- 提交暫存
git add .
如果提交到暫存區的文件想要移出暫存區怎麼處理?
可以使用下面的命令
git reset HEAD 文件名
或者
git rm --cached 文件名
- 提交到本地倉庫,-a代表all,將暫存區的所有文件提交,-m 是提交信息的簡要說明
git commit -a -m 'add message'
提交之後,發現文件少提了一個,或者註釋信息寫錯了,又或者codereview沒過,怎麼處理?
# 修改上一次的提交信息
git commit --amend -m 'modify message'
# 將忘記提交的文件,例如:忘記提交test.txt文件。 git add test.txt之後
git commit --amend test.txt
# 此時會調出vim編輯器頁面,如果想要修改提交信息,則修改之後,:wq保存退出即可
# 如果想使用上次的提交信息,則可以下面這樣寫
git commit --amend --no-edit test.txt
# 此時 git log查看兩次提交最終呈現爲一個提交
# 如果codereview沒過,不需要abandon,則修改文件之後,採用上面兩行任意一種方式之後,
git push
- 推送到GitHub上,有下面幾種寫法
-
第一種寫法:將本地develop分支推送到遠程,遠程會自動匹配develop這個分支的名字,如果沒有,則新建
格式: git push origin 遠程分支名字
git push origin develop
git push origin develop:
以上兩個命令相當於
git push origin develop:refs/heads/develop
注意:這種寫法可以在develop分支上對master上的commit進行push
寫法如下:
git push origin master
雖然極其不鼓勵此種做法,但是可以瞭解下
-
第二種寫法:將當前的HEAD所在的分支提交到遠程,如果沒有明確遠程分支,則還是默認找當前的分支,沒有則新建
格式: git push origin HEAD:refs/heads/遠程分支名
origin 是遠程源倉庫的別名,只有一個的時候,默認爲origin,如果需要推送到不同的源,則更換origin爲目標名字。
可以使用
git remote -v
查看添加了哪些遠程倉庫
注意因爲這裏指定了HEAD,HEAD所在的分支就是本地的分支,也就說,這個命令只能push HEAD所在的分支,想要在develop分支push master分支上的commit,除非切換到master分支上,使HEAD位於master上,或者使用第一中方式
git push origin HEAD:refs/heads/develop
git push origin HEAD
對於gerrit來說,如果需要codereview,則不能直接推送到遠程,則需要下面這樣寫
git push origin HEAD:refs/for/develop
-
第三種方式
不加任何分支名字,默認直接向遠程推送當前分支名,遠程沒找到,則新建分支
在第一次向當前分支的遠程分支推送時,如果不設置,則下面的命令報錯
git push --set-upstream origin develop
以後每次提交在該推送遠程時,只需要
git push
git push origin
兩種方式效果一樣
-
建議建議平時可以使用第三種方式,更簡單
-
推送到個人遠程分支之後,pull一下
-
直接拉取默認遠程倉庫origin的遠程分支對應的本地分支,如果遠程倉庫不止origin一個,則想要從哪個遠程倉庫拉取,直接替換origin名字即可
git pull
git pull origin
-
拉取遠程develop分支合併到當前分支
git pull origin develop
拉取另一個遠程倉庫upstream的master分支併合併到到當前分支
git pull upstream master
注意 這裏的origin代表遠程的源倉庫,默認是叫origin,可以有多個遠程的源倉庫,可以使用
git remote -v
查看本地都有哪些遠程的源倉庫
-
-
合併develop分支的某一個提交到master分支
切換到master分支
git checkout master
查看最近的git操作日誌
git reflog
找到develop分支上的一處提交
# commitId就是git reflog中找到的develop的commitId git cherry-pick commitID
-
回退HEAD指針到前幾步
-
保留本地提交信息
# HEAD~N,表示回到N步,N是數字 git reset --soft HEAD~2
-
不保留本地提交信息
git reset --hard HEAD~2
-
GitHub常用操作
問題
GitHub clone到本地太慢,經常失敗怎麼辦?
在GitHub上fork項目到自己的倉庫,當項目很大時,由於GitHub訪問速度慢,導致clone不到本地。
可以選擇使用gitee同步,然後
git clone gitee倉庫地址
克隆到本地,添加GitHub的個人倉庫地址爲另一個遠程源
格式: git remote add 自定義一個名字 遠程倉庫地址
遠程倉庫地址:可以在GitHub個人該項目的倉庫下clone,選擇HTTPS,複製即可
git remote add person_repo https://github.com/xxxx
此時默認的origin是gitee上的,如果僅僅是想快速從gitee上下載項目,但是origin對應的源想要是GitHub上的個人倉庫怎麼處理呢?
git remote set-url origin https://github.com/xxxx
將origin的url設置爲GitHub上的自己fork倉庫的地址,而不是gitee上的
設置成功之後,則把上一步相同的遠程源(person_repo)刪掉
git remote remove person_repo
那麼如何同官方的倉庫保持同步呢?
-
第一種方法,GitHub個人fork倉庫頁面,如圖
-
在個人fork倉庫頁面,點擊pull request
-
如果想要將自己的改動推送到原倉庫
-
如果是同步原倉庫到自己fork的倉庫(即同步原倉庫)
那麼向fork的倉庫提交PR即可,merge之後,即保持了原倉庫的同步
-
-
第二種方法,命令行的方式
-
再添加一個遠程的源,這個源的url是官方倉庫的url
git remote add upstream https://github.com/xxxx原倉庫的GitHub地址
-
每次修改issue或者有新的功能添加的時候,建議都新開一個分支。
本地新建並切換到issue#4673分支上,並將官方的master分支合併到當前分支git checkout -b issue#4673 upstream/master
# 上面git push也說到過,設置upstream的目的是爲了簡化其他命令 git branch --set-upstream-to=upstream/master
在這個分支上修改完之後,提交之前,拉取一下,看看有沒有衝突
git pull
此時會默認從upstream的遠程倉庫拉取,因爲上面設置了
小提示:如果使用git pull在拉取官方原倉庫的時候,有時候會彈出vim編輯器,git 默認會生成一個 merge branch master of…的信息,如果,此後提交PR的時候會發現會帶上這種信息,很不美觀
解決方案:git pull --rebase=true # 或者 git pull --rebase
或者當vim編輯器被打開時,什麼都不寫,:wq保存退出,此時就會生成兩條並行的線,然後再
git rebase
那麼此時就會變成一條直線
本地改動之後commit,然後推送到遠程自己fork的倉庫,origin是自己fork的遠程倉庫名字
git push -f origin issue#4673
這時,在GitHub個人fork的倉庫頁面,即可找到剛纔的提交上來的分支,向原倉庫提交PR即可.提交步驟參考上面的同步第二步驟
這裏爲什麼是push的時候使用了-f參數呢,強制將本機代碼推送到遠程。其實在切換到該分支的時候,包括提交之前,我們本地額issue分支已經和官方倉庫的master分支保持一致了,所以,push的時候直接讓遠程的issue和本機代碼保持一致。
同時還要注意:如果遠程origin的master分支,我們在本地pull 官方原倉庫之後,那本地肯定是領先於origin的master分支的,這時候,如果不加-f參數,那麼git push 會報錯,! [rejected] master -> master (non-fast-forward)
但是,個人建議,平時公司團隊開發push的時候儘量不要用-f參數.當PR被官方merge之後,則切換到origin的master分支,進行和原倉庫同步
# 如果不指定遠程倉庫,默認是origin,git checkout upstram/master 是切換到遠程倉庫upstream的master分支 git checkout master # 拉取遠程倉庫upstream的master分支,併合併到當前分支 git pull upstream master
此時,本地的代碼已經和fork的原倉庫代碼保持了一致
刪除本地剛纔修復bug的issue#4673分支
git branch -d issue#4673
刪除遠程對應的分支
git push origin --delete issue#4673
-
結束
到此爲止,完整的流程已經走完