---
# System prepended metadata

title: Git操作筆記
tags: [Git]

---

---
title: "Git操作筆記"
description: "Git操作筆記"
# image: https://hackmd.io/screenshot.png
tags: Git
# robots: noindex, nofollow
langs: zh-Hant
---

# Git操作筆記
[toc]

## 新建Git專案
可以使用`git branch -a`命令得知在Git初始化階段主分支尚未被建立，因使用`git checkout -b <branch_name>`時並不會創建新分支，而是更改未來的主分支名稱。

### 新的本地端 -> 新的遠端
GitHub為例(主要分支名為`main`)：
```bash
git init -b main
git remote add origin <your repository link>
git add .
git commit -m "Initial commit"
git push -u origin main
```

## 新的遠端 -> 新的本地端
GitHub為例(主要分支名為`main`)：
```bash
git init -b main
git remote add -f -m main origin <your repository link>
git checkout -b main -t origin/main
``` 

## 客隆遠端儲存庫
進行協作，先在目前資料夾路徑cloone遠端儲存庫
```bash
git https://github.com/[UserID]/[projetID].git .
```

## 新增多個遠端儲存庫(一次 Push 到多個遠端)
```
git remote set-url origin --push --add <遠端路徑>
```

## 移除目前git對目錄的追蹤
```
git rm -r --cached <your directory>
```

## Branch

### 建立branch
1. 創建本地branch並新增對應的遠端branch
   ```bash
   git checkout -b new_branch # 建立 local branch
   git push -u origin new_branch # 建立對應的遠端 branch
   ```
2. 根據遠端branch建立對應的本地branch
   ```bash
   git checkout origin/new_branch -b new_branch # 建立 local new_branch 並與遠端連接
   ```

### 切換branch
```bash
git checkout branch_name
```

### 合併branch
1. 強制不使用fast-forward來合併
   ```bash
   git merge -m "merge commit message ..." --no-ff otherBranch # 不使用fast-forward
   ```

### 刪除Branch
1. 本地Branch
   ```bash
   git branch -d <branch_name>
   git branch -D <branch_name> #強制刪除
   ```
2. 遠端Branch
   ```bash
   git push -d origin <branch_name>
   ```

### 設定Branch 的 upstream
```bash
git branch <branch_name> -u <remote_name>/<branch_name>
```

## Commit

### 撤銷Commit
1. 直接刪除本地的1個Commit,並強制更新至遠端
   option :
   - --soft : 緩存區和工作目錄都不會被改變。
   - --mixed :默認選項。緩存區和你指定的提交同步，但工作目錄不受影響。
   - --hard : 緩存區和工作目錄都同步到你指定的提交。
   ```bash
   git reset <option> HEAD~1
   git push origin -f
   ```
2. 創建新的Commit並在其中撤銷1個Commit的更改
   ```bash
   git revert HEAD~1
   ```

## Tag

### 重新命名標籤
```bash
git tag new old
git tag -d old
git push origin :refs/tags/old
git push --tags
```

### 刪除標籤
```bash
git push --delete origin <tagName> #遠端
git tag -d <tagName>
```

## Stash (擱置)

### 創建擱置
```
git stash save [message]
```

### 顯示擱置清單
```
git stash list
```

### 恢復到最新的擱置，或恢復到指定擱置
```
git stash pop [stash ID]
```

### 刪除最新的擱置，或刪除指定擱置
```
git stash drop [stash ID]
```

### 刪除所有擱置
```
git stash clear
```

## Sub Module

### 增加 submodule
```
git submodule add <.../Author/repo.git> <dir/repo>
```
### 更新 submodule
初始化更新
```
git submodule update --init --recursive
```
之後更新
```
git submodule update --recursive --remote
```

### 移除 submodule
```
git submodule deinit the_submodule
git rm the_submodule
# Unix
rm -rf .git/modules/path_to_submodule
# PowerShell
rm .git/modules/path_to_submodule -r -fo
```

