git
===
###### tags: `git`, `gitlab`, `git-lab`, `github`, `git-hub`, `git-submodules`, `git lfs`, `git stash`
<br>
[TOC]
<br>
## 教學
- [用Git版本控制【Git的基本介紹】 | 連猴子都能懂的Git入門指南 | 貝格樂(Backlog)](https://backlog.com/git-tutorial/tw/intro/intro1_1.html)
- [Git 面試題](https://gitbook.tw/interview) :+1: :+1: :+1: :100:
<br>
## github
### token
> [Settings](https://github.com/settings/) > [Developer settings](https://github.com/settings/apps) > [Personal access tokens](https://github.com/settings/tokens)
- `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`

> To https://github.com/tsungjung411/test1.git
! [remote rejected] master -> master (refusing to allow a Personal Access Token to create or update workflow `.github/workflows/build.yml` without `workflow` scope)
error: failed to push some refs to 'https://github.com/tsungjung411/test1.git'
會有 error ,說明缺少 `workflow` 權限
- ### 參考資料
- Elyra
- [[github] Creating a personal access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token)
- [Support for password authentication was removed. Please use a personal access token instead](https://stackoverflow.com/questions/68775869)
### 上 code
- ### create a new repository on the command line
```bash=
echo "# test1" >> README.md
git init
git add README.md
git commit -m "first commit"
git branch -M main
git remote add origin https://github.com/tsungjung411/test1.git
git push -u origin main
```
- ### push an existing repository from the command line
```bash=
git remote add origin https://github.com/tsungjung411/test1.git
git branch -M main
git push -u origin main
```
<br>
### 上 code (new branch)
```
$ git checkout -b v0.2
```
- [3.2 使用 Git 分支 - 分支和合併的基本用法](https://git-scm.com/book/zh-tw/v2/使用-Git-分支-分支和合併的基本用法)
```
$ git push
fatal: The current branch v0.2 has no upstream branch.
To push the current branch and set the remote as upstream, use
git push --set-upstream origin v0.2
```
<br>
<hr>
<br>
## 指令
### git gc
- [Git Status Takes a Long Time to Complete](https://stackoverflow.com/questions/1183769)
<br>
<hr>
<br>
## 檔案
### .gitignore
- ### 標準範本
```.gitignore
# [folder] adding / on the end ignores entire directory paths
.ipynb_checkpoints/
# [file]
.*
__pycache__
```
- ### ml-sklearn 範本
```
.*
*.pkl
__pycache__/
!/.gitignore
image/workspace/
output
```
- ### 特別用法
```
*.py[cod]
```
- ### 保留檔案,但不要在追蹤 config.json
`git update-index --assume-unchanged config.json`
重新追蹤:
`git update-index --no-assume-unchanged config.json`
- ### [【狀況題】有些檔案我不想放在 Git 裡面…](https://gitbook.tw/chapters/using-git/ignore)
- [各種程式語言常見的 .gitignore 檔案](https://github.com/github/gitignore)
- 可以忽略這個忽略嗎?
```
$ git add -f 檔案名稱
```
- 將規則套用到先前檔案
```
$ git rm --cached
```
- 如何清除忽略的檔案?
```
$ git clean -fX
```
- ### [Rules for writing a .gitignore file](https://opensource.com/article/20/8/dont-ignore-gitignore)
1. Any line that starts with a hash (`#`) is a comment.
2. The `\` character escapes special characters.
3. The `/` character means that the rule applies only to files and folders located in the same folder.
4. An asterisk (`*`) means any number of characters (zero or more).
5. Two asterisks (`**`) specify any number of subdirectories.
6. A question mark (`?`) replaces zero or one character.
7. An exclamation sign (`!`) designates the inversion rule (i.e., it includes any file that was excluded by a previous pattern).
8. Blank lines are ignored, so you can use them to add space and make your file easier to read.
9. Adding `/` on the end ignores entire directory paths.
<br>
<hr>
<br>
## git branch
### 刪除 branch
- [Git Delete Remote Branch – How to Remove a Remote Branch in Git](https://www.freecodecamp.org/news/git-delete-remote-branch/)
- list branch
```
$ git branch
* master
v0.2
```
```
# include the remote branches
$ git branch -a
* master
v0.2
remotes/origin/HEAD -> origin/master
remotes/origin/master
remotes/origin/v0.2
```
- delete a local branch
```
$ git branch -d branch-name
```
- delete a remote branch in git
```
$ git push origin -d branch-name
```
<br>
<hr>
<br>
## git clone
- [Download a specific tag with Git](https://stackoverflow.com/questions/791959/)
### Q&A
- ### [使用git報錯error: RPC failed; HTTP 504 curl 22 The requested URL returned error: 504 Gateway Time-out](https://www.itread01.com/content/1547477469.html)
- 解決辦法,只需要加上--depth=1
- `git clone --depth=1 https://git.oschina.net/xxxxxx.git`
- ### error: RPC failed; curl 92 HTTP/2 stream 0 was not closed cleanly: CANCEL (err 8)
`$ pip install git+https://github.com/huggingface/transformers@cae78c46`
[](https://hackmd.io/_uploads/BkG3t1xRa.png)
- ### error
```
Cloning https://github.com/huggingface/transformers (to revision cae78c46) to /tmp/pip-req-build-4box977g
Running command git clone --filter=blob:none --quiet https://github.com/huggingface/transformers /tmp/pip-req-build-4box977g
error: RPC failed; curl 92 HTTP/2 stream 0 was not closed cleanly: CANCEL (err 8)
fatal: the remote end hung up unexpectedly
fatal: early EOF
fatal: index-pack failed
error: subprocess-exited-with-error
```
- ### 單獨 clone 測試 -> failed
```
$ git clone --filter=blob:none --quiet https://github.com/huggingface/transformers /tmp/pip-req-build-4box977g
error: RPC failed; curl 18 transfer closed with outstanding read data remaining
fatal: the remote end hung up unexpectedly
fatal: early EOF
fatal: index-pack failed
```
- `--filter=blob:none` 濾掉所有的 blob
允許你根據特定的過濾條件來克隆存儲庫。`blob:none` 表示在克隆過程中不下載任何 blob 對象(即文件內容),這可以顯著減少克隆大型存儲庫時所需的數據量。需要注意的是,這會導致克隆的存儲庫缺少實際的文件內容,直到需要時才會從遠端存儲庫中獲取。
- ### 嘗試解法
- [error: RPC failed; curl 92 HTTP/2 stream 0 was not closed cleanly: PROTOCOL_ERROR (err 1)](https://stackoverflow.com/questions/59282476/)
- `git config --global http.version HTTP/1.1`
- `git config --global http.postBuffer 157286400`
- #### 加大到 `http.postbuffer=1572864000` 才下載成功
- 加大後雖然可單獨下載成功
但原始指令 `$ pip install git+https://github.com/huggingface/transformers@cae78c46` 還是下載失敗
顯然 `http.postbuffer` 沒有套用到 pip install ?
- #### `$ du -hs` 才 170MB
- 170MB > 157MB (失敗)
- 170MB < 1.57GB (成功)
- #### 完整下載 transformer -> 還是 failed
```
$ git clone https://github.com/huggingface/transformers
Cloning into 'transformers'...
remote: Enumerating objects: 191301, done.
remote: Counting objects: 100% (22585/22585), done.
remote: Compressing objects: 100% (1789/1789), done.
error: RPC failed; curl 18 transfer closed with outstanding read data remaining
fatal: the remote end hung up unexpectedly
fatal: early EOF
fatal: index-pack failed
```
- 把 postBuffer 設成 5GB 才整包下載下來,但整包也才不過 288M
- 有點詭異的是:設成 1.57GB 時還是下載不下來,只有 5GB 才下載成功
- #### Q&A:
**為何我設定 http.postbuffer=1572864000,還是遇到同樣問題
當我設定 http.postbuffer=5572864000 (超過 5GB) 才成功
但是下載下來的整包 git 卻只有 288M
理論上 http.postbuffer=1572864000 不是應該可以下載成功?**
[ChatGPT4]
當設置 http.postBuffer 大小能夠解決克隆過程中的問題,但需要設置到非常大(例如超過 5GB)時,這通常指示著問題可能不完全是由於實際傳輸的數據量導致的。http.postBuffer 參數設定的是 Git 通過 HTTP 在推送(push)或拉取(pull)操作時允許的最大數據量大小。如果您遇到需要將其設置得異常大才能成功的情況,這裡有幾個可能的考慮因素:
1. **配置過大的問題**:將 http.postBuffer 設置得非常大(超過需要的數據大小)其實是一種權宜之計,並不直接解決導致錯誤的根本原因。如果下載的 Git 倉庫實際大小只有 288MB,那麼理論上遠小於 1.5GB 的 http.postBuffer 配置就應該足夠。
2. **網絡穩定性和質量問題**:這種情況可能更多地指向網絡層面的問題,如網絡穩定性、速度波動或是中間網絡設備(比如代理、防火牆)的處理方式,這些因素可能對大型 HTTP 請求造成影響。
3. **Git 服務器的限制**:在某些情況下,遠端 Git 服務器(例如 GitHub)可能對 HTTP 請求施加特定限制或處理方式,這可能會影響大型倉庫的克隆過程。雖然這類限制通常是透明的,但在極端情況下可能會對操作造成影響。
4. **克隆過程中的臨時數據**:在 Git 克隆過程中,**可能會生成大量的臨時數據**,尤其是當倉庫中包含大型文件或大量歷史提交時。即使最終克隆的倉庫大小不大,臨時數據的處理也可能需要額外的緩存空間。
5. **其他 Git 配置**:考慮檢查是否有其他 Git 配置參數可能對克隆過程有影響,例如 core.compression 等,這些設置可能影響 Git 數據的處理和傳輸方式。
如果您在解決類似問題時需要設置異常大的 http.postBuffer,建議進一步檢查網絡環境和配置,並考慮與您的網絡管理員或 Git 服務器的提供商溝通,以找到更根本的解決方案。此外,使用 SSH 克隆而不是 HTTPS 也可能是一個避免類似問題的替代方案。
- ### git config 還原設定
```
$ git config --global --unset http.version
$ git config --global --unset http.postbuffer
```
- 移除這兩項設定後,原本 gie cline 反而成功
`$ git clone https://github.com/huggingface/transformers`
- 手動 clone 下載後安裝
```bash
$ git clone https://github.com/huggingface/transformers
$ cd transformers/
$ git checkout cae78c46
$ pip install . # 安裝當前 project (pyproject.toml)
```
<br>
<hr>
<br>
## git clone (via git lfs)
### Q&A
- ### 如何下載大型檔案
- ### Question
```bash
$ git clone https://huggingface.co/liuhaotian/LLaVA-7b-delta-v0
Cloning into 'LLaVA-7b-delta-v0'...
remote: Enumerating objects: 19, done.
remote: Total 19 (delta 0), reused 0 (delta 0), pack-reused 19
Unpacking objects: 100% (19/19), 4.71 KiB | 689.00 KiB/s, done.
Filtering content: 100% (4/4), 4.56 GiB | 8.62 MiB/s, done.
Encountered 1 file that may not have been copied correctly on Windows:
pytorch_model-00001-of-00002.bin
See: `git lfs help smudge` for more details.
```
我要如何下指令,才能把 pytorch_model-00001-of-00002.bin 下載下來?
- ### ChatGPT3.5
當你在使用 Git 克隆一個包含大型文件(這些文件通常由 Git Large File Storage, Git LFS 管理)的儲存庫時,可能會遇到某些文件沒有被正確下載的情況。這種情況下,你可以使用 Git LFS 提供的命令來單獨下載這些文件。
首先,確保你已經安裝了 Git LFS。如果還沒安裝,可以訪問 Git LFS 官方網站 獲取安裝指南。
安裝 Git LFS 後,你可以執行以下命令來單獨下載遇到問題的大型文件:
```bash
git lfs pull --include="pytorch_model-00001-of-00002.bin"
```
這個命令告訴 Git LFS 單獨下載 `pytorch_model-00001-of-00002.bin` 文件。`--include` 選項後面跟著的是文件的相對路徑或者是一個模式,用來指定你想要下載的特定文件或文件群組。
如果你不確定文件的確切路徑,或者想要重新下載所有由 Git LFS 管理的文件,可以省略 `--include` 選項,直接使用:
```bash
git lfs pull
```
這樣會下載儲存庫中所有由 Git LFS 管理的文件。
注意,進行這些操作前,確保你的 Git LFS 初始化已經完成,可以使用以下命令確認:
```bash
git lfs install
```
這個命令只需要在你第一次使用 Git LFS 時執行一次,它會設置好 Git LFS 的必要鉤子(hooks)。
- ### ChatGPT4
當您遇到關於 Git LFS (Large File Storage) 處理大文件時的問題,如提示“Encountered 1 file that may not have been copied correctly on Windows”時,這意味著該大文件未能通過 Git LFS 正確下載。要解決這個問題,並嘗試重新下載未成功的大文件,您可以使用以下 Git LFS 命令:
確保您已經安裝了 Git LFS。如果還沒有安裝,您可以從 Git LFS 官網 下載並安裝它。安裝後,您可能需要運行 `git lfs install` 來啟用 Git LFS 支持。
然後,您可以使用以下命令來單獨拉取未成功下載的大文件:
```bash
git lfs pull --include="pytorch_model-00001-of-00002.bin"
```
這個命令告訴 Git LFS 單獨拉取指定的文件。`--include` 選項後面跟的是要拉取的文件的路徑。如果您位於克隆的倉庫目錄中,這條命令會嘗試重新下載並替換指定的大文件。
如果您想確保所有 LFS 管理的文件都已正確下載,也可以不使用 `--include` 選項,直接運行` git lfs pul`l。這會拉取所有 Git LFS 跟蹤的文件。
請注意,在使用 Git LFS 命令之前,確保您的 Git LFS 初始化正確,並且您的網絡連接穩定。如果在拉取過程中遇到任何問題,檢查您的網絡設置或 Git LFS 配置可能會有所幫助。
<br>
<hr>
<br>
## git submodule
### 操作方式
How to import 'twcc-sdk' module into your module?
```
your_module
│
├── twcc-sdk
│ ├── README.md
│ └── twcc
│ └ ...
└── workspace
├── twcc -> ../twcc-sdk/twcc (symbolic link)
└── demo.py
```
In your module root, executing the following commands to add the twcc-sdk module.
```bash
$> git submodule add http://10.78.26.44:30000/genome/twcc-sdk.git twcc-sdk
$> ln -s ../twcc-sdk/twcc workspace/twcc
#submodule info
$> cat .gitmodules
$> ls .git/modules/
```
After cloning your module, git submodule init & update are also required for submodules.
```bash
# clone your code
$> git clone ${your_module}
$> cd ${your_module}
${your_module}/$> git submodule init
${your_module}/$> git submodule update # this will clone the twcc-sdk module into the local
```
Pull the latest changes for the twcc-sdk module
```bash
${your_module}/$> git submodule update --recursive --remote
```
### 遞迴抓 code
```
git submodule update --init --recursive
```
### 刪除 submodule
有三個地方要清乾淨
- `.gitmodules`
- `.git/modules`
- `.git/config`
### 參考資料
- [git Submodule 使用時機](https://blog.wu-boy.com/2011/09/introduction-to-git-submodule/)
- [Pull latest changes for all git submodules](Pull latest changes for all git submodules)
```bash
git submodule update --recursive --remote
```
### usages
```
usage: git submodule [--quiet] [--cached]
or: git submodule [--quiet] add [-b <branch>] [-f|--force] [--name <name>] [--reference <repository>] [--] <repository> [<path>]
or: git submodule [--quiet] status [--cached] [--recursive] [--] [<path>...]
or: git submodule [--quiet] init [--] [<path>...]
or: git submodule [--quiet] deinit [-f|--force] (--all| [--] <path>...)
or: git submodule [--quiet] update [--init] [--remote] [-N|--no-fetch] [-f|--force] [--checkout|--merge|--rebase] [--[no-]recommend-shallow] [--reference <repository>] [--recursive] [--] [<path>...]
or: git submodule [--quiet] set-branch (--default|--branch <branch>) [--] <path>
or: git submodule [--quiet] set-url [--] <path> <newurl>
or: git submodule [--quiet] summary [--cached|--files] [--summary-limit <n>] [commit] [--] [<path>...]
or: git submodule [--quiet] foreach [--recursive] <command>
or: git submodule [--quiet] sync [--recursive] [--] [<path>...]
or: git submodule [--quiet] absorbgitdirs [--] [<path>...]
```
<br>
<hr>
<br>
## git stash
- 如果你有未提交的變更,先暫存起來
```
git stash -u -m "wip from detached HEAD"
```
- 回復暫存
```
git stash pop
```
<br>
<hr>
<br>
## git tag
- [使用標籤](https://gitbook.tw/chapters/tag/using-tag)
```
$git tag big_cats 51d54ff
```
```
$ git tag big_cats 51d54ff -a -m "Big Cats are comming"
```
- [How do you push a tag to a remote repository using Git?](https://stackoverflow.com/questions/5195859)
```
$ git push origin <tag_name>
```
- [How To Delete Local and Remote Tags on Git](https://devconnected.com/how-to-delete-local-and-remote-tags-on-git/)
- delete a local Git tag
```
$ git tag -d <tag_name>
```
- delete a remote Git tag
```
git push --delete origin tagname
```
- In some cases, your tag may have the same name as your branch.
```
$ git push origin :refs/tags/<tag>
```
- [對照] delete a remote branch in git
```
$ git push origin -d branch-name
```
- [遠端節點叫做 origin](https://gitbook.tw/interview)
<br>
<hr>
<br>
## 專案管理
### transfer project
- ### 作法
- Settings > General > Advanced > Transfer project
- 原本的 repository 需要更新源頭
To update the remote url in your local repository run (for ssh):
`git remote set-url origin ssh://git@10.78.26.44:30001/genome/one-genome.git`
or for http(s):
`git remote set-url origin http://10.78.26.44:30000/genome/one-genome.git`
- ### 參考資料
- [https://docs.gitlab.com/ee/tutorials/move_personal_project_to_group/#move-your-project-to-a-group](https://docs.gitlab.com/ee/tutorials/move_personal_project_to_group/)
<br>
### copy project
- ### [How to Duplicate a GitHub Repo with History](https://medium.com/javarevisited/how-to-duplicate-a-github-repo-with-history-e2e9b02d2ae)
- Step1:建立空的專案
- Step2:執行 git 指令
```bash
git clone --mirror ssh://git@10.78.26.44:30001/Tj_Tsai/my_project.git
cd my_project.git
git remote set-url --push origin ssh://git@10.78.26.44:30001/Tj_Tsai/my_project-copy.git
git push --mirror
```
- 查看 remote
```
$ git remote show
origin
```
```
$ git remote -v
origin ssh://git@10.78.26.44:30001/Tj_Tsai/my_project.git (fetch)
origin ssh://git@10.78.26.44:30001/Tj_Tsai/my_project-copy.git (push)
```
```
```
- ### 建立 repo 副本
- Step1:建立空的專案

- Step2:執行 git 指令
```bash
cp -a my_project/ my_project-copy/
cd my_project-copy
git remote remove origin
git remote add origin ssh://git@10.78.26.44:30001/Tj_Tsai/my_project-copy.git
git push -u origin --all
git push -u origin --tags
```
- `-u`, `--set-upstream`
For every branch that is up to date or successfully pushed, add upstream (tracking) reference, used by argument-less git-pull(1) and other commands. For more information, see `branch.<name>.merge` in git-config(1).
對於每個處於最新狀態或成功推送的分支,添加上游(追蹤)參考,這個參考會被 git-pull(1) 和其他命令使用,而不需要額外的參數。更多信息,請參考 `git-config(1)` 中的 `branch.<name>.merge`
- `--all`
Push all branches (i.e. refs under `refs/heads/`); cannot be used with other `<refspec>`.
<br>
<hr>
<br>
## 參考資料
- ### [Git從庫中移除已刪除大檔案](https://www.796t.com/content/1550269805.html)
- ### [pre-commit](https://pre-commit.com/)
A framework for managing and maintaining multi-language pre-commit hooks.
<br>
<hr>
<hr>
<br>
## Errors
### error: failed to push
- ### Question
```
$ git push
Enumerating objects: 6376, done.
Counting objects: 100% (6376/6376), done.
Delta compression using up to 4 threads
Compressing objects: 100% (6371/6371), done.
remote: fatal: pack exceeds maximum allowed size (500.00 MiB)
remote:
remote: ========================================================================
remote:
remote: stdin send error: EOF
remote:
remote: ========================================================================
remote:
error: remote unpack failed: index-pack abnormal exit
To ssh://10.00.00.00:30001/Tj_Tsai/my-datasets.git
! [remote rejected] main -> main (unpacker error)
error: failed to push some refs to 'ssh://git@10.00.00.00:30001/Tj_Tsai/my-datasets.git'
```
該如何處理?
- ### gpt-4o-2024-08-06
這個錯誤訊息表明你的 Git push 操作因為遠端倉庫的 pack 檔案大小超過了允許的最大值(500 MiB)而失敗。以下是幾個解決方法:
### 方法 1:拆分提交,減少推送大小
可以將大的提交拆分成多個小的提交,以減少每次推送的數據量。
1. **檢查提交日誌:**
使用 `git log --stat` 來檢查哪些文件較大,並且看看哪些文件可以拆分成多個較小的提交。
2. **重新提交較大的文件:**
如果你發現某些大的二進制文件或檔案夾,考慮使用 `git reset` 或 `git rm` 從歷史紀錄中移除,然後再次提交。
### 方法 2:增加遠端倉庫的限制
如果你可以修改遠端的配置,則可以考慮增加允許的 pack 檔案大小。執行以下命令來更改遠端倉庫的限制:
1. 登入遠端伺服器。
2. 修改 Git 的配置來允許更大的檔案推送:
"""
git config --global http.postBuffer 1048576000
"""
這會將 Git 的 `postBuffer` 限制提高到 1 GB。
### 方法 3:分割推送的對象
你也可以嘗試只推送部分內容。假設你不想一次性推送所有內容,可以這樣做:
1. **使用 `git push` 的範圍參數:**
使用具體的提交或範圍來推送某些部分,例如:
"""
git push origin <commit>
"""
### 方法 4:大檔案處理
如果你推送的大檔案是不能輕易移除的,可以考慮使用 Git Large File Storage (LFS) 來處理大型檔案:
1. **安裝 Git LFS:**
"""
git lfs install
"""
2. **將大檔案加入 Git LFS 管理:**
"""
git lfs track "*.bin" # 假設 .bin 是大檔案
"""
3. **重新提交大檔案並推送:**
"""
git add .gitattributes
git add <large-file>
git commit -m "Added large files to Git LFS"
git push
"""
### 方法 5:清理 Git 歷史
如果有過多的歷史提交增加了數據量,可以使用 `git filter-repo` 來清理歷史記錄中的大檔案:
1. **使用 `git filter-repo` 移除不必要的檔案:**
"""
git filter-repo --path <path-to-large-file> --invert-paths
"""
2. **重新推送乾淨的歷史:**
重新推送歷史記錄以減少數據量。
希望這些方法能幫助你解決問題!
<br>
### git commit 如何取消?
- ### Question
git push 還是不行
git commit 如何取消?
- ### gpt-4o-2024-08-06
## 如何取消 Git Commit
### 1. 取消最近的提交,但保留已更改的檔案 (Uncommit)
如果你想要**取消最近的提交**,但是保留所有已修改的檔案在工作區中(即你不會失去任何改動,只是把它們變回暫存狀態),你可以執行:
```
git reset --soft HEAD^
```
這個命令會將 HEAD 回退到上一個提交,保留所有的改動在暫存區中。
### 2. 取消最近的提交,並且將改動移出暫存區 (Uncommit and Unstage)
如果你想**取消最近的提交**,並且讓改動回到未暫存狀態,使用這個命令:
```
git reset HEAD^
```
這會回退到上一個提交,並將改動移到工作目錄中(也就是未暫存狀態),你可以選擇重新暫存或做其他處理。
### 3. 取消最近的提交並丟棄改動 (完全撤銷)
如果你想要**完全取消最近的提交並且丟棄所有改動**,你可以使用這個命令:
```
git reset --hard HEAD^
```
這會將 HEAD 回退到上一個提交,並且刪除所有的改動(這樣改動就無法恢復了)。
### 4. 取消尚未推送的多個提交
如果你已經做了多個提交,並且想取消這些提交,你可以使用 `git reset` 並指定要回退的提交數目。例如,假設你想取消最近的 3 次提交:
```
git reset --soft HEAD~3
```
這樣會回退到三次提交前的狀態,並保留所有改動在暫存區中。
### 5. 如果已經推送提交,並且遠端存在提交
如果你已經推送了這些提交到遠端並且需要強制取消它們,你需要在本地回退提交,然後強制推送:
```
git reset --hard HEAD^
git push --force
```
**注意:** 強制推送會覆蓋遠端倉庫中的提交,其他與這個倉庫合作的同事可能會遇到問題,請謹慎使用這個方法。
### 總結
- **保留改動但取消提交:** `git reset --soft HEAD^`
- **取消提交並且移到未暫存狀態:** `git reset HEAD^`
- **完全取消並丟棄改動:** `git reset --hard HEAD^`