1. 程式人生 > >基於git的管理應用程序基線包和版本

基於git的管理應用程序基線包和版本

指定 有一個 行合並 禁用 remote AC 優雅 覆蓋 部分

由於工作的需要,身為git的小白的我開始研究git相關的命令和操作。結合網上收集和廖雪峰的git教程,記錄所學知識點。

相關的效果就不再這裏顯示了。

首先我們看一下git的常用命令:

常用命令

git init : 初始化倉庫
git add 文件名 :把文件添加到暫存區
git commit -m "操作記錄" : 提交到倉庫,設置相關操作的記錄

git status : 查看git狀態,用於查看做了哪些的操作

git diff 文件名 : 在提交之前查看文件到底修改了什麽,方便我們確認修改內容是否使我們想要的

git log : 查看歷史記錄
git log --pretty=oneline : 查看歷史記錄,單行顯示,一般我喜歡用戶這個,很清爽

版本回退:在工作區中回退,沒有在git上顯示,且回退之後用git log查看,改版本之後的記錄都沒有了
git reset --hard HEAD^ : 回退到上一個版本,上上個版本就用^^
git reset --hard HEAD~100 : 回退到前100個版本

版本恢復:如果想要回退到最新的版本,或者現在版本的之後版本
git reflog : 查看所有操作的版本號
git reset --hard 版本號 :按照指定的版本號進行恢復,當然這個命令也可以進行回退使用,只要加上對應的版本號即可

git checkout -- 文件名 :撤銷修改,恢復刪除(都是在沒有提交的情況下)
1.撤銷文件的修改,在add之前
2.如果有內容在暫存區,我們這時候再修改文件,我們想要恢復到和暫存區內的內容一樣,也可以用這個
3.恢復刪除了的文件

遠程倉庫:

1.ssh-keygen -t rsa –C “[email protected]” 創建私鑰密鑰,在用戶文件夾下的.ssh文件夾中
2.登錄GitHub,settings-》SSH keys->add ssh keys->填寫任意title->把.ssh/id_rsa.pub的內容復制到key裏面-》add key
創建倉庫:
new Repository
為空的倉庫與本地倉庫關聯:(命令在創建之後都有)
git remote add origin https://github.com/xuming2860/testgit
git push -u origin master 第一次推送master分支時,加上了 –u參數,Git不但會把本地的master分支內容推送的遠程新的master分支,還會把本地的master分支和遠程的master分支關聯起來,在以後的推送或者拉取時就可以簡化命令

此時本地倉庫中的所有東西就上傳到了github中

git push origin master : 把本地master分支的最新修改推送到github上了

git clone https://github.com/xxxxx/testgit2 :把github項目克隆到本地倉庫

分支:

git checkout -b 分支名 : 創建分支
git branch :查看當前所有分支。當前分支前面會添加一個星號
git checkout mater : 切換分支到master

在分支上做的操作一開始不會在主分支中顯示,需要進行合並

git merge dev :在master分支上合並dev分支的內容,合並指定分支到當前分支上
git branch -d dev : 刪除分支dev

註意:我們在分支上面提交了修改之後切換到主分支上,此時主分支對文件進行修改並提交。該操作結束後再進行合並分支的內容,那麽就會出現沖突。我們在修改的文件中也可看到相關的內容(主分支修改的內容以及分支修改的內容)。這個時候就需要我們自己去決定去留。

通常合並分支時,git一般使用”Fast forward”模式,在這種模式下,刪除分支後,會丟掉分支信息,我們可以使用帶參數 –no-ff來禁用”Fast forward”模式
1.git checkout -b dev : 創建一個dev分支。
2.修改readme.txt內容。
3.git add ‘‘;git commit -m ‘‘; 添加到暫存區。
4.git checkout master : 切換回主分支(master)。
5.git merge --no-ff -m “註釋” dev : 合並dev分支
6.git branch -d dev : 刪除dev分支
7.git log --graph --pretty=oneline --abbrev=commit
大家可以對比沒有加“--no-ff”之前的git log,可以看到被刪除的分支信息還在。

多人協作:
git remote :查看遠程庫的信息
git remote -v :查看遠程庫的詳細信息

git push origin master :把master分支推送到遠程分支origin上

那麽一般情況下,那些分支要推送呢?
1.master分支是主分支,因此要時刻與遠程同步。
2.一些修復bug分支不需要推送到遠程去,可以先合並到主分支上,然後把主分支master推送到遠程去。

分支的理解(摘取廖雪峰教程)

在版本回退裏,你已經知道,每次提交,Git都把它們串成一條時間線,這條時間線就是一個分支。截止到目前,只有一條時間線,在Git裏,這個分支叫主分支,即master分支。HEAD嚴格來說不是指向提交,而是指向mastermaster才是指向提交的,所以,HEAD指向的就是當前分支。

