1. 程式人生 > >Git入門到高級系列2-git高級操作

Git入門到高級系列2-git高級操作

configure 類型 開發模式 推斷 flow 生效 公鑰 ssd 分離

視頻課程地址

騰訊課堂

git 清理

git clean命令用來從你的工作目錄中刪除所有沒有tracked過的文件。

命令說明
git clean -n 告訴你哪些文件會被刪除. 記住他不會真正的刪除文件, 只是一個提醒。
git clean -d 刪除未跟蹤的目錄
git clean -f 刪除當前目錄下所有沒有track過的文件。忽略文件不被刪除!
git clean -df -d代表刪除目錄,-f強制刪除。
git clean -xf 刪除當前目錄下所有沒有track過的文件. 不管他是否是.gitignore文件裏面指定的文件夾和文件
git clean -X 刪除所有被忽略的文件

如果被刪除的子文件夾中有 .git目錄,那麽會被忽略掉,如果想刪除必須添加-f參數。

比如實例:讓當前工作目錄回滾到上一次提交的狀況,新添加的文件也被刪除掉。

# 讓暫存區和工作目錄把已經被跟蹤的文件清理幹凈
$ git reset --hard
# 讓未追蹤的文件進行清理
$ git clean -f

git分支管理

項目分支就是版本庫的一個副本,有了分支後可以把你的工作從開發主線上分離開來, 以免影響開發主線。

創建分支

創建分支: git branch 分支名字命令,切換分支的命令使用 git checkout 分支名字

$ git branch dev
$ git checkout dev

# -b創建分支,checkout是切換分支
$ git checkout -b dev

刪除分支

當一個分支完成了使命的時候,一般我們會把它刪除掉。

# -d 命令是刪除的意思,delete
$ git branch -d hotfix

查看所有的分支

$ git branch -v
  dev    eba9a31 update the a.txt by dev
* master d47fbfb update the a.txt by master;

帶*的代表是當前的分支。

合並分支

合並分支就是把其他分支的代碼合並到當前的分支中。git會自動將當前分支和要合並的分支找到共同的基點,然後將當前分支的所有變化和要合並分支的變化進行三方合並,並產生一個新的提交,此次提交有兩個父提交。

例如操作:

# 進入主分支
$ git checkout master

# 合並dev分支
$ git merge dev

合並分支:

  • 合並分支前,確保當前分支已經提交狀態

  • 快速合並: 如果兩個分支之間沒有分叉,要被合並的分支提交比當前分支更新,那麽只是HEAD指針的移動。

  • 沖突解決: 如果合並的兩個分支有分叉,那麽自動添加一個新的提交,如果有沖突需要先解決完沖突然後再提交。

解決沖突的辦法:就是移除代碼中的特殊符號,留下自己想要的代碼。比如:沖突文件如下:

ssss
<<<<<<< HEAD
22222222
33333333
44444444
=======
devdevdevdev
>>>>>>> dev

移除上面的 <<<<<<< HEAD======= >>>>>>> dev然後留下自己想要的代碼就完成了沖突解決,最後add和commit一下就可以了。

完整的解決沖突的流程:

# 切換到主分支
$ git checkout master

# 把dev分支的內容合並到主分支
$ git merge dev

# 如果產生沖突後,先修改文件,去掉沖突的符號。

# 最後提交修改到倉庫
$ git add .
$ git commit -m ‘合並沖突‘

合並過程中,隨時都可以停止合並,只需要 git merge abort ,倉庫和工作去會回到合並之前的狀態。

git標簽

Git 可以給歷史中的某一個提交打上標簽。 比較有代表性的是人 們會使用這個功能來標記發布結點(v1.0 等等)。

列出標簽

在 Git 中列出已有的標簽是非常簡單直觀的。 只需要輸入 git tag:

$ git tag
v0.1
v1.3

這個命令以字母順序列出標簽;

你也可以使用特定的模式查找標簽,如果只對 1.8.5 系列感興趣,可以運行:

