---
# System prepended metadata

title: git 操作跟觀念
tags: [git]

---

# git 操作跟觀念

## 最重要的concept
- 所有紀錄檔案都可以在.git底下找到
- <font color="#f00">head決定現在的位置,head跟branch一樣都是一個指針指到某一個commit,head決定現在的branch在哪</font>
- <font color="#f00">checkout回去到某一個commit,很容易發生斷頭,若想在某一次commit作更改,記得要開一個branch並且checkout過去來紀錄</font>
- info底下有一個exclude檔案,功用類似.gitignore,但不會push到遠端被別人看到你阻擋哪些東西上傳到遠端
- objects存放各個object的地方
- branchs紀錄branch
- refs放heads跟tag,heads此資料夾底下放各個branch的head




branch就像是一個tag連接在commit身上而已,但跟一般tag不同的是當你在此branch上commit時,branch會跟著你的commit前進
而相對於branch,tag單存是跟某一個commit綁在一起的,並不會跟著commit往前而有所變動

### git 儲存方式
- git並不是利用diff的方式來紀錄每一個commit,而是針對每一個commit裡有跟動過的檔案,自己額外會在作sha壓縮並且存放在.git/object底下
- 當檔案太大或有commit推到遠端的時候,git才會利用diff的方式對資料進行壓縮,減少空間利用

### 查看objects
可以利用
```shell=
git cat-file -p ${sha value}
#可以得到裡面的value
git cat-file -t ${sha value}
#可以得到所屬型態
```

.git/objects/底下會使用前兩個sha的value當作資料夾名稱,裡面檔案名稱則是剩下的sha value,因此當你要得到sha value,必須將資料夾名稱跟此資料夾中的檔案名稱相加起來


### 4 git type
下面這幾個type都紀錄在.git/objects/底下
- blob:物件內容
- tree:資料夾,內容會指到資料夾裡面的物件(可能有多個物件,故此檔案可能有多行)
- commit:也是一個檔案會指到所有跟此commit有關的檔案
***指到的意思:在檔案中會存著這些資料的sha value
- tag:針對某一個commit給一個標籤

### tag
<font color="#f00">常使用在設立某一個里程碑</font>
```shell=
#列出所有標籤
git tag -l "v1.8.5*"
#針對現在這個commit
#big treasure只是一個tag,{$commit content}是commit內容
git tag -a big_treasure -m {{$commit content} ex:"這個commit真棒"}
#針對過去的commit貼標籤
git tag -a v1.2 9fceb02
#將tag貼到遠端
git push origin v1.5
#將所有tags貼到遠端
git push origin --tags
#在某個標籤上開分支
git checkout -b version2 v2.0.0
```

### index
index就是save buffer(緩衝區,在add跟commit之間)
已經add但還沒commit之間會有一個buffer存放準備已經紀錄的資料
可以利用git ls-files查看已經紀錄哪些file進去

### others
- 當檔案為空的時候,"git add某個空的檔案"此指令並不會在.git/objects/下面再新增新的資料夾
- head可以利用@代替
- head前一個commit可以使用此符號@^作代替


## 回到merge,rebase(危險操作)之前的狀態
<font color="#f00">如果才剛merge或rebase可以使用</font>
ORIG_HEAD是在做merge或rebase之前,git會先把head的狀態存在這個到ORIG_HEAD
因此可以利用此方法回溯到危險動作之前的狀態
```shell=
git reset ORIG_HEAD --hard
```

### 想修改最新一次的commit 名稱
```shell=
git commit --amend -m "xxxx"
```
<font color="#f00">注意:對於不同branch,最新的commit都算是自己branch上的</font>

### branch

```shell=
git branch ${name}
#checkout到那個branch
git checkout ${name}
#delete this branch 
git branch ${name} -d 
#在當前此branch merge 其他的branch
git merge ${branch name}
```

### git stash
有時會不想commmit,但必須立馬切換到某一個commit,這時可以使用stash方式暫時把修改的東西暫存起來
```shell=
#存到stash stack裡面
git stash
#列出所有stash的紀錄
git stash list 
#pop出,2換成自己要的數字
git stash pop stash@{2}
#確定不要的
git stash drop stash@{0}
#這個跟pop不一樣的地方在於他不會從stash stack裡刪除,但pop會,所以stack裡面還會有一份
git stash apply stash@{0}
```

### calculate sha value
```shell=
cat ${filepath} | git hash-object --stdin
```

### git alias
```
#put this code on ~/.gitconfig
[alias]
    ll = log --graph --pretty=format:\"%h <%an> %ar%n        comment: %s%n\"
    la = log --graph --oneline --all
    ls = log --graph --oneline
```

### log
顯示所有commit
```shell=
git log --oneline
```

### diff
```shell=
#比對兩個commit
git diff ${commit id} ${commit id}
#比對目前目前HEAD所指的這個commit之間跟此commit id之間的差異
git diff ${commit id}
#比對工作目錄跟暫存區之間的差異
git diff
#目前暫存區與HEAD所指向的那個commit之間的差異。
git diff --cached 
```

### pull
```shell=
git add .
git commit -m "自訂的檔案名稱"
git pull oringin master
```


### push
```shell=
git add .
git commit -m "自訂的檔案名稱"
git push oringin master
```

### 想要將某一個東西(或修改)加入到最新的commit
有時會忘記有些東西要加入到前一次commit中(最新的commit),這時可以利用下面此方法加進去
```shell=
git add ${filepath}
#no-edit代表不要改變git commit 訊息
git commit --amend --no-edit
```
###### tags: `git`
