git 基礎知識整理(一)

前言

發現 git 這塊所知甚淺,打算利用空閒時間好好學習一下;

git 整理

(DVCS Distributed version controll system 分佈式版本控制系統)

git官網系統知識鏈接

git簡介

  • 直接記錄快照,而非差異比較; 文件變化,保存一個指向這次快照的索引,文件沒有變化,對上次保存的快照做一鏈接;

  • 本地操作;
  • SHA-1哈希值作爲索引,校驗保持數據完整性;
  • 文件三種狀態;committed,modified,staged;
    • committed: 已提交該文件已被安全的保存在本地數據庫中;
    • modified: 已修改修改了某個文件,還沒有提交保存;
    • staged: 已暫存已修改的文件放在下次提交時要保存的清單中;

git流轉過程:

git的工作區域(modified),暫存區域(staged),本地倉庫(committed)

git目錄:保存元數據和對象數據庫的地方


	git clone 就是.git目錄;
	
	git clone --bare 新建的目錄本身就是git目錄;

基本工作流程:

工作目錄中修改文件(modified)->對修改的文件進行快照,保存到暫存區域(staged)->提交更新,將保存在暫存區的文件快照永久轉存到git目錄中(commited);

git配置 .git/config


	--global 表示更改的配置文件就是用戶主目錄下,以後所有的項目默認使用這裏配置的用戶信息,可去除表示特定的項目中運用;
	
	git config --global user.name "John Doe"
	git config --global user.email [email protected]

	git config --list 查看配置信息;

	git help 查看幫助信息;

	git config可用於設置別名;
	git config --global alias.br branch 設置branch的快捷名稱;
	即`git br 查看所有分支;`

git 基礎

工作目錄中初始化新倉庫


	git init : 對現有的某個項目開始用git管理,只需到此項目所有的目錄執行;

	git clone [url] newfolder:克隆url的文件;保存下載下來的所有版本記錄,並從中取出最新版本的文件拷貝; 
	可自定義新建的項目目錄;
	自動使用默認的`master`和`origin`名字;

	git add *.c 納入版本控制,多功能命令;
	

記錄每次更新到倉庫

工作目錄下的所有文件不外乎兩種狀態: 已跟蹤未跟蹤;已跟蹤指本來就被納入控制的文件,狀態可能爲未更新,已修改,已暫存(unmodified,modified,staged);其他的所有文件屬於未跟蹤(untracked);

查看文件狀態 git status

  • clean: 現在的工作目錄是乾淨的,已跟蹤文件沒有修改過,沒有出現未跟蹤的新文件;

  • 創建文件後: untracked files; 出現未跟蹤文件;

  • 跟蹤新文件: git add 文件 後,Changes to be committed new file 已被跟蹤,暫存區,處於已暫存狀態;提交後被留在歷史記錄中;

  • 暫存已修改文件: 修改已經跟蹤的文件,會出現Changes not staged for commit modified 已跟蹤文件的內容產生變化,但還沒有暫存,需要運行git add 後出現: Changes to be committed newfile or modified表明已經暫存;此時再次修改後還需要git add;

添加至暫存區 git add

多功能命令,根據目標文件的狀態不同,命令效果不同;

  • 未跟蹤過的文件標記爲需要跟蹤;
  • 將已跟蹤目標文件快照放入暫存區,git會暫存運行命令時的版本;
  • 用於合併時把有衝突的文件標記爲已解決狀態;

忽略文件格式 .gitignore

  • 所有空行或者以註釋符號 # 開頭的行都會被 Git 忽略。
  • 可以使用標準的 glob 模式匹配 (shell 所使用的簡化了的正則表達式)。
    • *: 0個或多個任意字符; [abc]:匹配任意一個列在方括號中的字符,a,b,c; ?:只匹配一個任意字符;[0-9]兩個字符範圍內的都可以匹配;
  • 匹配模式最後跟反斜槓(/)說明要忽略的是目錄。
  • 要忽略指定模式以外的文件或目錄,可以在模式前加上驚歎號(!)取反。

	# 此爲註釋 – 將被 Git 忽略
	# 忽略所有 .a 結尾的文件
	*.a
	# 但 lib.a 除外
	!lib.a
	# 僅僅忽略項目根目錄下的 TODO 文件,不包括 subdir/TODO
	/TODO
	# 忽略 build/ 目錄下的所有文件
	build/
	# 會忽略 doc/notes.txt 但不包括 doc/server/arch.txt
	doc/*.txt
	# 忽略 doc/ 目錄下所有擴展名爲 txt 的文件
	doc/**/*.txt