$ git tag -l ‘v1.8.5*‘
v1.8.5
v1.8.5-rc0
v1.8.5-rc1
v1.8.5-rc2
v1.8.5-rc3
v1.8.5.1
v1.8.5.2
v1.8.5.3
v1.8.5.4
v1.8.5.5

創建標簽

Git 使用兩種主要類型的標簽:輕量標簽(lightweight)與附註標簽(annotated)。 一個輕量標簽很像一個不會改變的分支 - 它只是一個特定提交的引用。

  • 註標簽

在 Git 中創建一個附註標簽是很簡單的。 最簡單的方式是當你在運行 tag 命令時指定 -a 選項:

$ git tag -a v1.4 -m ‘my version 1.4‘
$ git tag
v0.1
v1.3
v1.4

-m 選項指定了一條將會存儲在標簽中的信息。

通過使用git show命令可以看到標簽信息與對應的提交信息:

$ git show v1.4
tag v1.4
Tagger: Ben Straub <[email protected]>
Date:   Sat May 3 20:19:12 2014 -0700
my version 1.4
commit ca82a6dff817ec66f44342007202690a93763949
Author: Scott Chacon <[email protected]>
Date:   Mon Mar 17 21:52:11 2008 -0700
  changed the version number

輸出顯示了打標簽者的信息、打標簽的日期時間、附註信息,然後顯示具體的提交信息。

  • 輕量標簽

另一種給提交打標簽的方式是使用輕量標簽。 輕量標簽本質上是將提交校驗和存儲到一個文件中 - 沒有保存任 何其他信息。 創建輕量標簽,不需要使用 -a、-s 或 -m 選項,只需要提供標簽名字:

$ git tag v1.4-lw
$ git tag
v0.1
v1.3
v1.4
v1.4-lw
v1.5

後期打標簽

你也可以對過去的提交打標簽。

$ git tag -a v1.2 9fceb02

檢出標簽

在 Git 中你並不能真的檢出一個標簽,因為它們並不能像分支一樣來回移動。 如果你想要工作目錄與倉庫中特定 的標簽版本完全一樣,可以使用git checkout -b [branchname] [tagname]在特定的標簽上創建一個 新分支:

$ git checkout -b version2 v2.0.0
Switched to a new branch ‘version2‘

當然,如果在這之後又進行了一次提交,version2 分支會因為改動向前移動了,那麽 version2 分支就會和 v2.0.0 標簽稍微有些不同,這時就應該當心了。

變基

變基的基本操作

rebase 命令將提交到某一分支上的所有修改都移至另一分支上,就好像“重新 播放”一樣。翻譯成通俗的話: 找到參照的倉庫和當前的倉庫的相同的提交,然後把當前分支後續的提交挪動到參照倉庫的提交的最後,形成一條線性的提交順序。

例如:experiment分支參照master分支進行變基

技術分享圖片 變基之前
$ git checkout experiment
$ git rebase master
技術分享圖片 變基之後

遠程分支的pull命令的時候的--base可以直接變基合並

改變提交歷史

修改多個提交信息.如果想要修改最近三次提交信息,或者那組提交中的任意一個提交信息,將想要修改的最近一次提交的父 提交作為參數傳遞給git rebase -i命令,即HEAD2^或HEAD3。記住~3可能比較容易,因為你正嘗試 修改最後三次提交;

$ git rebase -i HEAD~3

此時會進入vi的編輯器模式,這是需要你了解一點vi的快捷鍵不然沒法繼續操作。

pick f7f3f6d changed my name a bit
pick 310154e updated README formatting and added blame
pick a5f4a0d added cat-file
# Rebase 710f0f8..a5f4a0d onto 710f0f8
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit‘s log message
# x, exec <command> = run command (the rest of the line) using shell
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# .       create a merge commit using the original merge commit‘s
# .       message (or the oneline, if no original merge commit was
# .       specified). Use -c <commit> to reword the commit message.
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.