一開始的時候,master分支是一條線,Git用master指向最新的提交,再用HEAD指向master,就能確定當前分支,以及當前分支的提交點

技術分享圖片

每次提交,master分支都會向前移動一步,這樣,隨著你不斷提交,master分支的線也越來越長:

技術分享圖片

當我們創建新的分支,例如dev時,Git新建了一個指針叫dev,指向master相同的提交,再把HEAD指向dev,就表示當前分支在dev

技術分享圖片

你看,Git創建一個分支很快,因為除了增加一個dev指針,改改HEAD的指向,工作區的文件都沒有任何變化!

不過,從現在開始,對工作區的修改和提交就是針對dev分支了,比如新提交一次後,dev指針往前移動一步,而master指針不變:

技術分享圖片

假如我們在dev上的工作完成了,就可以把dev合並到master上。Git怎麽合並呢?最簡單的方法,就是直接把master指向dev的當前提交,就完成了合並:

技術分享圖片

所以Git合並分支也很快!就改改指針,工作區內容也不變!

合並完分支後,甚至可以刪除dev分支。刪除dev分支就是把dev指針給刪掉,刪掉後,我們就剩下了一條master分支:

技術分享圖片

分支策略

在實際開發中,我們應該按照幾個基本原則進行分支管理:

首先,master分支應該是非常穩定的,也就是僅用來發布新版本,平時不能在上面幹活;

那在哪幹活呢?幹活都在dev分支上,也就是說,dev分支是不穩定的,到某個時候,比如1.0版本發布時,再把dev分支合並到master上,在master分支發布1.0版本;

你和你的小夥伴們每個人都在dev分支上幹活,每個人都有自己的分支,時不時地往dev分支上合並就可以了。

所以,團隊合作的分支看起來就像這樣:

技術分享圖片

以上就是相關操作的介紹,關於標簽管理和解決沖突等知識,可以到官網查看:

案例

首先我們有這樣的需求:我們有一個應用程序,後續要對這個應用程序不斷的開發,更新版本,並且不定期的打補丁。這些所有的記錄我都想要記錄下來,以便於版本的更新與回退。

  • 如果對這個操作不滿意可以回退到之前的版本,
  • 如果回退錯誤了,我們需要恢復成原來的樣子。

下面是我的想法已經方案:

我們用文件夾和txt文件模擬應用程序,版本,補丁:

目錄結構:
testgit:
-- main-master.txt                一開始1.0的應用版本
-- main-v1.1                        1.1版本
----- main-v1.1.txt
----- mendbug1.1.1              對應的補丁(當然實際不止1個補丁)
---------mendbug1.1.1.txt
-- main-v1.2                        1.2版本
----- main-v1.2.txt
----- mendbug1.2.1              對應的補丁
---------mendbug1.1.1.txt
-- main-v1.3                        1.3版本
----- main-v1.3.txt 
----- mendbug1.3.1              對應的補丁
---------mendbug1.3.1.txt

創建過程:

1.初始化倉庫創建main-master.txt應用版本

git init,添加文件,git add main-test.txt,git commit -m "第一次main版本"

2.創建分支dev模擬版本更新

  • 創建分支:git checkout -b dev,
  • 創建main-v1.1文件和txt文件,
  • git add main-v1.1,
  • git commit -m "1.1版本的發布"
  • 切換到master分支:git checkout master
  • 合並dev的版本到master:git merge dev
  • 查看日誌記錄:git status --pretty=oneline

按照上面步驟創建1.2版本和1.3版本

3.提交到git上:

  • 在git上創建一個倉庫create new repository
  • 在客戶端運行git上給你的命令關聯本地倉庫:git remote add origin https://github.com/xxxx/testgit
  • 把本地倉庫中的master分支上的東西都上傳到git上:git push -u origin master

這個時候我們查看git上面就有了我們的所有文件和log:

技術分享圖片

技術分享圖片

4.創建patch分支,用於打補丁:

  • 創建分支:git checkout -b patch
  • 創建mendbug1.1.1文件夾和txt文件
  • git add mendbug1.1.1
  • git commit -m "添加補丁mengbug1.2.1"
  • 切換會dev分支:git checkout dev
  • 合並patch內容:git merge patch
  • 切換到master分支:git checkout master
  • 合並dev內容:git merge devd

重復上述步驟創建1.2.1和1.3.1版本的補丁

5.把master的內容上傳到git上:

git push origin master

技術分享圖片

技術分享圖片

提交的記錄和所有文件就都在git上面了。

這裏要說一句,其實應該開發一個版本之後開發對應版本的補丁,我這裏的執行的順序有問題。但是該有的記錄是已經有了。下面就可以根據對應操作的版本號進行版本的回退和恢復:

需求一:我們現在提交了1.3版本,但是感覺不好,想要回到1.2版本:

1.git reset --hard 865c72

技術分享圖片

這時候我們可以看一下我們的目錄文件夾:

技術分享圖片

原來的main-v1.3已經沒有了,我們回退到1.2版本

技術分享圖片

我們通過log看到在發布1.2版本之後之前的所有的東西都沒有了。

2.提交到git上面

我們如果使用正常的命令:git push origin master,會出錯:

技術分享圖片

說遠端做了更改需要先pull一下, 如果pull那就又回到最新版本了,相當於沒回退。
a.思路1:我們可以新建一個分支temp,然後把回退後的代碼提交到temp分支上暫存,然後刪除master主分支,新建一個master分支,提交現有代碼到master上。

/*1.新建分支*/
git checkout -b temp              //新建分支並切換到temp分支
git push origin temp :temp              //將代碼push到temp分支
/*2.刪除主分支*/
git push origin --delete master   //刪除遠端主分支
git branch -d master              //刪除本地主分支
/*3.新建主分支*/
git checkout -b master            //新建主分支並切換到主分支
git push origin master            //提交主分支
/*4.刪除暫存分支*/
git branch -d temp
git push origin --delete temp

註意:在github下,操作(刪除或重建分支)需要在github網頁上切換當前分支,如你要刪除master,就要將分支切換到建的temp分支上。(可以理解為自己不能刪除自己)

b.思路2:或者還有一種方法,就是強制提交:

git push -f origin master

技術分享圖片

技術分享圖片

這樣git上面也就和我們倉庫一樣

需求二:我們想要恢復之前的樣子,我們後悔了:

1.查找到最後操作的commit id:git reflog

技術分享圖片

我們可以看到我們每個操作的版本號,按照版本號恢復就可以了。這裏我們恢復到第三個補丁打過之後:

方法一:$ git reset --hard HEAD^回退到上一個操作之前

方法二:$ git reset --hard 版本號

技術分享圖片

技術分享圖片

這個時候我們可以看到v1.3又回來了。

2.上傳到git上:因為這個是回退倉庫中沒有的,所以不需要強制:

git push origin master

技術分享圖片

技術分享圖片

謝天謝地,熟悉的趕腳又回來了。大功告成。

此時我們可以註意到一個問題,我們每個操作的版本號是不是固定的,及時刪除了我們的版本號也不會重新賦值改變,一開始是481b91,之後還是。所以我們可以把這個存儲下來,然後恢復的時候直接拿這個數據就可以了

好了,我們的需求是實現了,但是在版本回退的時候其實還是有東西要註意的:

我們已經能夠回滾遠程分支的版本了,那麽你也許會問了,回滾公共遠程分支和回滾自己的遠程分支有區別嗎? 答案是,當然有區別啦。

如果你回退公共遠程分支,把別人的提交給丟掉了怎麽辦?

假如你的遠程master分支情況是這樣的:A1–A2–B1

其中A、B分別代表兩個人,A1、A2、B1代表各自的提交。並且所有人的本地分支都已經更新到最新版本,和遠程分支一致。

這個時候你發現A2這次提交有錯誤,你用reset回滾遠程分支master到A1,那麽理想狀態是你的隊友一拉代碼git pull,他們的master分支也回滾了,然而現實卻是,你的隊友會看到下面的提示:

$ git status
On branch master
Your branch is ahead of ‘origin/master‘ by 2 commits.
  (use "git push" to publish your local commits)
nothing to commit, working directory clean

也就是說,你的隊友的分支並沒有主動回退,而是比遠程分支超前了兩次提交,因為遠程分支回退了嘛。

(1) 這個時候,你大吼一聲:兄弟們,老子回退版本了。如果你的隊友都是神之隊友,比如: Tony(騰訊CTO),那麽Tony會冷靜的使用下面的命令來找出你回退版本後覆蓋掉的他的提交,也就是B1那次提交:

git reflog

然後冷靜的把自己的分支回退到那次提交,並且拉個分支:

git checkout tony_branch        //先回到自己的分支  
git reflog                      //接著看看當前的commit id,例如:0bbbbb    
git reset --hard B1             //回到被覆蓋的那次提交B1
git checkout -b tony_backup     //拉個分支,用於保存之前因為回退版本被覆蓋掉的提交B1
git checkout tony_branch        //拉完分支,迅速回到自己分支
git reset --hard 0bbbbbb        //馬上回到自己分支的最前端

通過上面一通敲,Tony暫時舒了一口氣,還好,B1那次提交找回來了,這時tony_backup分支最新的一次提交就是B1,接著Tony要把自己的本地master分支和遠程master分支保持一致:

git reset --hard origin/master

