注意:
1、很多分支圖中的箭頭表示的是該分支的父分支,也是用來表示上一層的分支。
工作流程:
git支持很多種工作流程,我們採用的一般是這樣,遠程創建一個主分支,本地每人創建功能分支,日常工作流程如下:
去自己的工作分支
$ git checkout work
工作
….開始修改文件代碼
提交工作分支的修改
$ git commit -a
回到主分支
$ git checkout master
獲取遠程最新的修改,此時不會產生衝突
$ git pull
回到工作分支
$ git checkout work
用rebase合併主幹的修改,如果有衝突在此時解決
$ git rebase master (這一步可以看到都有的還有兩者衝突的地方,如果小分支上有其他東西,主分支沒有,則這一步不會顯示小分支上的東西)大多數時候,使用 git pull –rebase 是爲了使提交線圖更好看,因爲他會將你的分支上的commit移走,使得提交線路圖沒有,從而方便 code review,看起來就更加的簡潔明朗。
回到主分支
$ git checkout master
合併工作分支的修改,此時不會產生衝突。
$ git merge work
提交到遠程主幹
$ git push
(本地的160421feature分支利用命令git push origin 160421feature後,將提交的信息給了遠程160421feature分支(如果分支不存在,則會自動創建這個遠程分支),然後要手動的提交一個 pull request,然後master端進行合併就可以了,否則沒有效果。
這樣做的好處是,遠程主幹上的歷史永遠是線性的。每個人在本地分支解決衝突,不會在主幹上產生衝突。
關於協同合作:
1、fork別人了代碼之後,clone到本地,
2、然後增加一個分支,提交之後,在使用簡單的git push將feature分支推送到了她自己的Github倉庫上(不是官方的倉庫):
git push origin some-branch
3、用自己的Github賬號在自己的遠程倉庫上對剛提交的分支創建一個pull request,這樣項目維護者就看到了,審覈通過了就點擊Merge Pull Request按鈕來通過這個pull request,將Mary的feature分支併入他的master分支
誤刪除一個文件的時候可以用指令來返回救回 自己的文件,bac.c這個文件被刪除了,
命令行:
git reset HEAD bac.c
(將文件返回到前一個狀態)
git checkout bac.c 恢復這個文件
git 目錄中經常會出現一些[ +1 ~1 ~0] 這樣形式的東西,
第一個數字表示:增加的文件的個數。
第二個數字代表修改的文件個數。
第三個數字表示已經刪除的文件個數。
如果出現第四個數字,且數字前有感嘆號,這就表示:有衝突,數字代表衝突的文件個數。
設置一些過濾文件的通用副:
*.class
.classpath
.gitignore
.myhibernatedata
.mymetadata
.paoject
github 中的同步是將本地的 master同步到遠程倉庫的master,但是如果你沒有commit,則不會同步到遠程master,沒有commit表示沒有提交修改,github也沒有更新你的修改操作,本地的master自然也就沒有修改,所以這個時候同步沒有任何問題,自然同步都不會有新的更新到遠程(做過實驗)。
建議在本地建立一個分支,在本地的分支上修改代碼,然後commit(提交到本地的分支上),這樣你的分支代碼就有一個形成了一個新的版本,但是並沒有在你本地的master上更新,也沒有更新遠程的master。
此時:
1.利用本地的分支,將更新提交到遠程master,也就是提交合並,但這是你本地的master也沒有更新。
2. 切換到你本地的master,將遠程的master更新到本地的master,將本地master與本地分支對比修改的代碼,沒有衝突,沒有問題之後,將本地分支和本地master 合併 到本地master,最後向遠程master提交合並請求 或者 同步到遠程的master。
關於分支的幾點問題:
- 1.分支上的代碼是最新的,並且已經commit了,如果此時你將 HEAD (指針)指向了 本地master,因爲本地master沒有你剛剛修改的東西,這時候你會發現你的myeclipse上的代碼回到了你沒修改的狀態去了,但是如果你這時在切換到分支,你的代碼就有恢復了。這也是github的強大之處,你可以隨便創建分支修改、調試修復bug、增加、刪除,然後不行就切換到其他分支,刪除這個分支。
- 2.github只記住你的修改操作,不會記住文件,通過指令:git status,可以看到你的項目的一些狀態,git log ,可以看到你commit的操作。
- 3. 如果你修改了代碼或者文件,沒有提交到本地該分支,則這個時候不可以切換到其他分支去,只有提交了纔可以切換,但是 如果你只是增加了一個文件,並寫上一些內容,這個時候是可以切換到其他分支的,因爲程序默認是沒有這個文件的。
git branch <branch> // 創建一個分支
git branch -d <branch> // 刪除一個分支
git branch -D <branch> //強行刪除一個未合併更改的分支,永遠刪除某一個分支的所有提交,就可以用這個命令
git branch -m <branch> // 給當前分支修改名稱爲<branch>
Git執行 三路合併 。三路合併使用一個專門的提交來合併兩個分支的歷史。這個術語取自這樣一個事實,Git使用 三個 提交來生成合並提交:兩個分支頂端和它們共同的祖先。
如果你寫錯了代碼,並且commit了,那麼你想撤銷commit,可以利用命令:git reset –hard HEAD^ 。但是這是回到你的上一個版本,並不會保留你commit之前到上一個版本這之間的所有修改操作,也就意味着你必須重新寫代碼。
Untracked---有修改但是沒有git add操作,它的狀態是Untracked。
staged(暫存區)---將有修改的文件進行git add 操作之後,文件就在 staged( 暫存區)了。
discard changes---放棄更改。
git remote -v 可以查看當前項目與那些遠程倉庫有url 遠程連接
git remote add john http://dev.example.com/john.git 添加同事的賬號
————————————————————創建本地的倉庫——————————————————————
在本地寫代碼的時候必須做測試,測試功能,如果自己改代碼之後還要改回來,如果遺漏了 一步就會造成自己忽略掉的錯誤,用github可以幫我很好的進行版本控制,
建議本地的倉庫路徑是———-G:\GitHub
- (1)如果要自己創建一個文件並初始化爲github管理,執行以下命令
$ mkdir learngit 創建一個文件夾
$ cd learngit (可省略)
$ pwd (可省略)用於顯示當前目錄
$ git init 把這個目錄變成Git可以管理的倉庫
- (2)將已經有的項目導入github的目錄中,也就是 G:\GitHub目錄中
使用git init 把這個目錄編程git可以管理的倉庫
以上兩步做完了還有一件重要的事情要做,那就是創建分支,就是利用分支這種套路來改程序的,最好創建多個分支,主分支不要改動太大,一個分支A用來寫代碼,一個分支B用來做測試,測試好了A的代碼,就吧A提交到主分支上去。
創建分支:$ git branch test
切換分支:$ git checkout test
或者利用一個命令就可以吧上面兩句命令一同處理掉 :
$git checkout -b test
一些基本處理命令:
git status 查看狀態,列出已緩存、未緩存、未追蹤的文件。
git add 添加文件到緩存區
git commit -m "<在此處添加提交理由或者改動理由>" 提交文件到正式工作區中
- git status 允許你查看工作目錄和緩存區,而git log只作用於提交的項目歷史。
- git log 相關命令如下
git log ---使用默認格式顯示完整地項目歷史。如果輸出超過一屏,你可以用空格鍵來滾動,按q退出。
git log -n <limit> ---用<limit>限制提交的數量。比如git log -n 3只會顯示3個提交。
git log --oneline ---將每個提交壓縮到一行。當你需要查看項目歷史的上層情況時這會很有用。
git log --stat ---除了git log信息之外,包含哪些文件被更改了,以及每個文件相對的增刪行數。
git log -p ---顯示代表每個提交的一堆信息。顯示每個提交全部的差異(diff),這也是項目歷史中最詳細的視圖。
git log --author="<pattern>" ---搜索特定作者的提交。<pattern>可以是字符串或正則表達式。
git log --grep="<pattern>" ---搜索提交信息匹配特定<pattern>的提交。<pattern>可以是字符串或正則表達式。
git log <since>..<until> ---只顯示發生在<since>和<until>之間的提交。兩個參數可以是提交ID、分支名、HEAD或是任何一種引用。
git log <file> ---只顯示包含特定文件的提交。查找特定文件的歷史這樣做會很方便。
git log --graph --decorate --oneline ---還有一些有用的選項。--graph標記會繪製一幅字符組成的圖形,左邊是提交,右邊是提交信息。--decorate標記會加上提交所在的分支名稱和標籤。--oneline標記將提交信息顯示在同一行,一目瞭然。
上面提供了git log很多的栗子,但請記住,你可以將很多選項
用在同一個命令中:
git log --author="John Smith" -p hello.py ---這個命令會顯示John Smith作者對hello.py文件所做的所有更改的
差異比較(diff)。
..句法是比較分支很有用的工具。
下面的栗子顯示了在some-feature分支而不在master分支的所有
提交的概覽。
git log --oneline master..some-feature
關於checkout 命令詳解
———-檢查提交———
git log –oneline // 查看當前的所有提交
git checkout a1e2fb5 // 查看某一個提交的當時所有文件的狀態,在此狀態你可以測試、修改,但是你的修改不會更新到倉庫裏。
git checkout master //退出此commit狀態,切換到master狀態
———檢查提交中的某一個文件——-
git log –oneline // 查看當前的所有提交
git checkout a1e2fb5 hello.py // 查看某一個提交的當時某一個文件的狀態,在此狀態你可以測試、修改,但是你的修改會更新到倉庫裏。
git checkout HEAD hello.py //如果你不想保留修改的舊的版本文件,你可以用命令檢出到最近文件版本,
git 退出 git log:經常輸入 git log 後, 即使按ctrl+c (z)都無法完全退出,後來google了一下,原來要輸入q。
——————————-常見工作流流程—————————–
1、中心化的工作流
只需要一個master分支,不需要其他分支,所有的提交都到了master分支上,所以在各個開發者提交他們自己的代碼之前,要先fetch下中央倉庫的代碼,在他們上rebase自己的更改。
git pull --rebase origin master
--rebase選項告訴Git,在同步了中央倉庫的修改之後,將Mary所有的提交移到master分支的頂端
如果發現了衝突,合併提交會終止,利用git status就可以看到那些文件發生了衝突,
接下來就是修改衝突,git add 來添加這些被你修改的文件,
然後執行 git rebase --continue ---繼續執行合併提交操作,
最後 git push origin master.
2、基於功能分支的工作流
創建本地分支,對分支進行修改提交,feature分支可以(也應該)被推送到中央倉庫,這樣master上也會有多個feature分支,最後通過 pull request來請求合併到master。
而不是直接將分支推送到master上,這樣就給了其他開發者審覈代碼的機會,不僅可以審查還可以討論代碼,
git push -u origin marys-feature
這個命令將marys-feature推送到中央倉庫(origin),-u標記將它添加爲遠程跟蹤的分支。在設置完跟蹤的分支之後,Mary調用不帶任何參數的git push來推送她的功能。
然後在他自己的Git界面上發起了一個pull request,請求將marys-feature合併進master。
當大家都覺得這個功能代碼做的很出色的時候,一致認可可以將該分支合併到主分支master上的時候,我們就需要以下操作:
git checkout master
git pull
git pull origin marys-feature
git push
3、Gitflow工作流
- 該工作流圍繞項目發佈定義了一個嚴格的分支模型。和功能分支工作流相比,這種工作流沒有增加任何新的概念或命令。它給不同的分支指定了特定的角色,定義它們應該如何、什麼時候交流。除了功能分支之外,它還爲準備發佈、維護髮布、記錄發佈分別使用了單獨的分支。當然,你還能享受到功能分支工作流帶來的所有好處:pull request、隔離實驗和更高效的協作。
- 開發者將分支推送到遠程倉庫,不同的是項目的分支結構變化了,使用兩個分支來記錄項目歷史,master分支存儲官方發佈歷史,develop分支用來整合功能分支,這還可以在master分支上給所有提交打上版本號標籤,
- 所有開發者將develop分支作爲父分支,提交功能分支到develop分支,與develop分支進行交互,功能分支加上develop分支就是我們之前所說的功能分支工作流。但是,Gitflow工作流不止於此。
步驟:
- 首先在本地的master分支上創建一個空的develop分支,將其推送到服務器上:
git branch develop
git push -u origin develop
develop分支其實是包含master的所有內容,所有歷史。
然後其他的開發者對develop分支克隆,並且在本地創建一個分支來追蹤develop分支:
git clone ssh://user@host/path/to/repo.git
git checkout -b develop origin/develop
創建本地的特徵分支:
git checkout -b some-feature develop
當完成了功能分支,他提交到develop分支,最好發起一個pull request,
採納這個功能分支:
git checkout master
git merge release-0.1
git push 或者下面兩句話
git tag -a 0.1 -m "Initial public release" master
git push --tags
git checkout develop
git merge release-0.1
git push
git branch -d release-0.1
4、Fork工作流
Fork工作流和教程中討論的其它工作流截然不同。與其使用唯一的服務端倉庫作爲”中央“代碼庫,它給予 每個 開發者一個服務端倉庫。也就是說每個貢獻者都有兩個Git倉庫,而不是一個:一個私有的本地倉庫和一個公開的服務端倉庫。
Fork工作流的主要優點在於貢獻可以輕易地整合進項目,而不需要每個人都推送到單一的中央倉庫。開發者推送到他們 自己的 服務端倉庫,只有項目管理者可以推送到官方倉庫。這使得管理者可以接受任何開發者的提交,卻不需要給他們中央倉庫的權限。
結論是,這種分佈式的工作流爲大型、組織性強的團隊(包括不可信的第三方)提供了安全的協作方式。它同時也是開源項目理想的工作流。
fork工作流會克隆開源項目到自己的私人服務器上,然後自己從自己私人服務器上克隆到本地,並進行修改,然後提交合併到自己私人服務器,通過pull request 告知項目維護者,我要將更新的操作添加到官方項目中,維護者會去檢測你的代碼,沒有問題就會合併到官方項目中。
因爲主代碼庫已經取得了新的進展,其他開發者應該和官方倉庫同步:
git pull upstream master
5、遠程分支的操作
當你的代碼不是最新的時候,需要用 git fetch origin 從遠程服務器上獲取數據.git fetch 命令會更新 remote 索引,但不會覆蓋你本地的分支操作。
也可以用 $ git push origin serverfix(分支名字) 來將本地操作同步到遠程倉庫
6、跟蹤分支
從遠程分支 checkout 出來的本地分支,稱爲 跟蹤分支 (tracking branch)。跟蹤分支是一種和某個遠程分支有直接聯繫的本地分支。
git checkout -b serverfix_1 origin/serverfix
從遠程分支serverfix中獲取一個分支serverfix_1,這兩者可以名字一樣,因爲涉及到另一個問題,名字一樣,本地的跟蹤分支可以直接利用 git push,來更新內容到遠程分支上,如果名字不一樣就必須使用:git push origin HEAD:serverfix 更新代碼到遠程serverfix分支。
同樣支持 改名:git checkout -b sf origin/serverfix 將本地的serverfix分支改名爲 sf。
同樣利用 git push origin :serverfix 將服務器上的遠程分支serverfix刪除。遠程主頁上也可以刪除。不過建議在其他分支上刪除遠程分支,不要在跟蹤分支上刪除遠程分支。
6、衝突解決
如果有衝突發生,最簡單的方法就是修改衝突,然後再次add 和commit,這樣就手動修改衝突,
如果大量的工作發生,就很恐怖,所以,需要撤銷一個合併操作,思考。
你應該始終牢記,你可以在任何時間執行撤銷操作,並返回到你開始合併之前的狀態。要對自己有信心,你不會破壞項目中的任何東西。只要在命令行界面中鍵入 “git merge –abort” 命令,你的合併操作就會被安全的撤銷。
當你解決完衝突,並且在合併完成後發現一個錯誤,你仍然還是有機會來簡單地撤銷它(前提是沒有commit)。你只須要鍵入 “git reset –hard ” 命令,系統就會回滾到那個合併開始前的狀態,然後重新開始吧!
7、add操作之後,如何回退
萬一你不小心git add file(add File文件了,哪怕文件置灰,也是能提交的)了,怎麼辦,不用急
兩種思路:
- 用git命令來操作
使用git 命令如下:
git rm --cached file_path
git commit -m '移除測試文件'
刪除本地緩存,但是不刪除文件。測試的文件在處於置灰狀態就不能提交了!
或者 git reset HEAD 將文件回退
直接手動重新修改,再add操作。
手動重新編輯,因爲並沒有commit,所以可以重新編輯再提交。
如果一個文件不需要提交,當然也不需要commit,可以採用第一種方法。
8、commit操作後撤銷
撤銷操作
- 提交一份快照
git commit -m “Make some changes that will be undone”
- 撤銷剛剛的提交
git revert HEAD // 將緩存區的文件撤銷掉到非緩存區
git reset命令在準備緩存快照時經常被用到,可以單獨撤銷一個文件的狀態,也可以撤銷所有文件的緩存區。
9、git status的相關文件狀態說明
Untracked files: 表示未跟蹤的文件,也表示這些文件不在之前的狀態裏,是新建立的文件,有可能這些文件是你創建的,也有可能是運行程序產生的.class文件,這些文件要被你忽略。 通過git add 操作就可以來添加跟蹤。
Changes not staged for commit:表示文件被修改,但是沒有add,沒有添加到暫存區。要暫存這次更新,需要運行 git add 命令。
Changes to be committed: 等待提交,目前已經在暫存區了。
注意:可能存在同樣一個文件同時是在暫存區和 等待提交區。這是因爲你把文件添加到暫存區後沒有commit,但是有同樣修改了這個文件。
- deleted: 有些文件的狀態是deleted,這表明這些個文件是被刪除的文件,一般這些刪除的文件是處於Changes not staged for commit 。可以使用 git add/rm 等操作將這些文件添加到暫存區。然後最後commit的時候,該文件就不再納入版本管理了。
10、怎樣從之前的版本中創建分支?
這個問題也可以稱爲:git基於歷史commit創建分支
- 利用 git log 來獲取歷史commit 操作,
- 利用 git checkout -b 從歷史中某個commit中創建一個新的分支,這條命令中: 表示分支名, 表示 commit 的 序列號,每次commit都會自動生成。
- 在新分支上開發,後續繼續合併或者回退
11、關於 Your branch and ‘origin/master’ have diverged, and have 1 and 1 different commits each, respectively.
首先解釋一下:
- 這裏的第一個 數字 1 表示本地master 比 origin/master 多了1個patch。
- 第二個數字 1 表示表示本地master 比 origin/master 少了1個 patch。
12、從遠程分支上 clone 下代碼
使用命令:git clone -b v2.8.1 https://git.oschina.net/oschina/android-app.git
-b表示要從分支下載,v2.8.1就是具體的某個分支的名稱,https://git.oschina.net/oschina/android-app.git這是app源碼的git倉庫地址。
13、將本地項目上傳到git目錄中
- 初始化項目 git init
- 將項目文件add, git add <文件名>
- 提交,git commit -m “<說明>”
- 跟遠程git關聯 git remote add origin
- 上傳項目到遠程git git push -u origin master
14、在本地新建一個與遠程的dev版本相同(被合併的版本)的dev分支
- 將master分支弄下來
git clone [ssh:XXXX.git]
- 將遠程分支弄下來,弄到本地
git checkout -b dev origin/dev
- 返回到master版本
git checkout master
- 把本地的dev合併到master.
git merge dev
- 把本地的master同步到遠程
git push origin master
參考博客
參考的博客較多,長期積累的,也找不到博客鏈接了,總之,感謝各位大佬的分享。
————————————————————————END————————————————————————–