### Reset submodule
```
git submodule deinit -f .
git submodule update --init --recursive
```

## Squash (壓縮)
將多個commit壓縮成一個提交記錄。

### Merge Squash
用於合併不同分支時，希望在合併後只有一個提交記錄。
```
$ git merge —-squash <branch_name>
```
### Rebase Squash
合併本地端所在分支的提交紀錄，用於整理自己的開發歷程。
```
$ git rebase -i <shl-1>
```
> 可使用`git log —-oneline`查看目前提交記錄

## Cherry pick

### 在原始提交消息中附加`(cherry pick from commit ...)`並合併提交
```
git cherry-pick -e -x <commit>
```

### 從commit選擇某些檔案的更改
Get the commit
```
git cherry-pick -n <commit>
```

Unstage everything
```
git reset HEAD
```

Stage the modifications you want to keep
```
git add <path>
```

Make the work tree match the index
```
# (do this from the top level of the repo)
git checkout .
```

## 使用git worktree簡單部署到GitHub頁面
```bash
git checkout --orphan gh-pages #建立並切換本地孤立分支 gh-pages
git reset #清除內容索引
git commit --allow-empty -m "Initial commit" #創建空的初始commit
git checkout --force master #強制切換本地分支 master，消除有關孤立分支覆蓋文件的警告
git worktree add <folderPath> gh-pages # 新增一個子目錄到worktree，並成為gh-pages分支

#...產生文件到子目錄...

cd <folderPath> #切換至子目錄，即切換至gh-pages分支
git add --all #文件加入暫存區
git commit -m 'commit message' #創建commit
git push #推送至遠端
cd .. #切換回工作目錄
```

## 上游Git：保持最新並做出貢獻

新增upstream git
```
git remote add upstream <git link>
```
獲取上游git最新進度
```
git fetch upstream
git fetch upstream --tags # If the project has tags
```
本地 git master 分支為上游git鏡像
```
git checkout master
git merge upstream/master
```

當您想與上游維護人員分享一些工作時，您將創建一個功能分支。如果您滿意，請將其推送到您的遠程存儲庫。

您也可以使用rebase，然後merge以確保上游有一組乾淨的提交（理想情況是一個）來評估：
```
git checkout -b feature-x
#some work and some commits happen
#some time passes
git fetch upstream
git rebase upstream/master
```

如果你需要將一些提交壓縮成一個，你可以在這一點上使用[rebase interactive](https://www.atlassian.com/git/tutorials/rewriting-history/git-rebase)

完成上述步驟後，只需簡單推送即可在遠程fork中發布您的工作：
```
git push origin feature-x
```

如果您在發布遠程分支功能後，因為上游維護人員提供了一些反饋必須更新遠程分支功能-x，則會出現一個小問題。你有幾個選擇：
- 使用您和上游的更新創建一個新分支。
- 在本地分支合併來自上游的更新，這將記錄合併提交。這將使上游存儲庫混亂。
- (建議使用)在上游更新的基礎上Rebase本地分支，並強制推送到遠程分支：
  ```
  git push -f origin feature-x
  ```
  
## Gerrit
  
### 拉取Patchset
```sh
# list changes
git ls-remote
# fetch patchset 1 of change 10647
git fetch <repo> refs/changes/47/10647/1
# checkout new branch as the patchset
git checkout -b <branch> FETCH_HEAD 
```
  
## 修改先前commit (before HEAD)
```
# if to modify commit bbc643cd
git rebase --interactive bbc643cd~
```
  
在預設編輯器中，在提到`bbc643cd`的行中修改`pick`為`edit`, 儲存文件並退出。

git 會移到`bbc643cd`提交，執行以下命令進行更改
```
git commit --amend
```

更改完畢後執行以下命令返回HEAD
```
git rebase --continue
```

提交更改到Gerrit
```
git push origin HEAD:refs/for/<target-branch>
```