最好最易懂的Git教学——分享“好麻烦部落格”Git教学(2)

Git branch

branch (分支)應該是 Git 最重要的技能了,在一個多人專案的開發過程中我們有時候要開發新功能,有時候是要修正某個Bug,有時候想要測試某個特異功能能不能 work ,這時候我們通常都會從主 branch 再開出一條新的 branch 來做,這支新開的 branch 會帶著你的主 branch 目前的最新狀態,當你完成你所要開發的新功能/ Bug 修正後確認沒問題就再把它 merge(合併)回主 Branch ,如此便完成了新功能的開發或是 Bug 的修正,因此每個人都可以從主 branch 拉一條新的
branch 來做自己想做的事,再來我們好好了解一下 branch 的使用。

了解 branch 最好的方法就是有圖像可以看,你可以用任何你已安裝的GUI來查看,但在你安裝 Git 的時候其實同時也安裝了最基本的 Git GUI 叫做 gitk,你可以使用 gitk
--all
 這個指令來呼叫他,此時你應該能看到以下的畫面:

點擊左上方區塊的 commit 節點你可以看到當次 commit 的詳細資料,例如作者以及他的更新記錄,但你會發現這時候終端機是無法輸入的,因此請你先關掉 gitk ,改打指令 gitk
--all &
 來讓 gitk 在背景執行。

git
branch
 這個指令可以列出所有的 branch 並告訴你目前正在哪個 branch:

$ git br
* master
  develop
  feature/test

上面的訊息告訴我們在這個 Git repository裡有3支 branch ,而你目前正在 master branch 上。假設我們現在要開一支新的 branch 叫做 cat ,使用 git
branch
 來幫助你開一支新的 branch

$ git branch cat
$ git branch
  cat
* master

上面我們開了一支新的 branch 叫做 cat ,使用 git
branch
 再查看一次發現已經多了這支新的 branch了,這時候你去查看你的 gitk 的圖像狀態會發現像下圖一樣,新的 branch cat 與 master 在同一條水平線上,表示目前他們的狀態是一模一樣的。

你應該也有發現,雖然我們建立了一個 cat 的 branch ,但其實我們所在的 branch 還是在 master branch,因此我們現在還需要切換過去,因此我們使用 git
checkout
 來切換:

$ git checkout cat
Switched to branch ‘cat‘

這樣就會從原本的 mater branch 切換到 cat branch 了。

接下來假設我正在 cat 這支 branch 做開發,因此新增一個檔案,加上一些內容,將它 add 到 stage 後再 commit 它。

$ vim lib/cat.rb
$ git status
# On branch cat
# Untracked files:
#   (use "git add ..." to include in what will be committed)
#
#   lib/cat.rb
nothing added to commit but untracked files present (use "git add" to track)
$ git add lib/cat.rb
$ git commit -m "Add Cat.rb"
[cat ea7d309] Add Cat.rb
 1 files changed, 3 insertions(+), 0 deletions(-)
 create mode 100644 lib/cat.rb

上面的流程你已經很熟悉了,接下來我們再切換到原本的 master branch ,這時候你會發現剛剛在 cat branch 新增的 cat.rb 檔案已經不見了。

$ git checkout master
Switched to branch ‘master‘
Your branch is ahead of ‘origin/master‘ by 1 commit.

Git 在我們切換 branch 的同時就會很聰明的會把我們的工作目錄更動成那個 branch 該有的狀態,如果你這時候切換到 GUI 去看,你會發現到與剛剛 cat 和 master branch 在同一條水平線上不同,cat branch現在已經比 master branch 再多出了一個 commit 的內容。

現在我在切換到 cat branch 去增加更多的內容,一樣再將它 add 到 stage 後,再 commit 它。

$ git checkout cat
Switched to branch ‘cat‘
$ mvim lib/cat.rb
$ git add lib/cat.rb
$ git commit -m "Add initializer"
[cat a3bce42] Add initializer
 1 files changed, 3 insertions(+), 1 deletions(-)

切到 GUI 來看的話你會發現現在 cat 這支 branch 比 master branch 要在多上兩個 commit 的內容。

如果這時候我們在 master 上繼續開發會發生什麼事呢? 我們現在切換到 master branch 並增加一個檔案及內容,照慣例 add 後 commit。

$ git co master
Switched to branch ‘master‘
Your branch is ahead of ‘origin/master‘ by 1 commit.
$ git add spec/animal_spec.rb
$ git commit -m "Another spec"
[master 7d72927] Another spec
 1 files changed, 2 insertions(+), 0 deletions(-)

我在 master branch 的 animal_spec.rb 增加了一些內容,把它 commit 之後我們切換到 GUI 來看。

