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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` ![](https://i.imgur.com/UvOMvvQ.png) > 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)](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:建立空的專案 ![](https://hackmd.io/_uploads/BJ8R14C_a.png) - 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^`