執行了上面這條命令後,Tony的master分支才真正的回滾了,也就是說你的回滾操作才能對Tony生效,這個時候Tony的本地maser是這樣的:A1

接著Tony要再次合並那個被丟掉的B1提交:

git checkout master             //切換到master
git merge tony_backup           //再合並一次帶有B1的分支到master

好了,Tony終於長舒一口氣,這個時候他的master分支是下面這樣的:A1 – B1

終於把丟掉的B1給找回來了,接著他push一下,你一拉也能同步。

同理對於所有隊友也要這樣做,但是如果該隊友沒有提交被你丟掉,那麽他拉完代碼git pull之後,只需要強制用遠程master覆蓋掉本地master就可以了:

git reset --hard origin/master

(2) 然而很不幸的是,現實中,我們經常遇到的都是豬一樣的隊友,他們一看到下面提示:

$ git status
On branch master
Your branch is ahead of ‘origin/master‘ by 2 commits.
  (use "git push" to publish your local commits)
nothing to commit, working directory clean

就習慣性的git push一下,或者他們直接用的SourceTree這樣的圖形界面工具,一看到界面上顯示的是推送的提示就直接點了推送按鈕,臥&槽,你辛辛苦苦回滾的版本就這樣輕松的被你豬一樣的隊友給還原了,所以,只要有一個隊友push之後,遠程master又變成了:A1 – A2 – B1

這就是分布式,每個人都有副本。這個時候你連揍他的心都有了,怎麽辦呢?你不能指望每個人隊友都是git高手,下面我們用另外一種方法來回退版本。

公共遠程分支版本回退的方法

使用git reset回退公共遠程分支的版本後,需要其他所有人手動用遠程master分支覆蓋本地master分支,顯然,這不是優雅的回退方法,下面我們使用另個一個命令來回退版本:

git revert HEAD                     //撤銷最近一次提交
git revert HEAD~1                   //撤銷上上次的提交,註意:數字從0開始
git revert 0ffaacc                  //撤銷0ffaacc這次提交

git revert 命令意思是撤銷某次提交。它會產生一個新的提交,雖然代碼回退了,但是版本依然是向前的,所以,當你用revert回退之後,所有人pull之後,他們的代碼也自動的回退了。
但是,要註意以下幾點:

  1. revert 是撤銷一次提交,所以後面的commit id是你需要回滾到的版本的前一次提交
  2. 使用revert HEAD是撤銷最近的一次提交,如果你最近一次提交是用revert命令產生的,那麽你再執行一次,就相當於撤銷了上次的撤銷操作,換句話說,你連續執行兩次revert HEAD命令,就跟沒執行是一樣的
  3. 使用revert HEAD~1 表示撤銷最近2次提交,這個數字是從0開始的,如果你之前撤銷過產生了commi id,那麽也會計算在內的。
  4. 如果使用 revert 撤銷的不是最近一次提交,那麽一定會有代碼沖突,需要你合並代碼,合並代碼只需要把當前的代碼全部去掉,保留之前版本的代碼就可以了.

git revert 命令的好處就是不會丟掉別人的提交,即使你撤銷後覆蓋了別人的提交,他更新代碼後,可以在本地用 reset 向前回滾,找到自己的代碼,然後拉一下分支,再回來合並上去就可以找回被你覆蓋的提交了。

revert 合並代碼,解決沖突

使用revert命令,如果不是撤銷的最近一次提交,那麽一定會有沖突,如下所示:

<<<<<<< HEAD
全部清空
第一次提交
=======
全部清空
>>>>>>> parent of c24cde7... 全部清空

解決沖突很簡單,因為我們只想回到某次提交,因此需要把當前最新的代碼去掉即可,也就是HEAD標記的代碼:

<<<<<<< HEAD
全部清空
第一次提交
=======

把上面部分代碼去掉就可以了,然後再提交一次代碼就可以解決沖突了。

簡單粗暴的回滾方法

如果你們開發中,忽然發現前面很遠的地方有一次錯誤的合並代碼,把本來下一次才能發的功能的代碼合並到了這一次來了,這個時候全體成員都覺得直接回滾比較快,因為他們都有備份,覆蓋了無所謂,這個時候用reset的話對隊友的要求比較高,用revert的話呢要大面積的解決沖突,也很麻煩呀,怎麽辦呢?

這個時候,可以使用簡單粗暴的辦法,直接從那個錯誤的提交的前一次拉取一份代碼放到其他目錄,然後將master代碼全部刪除,把那份新代碼方進去,然後提交。

總結

遠程分支回滾的三種方法:

  1. 自己的分支回滾直接用reset
  2. 公共分支回滾用revert
  3. 錯的太遠了直接將代碼全部刪掉,用正確代碼替代

基於git的管理應用程序基線包和版本