把最上面的pick對應改成你想要的效果,比如刪除某個提交信息,則把pick改成 d為刪除當前提交信息,e是修改,p默認就留下

git遠程倉庫

遠程倉庫是指托管在因特網或其他網絡中 的你的項目的版本庫。

遠程分支克隆

克隆遠程倉庫,就是把遠程倉庫拷貝一個副本下載到本地。

$ git clone https://github.com/malun666/aicoder_vip_doc
# 本地目錄會增加一個文件,就是把遠程倉庫下載到本地了

查看遠程倉庫的遠程的關聯信息

$ git remote -v
origin  https://github.com/malun666/aicoder_vip_doc (fetch)
origin  https://github.com/malun666/aicoder_vip_doc (push)

origin - 這是 Git 給你克隆的倉庫服務器的默認名字。origin就代表遠程倉庫的別名。

添加遠程倉庫

語法:git remote add <shortname> <url>

$ cd /path/to/gitresp
$ git remote add aicoder https://github.com/malun666/aicoder_vip_doc
$ git remote -v

遠程分支拉取

一般先建立好遠程倉庫的別名後,然後用fetch命令進行拉取遠程倉庫的內容。

$ git fetch <遠程倉庫別名> <遠程分支名>
# 例如:
$ git fetch origin dev

# 下載所有的遠程分支
$ git fetch --all

如果你使用 clone 命令克隆了一個倉庫,命令會自動將其添加為遠程倉庫並默認以 “origin” 為簡寫。

遠程倉庫的移除與重命名

如果想要重命名引用的名字可以運行 git remote rename 去修改一個遠程倉庫的簡寫名。 例如,想要將 pb 重命名為paul,可以用git remote rename這樣做:

  • 修改別名
$ git remote rename pb paul
$ git remote
origin
paul
  • 刪除別名
$ git remote rm paul
$ git remote
origin

查看遠程倉庫詳情

如果想要查看某一個遠程倉庫的更多信息,可以使用 git remote show [remote-name]命令。

$ git remote show origin
* remote origin
  Fetch URL: git@github.com:malun666/aicoder_egg.git
  Push  URL: git@github.com:malun666/aicoder_egg.git
  HEAD branch: master
  Remote branches:
    dev    tracked
    master tracked
  Local branches configured for ‘git pull‘:
    dev    merges with remote dev
    master merges with remote master
  Local refs configured for ‘git push‘:
    dev    pushes to dev    (up to date)
    master pushes to master (up to date)

推送到遠程倉庫

當你想分享你的項目時,必須將其推送到上遊。 這個命令很簡單:git push [remote-name] [branch-name]。 當你想要將 master 分支推送到 origin 服務器時(再次說明,克隆時通常會自動幫你設置好那兩個 名字),那麽運行這個命令就可以將你所做的備份到服務器

具體語法:

$ git push <遠程主機名> <本地分支名>:<遠程分支名>

實例:

$ git push origin master

只有當你有所克隆服務器的寫入權限,並且之前沒有人推送過時,這條命令才能生效。

註意推送之前,必須先把遠程分支的最新內容拉取下來合並或者變基成為最新的內容才可以推送。

設置關聯,自動推送。

第一次執行推送的時候,添加 -u參數,例如:

$ git push -u origin master
# 後續的推送,就直接使用  git push即可,已經關聯無需再指定 origin和master

遠程分支拉取與合並

拉取之前,確保當前倉庫為提交完成狀態。

拉取所有的遠程分支:

$ git fetch --all
$ git branch --all
# 此時可以看到所有的遠程分支和當前分支內容
  aicoder
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/aicoder
  remotes/origin/master

此時remotes開頭的都是遠程的分支的最新的內容,可以用merge命令進行合並分支,也可以rebase變基。

例如:

# 切換到aicoder分支
$ git checkout aicoder

# 合並遠程的aicoder分支
$ git merge remotes/origin/aicoder

以上操作都太麻煩,最簡單的辦法就是直接使用pull命令,是以上fetch命令和merge命令的合體:

