項目經驗,如需轉載,請註明做者:Yuloran (t.cn/EGU6c76)git
本文介紹如何使用 Git Bash 命令行,提交代碼、解決衝突,以及如何避免衝突。有助於理解 Android Studio 的 VCS 背後的原理。github
git clone https://github.com/Yuloran/GitTutorial.git
複製代碼
能夠檢出 origin/master
分支到本地,這是 GitHub 建立倉庫時默認的 主機名/分支名
。使用 git branch -vv
查看本地分支狀態:vim
可見,本地分支名爲 master,關聯的遠程分支名爲 origin/master(origin 是主機名,master 是分支名)。bash
不少時候,配置管理員須要新建不少遠程分支,以進行同一項目不一樣版本的並行開發。好比,有的分支用於需求開發,有的分支用於 Bug 修復等。此時,咱們須要檢出各自對應的分支,修改並提交代碼。編輯器
管理員新建遠程分支後,咱們須要先同步一下遠程分支,才能看到新建的分支:fetch
如上圖所示,先使用 git branch -a
查看本地和遠程全部分支,發現並無管理員新建的 bug_fix
分支,此時輸入 git fetch
,提示有一個新分支 bug_fix
。再次輸入 git branch -a
查看全部分支:ui
嗯,確實多了一個 bug_fix
分支。spa
git checkout -b bug_fix -t remotes/origin/bug_fix
複製代碼
checkout -b
表示新建本地分支,bug_fix
爲本地分支名,你也能夠起別的名字。-t
表示追蹤遠程分支(track),remotes/origin/bug_fix
爲遠程分支名,查看檢出結果:命令行
輸入 git branch
查看當前所在的本地分支:3d
輸入 git status
查看當前分支狀態:
提示你目前修改是最新的,沒有任何修改能夠提交。
不少開發人員,喜歡在一個本地分支上,連續提交代碼。這是一個很很差的習慣,尤爲是在多人協做的狀況下。這會致使每筆提交之間存在依賴關係,即便每筆修改之間毫無瓜葛。進而可能致使 merge
衝突、cherry-pick
合入冗餘代碼。並且,若是你忽然發現,上上一筆提交有問題的時候,我以爲你可能有種想 shi 的感受。
保留一個本地分支,專門用於同步代碼。
好比,咱們如今須要在 master
分支上作一個需求,首先輸入 git status
查看本地 master
分支的狀態:
提示本地有修改文件,沒有提交。咋整呢?有兩種處理方法:
git pull
進行同步,有衝突會自動合併,合併不了再手動解決。-> 不推薦,可能會在本地產生一條 merge 記錄stash save
,再使用 git pull --rebase
進行同步,最後將暫存的修改 stash pop
,有衝突會自動合併,合併不了再手動解決。-> 推薦,自動變基,不會在本地產生 merge 記錄git stash save [-u] 'update readme.md'
複製代碼
[-u]
表示參數可選,加 -u
會將本地新增文件也暫存,不加則僅暫存本地修改部分。'update readme.md'
爲描述,下面列出 git stash
支持的全部操做:
git stash list
顯示全部暫存記錄git stash show stash@{0}
查看指定的暫存記錄git stash pop stash@{0}
彈出指定的暫存記錄git stash drop stash@{0}
刪除指定的暫存記錄git stash clear
清空暫存記錄git pull --rebase
複製代碼
同步結果:
提示已是最新的。若是本地代碼不是最新的,應當相似於下圖:
git stash pop [stash@{0}]
複製代碼
[stash@{0}]
表示可選,不加默認彈出棧頂元素,也能夠指定彈出哪個暫存記錄。彈出結果以下:
提示有衝突。莫要驚慌,有衝突解決就是了,畢竟我們乾的都是「小項目」,除非文件換行符變了,不然不會衝突太多。像 AOSP
、Mokee
那種大型項目,發生衝突纔是坑爹。好比國內的手機廠商,每次大版本升級時(好比從 Android 8.0 升到 Android 9.0),都須要花幾個月的時間才能使版本穩定,這也是爲何國產手機安卓版本老是落後於 Google 的緣由。扯遠了,仍是先 git status
看一下工做區狀態:
原來是 README.md
文件修改衝突了,並且 Git 還貼心地提示你:
git reset HEAD <file>
來丟棄本地修改git add <file>...
標記衝突解決(省略號表示後面可接多個文件,以空格分隔)咱們先使用 git diff <file>
看看哪裏衝突了:
git 使用:
<<<<<<< Updated upstream
=======
>>>>>>> Stashed changes
複製代碼
標記衝突狀態,=======
上面的是遠程倉庫上別人的修改,下面的是咱們的本地修改。嗯,這個衝突是我人爲製做的,因此比較簡單。在 IDE 中手動解決該衝突後,使用 git add README.md
命令標記衝突已解決:
README.md
咋變原諒色了呢?由於咱們剛纔用了 git add
命令,將其添加到了暫存區,因此上面顯示的是 Changes to be committed
,也就是待提交。提交啥啊,剛解決完衝突,需求還沒作呢!因此,咱們使用 git reset <file>...
命令,將其從暫存區撤出:
<file>...
表示可選,不加即撤出全部,加了即撤出指定的文件。Linux 幫助手冊中不少使用 <arg>
或者 [arg]
表示參數可選,<>
和 []
是不須要輸入的,這個已經成爲開發人員的習慣用法。
不少人這個時候,就直接在本地 master
分支上瘋狂輸出需求代碼了。NO!咱們應該針對不一樣的開發內容,新建不一樣的本地分支。好比 feature_shopping
,bugfix_tombstone
等等,假設咱們如今須要實現一個購物功能,咱們應該使用 git checkout -b feature_shopping
新建一個本地分支來實現這個需求:
連續通宵5天后,咱們的需求終於作完了,能夠提交代碼了:
git commit -m "update README.md"
表示將修改提交到本地倉庫,此時尚未推送到遠程倉庫。-m
後面的是修改描述,這是一種簡便寫法。而大公司都會對提交的描述有格式要求,因此須要先配置 commit 模板:
git config --global commit.template ~/.gitmsg
複製代碼
編輯該模板:
輸入 git commit
:
模板已經生效了,輸入修改描述便可。我這裏配置的 Git 編輯器是 vim,你也能夠配置成別的:
git config --global core.editor notepad
複製代碼
這樣,就能夠用記事原本編寫修改描述了。
commit
以後,本地又修改了一些文件,此時須要使用 git commit --amend
追加提交:
commit
以後,發現提交多了,把不須要提交的也提交了,此時須要回退,有兩種方式:
git reset [--soft] commit_id
,軟回退,不會丟棄文件修改記錄,--soft
不加也能夠。git reset --hard commit_id
,硬回退,丟棄全部修改。通常僅在須要回退到指定節點驗證問題時使用。查看 commit_id:
git log -1
複製代碼
-1
表示只查看提交記錄裏的最後一條:
輸入 git reset 306c8b26360adfbdb3992f62514e8d58626f2d20
,便可回退提交。而後從新 git add <file>...
,git commit
。
commit
以後不少人就直接 git push
了,這是不對的,應當先同步代碼。因爲咱們如今在新建的本地分支 feature_shopping
上,這個分支沒有關聯遠程分支,因此沒法也不該該使用 git pull --rebase
來同步代碼。正確的操做爲:
git checkout master
:切到本地主分支git pull --rebase
:同步代碼git checkout feature_shopping
:切換到本地需求分支git rebase master
:將本地主分支代碼,合入到本地需求分支(可能有衝突,按照 Git 的提示修復便可)git push origin HEAD:refs/for/master
:將本地需求分支的提交推送到遠程 master
分支Git Bash 每個命令的操做結果,成功或者出錯的描述都很詳細。遇到問題的時候,只要按照提示,一步步操做,通常都能解決。