git筆記

這篇是看完高見龍的「為你自己學git這本書」紀錄的筆記
有興趣可以找原書來看

 

terminal操作
cd 切換目錄
cd 取得目前所在位置
dir 列出目前檔案列表
mkdir 建立新目錄
copy 複製檔案
move 移動檔案
del 刪除檔案
cls 清除畫面內容
ls 列出目前所有檔案跟目錄
cp oldfile newfile 複製一份檔案
mv oldfile newfile更改檔案名稱
rm filename 刪除檔案
rm *.html 刪除所有html擋

 

vim指令
Normal模式>Insert模式
i=insert
a=append
o=new line
:w存檔
:q離開
:wq存檔然後離開
Esc或ctrl+[ 返回normal模式

Git指令


1.設定名稱跟mail
git config --global user.name "kuan"
git config --global user.email "kuan@gmailc.oom"
檢視設定
git config --list
也可以在使用者資料夾下的.gitconfig直接改

若是要每個專案設定不同使用者
在專案目錄下 改成用--local設定

2.
設定縮寫
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.st status

EX:輸入git co ==git checkout

git config --global alias.l "log --oneline --graph"
縮短原來比較長的指令

3.git status 看狀態
untracked files 檔案剛被加入 還沒被追蹤

sourcetree用右鍵add git開始追蹤
untracked files > Staging Area暫存區
可以用git add -all ==git add .
或git add *.html指定

git add -all不管在專案哪個目錄執行都會加入暫存區
git add .只會把當下目錄跟子目錄的加入

4.commit後才會存到repository
只會處理暫存區Staging Area的檔案

git commit --allow-empty -m 'empty commit'
這樣可以做空的commit出來,不需要改檔案

5.工作目錄>暫存區>儲存庫
可以git commit -a -m 'message'
跳過add的步驟
但是只限於已存在repository的檔案
untracked file是無效

6.git log看紀錄
時間 作者 commit做了什麼
也可以用git log --oneline --graph看比較精簡的內容

指定作者是誰
git log --oneline --author="Sherly"

找commit訊息有符合條件的 使用--grep
git log --oneline --grep="WTF"

查指定時間或日期
git log --oneline --since="9am" --until="12am" --after="2017-01"

sourcetree也有工具可以搜尋


7.刪除git rm filename
跟手動刪除相比不需要再git add
加上--cache可以讓檔案不被git 控制
變成untracked的

8.改名
git mv oldfile newfile
狀態會是renamed

9.修改commit訊息
可以用git rebase修改
get reset拆掉 再重新commit
git commit --amend -m "要修改的訊息" (只能處理最後一次)

10.把新增的檔案加到最後一次commit裡

一樣要先add
然後
git commit --amend --no-edit
--no-edit表示不要編輯commit訊息

sourcetree commit是用Amend last commit


11.如果在.gitignore檔案存在之前就已存在的檔案
不會被忽略
可以使用git rm --cached把這些檔案移出控管

12清除被忽略的檔案
git clean -fx

13.看檔案的commit紀錄
git log filename
 -p看實際變動內容
 
14.看檔案某一行是誰寫的
git blame filename 
會顯示每次commit的識別碼跟作者
sourcetree右鍵Annotate Selected

15.把刪掉的檔案復原
git checkout filename
git checkout . 把全部被刪的救回來

sourcetree可以右鍵discard救回

這指令會把檔案回復到上一次commit的狀態

git checkout HEAD~2 .
拿距離現在兩個版本以前的檔案來覆蓋現在⼯作⽬錄的檔案,同時也更
新暫存區裡的狀態

16.拆掉最後一次的commit
相對方式
git reset HEAD^
get reset master^
表示前一次

倒退五次會寫成HEAD~5
reset可以想成前往

絕對
git reset 指定hash

17.reset的模式
mixed:把暫存區檔案丟掉,但不會動到工作目錄的檔案
soft :工作目錄跟暫存區的檔案都不會被丟掉,所以看起來就只有 HEAD 的移動
hard:不管是工作目錄以及暫存區的檔案都會丟掉

18.用hard reset之後再救回來
get reset 一開始的HEAD的SHA-1 --hard

19.git reflog
保留操作的紀錄
可以用SHA1值做reset

20.HEAD通常會指向目前所在分支
.git/HEAD檔案可以看到
分支就只是一個40位元檔案

21.可以只commit部分內容
git add -p filename
 
sourcetree 右鍵 Stage Selected Lines


22.git的物件
Blob(Binary large object 的縮寫):存放檔案內容,計算SHA-1值然後放在.git/objects裡面
Tree
Commit
Tag

echo "hello, 5xRuby" | git hash-object --stdin
cat config/database.txt | git hash-object --stdin
可以計算SHA-1值

git cat-file -t 30ab28d3acb37f96ad61ad8be82c8da46d0a7307
這指令可以看物件型態
-t改成-p可以看物件內容

23.檔案在git會以Blob物件方式存放
目錄跟檔案檔名會用Tree存放

Commit物件會指向某個Tree物件
Tree 物件的內容會指向某個或某些 Blob 物件,或是其它的 Tree 物件
除了第一個 Commit 物件以外,所有 Commit 物件都會指向它的前一次的 Commit 物件
Tag 物件(Annotated Tag)會指向某個 Commit 物件
分支雖然不屬於這四個物件之一,但它會指向某個 Commit 物件
當開始往 Git Server 上推送之後,在 .git/refs 底下就會多出一個 remote 的紀錄,裡面
放的是遠端的分支,基本上跟本地的分支是差不多的概念,同樣也會指向某個 Commit 物
件。


只要檔案內容是一樣,git裡面就會是同一個Blob物件

24.Tag掛在commit上


輕量標籤:
git tag tag名稱 SHA-1值(指定某個commit貼上)
如果後面沒指定就是貼在現在的commit
sourcetree可以在commit上按右鍵Tag>Advanced Options>Lightweight tag(not recommended)

有附註標籤:
git tag  tag名稱 -a -m "訊息"

有附註標籤主要用來做像是軟體版號之類的用途,而輕量標籤則是用來個人使用或是暫時標記用途
要刪除就git tag -d tag名稱

分支會隨著commit移動,但tag不會
都放在.git/ref目錄下


25.
git不是做差異備份
改一個檔案就會建一個Blob物件
Git會自動回收
或是用git gc指令
.git/objects的物件會打包到.git/objects/pack
會使用類似差異備份的方式,參照被打包的檔案

26.git branch 列出所有分支

新增分支git branch name
改名git branch -m oldname newname
刪除 git branch -d/-D name
切換git checkout name
切換如果不存在就新建git checkout -b name

27.
Git 在切換分支的時候,會用該分支指向的 Commit 的內容來「更新」暫存區(Staging
Area)以及工作目錄(Working Directory)。但在切換分支之前做的修改則還是會留在工
作目錄,不受影響

28.合併分支
先切到要被合併的分支
再git merge 來源分支

Fast Forward快轉模式合併
當只有master跟另一個分支的時候
不會製造出新的commit

git merge cat --no-ff
就不會用快轉模式合併

29.刪除分支
git branch -d或-D name

被刪除的分支如果要救回來
就要先找到它的commit hash值
然後跟建新分支一樣
git branch newbranch hash值

git reflog可以找SHA-1值
預設保留30天


30.另一種合併分支
git rebase
重新定義參考基準
它不會新建一個commit
而是把現在這個分支改接在另一個上面
把 cat 分支剪下來,然後貼在 dog 分支上面
p.170 會重新計算SHA-1

要取消rebase也是用reflog查SHA-1再reset切回去

31.危險記錄點ORIG_HEAD
git reset ORIG_HEAD --hard
會記錄分支合併或reset之前HEAD的位置

32.rebase有衝突的時後
先把檔案調整好
然後用git rebase --continue接續完成


33.合併的時候衝突用某個分支的為主

git checkout --ours cute_animal.jpg
git checkout --theirs cute_animal.jpg

34.HEAD縮寫@
git reset HEAD^
等同
git reset @^

35.如果想在過去commit上開分支
可以先git checkout SHA-1
再git checkout -b 分支名稱

等同於git branch 分支名稱 [要建分支的Commit SHA-1]

36.rebase指令模式
git rebase -i SHA-1值
選擇要調整的範圍
會開啟Vim編輯器
pick改成reword可以修改訊息
修改完再存檔離開

更改過的commit會建新的commit物件(SHA-1值不一樣)

squash可以合併commit(前一個)
pick是保留不做修改

edit可以拆掉commit成多個commit
會停在要拆的那個commit上
然後用git reset HEAD^ --hard拆掉
add、commit完後記得要git rebase --continue


要更新commit順序
一樣開啟指令模式,然後改pick的順序就可以

刪除commit
pick改成drop或直接刪除那行
P.191

37.Revert取消最後這次的commit
git revert HEAD --no-edit
no edit表示不編輯訊息
表示再做一個新的commit 取消不要的commit
會跟前一個commit反向操作
所以要刪掉的那個commit還會存在


38.
做到一半要暫存進度
第一種方法可以先commit
之後再回來用git reset拆掉

第二種可以用git stash暫存

git stash list
會顯示狀態
stash@{0}: WIP on cat: b174a5a add cat 2

WIP表示Work In Progress
會保存目前改的進度,然後回到上次commit的狀態

如果要把stash撿回來用
可以用git stash pop stash@{0}
會把某個Stash拿出來套用在目前分支上,然後那個Stash會被刪除
預設會從編號最小開始拿

不要的話可以用git stash drop stash@{0}

git stash apply stash@{0}
跟pop差別是不會刪除掉stash
pop = apply stash + drop stash


39.filter-branch過濾每個commit紀錄

想要刪除某個檔案
git filter-branch --tree-filter "rm -f config/database.yml"

--tree-filter可以執行我要的指令,執行完再自動commit
執行前會先備份狀態在.git/refs/original/refs/heads
再用reset --hard 復原回去
git reset refs/original/refs/heads/master --hard

但狀況如果是已經推出去的
git push -f強制推一份剛commit過得上去

斷乾淨的方法 不能復原:
(1)git filter-branch -f --tree-filter "rm -f config/database.yml"
強制覆寫備份點
(2)rm .git/refs/original/refs/heads/master 刪除備份點
(3)清掉log
git reflog expire --all --expire=now 讓log過期

git fsck --unreachable 檢查物件狀態
(4)啟動資源回收
git gc --prune=now


40.撿別的分支的commit來用
但不是合併整個分支

git cherry-pick SHA-1值

複製commit內容過來
也可以放多個commit的SHA-1值

sourcetree直接右鍵選cherry pick

加上--no-commit參數 不會直接合併 會先放在暫存區

41.detached HEAD斷頭

(1) 使用 Checkout 指令直接跳到某個 Commit,而那個 Commit 剛好目前沒有分支指著它。
(2) Rebase 的過程其實也是處於不斷的 detached HEAD 狀態。
(3) 切換到某個遠端分支的時候。

如果是第一種狀況,有新增或修改檔案
可以直接建一個分支指向他
git branch name SHA-1

第三種狀況
看遠端分支
git branch --remote
切到遠端分支的時候也會
如果不要detached HEAD狀態
可以加上--track或-tag
git checkout -t origin/refactoring

解除detached HEAD狀態只要切到某個分支就好


42.git push -u origin master
-u是upstream的意思
每個分支可以設定一個上游
會指向並追蹤某個分支

43.
git pull = git fetch + git merge

可以加上rebase
git pull --rebase

44.PR的做法
先Fork到自己帳號下
clone到本地端
做完push
再自己頁面按New pull request
發PR給原作者

原作者可以去pull request下面看
同意的話按Merge pull request合併commit

45.跟上fork專案的進度
git remote -v 看目前專案的遠端節點

現在要加上原作的遠端
git remote add dummy-kao https://github.com/kaochenlong/dummy-git.git
dummy-kao一般會用upstream來當遠端節點的名字

然後再fetch遠端原作專案
git fetch dummy-kao
git merge 回原本分支

46.刪除遠端分支
git push origin :cat 前面加:

git push origin master:cat
意思是把本地master分支推上去 在Server上建立Cat分支

47.製作更新檔
git format-patch SHA-1_Start..SHA-1_End
後面要放commit的紀錄 要更新的部分

或是
git format-patch -2
表示產生最近兩次commit的更新檔

-o可以指定檔按位置

使用更新檔要用git am指令(記得加副檔名)
使用前要先git am --abort取消之前匯入失敗結果

48.Git Flow流程
主要分支有master,develop,hotfix,release,feature
master:主要是用來放穩定、隨時可上線的版本。這個分支的來源只能從別的分支合併過來,開發者不
會直接 Commit 到這個分支。因為是穩定版本,所以通常也會在這個分支上的 Commit 上打上
版本號標籤

develop:這個分支主要是所有開發的基礎分⽀,當要新增功能的時候,所有的 Feature 分支都是從這個
分支切出去的。而Feature 分支的功能完成後,也都會合併回來這個分支

hotfix:從master分支開出來的,用來修緊急bug,結束後會合併回develop跟master

release:上線前最後測試用,develop合併過來,如果有修改會合併回develop
最後合到master

feature:新增功能的時候用的分支


https://nvie.com/posts/a-successful-git-branching-model/

sourcetree可以用git flow功能


49.移動分支位置
git branch bird 657fce7
在這個commit上建一個bird分支

git branch cat master
在master上的commit建cat分支
如果cat已存在 就要加上-f強制執行
原本的會被刪掉

50.在master上開發 要改在別的分支上開發

可以改分支名稱
先把HEAD移到別的地方 git checkout SHA-1
git branch -m cat tmp 把cat改成tmp
git branch -m master cat
git branch -m tmp master

51.如果在跑測試,但想要去做別的事 改專案或開發之類的

可以用git worktree add -b cat ../copycat
會建一個cat分支, 然後在專案的上層目錄建一個copycat目錄
操作跟原本一模一樣

52.
HEAD^^跟HEAD~2的差別
^2會往第2個parent commit移動 (取決於誰合併誰)
~2沒有 等同於^1^1=^^