# 獲取遠程的aicoder分支並與當前的aicoder分支進行合並。
$ git pull origin aicoder

# 如果合並的不同分支名字:  最後需要用 遠程分支名:本地分支名
# $ git pull <遠程主機名> <遠程分支名>:<本地分支名>
$ git pull origin aicoder:master

如果合並過程中有任何的沖突,需要手動修改沖突代碼,最後git add 和git commit提交。

遠程分支拉取與變基

遠程拉取和合並可以只用git pull命令,變基也是可以的。

git pull --rebase origin master
# 簡寫
git pull -r origin master

# 從遠程origin的master分支上拉取最新的結果並且讓當前倉庫依照遠程倉庫進行變基操作。

變基過程中可以隨時進行 abort停止。

github

GitHub 是最大的 Git 版本庫在線托管商,是一個免費托管開源項目的遠程倉庫,非開源項目收費。

註冊賬號

直接訪問 https://github.com

配置SSH 訪問

第一步:登錄github 第二步:點擊github右上角頭像,彈出菜單選擇setting,然後選擇SSH and GPG keys菜單,點擊 New SSH Key按鈕.

技術分享圖片 設置ssh key

第三步:找到之前生成的ssh的公鑰 打開終端或者命令行(gitbash)

$ cat ~/.ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC/ssdfsfsdfadfadfasdfasdfaslajfdaljADFASdfkasdflasjflasjdflajA23ljlsdjfaljf

~/.ssh/id_rsa.pub文件中的內容拷貝到github的秘鑰框中。如下圖所示:

技術分享圖片 設置ssh key

github 創建倉庫並設置管理

在github的網站頂部點擊 加號按鈕。

技術分享圖片 設置ssh key

然後輸入倉庫的名字和倉庫的描述。

技術分享圖片 設置ssh key

好的此時遠程倉庫創建好了,然後就可以進行遠程關聯和推送和拉取工作。

例如:

在本地新建倉庫並進行關聯:

echo "# gitlearn" >> README.md
git init
git add README.md
git commit -m "first commit"
git remote add origin git@github.com:malun666/gitlearn.git
git push -u origin master

在本地已有的倉庫上進行關聯:

git remote add origin git@github.com:malun666/gitlearn.git
git push -u origin master

git工作流

詳情請參考: Git工作流指南

git集中式工作流

集中式工作流以中央倉庫作為項目所有修改的單點實體。相比SVN缺省的開發分支trunk,Git叫做master,所有修改提交到這個分支上。

技術分享圖片 設置ssh key
  • 所有成員都以中央倉庫為基礎進行clone
  • 所有成員代碼提交到本地倉庫,進行遠程推送前先進行獲取最新解決沖突後再push
  • 可以選擇merge模式也可以rebase模式

基本的開發模式:

  1. 項目維護者推送到主倉庫。
  2. 貢獻者克隆此住倉庫,做出修改。
  3. 貢獻者將數據推送到自己的公開倉庫。
  4. 貢獻者給維護者發送郵件,請求拉取自己的更新。
  5. 維護者在自己本地的倉庫中,將貢獻者的倉庫加為遠程倉庫並合並修改。
  6. 維護者將合並後的修改推送到主倉庫。
技術分享圖片 集中式工作流

進入公司後,需要問項目經理要一下公司的源碼git倉庫的地址,以及把自己的公鑰給管理員,讓他們幫你設置上權限,就可以clone項目了。

本工作流比較簡單,就不再概述。

github的fork工作流

派生(Fork)項目,如果你想要參與某個項目,但是並沒有推送權限,這時可以對這個項目進行“派生”。 派生的意思是 指,GitHub 將在你的空間中創建一個完全屬於你的項目副本,且你對其具有推送權限。

流程通常如下:

  1. 從 master 分支中創建一個新分支
  2. 提交一些修改來改進項目
  3. 將這個分支推送到 GitHub 上
  4. 創建一個合並請求(pr)
  5. 討論,根據實際情況繼續修改
  6. 項目的擁有者合並或關閉你的合並請求