git diff

無參數比較的是修改之後還沒有暫存起來的變化;

git diff --cached 查看已經暫存起來的文件和上次提交時的快照之間的差異;

git commit -m “msg”

提交時記錄的是放在暫存區的快照,沒有暫存的仍然保持已修改狀態,可以下次提交時納入版本管理; 每一次提交都是對項目做個快照,可以回到這個狀態或者進行比較;

跳過使用暫存區域 git commit -a -m "msg" 自動將素有已經跟蹤過的文件暫存起來一併提交;

git commit --amend 修改最後一次提交,將使用當前的暫存區域快照提交,可以用於添加額外的文件或者提交信息寫錯了,較少commit節點;

git rm 移出文件;

必須從暫存區移除,然後提交; 如果直接刪除文件 會出現changes not staged for commit deleted ;

刪除git倉庫,但保留在當前工作目錄中,以便加入到gitignore中;使用 git rm --cached 文件

git rm log/*.log

git rm *.~ (刪除所有以~結尾的文件;)

git mv

git mv oldfile newfile 相當於

  • mv oldname newname
  • git rm oldname
  • git add newname

git log && gitk

顯示歷史記錄和圖形化記錄

git reset HEAD 取消已經暫存的文件;

  • 取消暫存區域的文件;(一個是add 的撤銷操作)
    • git reset HEAD 文件名 將暫存區的文件回到已修改未暫存的狀態;
  • 取消工作目錄中已修改的文件;(一個是commit的撤銷操作)
    • git checkout -- 文件名 取消對文件的修改,需要回到已修改未暫存狀態,會吧之前對改文件的修改取消了;

git remote 遠程項目的管理

git remote 列出每個遠程庫的簡短名字(origin);

git remote -v 顯示對應的克隆地址;

git remote add [shortname] [url] 添加一個新的遠程倉庫,指定一個簡單名稱;使用shortname指代對應的倉庫地址;

git remote show [remote-name] 查看遠程倉庫信息;

git remote rename oldname newname 遠程倉庫的重命名;

git remote rm [remote-name]遠程倉庫的刪除

git fetch 從遠程倉庫中抓取數據

git fetch [remote-name] 此命令會到遠程倉庫中拉取所有你本地倉庫中還沒有的數據; 只是將遠端的數據拉取到本地倉庫,不會自動合併到當前工作分支;

git pull

自動抓取數據,git fetch + git merge

git push 推送數據到遠程倉庫

git push [remote-name] [branch-name] 將本地的branchname分支推送到遠程的origin服務器上;

git tag 打標籤

git tag 顯示現有的所有標籤; 搜索加 (-l v1.4.2.*)

  • -l lightweight 輕量級的,指向特定提交對象的引用;
  • -a annotated 含附註的,存儲在倉庫中的一個獨立對象;

git tag v1.4輕量級標記;

git tag -a v1.4 -m "my version 1.4" 打附註標籤;

git tag -a v1.2 序列號 對某次提交打tag;

git push origin [tagname] 分享某個標籤到遠程;

git push origin --tags 推送所有的標籤到遠程;

git show 查看相關標籤信息;

git tag -s v1.2 -m "msg" 簽署標籤,使用GPG來簽署標籤;

git tag -v [tag-name] 驗證標籤;


git分支的原理簡介

因爲git保存的是一系列文件快照;

git commit新建一個提交對象前,git會對每一個文件計算校驗和(SHA1)將當前版本的文件快照保存在git倉庫中(blob對象);對每一個子目錄計算校驗和,然後在git倉庫中將這些目錄保存爲tree對象;之後創建的提交對象,除了包含相關提交信息以外,還包含着指向這個tree對象的指針;

  • blob對象: 表示文件快照內容;

  • tree對象: 記錄着目錄樹內容及其中各個文件對應blob對象索引;

  • commit對象: 包含指向tree對象(根目錄)的索引和其他提交信息元數據的commit對象;

單個提交對象在倉庫中的數據結構

修改後再次提交,提交對象會包含一個指向上次提交對象的指針(parent對象)

多個提交對象之間的鏈接關係

分支 本質上是一個指向commit對象的可變指針;

git 使用master作爲分支的默認名稱;在若干次提交後,其實已經有一個指向最後一次提交對象的master分支,它在每次提交的時候都會自動向前移動;

分支其實就是從某個提交對象往回看的歷史

git branch newbranchname 在當前commit對象上新建一個分支指針,但不切換至新分支;

多個分支指向提交數據的歷史

HEAD 判斷當前在哪個分支上工作

git保存了一個名叫HEAD的特別指針; git中HEAD指向你正在工作中的本地分支的指針(當前分支的別名)

HEAD 指向當前所在的分支

git checkout newbranchname 切換到其他分支上;

HEAD 切換分支時指向新的分支

每次提交head都會隨着分支一起向前移動,原master分支仍然指向原先git checkout時所在的commit對象;

每次提交後HEAD隨着分支一起向前移動

若此時運行git checkout master,head指向另一個分支;

 將HEAD指針移回到master分支;
 並把工作目錄中的文件換成了master分支所指向的快照內容; 

HEAD 在一次checkout之後移動到了另一個分支

git commit 新建一個新的提交對象,向不同方向開發;

不同流向的分支歷史

分支的新建和合並

git checkout -b newbranch

git checkout -d branchname

  • -b : 新建一個分支,並切換head指向新建分支;(branch + checkout)
  • -d : 刪除一個分支;

clean 後的切換分支;

如果你的暫存區或者工作目錄中,有沒有提交的修改,它會和你即將檢出的分支產生衝突從而阻止git爲你切換分支;保持clean後,可切換分支;

hotfix 分支從master分支所在點分化出來的;master是線上版本,iss53分支是當前正在開發的feature功能;

git checkout -b hotfix,git checkout master ,git merge hotfix

Fast-forward: 向前合併,由於master分支所在的提交對象是要併入hotfix分支的直接上游,git只需把master分支指針直接右移,這種單線的歷史分支不存在任何需要解決的分歧,這種合併方式可以稱爲Fast forward;

hotfix 分支是從 master 分支所在點分化出來的

合併之後,master分支和hotfix分支指向同一位置;刪除不需要的hotfix分支(指針);
切換回正在開發的分支iss53,不受影響;如果想要納入hotfix的修改,需要git merge master or 等iss53完成後將iss53分支中的更新併入master;

合併之後,master 分支和 hotfix 分支指向同一位置。

分支的合併

git checkout master ,git merge iss53

Auto-merging: 這次合併並不同於hotfix的合併;因爲開發歷史從更早的地方開始分叉的;由於master分支所指向的提交對象並不是iss53分支的直接祖先,git需要用兩個分支的末端(C4,C5)以及他們公共的祖先(C2)進行一次簡單的三方合併,紅框是需要合併的提交對象;

Git 爲分支合併自動識別出最佳的同源合併點。

不同方向的分支合併,需要對三方合併後的結果重新做一個新的快照,自動創建一個指向它的提交對象C6,此提交對象有兩個祖先(C4,C5); 刪除feature功能分支即可完成開發;

Git 自動創建了一個包含了合併結果的提交對象

遇到衝突後的分支合併;

git status 查看合併衝突;

Automatic merge failed ,unmerged paths

  • 衝突標記
    • ===========隔開衝突;<<<<<<<<HEAD開始衝突,>>>>>>>iss53與分支結束衝突地方;
    • 上方是HEAD(即master分支,當前分支,運行merge命令時所切換的分支)的內容;
    • 下方是iss53分支中的內容;

解決衝突之後,git add再來一次快照保存到暫存區域,一旦暫存表示衝突已解決;

git mergetool 運行可視化的合併工具並引導你解決所有衝突;

總結merge
合併分爲兩種合併:fast-forward和非共同祖先的三方合併;

  • fast-forward : 單線的提交歷史,如果低節點的master分支指針的想去高節點的dev分支指針,使用merge命令 fast-forward 合併,指向同一個commit 提交對象節點;
  • 非共同祖先的兩分支的合併,使用兩分支的末節點和共同祖先的節點進行三方合併,產生一個新的虛擬節點; 可使用的命令爲三個,merge ,rebase 😭cherry pick 遴選節點再重演)

分支的管理

  • git branch 查看所有分支
    • -v 查看各個分支最後一次的提交信息;
    • --no-merged 查看尚未合併的分支;刪除未合併的分支使用get branch -D name強制刪除;
    • --merged 查看哪些分支已被併入當前分支(哪些分支是當前分支的直接上游,父提交對象),此時可將沒有*的分支刪除掉;

利用分支進行開發的工作流程;(git flow 雛形)

  • 長期分支

隨着提交對象不斷的右移指針,穩定分支的指針總是在提交歷史中落後於前沿特性開發的指針;展現不同層次的穩定新,當前沿指針分支進入到穩定階段,將之合併到更高層的分支中去;

穩定分支總是比較老舊

  • 特性分支

特性(Topic)分支,短期的用來實現單一特性,通常創建特性分支,提交若干提交對象更新後,合併到主幹分支,然後刪除特性分支;

新建多個特性分支,針對於不同提交對象的節點進行新建分支的功能嘗試;

擁有多個分支的提交歷史

具體情景: 決定使用iss91v2特性分支嘗試的解決方案,並拋棄原來的iss91分支的內容(拋棄C5,C6提交對象),直接在主幹中併入另外兩個分支,這些分支都是本地分支,完全不涉及與服務器的交互;

主幹合併兩個特性分支的內容

遠程分支

對遠程倉庫中的分支的索引; 使用(遠程倉庫名/(分支名))形式表示遠程分支,如origin/master;一次克隆建立本地分支和遠程分支,都指向origin上的master分支;

一次 Git 克隆會建立你自己的本地分支 master 和遠程分支 origin/master,並且將它們都指向 origin 上的 master 分支

多人開發中,遠程倉庫master向前推進,本地master也朝不同方向推進;

在本地工作的同時有人向遠程倉庫推送內容會讓提交歷史開始分流。

此時運行git fetch origin 同步遠程服務器上數據到本地;找到origin是哪個服務器,獲取未擁有的數據,更新本地的數據庫,將origin/master指針移到它最新的位置上;

git fetch 命令會更新 remote 索引

多個遠程倉庫,添加另一個遠程倉庫和拉取另一個遠程倉庫,在本地提交中新建一個指針;

 把另一個服務器加爲遠程倉庫

你在本地有了一個指向 teamone 服務器上 master 分支的索引

推動本地分支 (分支全面: refs/head/分支名)

git push (遠程倉庫名) (分支名) : 取出我的本地分支,推送到遠程倉庫分支,git分支名擴展爲refs/head/localbranchname:refs/head/remotebranchname;

git push origin branchname == git push origin branchname:branchname
git push [遠程名] [本地分支名]:[遠程分支名]

git push origin branchname:awebranchname 推送本地branchname分支到遠程倉庫創建awebranchname分支;

git merge origin/master 合併遠程分支到當前分支
git checkout -b branchname origin/branchname 在遠程分支的基礎上,分化出一個新的分支並切換; git checkout -b [本地分支名] [遠程名/分支名] == git checkout --track [遠程名/分支名]

跟蹤遠程分支

從遠程分支checkout 出來的分支被稱爲跟蹤分支,是一種和某個遠程分支有直接聯繫的本地分支;在跟蹤分支中使用git push or git pull,git會判斷應該向哪個服務器的哪個分支推送or拉取數據;

克隆倉庫clone時,git自動創建一個名爲master 的分支來跟蹤origin/master,可使用--track簡化;

刪除遠程分支

git push [遠程名] : [遠程分支名] 刪除遠程服務器上的某個分支;

分支的變基 (NICE)

將一個分支的修改整合到另一個分支上有兩種方法: rebase,merge

基本的變基操作

git rebase --abort 變基衝突,回退所有的變基操作;

git rebase --continue 合併衝突後的繼續變基;

最初分叉的提交歷史

如果使用merge,三方合併(C2基,C3快照,C4快照),會產生一個新的基於兩個祖先的提交對象節點(C5);

通過合併一個分支來整合分叉了的歷史

rebase可以將C3裏產生的變化補丁 在C4的基礎上重新打一遍,即一個分支裏提交的變化移到另一個分支裏重新放一遍,git中操作叫變基;

git checkout experment,git rebase master

首先回到兩個分支最近的共同祖先,根據當前分支(也就是要進行變基的分支experiment)後續的歷次提交對象(C3,)生成一系列文件補丁,然後以基底分支(也就是主幹分支master)最後一個提交對象(C4)爲新的出發點,逐個應用之前準備好的補丁文件,最後會生成一個新的合併提交對象(C3`),從而改變experiment的提交歷史,使它成爲master的直接下游;

把 C3 裏產生的改變到 C4 上重演一遍

回到master分支,進行一次Fast-Forward合併;

master 分支的快進

變基的好處

變基可以產生一個更爲整潔的提交歷史;一般使用變基的目的,是想得到一個能在遠程分支上乾淨應用的補丁,按照每行的修改次序重演一遍修改;(實際上是把解決分支補丁最新主幹代碼之間衝突的責任,劃轉爲由提交補丁的人來解決;這樣維護者不需要做任何整合工作,只需要根據你提供的倉庫地址做一次快進合併,或者直接採納你提交的代碼)

情景分析

從一個特性分支裏再分出一個特性分支的歷史

決定將client分支中的修改(C8,C9)併到master中,跳過server分支直接放到master分支中重演一遍,--onto 指定新的基底分支;

git rebase --onto master server client : 取出client分支,找出client分支和server分支的共同祖先之後的變化,然後把它們在master上重演一遍;

將特性分支上的另一個特性分支變基到其他分支

快進合併master分支,包含client分支的變化;git checkout master,git merge client

快進 master 分支,使之包含 client 分支的變化

將server分支的變化也包含過來,將server變基到master git rebase master server

git rebase [主幹分支] [特性分支] 不需要切換分支的情況下,取出特性分支server,在master分支上重演;

在 master 分支上變基 server 分支

再次快進合併,刪除特性分支 git branch -d client,git branch -d server

 最終的提交歷史

變基的風險

準則:

一旦分支中的提交對象發佈到公共倉庫,就千萬不要對該分支進行變基操作

在進行變基的時候,實際上拋棄了一些現存的提交對象而創造了一些類似但不同的新的提交對象;如果你將原來分支中的提交對象發佈出去,並且其他人更新下載後再其基礎上開展工作,而稍後你又用git rebase拋棄這些提交對象,把新的重演後的提交對象發佈出去的話,合作者們就必須重新合併他們的工作,當你再次從他們那獲取代碼時,就會一團亂;

如:獲取遠程倉庫的代碼,並提交幾個提交對象;

克隆一個倉庫,在其基礎上工作一番

合作者提交變化C2,合併他自己的分支提交對象C5得到新的提交對象C6,推送到遠程;當你抓取併合併到本地的開發分支,顯示:

抓取他人提交,併入自己主幹

接下來,推送C6的人決定用變基取代之前的合併操作;繼而又使用git push --force覆蓋了服務器上的歷史,得到C4`,而之後你再從服務器上下載最新提交後,得到:

有人推送了變基後得到的 C4',丟棄了你作爲開發基礎的 C4 和 C6。

你獲取遠程數據合併後,此時C4`和之前的C4的sha1值完全不同,git會當做新的提交對象處理,而C7中已經包含了C4的修改內容,於是合併操作會將C7和C4`合併成C8;

你把相同的內容又合併了一遍,生成一個新的提交 C8

所以把變基當成一種在推送之前清理提交歷史的手段,而且僅僅變基那些尚未公開的提交對象,就沒問題;

繞過 clean 的切換分支;

  • stashing commit amending; git stash

git工作流

集中式工作流

一箇中心庫,開發者pull,push;

集成管理員工作流

github網站的開發流,每個開發者有自己的公共倉庫,pull request由維護者處理你提交的更新;

司令官和副官工作流

大型項目使用,dictator(司令官)合併lieutenant(副官)的分支,副官合併零散的特性分支,司令將集成後的分支推送到共享倉庫中,其他開發者以共享倉庫爲基礎衍合;

衍合與挑揀(cherry-pick)的流程(對應於sourcetree的遴選)

查看不同分支diff命令

git diff master...contrib ...語法,加在原始分支(擁有共同祖先)和當前分支之間;

cherry-pick

也可以保持線性的提交歷史;類似於針對某次特定提交的衍合,首先提取某次提交的補丁,然後試着應用在當前分支上;如果某個特性分支上有多個commit,你只想引入其中之一就可以使用這種方法;

挑揀(cherry-pick)之前的歷史

master中git cherry-pick e43a6fd3e94888d76779ad79fb568ed180e5fcdf 引入另一個分支挑揀一些提交對象進行應用;

挑揀(cherry-pick)之後的歷史

交互式暫存

交互式命令,幫助你方便的構建至包含特定組合和部分文件的提交對象,確保你的提交在邏輯上劃分爲相應的變更集;

git add -i or git add -interactive git進入一個交互式的shell模式;

顯示暫存區,類似與sourcetree中的挑選某些提交對象暫存;

儲藏(Stashing)

  • git stash 不想提交你正在進行中的工作,所以儲藏這些變更,往堆棧中推送一個新的儲藏;執行後工作目錄就clean了,可以方便的切換到其他分支上;你的變更都保存在棧上;

  • git stash list 查看現有的儲藏;

  • git stash apply 默認應用最近儲藏,git stash apply stash@{2}應用指定的儲藏;

    • git stash apply --index 對文件的變更被重新應用,但是被暫存的文件沒有重新被暫存,帶–index 來重新應用被暫存的變更;
  • git stash drop 移除儲藏;

  • git stash pop 移除儲藏,並應用儲藏;

獲取你工作目錄的中間狀態,也就是你修改過的被追蹤的文件和暫存的變更(modified類型),並將它保存到一個未完結變更的堆棧中,隨時可以重新應用;

取消儲藏

git stash show -p stash@{0} | git apply -R 取消某個stash的應用;

git stash show -p | git apply -R 沒有指定具體的儲藏,會選擇最近的儲藏;

從儲藏中創建分支

git stash branch branchname 創建一個新的分支,檢出你儲藏工作時的所處的提交, 重新應用你的工作,如果成功,將會丟棄儲藏;可以恢復儲藏的工作然後在新的分支上繼續當前的工作;

重寫歷史

改變最近一次提交

  • 改變提交說明
  • 改變快照內容;

git commit --amend 修改最後一次提交說明

修改多個提交說明

可以使用交互式rebase來衍合一系列的提交到它們原來所在的HEAD上而不是移到新的;

git rebase -i HEAD~3 指明你想要的修改的提交的父提交,衍合命令(HEAD~3…HEAD範圍內的每一個提交都會被重寫,不要涵蓋已經推送到遠程的提交,因爲其他開發者可能基於之前提交作爲基礎開發;);

rebase順序爲 1,2,3,從上到下,最底部爲最後一次提交對象;不同於log的記錄順序,最近的位於最上方;

  • p pick: 使用當前commit;

  • e edit: 使用當前commit,停止修改;

  • s squash(壓扁): 使用當前commit,和先前的commit合併;

將某次commit 前方的 pick 改爲 edit ,可多次修正提交內容;之後多次

git commit --amend , git rebase --continue;完成對多個提交的修改;

重排提交和刪除提交

修改commit的順序和刪除某些commit對象;直接使用vim 將多個文件交換位置,和刪除某些節點;

squash壓扁提交

交互式的衍合可以將一系列的提交壓爲單一提交; 指定某一提交前爲squash,git會同時應用那個變更和它之前的變更並將提交說明歸併;

拆分提交

撤銷一次提交,多次部分的暫存或提交直到結束;rebase -i腳本中對commit對象使用edit;
那裏你可以用git reset HEAD^對那次提交進行一次混合的重置,這將撤銷那次提交併且將修改的文件撤回。此時可暫存並提交文件,直到你擁有多次提交,結束後,git rebase --continue;

原歷史記錄
pick f7f3f6d changed my name a bit
edit 310154e updated README formatting and added blame
pick a5f4a0d added `cat-file`

退出命令後,先應用第一次提交f7f3f6d,後進入edit;
git操作;
$ git reset HEAD^
$ git add README
$ git commit -m 'updated README formatting'
$ git add lib/simplegit.rb
$ git commit -m 'added blame'
$ git rebase --continue

應用後最後一次提交a5f4a0d,提交歷史:
$ git log -4 --pretty=format:"%h %s"
1c002dd added `cat-file`
9b29157 added blame
35cfb2b updated README formatting
f3cc40e changed my name a bit

與rebase一樣,確保不包含已經推送到共享倉庫的提交;

核彈級選項filter-branch

使用腳本的方式修改大量的提交;

從所有提交中刪除一個文件

git filter-branch --tree-filter 'rm -f passwords.txt' HEAD

--tree-filter 每次檢出項目時先執行指定的命令然後重新提交結果;

將一個子目錄設置爲新的根目錄

git filter-branch --subdirectory-filter 子目錄名 HEAD

全局性地更換電子郵件地址

$ git filter-branch --commit-filter '
    if [ "$GIT_AUTHOR_EMAIL" = "schacon@localhost" ];
    then
            GIT_AUTHOR_NAME="Scott Chacon";
            GIT_AUTHOR_EMAIL="[email protected]";
            git commit-tree "$@";
    else
            git commit-tree "$@";
    fi' HEAD

最後

項目還是推薦使用sourceTree等圖形化工具吧;

兩個重點:

  • git要常用分支;
  • 使用rebase -i 交互性的變基 可產生線性的提交歷史,更直觀;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章