我們發現現在 master branch 與 cat branch 已經產生分歧了,因為兩支 branch 都有了各自往後開發的 commit ,而且由於 master branch 最後一次的 commit 時間較新因此排列在最前面。

Git rebase 整理現在的 branch

假設我們現在在 cat branch 的開發動作已經完畢,通常我們現在要做的事情會是將 cat branch 合併回 master branch,在開發流程上, master branch 就像是一個主要的 branch ,每個開發人員都是從 master branch checkout 出去一支新的 branch 做開發,在開發完畢後就再將開發完的 branch 合併回 master branch,因此 master branch 都會保有最新的開發好的狀態,一般在 Git 教學中會教你現在使用 git
merge
 這個指令來將兩個 branch 合併,但這邊我要先教你的是 git
rebase
 這個指令。

與 git
merge
 不同的是, git
rebase
 不單單只是將兩個不同的 branch 合併起來,而是將某一支 branch 基於另一支 branch 的內容合併起來,這是什麼意思? 以我們的例子來說,我們在
cat branch 開發完了以後,這時候我們的 master branch 也有了其他開發者所合併回去的內容,換句話說現在的 master branch 與我們當初 checkout 出去的時候的狀態已經不同了,但我們會希望我們現在這支 cat branch 的內容就像是剛剛從 master branch checkout出來一樣乾淨,也就是說讓 cat branch 中保有 master branch 最新的狀態, git
rebase
會基於 master branch 目前最後一次的 commit 內容再往後把你在 cat branch 上commit 的內容加上去,我們現在在 cat branch 輸入 git
rebase master
 來將 cat branch 基於 master branch 做 rebase。

$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: Add Cat.rb
Applying: Add initializer

過程中沒有發生衝突,這時候我們到 GUI 看看現在的結果。

原先 cat branch 上的兩個 commit (Add Cat.rb 和 Add initializer) 已經合併到 master branch 最新的 commit (Another spec),換句話說目前 cat branch 的內容就像是剛從 master branch 所 checkout 出來然後再加上自己的 commit,因此不同於 git
merge
 的線圖會把 cat branch 合併到 master branch , 而是把原本的 cat branch 接到 master branch 因此只有一條線,當一個專案有很多的 branch 再做開發的時候會避免很多 branch 的線接來接去難以辨認。

開發過程中,若你在開發的 branch 功能比較多, commit 的量也比較多時,建議使用rebase將你現在的 branch 整理過再合併回主幹,這樣會產生較漂亮的線圖

若你想要看看目前的 branch 與其他 branch 有哪些差異,你可以使用 git
diff
 的指令去觀察,例如我現在想要看 master 跟 cat 這兩個 branch 的差異,我只要下:

$ git diff cat master
diff --git a/lib/cat.rb b/lib/cat.rb
deleted file mode 100644
index 1227d26..0000000
--- a/lib/cat.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-class Cat < Animal
-  def initialize
-    super
-  end
-end

你就可以看到現在的 cat branch 跟 master branch 的差異在哪了。

如果我們開發完畢時,我們會把開發好的東西合併回 master 很自然的我們通常都會使用 git
merge
 這個指令來合併兩個branch

$ git merge cat
Merge made by recursive.
 lib/cat.rb |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)
 create mode 100644 lib/cat.rb

這時候我們看圖的話會是這樣:

可以看到我剛剛在 master branch 下了 git
merge cat
 這個指令來告訴 git 要 merge cat 到現在所在的 branch ,因此在圖上就看到了 cat branch 拉一條線回來合併到了 master 這個 branch 了,解釋這張圖的意思就是, cat branch 從 master branch 的 Another spec 這一次的 commit 分支出來後,自己產生了三次的 commit (Add Cat.rb、Add initializer、Rever “Add initializer”) 然後合併到 master。

Confict: 處理 Git 合併時的衝突:

很常發生的情況是再 merge 或是 rebase 的圖中產生了 convict (衝突),這時候 Git 會停下來請你去處理,例如我們在 cat 和 master 的 branch 都對 lib/cat.rb 這支檔案做編輯,然後我們將他們 merge:

$ git merge cat
Auto-merging lib/cat.rb
CONFLICT (content): Merge conflict in lib/cat.rb
Automatic merge failed; fix conflicts and then commit the result.

你會看到 Git 告訴你在你合併的過程中在 lib/cat.rb 這支檔案發生了衝突,Git 不知道該怎麼處理因此要你去處理它,這時候我們打開這支檔案會看到這樣的情況:

<<<<<<<<<< HEAD 到 ========== 的中間區域是目前你所在 branch 的 commit 內容,而從 =========== 到 >>>>>>>>>>> cat 則是你要合併的 cat branch 的內容,你必須做出決定看是要兩個都留下,或是選一個,或是改成你想要的內容,改好後記得要將 Git 自動產生的 <<< 、 =====、 <<< 的內容都刪除,修改完畢後存檔,將剛剛修改過的檔案再使用 git
add
 加入 stage ,將所有的衝突都修正完畢後就使用 git
