首頁 > 軟體

Git進階教學

2020-06-16 17:55:48

今天無意中看到據說是Git入門教學 http://www.linuxidc.com/Linux/2014-09/107300.htm,看完後又學到了不少新東西,把自己學到東西總結並記錄下,否則總覺得少了些什麼東西。

下面用一張圖來說明工作區(working directory)、版本庫(Repository)、暫存區(stage),以及分支的概念。

下面解釋不是完全嚴謹,請結合上圖來理解下面四個概念。
工作區(working dicrectory):包含.git目錄的父目錄一般就是工作區,就是我們的工程目錄。新建立的檔案都處於工作區,此時還沒有加入到後面要解釋的的暫緩區。

版本庫(Repository):.git目錄就是版本庫,版本管理的相關檔案都在此目錄下。

暫緩區(stage):對於曾經加入了版本控制的檔案作了修改後,執行git add後的檔案就進入暫緩區。

分支:git初始會預設建立一個master分支,執行git commit後,暫緩區的檔案就到了分支裡面。

如下有一個readme.rst檔案是已經加入了版本庫的,現在對內容進行修改後,檢視下狀態

E:Usersliuzhijunworkspaceblog>git status

# On branch master
# Your branch is ahead of 'origin/master' by 4 commits.
#   (use "git push" to publish your local commits)
#
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working d
#
#       modified:   README.rst
#
no changes added to commit (use "git add" and/or "git commit -a")

git提示README.rst已經修改了,但還不是暫緩區的檔案(not staged),待commit。接著還告訴你可以進行怎麼的操作,checkout指復原本次修改,注意後面有--,如果不帶這個字元,checkout又是另外一層意思了。

退回到指定版本

退回到指定版本使用命令git reset --hard <version>, HEAD始終指向當前版本,HEAD^^表示上一個版本。如果想退回到上一個版本就可以使用:

git reset --hard HEAD^^  

如果想退回到指定的某個版本呢?可以使用git log檢視獲取commit 版本號:

commit 33b351ae746edaf3fd5a56a0318235096b6ed1ce
Author: liuzhijun <lzjun567@gmail.com>
Date:   Sat Mar 15 11:43:56 2014 +0800
    commit many files

commit 86eefaaea5251fa5707ecd02009c893c098ab6cd
Author: liuzhijun <lzjun567@gmai..com>
Date:   Thu Mar 14 03:20:27 2013 +0800

    add author myself

commit 後面的那串就是版本號, 一般只要選擇前面幾位就可以了。git會自動去查詢。

git reset --hard 86eefa

執行上面的命令就是退回到指定的版本,如果現在我又反悔了,想恢復到最近的那個版本怎麼辦?只要你還記得這個最近的版本號的話直接執行如上的命令就好了,但是誰會去記這個號啊?那麼還有一個辦法是使用git reflog檢視,這個指令記錄了每次的操作。

E:Usersliuzhijunworkspaceblog>git reflog
a11c917 HEAD@{0}: reset: moving to a11c
        HEAD@{1}: reset: moving to HEAD^
        HEAD@{2}: reset: moving to a11c917430050a94549e48d205ef01cacc82c1cf
        HEAD@{3}: reset: moving to HEAD^

上面的allc...就是我最近的一次修改。

修改(change)

這裡的修改不是動詞,而是名詞,只要檔案發生了變化就表示修改,包括對檔案內容的更改或者新建立的一個檔案或者刪除一個檔案都叫一個修改。 git跟蹤(track)的就是修改,而不是檔案本身。

復原(checkout)

復原是指檔案修改後,還沒有新增到暫緩區(還沒有執行git add)過程中的修改復原掉,如果已經新增到了暫緩區,但是還沒有commit到分支中去,又做了修改後又想復原,那麼這裡的復原就是復原到暫緩區的狀態。比如現在對檔案新增內容"add some to file":

E:Usersliuzhijunworkspaceblog>git status
# On branch master
# Your branch is ahead of 'origin/master' by 4 commits.
#   (use "git push" to publish your local commits)
#
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       modified:   README.rst

然後把它新增到暫緩區:

git add README.rst

再新增內容 "add some again to file",復原後,你會發現第一次新增的內容保留了,第二次新增的內容復原了。

E:Usersliuzhijunworkspaceblog>git checkout -- README.rst

E:Usersliuzhijunworkspaceblog>git status
# On branch master
# Your branch is ahead of 'origin/master' by 4 commits.
#   (use "git push" to publish your local commits)
#
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       modified:   README.rst

分支管理

開發一個新功能時,可能需要幾週的時間才能完成,那麼可以建立一個分支,在分支上做開發,而不影響主分支的功能。
建立分支

git branch dev
git checkout dev

或者合併成一條命令:

git checkout -b dev

建立dev分支切換後,HEAD指標就從原來的master轉移指向dev分支,git branch可以檢視有哪些分支,並且當前是在哪個分支上。

E:Usersliuzhijunworkspaceblog>git branch
* dev
  master

星號就代表當前的所在的分支。

切換分支

git checkout master

合併分支
切換分支後,dev分支上做的修改在master分支看不到,如果dev分支的功能開發完成後,就可以考慮合併分支了,合併後還可以刪除dev分支,因為此時dev分支對於我們來說沒有多大意義了。

git merge dev

合併分支就是把master執行dev分支,接著還可以刪除分支

git branch -d dev

git鼓勵大家使用分支,因此大家記得多用啊,只有多用才是熟練掌握。

衝突

如果不同的人對同一個檔案的同一個地方做了修改,那麼提交後就會遇到衝突,或者在不同的分支上修改了同一個檔案的同一個地方也會出現衝突,當出現衝突了,就必須手動把有衝突的地方修改後再提交才能解決衝突。

建立分支dev,然後新增內容"add new branch dev",commit後切換到master分支,在同一行新增內容"may be here is conflict",commit後合併。

git checkout -b dev
git add README.rst
git commit -m "add new branch"
git checkout master
git add README.rst
git commit -m "add new line"
git merge dev

#出現錯誤
Auto-merging README.rst
CONFLICT (content): Merge conflict in README.rst
Automatic merge failed; fix conflicts and then commit the result.

README.rst內容出現了如下情況:

<<<<<<< HEAD
may be here is conflict
=======
add new branch dev 
>>>>>>> dev

<<<<<<< 到=======表示當前分支的內容, >>>>>表示dev裡面的內容。手動修改裡面的內容後再提交。那麼master就是最新的檔案了。當然dev還是停留在上次commit的狀態。此時你可能會想,我想在dev分支上與master保持同樣的最新狀態,那麼你可以這樣:

git checkout dev
git rebase master

相當於快速的把dev分支指向master。

分支策略

開發過程中,都應該按照以下方式來管理分支。
主分支:程式碼庫應該有且只有一個主分支master,master分支的程式碼是穩定的,僅用於正式版本發布使用。

開發分支:日常開發工作應該在開發分支dev上完成,待某個時間dev分支的功能完善了就可以考慮merge到master分支上去。

自己的分支:每個人在dev分支上建立自己的分支。
預設情況下,git合併使用"fast forward”模式,相當於直接把master分支指向dev分支。刪除分支後,分支資訊也隨即丟失。

在合併的時候附上引數 --no-ff就可以禁用fast-forward合併模式。這樣在master上能生成一個新的節點,意味著master保留的分支資訊,而這種合併方式我們希望採用的。

git merge --no-ff dev


IT145.com E-mail:sddin#qq.com