技術分享圖片 github-fork工作流

項目分支管理模型

一般一個完整的項目都會有很多分支,每個分支都有一些管理的規則。

技術分享圖片 設置ssh key

如何刪除遠程分支

# 把一個空分支推送到遠程的dev分支,也就是刪除遠程的dev分支
$ git push origin :dev

git的鉤子與自動化集成

Git 能在特定的重要動作發生時觸發自定義腳本。這些特定的能註冊執行腳本的事件就稱為鉤子。

客戶端鉤子

客戶端鉤子分為很多種。 下面把它們分為:提交工作流鉤子、電子郵件工作流鉤子和其它鉤子。

提交鉤子

鉤子名作用
pre-commit 鉤子在鍵入提交信息前運行。 它用於檢查即將提交的快照,例如,檢查是否有所遺漏,確保測試 運行,以及核查代碼。 如果該鉤子以非零值退出,Git 將放棄此次提交,不過你可以用 git commit --no -verify 來繞過這個環節。 你可以利用該鉤子,來檢查代碼風格是否一致(運行類似 lint 的程序)、尾隨空 白字符是否存在(自帶的鉤子就是這麽做的),或新方法的文檔是否適當。
prepare-commit-msg 鉤子在啟動提交信息編輯器之前,默認信息被創建之後運行。 它允許你編輯提交者所 看到的默認信息。 該鉤子接收一些選項:存有當前提交信息的文件的路徑、提交類型和修補提交的提交的 SHA- 1 校驗。 它對一般的提交來說並沒有什麽用;然而對那些會自動產生默認信息的提交,如提交信息模板、合並提 交、壓縮提交和修訂提交等非常實用。 你可以結合提交模板來使用它,動態地插入信息。
commit-msg 鉤子接收一個參數,此參數即上文提到的,存有當前提交信息的臨時文件的路徑。 如果該鉤子腳本以非零值退出,Git 將放棄提交,因此,可以用來在提交通過前驗證項目狀態或提交信息。 在本章的最後一節,我們將展示如何使用該鉤子來核對提交信息是否遵循指定的模板。
post-commit 鉤子在整個提交過程完成後運行。 它不接收任何參數,但你可以很容易地通過運行 git log -1 HEAD來獲得最後一次的提交信息。該鉤子一般用於通知之類的事情。

例如: git提交的標簽工具

An emoji guide for your commit messages. ??

其他鉤子請直接參考官網。

服務器端鉤子

服務器端的鉤子可以幫我做很多事情,比如檢測到提交好自動執行某些自動化部署的腳本,就能實現自動化的部署和提交。 所有服務器端的工作都將在你的 hooks 目錄下的 update 腳本中完成。 update 腳本會為每一個提交的分支各 運行一次,它接受三個參數:

  • 被推送的引用的名字
  • 推送前分支的修訂版本(revision)
  • 用戶準備推送的修訂版本(revision)

例如:

技術分享圖片 git鉤子

git其他

git命令別名

Git 並不會在你輸入部分命令時自動推斷出你想要的命令。 如果不想每次都輸入完整的 Git 命令,可以通過 git config 文件來輕松地為每一個命令設置一個別名。 這裏有一些例子你可以試試:

$ git config --global alias.co checkout
$ git config --global alias.br branch
$ git config --global alias.ci commit
$ git config --global alias.st status

如果定義的別名想帶上參數,那麽需要對命令名加上引號。

$ git config --global alias.lf ‘log --graph --oneline‘

# 使用:
$ git lf

# 等價於:
$ git log --graph --oneline

git服務器端私有部署及權限管理

請直接參考: CentOS搭建Git服務器及權限管理

搭建gitlab

直接參考:4.8 服務器上的 Git - GitLab

作業

git stash命令

視頻課程地址

騰訊課堂

Git入門到高級系列2-git高級操作