commit
 提交一次 commit,由於這次的 commit 是在處理 merge 時的衝突,因此 Git 很聰明的已經幫我們加上了一些預設的訊息 “Merge branch ‘cat’”, commit 提交後就會看到合併成功的訊息了。

$ git add lib/cat.rb
$ git commit
[master c37c9e3] Merge branch ‘cat‘

發生 confict 時的處理步驟

  1. 將發生 confict 的檔案打開,處理內容( 別忘了刪除<<<、===、>>> )。
  2. 使用 git
    add
     將處理好的檔案加入 stage。
  3. 反覆步驟 1~2 直到所有 confict 處理完畢。
  4. git
    commit
     提交合併訊息。
  5. 完成

講到這裡我們再來整理一下工作流程,讓大家再複習一下 git 的使用:

  1. 在專案中會有一條主 branch 是大家將開發好或是修好的東西合併回去的對象,所有要開發的新功能或是修 bug 都是從主 branch 拉出一條新的 branch 去工作。
  2. 當你完成一個階段性的任務時,將你剛剛 所新增的內容使用 git
    add
    加入到 stage 的狀態,並且使用 git
    commit
     加上 commit 的訊息來提交一次的 commit。
  3. 反覆動作 2 直到你完成這支 branch 的主要目的(新功能/修 bug ),若這時你離主 branch 已經有一段時間,或是確定主 branch 上已經有新的 commit ,使用 git
    rebase
     將自己的分支整理然後使用 git
    merge
     合併回主 branch,反之則是直接使用 git
    merge
     將自己 branch 的內容合併回去。

Git reset 取消上一次的操作

取消 merge

版本控制最大的好處之一就是讓你永遠可以後悔,因此我們常會希望把已暫存的檔案、已提交的 commit 或是已合併的 branch 取消修改,這時候我們可以使用 git
reset
 這個指令來幫助我們,像現在我若是想要取消剛剛的 merge 動作,我只要下:

$ git reset --hard ORIG_HEAD
HEAD is now at c126ff9 Config initialze

這時候再回去看圖你會發現已經回到合併前的樣子了:

取消已暫存的檔案

有時候手殘不小心將還沒修改完的檔案使用 git
add
 加入了 stage ,這時候可以使用 git
reset HEAD <file>
 來將這支檔案取消 stage:

你可以看到我使用 git
add
 將檔案加入 stage 後,在我的 status 狀態顯示 lib/cat.rb 這支檔案現在已經準備好被 commit ,但這時我使用了 git
reset HEAD
 將這支檔案取消 stage,再使用 status 查看時它就變回一支還沒加入 stage 的檔案了。

取消修改過的檔案

連續剛剛的情況,若是我想完全放棄這次修改 (將檔案狀態回復到最新的一次 commit 時的狀態),我可以使用 git
checkout -- <file>
 來回復這支檔案:

$ git checkout -- lib/cat.rb

取消變更不會有任何訊息,但這時你去看檔案會發現他已經回復成沒修改過時的模樣了。

修改上一次的commit

手誤打太快, commit 訊息打錯時,我們可以使用 git
commit --amend
 來幫助我們重新修改:

 

在上面我想要修改打錯字的 commit 訊息 “Cat initiae”,因此我使用 git
commit --amend
 來修改成正確的訊息。

強制回復到上一次 commit 的版本

有時候我們想要放棄所有修改回到 commit 時的狀態,這時候我們可以下 git
reset --hard HEAD
 來回復,HEAD 參數可以加上一些變化,例如 HEAD^ 表示目前版本的上一個版本 HEAD~2 則是再上一個,因此你可以自由的跳回去之前的狀態。

git reset, hard 與 soft 的差異

你可能會在這邊感到疑惑,在使用 git
reset
 的時候都會看到一個 soft 或是 hard 的參數,這代表什麼樣的意義?基本上在使用 git
reset
 的時候,都會把目前狀態回復到你想回復的版本,但若是不加參數的情況,會把你做過的修改仍然保留,但是,若是加上 —soft 參數,則會把做過的修改加入 stage ,若是加上 hard 參數的話則是把做過的修改完全刪除,回到那個版本原本的樣子。

版权声明:本文为博主原创文章,转载请注明出处。

时间: 2024-10-11 17:59:19

最好最易懂的Git教学——分享“好麻烦部落格”Git教学(2)的相关文章

git会议分享

git add . git add -A git add common.scss   只迁入某个文件 git pull h5 远程的:分支    这样就成功拉取一个新分支了 git push h5(远程的  remote -v看)  master(自己当前分支):common(想要提交的分支) git push  之后  gulp重启一下   然后重新提交  fix:merge common  不用pull  直接提交  避免版本号不一致有冲突不能提交 git remote h5 [email 

Git详解之四 服务器上的Git

来自:http://www.open-open.com/lib/view/open1328069988843.html 服务器上的 Git 到目前为止,你应该已经学会了使用 Git 来完成日常工作.然而,如果想与他人合作,还需要一个远程的 Git 仓库.尽管技术上可以从个人的仓库里推送和拉取修改内容,但我们不鼓励这样做,因为一不留心就很容易弄混其他人的进度.另外,你也一定希望合作者们即使在 自己不开机的时候也能从仓库获取数据 — 拥有一个更稳定的公共仓库十分有用.因此,更好的合作方式是建立一个大

git下的团队合作模型及git基础知识汇集

https://www.atlassian.com/git/tutorials/syncing/git-fetch Syncing svn使用单个中央库来作为开发者之间沟通的桥梁,而协同合作是通过在开发者和中央库之间传递changeset来实现的.这种情况对于GIT的协同模型是有区别的,在git下每一个开发者都拥有他们自己的整库copy.取而代之于从working copy来提交变更集到一个中央库中,git允许你在不同的repo之间分享整个分支. 下面的命令允许你管理你和其他repo之间的连接,

git入门(4)团队中git保管代码常用操作

在团队中协作代码时候,一定要熟练使用以下git命令,不至于把代码库弄乱, PS:一定要提交自己代码(git push)时候,先进行更新本地代码库(git pull),不然提交异常 git常用命令 1·.clone相应项目 git clone ... 举个栗子(只是个栗子) git clone https://github.com/saucxs/watermark.git 2.新建分支并且切换到这个分支 git checkout -b 分支名(英文名) git chenckout -b dialy

版本控制——Git 使用笔记,以及Windows搭建Git服务器

Git和Github的关系 链接:http://www.zhihu.com/question/21907548/answer/95284202 来源:知乎 Git是一款免费.开源的分布式版本控制系统 Github是用Git做版本控制的代码托管平台 相当于本地.公司服务器.Github网站服务器都装Git做版本控制,只不过Github的服务器强大些,对全球用户托管的项目用Git做版本控制! 正是由于Github用Git做版本控制,所以可以轻松的记录项目的变迁史,然后有了下图 git是一张弓,git

【Git入门之十二】DIY Git

[Git入门之十二]DIY Git - JackyStudio - 博客频道 - CSDN.NET Git的配置是很有学问的,如果弄懂它,将对你帮助很大. 1.用户配置 这是全局的. ? [cpp]?view plaincopy ? #设置用户名?? $Snbsp;git?config?--global?user.name?"Jacky"?? ?? #设置邮箱?? $Snbsp;[email protected]?? ? 2.设置默认编辑器 在需要输入文本信息时调用,比如之前的reba

【Git入门之十三】Ubuntu和git

[Git入门之十三]Ubuntu和git - JackyStudio - 博客频道 - CSDN.NET 之前我们都是在Windows平台下操作git.现在我们改用Ubuntu试一试吧!先准备好Ubuntu或者Linux系统吧.这里采用13.04版本虚拟机环境 1.Ubuntu下使用git 打开终端(Ctrl+Alt+T).Ubuntu下就没有git bash了,都是使用terminal. 1.1.安装SSH ? [cpp]?view plaincopy ? sudo?apt-get?insta

git 上传代码到GitHub 以及git删除github上文件和文件的命令

Git入门 如果你完全没有接触过Git,你现在只需要理解通过Git的语法(敲入一些命令)就可以将代码上传到远程的仓库或者下载到本地的仓库(服务器),可知我们此时应该有两个仓库,就是两个放代码的地方,一个是本地,一个是远程的(如Github).企业或者团队可以通过Git来对项目进行管理,每个程序员只需将自己的本地仓库写好的代码上传到远程仓库,另一个程序员就可以下载到本地仓库了.今天我们就从Git终端软件的安装开始,再这之前我也简单介绍一下Github. Git上传代码 一.准备工作 1.注册一个g

Git ~ 回到过去 , 进入未来 ~ Git

概述 我们已经成功的添加了一个 readme.txt文件 , 现在是时候 继续工作了 , 于是 我们开始尝试一下 Git给我们所带来的便利下面修改read.txt 改成如下内容 为了尝试 Git 给我们带来的便利 这是 第一次修改 ! 现在运行 git  status 查看 暂存去的状态 . 1 [email protected]:~/learngit$ git status 2 位于分支 master 3 尚未暂存以备提交的变更: 4 (使用 "git add <文件>...&qu