在 Meta Quest 3 安裝 Google 注音中文輸入法完整教學 - 支援 2D 和 VR 應用程式 (全局輸入法)

-
更新於

前言

我覺得 Meta 不開放中文根本就是歧視中文母語使用者。內建鍵盤竟然沒有任何中文輸入法可以選擇,也無從安裝,安裝得用非常麻煩的方法,類似利用漏洞,真的很可惡。

明明底層是安卓系統,偏偏不開放直接讓人安裝 APK,故意把鍵盤設定拿掉,太噁心了。

啟用開發人員模式

我目前的 Meta Quest 3 版本號碼是 v77.0,先確定版本號沒問題再試。不確定未來會不會修掉,也許未來就不能改了,使用後記得要關閉更新。

首先,開啟手機上的 「Meta Horizon」 App,然後點自己頭盔的圖示按鈕。

頭盔要開機能和手機連線,接著點「頭戴式裝置設定」,再點「開發者模式」,啟用開發人員模式。

安裝能夠 side load APK 的軟體

我是使用「Mobile VR Station」,可以在商店中搜尋到。

安裝完後,點開,選擇 Android 配置精靈。

點顯示所有選項。

請求權限

這時候應該會有彈窗,都按允許,接著換下一個也點點看。

都開啟後,應該能夠開啟安卓內建的【文件】。

使用那個 App 到 Downloads 資料夾安裝 Quest助手(APK)。

https://quest.vrzwk.cn/

接著安裝各種輸入法的 APK,例如 Google注音輸入法 APK。

開啟 Quest助手

點開設定 App,這邊沒辦法截圖,就只能口頭說了,從【系統】,找到【鍵盤】,接著選擇啟用剛剛安裝的 Google注音輸入法。

然後,從 Quest助手中啟動 Google注音輸入法,點開,會提示彈出輸入法選單,直接選擇 Google注音輸入法。

然後重開機,就有全局 Google注音輸入法了。

完成

更新說明

似乎在 2025/06/04 的 v77.1027 版本中,這個功能被又拿掉了,底層系統現在叫不出切換輸入法的 UI 介面,萬惡的 Meta.,已經升級上去就沒救了。

這邊我有開發一款 App 可以在 Quest3 中使用注音輸入法,但只能在 App 中打好字後,用複製貼上的。畢竟底層不開放,就算真的 Support 輸入法功能也沒意義。

有需要可以到這裡下載:https://github.com/WeilJimmer/ChineseInputKeyboardVRApp

By Weil Jimmer


This entry was posted in Android, Experience, General, VR By .

[筆記] Git 儲存庫從 SHA256 降級為 SHA1 經驗

-
發布於

前言

昨晚心血來潮,用了 Gitea 建了一個儲存庫,那時候手賤選了 SHA256,想說要用最新的,結果當我寫完專案,想要備份到 Github 上,才發現推送不上去,跳出錯誤。


fatal: the receiving end does not support this repository's hash algorithm
fatal: the remote end hung up unexpectedly

看到關鍵詞 hash algorithm 就知道是選了 SHA256 的黑鍋。

如果遇到,最快的方式是直接建一個新專案,然後 add 全部代碼,然後 commit,這是最快的解法。

當時,就是想要保留歷史紀錄,結果找老半天,沒找到怎麼保留歷史紀錄轉換成 SHA-1 的方法,真的是爬很多資料,試了一堆方法。

下面分享我試成功的命令。

將 SHA256 專案轉成 SHA1 的格式

在 SHA-256 repo 中,export 紀錄。

cd original-repo
git fast-export --all --use-done-feature --reencode=yes > ../export.dat

建立 SHA1 的新專案

cd ../new-repo
rm -rf * .git  # 清空目錄
git init --object-format=sha1

匯入所有歷史紀錄

git fast-import --quiet < ../export.dat

重建 & 清理

git checkout main
git gc --aggressive

重新簽章(非必要)(Rebase)


git rebase --root -i --exec 'git commit --amend --no-edit -S'
# -i 代表互動模式
# --root 從第一個提交開始
# -S 代表用目前的 GPG key 簽署

By Weil Jimmer


This entry was posted in Experience, General, Git, Note By .

[筆記] WireGuard 架設伺服器

-
更新於

前言

最近要搞 Wireguard 才發現要弄這個好麻煩,之前做過的事都忘光光,在這裡留個筆記,下次直接抄。

伺服端

安裝套件

sudo apt install wireguard

生成私鑰

wg genkey | sudo tee /etc/wireguard/private.key
sudo chmod 600 /etc/wireguard/private.key

生成公鑰

sudo cat /etc/wireguard/private.key | wg pubkey | sudo tee /etc/wireguard/public.key

設定允許 IPv4 轉發

修改 `/etc/sysctl.conf`

sysctl net.ipv4.ip_forward=1

建立配置文件

sudo nano /etc/wireguard/wg0.conf
[Interface]
PrivateKey = 伺服端私鑰
Address = 10.6.0.1/24
DNS = 8.8.8.8
ListenPort = 51820

[peer]
PublicKey = 客戶端公鑰
AllowedIPs = 10.6.0.2/32
PersistentKeepalive = 25

對 Server 來說自己的 IP 為 10.6.0.1,客戶端 IP 為 10.6.0.2。

啟動指令

sudo wg-quick up wg0

關閉指令

sudo wg-quick down wg0

開啟端口 51820 的指令

sudo iptables -I INPUT -p udp -m udp --dport 51820 -j ACCEPT

客戶端

配置文件

[Interface]
PrivateKey = 客戶端私鑰
Address = 10.6.0.2/24
DNS = 8.8.8.8

[Peer]
PublicKey = 伺服端公鑰
AllowedIPs = 10.6.0.0/24
Endpoint = domain.net:51820
PersistentKeepalive = 25

對 Client 來說自己的 IP 為 10.6.0.2,伺服端 IP 為 10.6.0.1。並且,10.6.0.0/24 的路由會通過 wg0 的網路介面。

如果要設定全部流量則是把 AllowedIPs 設定成 0.0.0.0/0。

By Weil Jimmer


This entry was posted in General, Note, The Internet By .

使用 PVE 與 OpenWrt 23.05 實現鏈路聚合 LACP 及 VLAN 建立多個虛擬區域網路的踩坑經驗

-
更新於

前言

按照最近的慣例,開頭要先說一段廢話,最近因為家裡空間不夠放交換器,於是訂了一個機櫃,打算重新整理我亂七八糟的網線和複雜的網路環境,以及升級我的 OpenWrt 版本,下為我房間的機櫃照。

花了我滿長的時間在進行除錯,裝設機櫃反而沒什麼,最大的問題在於用 OpenWrt 設定 VLAN。

先前我灌了 ImmortalWrt 23.05.2,想說我之前裝的 OpenWrt 有點舊,而且還是當時的 SNAPSHOT 版本,已經遇到過好幾次要安裝什麼軟體包,出現內核版本過新或過舊的問題,實在不能接受,所以趁這個時機升級一下。

然後在 ImmortalWrt 安裝鏈路聚合所需要的軟體:

opkg update
opkg install kmod-bonding luci-proto-bonding

試了老半天,都沒有成功耶,在交換器那邊總是顯示 Blocking,害我在思考是不是交換器的問題,但是後來我在 NAS 上設置成功,所以我覺得是 ImmortalWrt 的問題。

直到一天後,我才終於意識到問題出在哪裡,在於那個被我遺忘的 PVE 阿!原來我一直錯怪了 ImmortalWrt。

因為底層是 PVE,我在虛擬機中設置鏈路聚合只是在它的虛擬網卡上聚合而已啊,所以應該在 PVE 上設置。

在 PVE 上建立 Linux Bond

首先到你的資料中心,然後選擇你的「節點」,再選擇 System → Network,點 Create 選擇 「Linux Bond」。

Slaves 輸入你想要聚合的網卡,我目前軟路由上有四張網卡,但我只選擇其中三張聚合,其中一張要給 WAN 使用,而且 PVE 也使用這張網卡,設定下去的話,會失去 PVE 的連線,因此我只選中三張。

模式就用 LACP,接著直接創建即可,之後你多出來一個 bond0 網卡,就是你聚合後的結果。

接著就到你的交換器上設定鏈路聚合(Link Aggregation, LACP),LACP 是我比較推薦的模式。

在 PVE 上建立 Linux Bridge

建立一個虛擬網橋 vmbr1,作為我的 LAN 區網用,這裡有一步驟很重要,那就是要把 VLAN aware 打勾。

回想起幾個月前,第一次在 ImmortalWrt 設定的時候,老是出問題,其實就是 PVE 沒設定好,那時候沒有打勾這個選項(我也根本沒注意到這選項),自然 VLAN 接口收不到封包阿。

到這步,PVE 設定完之後就沒 PVE 的事了。

開啟 OpenWrt 23.05

這次我安裝的版本是 OpenWrt 官方的 openwrt-23.05.3-x86-64-generic-squashfs-combined-efi.img。

手動裝了一些軟體包,比如主題 (Argon)、和繁體中文。

建立 VLAN 裝置

鑒於有了先前的經驗,基本駕輕就熟。直接到 網路 → 介面 → 裝置 → 加入裝置設定。

這邊直接選擇 VLAN (802.1q),預設值應該已經有了,新版本的 OpenWrt 已經拔掉了 Switch,所以很多文章和教學都過時了,很少人提到新版本的 OpenWrt VLAN 的設置。

VLAN ID,按照我這邊的環境,就是 10、20、30、40、50,直接重複五次,建好建滿。即使網路孔位沒有那麼多也沒關係,這邊已經虛擬化了。

像這樣,我建立了 VLAN 10~50 的網路裝置。

建立網卡介面

到「介面」列表,點「新增新介面」,靜態位址,選擇各自的 VLAN 裝置。

比如 LAN 配 eth0.10,LAN2 配 eth0.20,LAN3 配 eth0.30…

IP 的話,按照慣例,根據 VLAN TAG 定義 Gateway IP,VLAN 10 的話,設定 192.168.10.1/24。

然後是巨坑,防火牆要建立一個新的 Zone,如果沒設定防火牆是不會通的,沒有路由的話,DHCP Server 連分配 IP 都不會分配!

然後是必須的 DHCP 伺服器,直接點安裝即可。

這邊都不需要動,維持預設就可以了。

為了防止意外,建議開啟這個功能,「強制」DHCP,以防詭異的狀況發生。

建立防火牆規則

這裡就是老話重談了,為每個新創建的區域網路新增規則,允許轉發到 WAN。

我這邊比較特別,LAN 轉發到 WG0,是 VPN 通道,這個不是通常操作。而 LAN5,我是想建立一個隔離的網路,所以沒有轉發的能力。

建立 DNS 伺服器

建立好網路後,記得要在監聽介面打開剛剛新建的所有介面,否則即使有連線遠端 IP 的能力,卻沒辦法解析網域。

到這步,基本就大功告成。

接下來就是配置交換器,設置路由器所連接的 3 個 Port 為 TRUNK 接口。

同時給予其接口為 VLAN 10、20、30、40、50 的成員。

之後有空,會再補篇關於 VLAN 的基礎知識的文章。

By Weil Jimmer


This entry was posted in Experience, General, OpenWrt, The Internet By .

[筆記] Git 快速入門教學

-
更新於

前言

最近用 Git 用得很順手,但同事們都是用 SVN,不怎麼熟 Git,打這篇文章順便是幫自己複習,寫筆記作為紀錄以免自己忘記,也能順便讓他們當成教學。

簡介

Git 克隆下來的本機儲存庫,其結構通常是不僅僅有工作目錄(就是你的原始碼),也包含一個 .git 的隱藏資料夾,如下圖左側的橘色橢圓的「本機儲存庫」,即歷史紀錄。

而遠端儲存庫通常是沒有工作目錄的「裸」儲存庫,也就是 .git 資料夾內的內容。

Git 本機目錄,主要分為三個區域,工作目錄、暫存區、儲存庫。

  1. 工作目錄:需要被版本管控的內容,例如:程式原始碼、二進位資料等。
  2. 儲存庫:完整歷史紀錄(實際為 .git 資料夾),你可以理解成「精簡過 (不重複檔案)」的所有版本的所有程式碼快照內容。
  3. 暫存區:即將要被提交(commit)的內容,透過 git add 指令可以把內容加入到暫存區。

被提交過的內容,只要歷史紀錄還在,隨時都可以還原成各種版本,每次提交(commit)相當於一個快照,並且是去中心化的,即使離線也可以 commit。

常見的工作流程

  1. 修改工作目錄的原始碼。
  2. 儲存檔案到工作目錄。
  3. 使用 git add 將程式碼加入到暫存區。
  4. 使用 git commit 建立提交(類似快照)。
  5. 使用 git pull --rebase 將遠端儲存庫拉取最新進度合併。
  6. 最後用 git push 上傳到遠端儲存庫。

Commit

下面簡短圖說介紹 commit 流程。

Pull Rebase

簡單來講就是:拉取遠端紀錄,以遠端的紀錄優先,自己的變更加在遠端紀錄之後。後面在說明分支合併的時候會再介紹一次。

下面介紹各種指令。

常用指令

git clone

複製克隆一個倉庫。


git clone <repo_url> <folder_name>
git clone http://192.168.2.5/git/project.git project
git clone ./file/to/git/folder.git

git init

初始化一個倉庫,會自動建立 .git 資料夾。

git init

如果要建立裸倉庫當伺服端,需加上 --bare,此時建立的倉庫不存在工作目錄,也就是說即便有人提交內容,也並不會有原始碼。

git init --bare

git remote

查看遠端有哪些儲存庫,只下 git remote 通常只會看到遠端儲存庫的命名。

用下面的命令可以看到更完整的路徑。

git remote -v

添加新的遠端儲存庫。

git remote add <origin_name> <repo_url>

修改當前 origin 的遠端儲存庫的位置,如果伺服器 IP 有變,或網址有異動。

git remote set-url <orgin_name> <new_repo_url>

git log

查看目前的 commit 歷史紀錄。

git log

用下面的指令能看到比較完整的包含線圖的 log。

git log --oneline --graph

我在網路上有找到更加華麗的客製化命令。

git config --global alias.lg1 "log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold green)(%ar)%C(reset) %C(white)%s%C(reset) %C(dim white)- %an%C(reset)%C(auto)%d%C(reset)' --all"
git config --global alias.lg2 "log --graph --abbrev-commit --decorate --format=format:'%C(bold blue)%h%C(reset) - %C(bold cyan)%aD%C(reset) %C(bold green)(%ar)%C(reset)%C(auto)%d%C(reset)%n''          %C(white)%s%C(reset) %C(dim white)- %an%C(reset)'"
git config --global alias.lg lg1

顯示歷史紀錄中的簽章資訊,如果有用 PGP 簽名的話會顯示出來。

git log --show-signature

git fetch

抓取遠端儲存庫至本機儲存庫。

git fetch

如果要抓取所有遠端儲存庫的所有分支。

git fetch --all

如果也要抓取遠端儲存庫的所有標籤(Tag)。

git fetch --tags

git merge

合併分支

假如當前在 master 分支,要合併目標分支 branch_name。

git merge <branch_name>

要合併包括目標 commit 之前的所有提交。

git merge <commit_hash>

普通合併如下圖:

舉例:master 分支的紀錄是 A←B←C←D←E (HEAD),在 D 點開始分岔,產生新分支 feature,紀錄為 A←B←C←D←F←G (HEAD)。

在 master 上執行合併後,會產生 H 點,其父節點為 E、G,只有 master 包含 H 點提交,而 feature 分支不包含 H 點提交。

此時,master 上的分支紀錄變成 A←B←C←D←E←H (HEAD),而 feature 上的分支紀錄還是原本的紀錄:A←B←C←D←F←G (HEAD)。

如果不能快轉合併的話,這是 Git 的預設動作,下面介紹快轉合併。

快轉合併 (Fast-forward Merge)

快轉合併發生在目標分支的分岔點在來源分支中為 HEAD,來源分支分岔點之後正好沒有新的提交,那就可以進行快轉(快進)合併。

舉例:master 分支的紀錄是 A←B←C←D (HEAD),在 D 點開始分岔,產生新分支 feature,其紀錄為 A←B←C←D←E←F (HEAD)。

在 master 上執行後,通常是自動快轉合併,master 分支的 HEAD 會直接移動到 F,變成 A←B←C←D←E←F (HEAD)。兩條分支都會包含 E、F 點提交。

下面介紹 Rebase 合併。

git rebase

Rebase 合併能夠讓線圖呈現線性的,歷史線圖比較簡潔、清楚明瞭,在 commit 數量很大量、團隊人數很多,可能會導致線圖很亂的情況下,推薦採用這個方法。

git rebase <branch_name>

舉例:master 分支的紀錄是 A←B←C←D←E (HEAD),在 D 點開始分岔,產生新分支 feature,紀錄為 A←B←C←D←F←G (HEAD)。

在 feature 分支上執行 git rebase master 時,會將 feature 分支從 D 點開始的提交(F 和 G)重新應用於 master 分支的最新提交 E 之後。這樣,feature 分支的提交基底變為 E,並重新應用這些變更以形成新的提交 F' 和 G'。

合併後 feature 分支會變成 A←B←C←D←E←F'←G'。而 master 分支還是原來的 A←B←C←D←E,除非切換成 master 分支後,執行 git merge feature,才會使得 master 分支變成 A←B←C←D←E←F'←G'。

git pull

將本機的進度拉到最新。git pull 相當於 git fetch + git merge。

git pull

在進行 git pull 時,Rebase 合併通常不是預設值,如果在拉取遠端儲存庫進行合併時,遇到建立新提交點的狀況,可以使用上面提到的 --rebase 參數,使得提交線圖呈現線性的,較為美觀以及清楚明瞭。

git pull --rebase

git add

將目標檔案的變更加入到暫存區。在 Git 中,所有變更(無論是新檔案還是對已追蹤檔案的修改)都必須先加入暫存區才能被提交。如果在工作目錄建立一個新檔案,但沒有執行 git add,Git 會將其標記為未追蹤(untracked)檔案,因此無法提交這些變更。

需要注意的是,如果在將檔案加入暫存區後,又對該檔案進行了修改,然後沒有再次執行 git add 就直接 git commit 的話,只有上一次加入暫存區的內容會被提交,而不是工作目錄中最新的版本。Git 允許檔案在暫存區和工作目錄中有不同的版本。

git add <...files>

加入所有已經追蹤但修改過的檔案到暫存區,不存在的檔案會被視為不追蹤。

git add -u

下面的指令會把已經不存在的檔案視為不追蹤,任何新添加的檔案加入到追蹤,相當於將目錄的所有檔案整個提交到暫存區。

git add -A

命令 新文件 修改文件 刪除文件
git add -A / git add --all ✅ ✅ ✅
git add -u / git add --update ❌ ✅ ✅
git add . (現代Git版本) ✅ ✅ ✅

git rm

git rm 用於從工作目錄中刪除文件並將此刪除操作記錄到暫存區中,基本上是 git add 的反向操作。當你執行 git rm <file> 時,該文件將從你的工作目錄和索引(暫存區)中被移除。

git rm <...files>

如果你想從 Git 的追蹤中移除文件但仍想保留它在工作目錄中的物理文件,可使用 --cached。

git rm --cached <...files>

git mv

檔案重命名。

git mv old_filename new_filename

git status

查看當前的工作區與暫存區狀態。能通過這指令了解哪些檔案已經修改了,有沒有加入暫存區等。

git status

如果你的工作目錄太多沒有被追蹤的檔案,而你不想看到它,可以使用 -uno 參數。

git status -uno

git commit

將目前的暫存區的變更套用提交至儲存庫,相當於一次快照。通常情況下,不允許空提交(暫存區未有變更的狀態)。

git commit -m 'update message'

將有變更的已追蹤的檔案自動加入到暫存區,不包括全新創建的文件,會把已追蹤但不存在的檔案視為不追蹤。

下面這個指令我非常非常常用。

git commit -a -m 'update messsage'

如果不小心發現打錯 commit 訊息,想要修改的話,可以使用 --amend,可以讓你修改最後一則 commit 的訊息。

git commit --amend

但如果你已經先 push 歷史紀錄上去遠端儲存庫的話,那麼已經來不及了,下這個指令的話只會導致你跟遠端分支不同步,產生分歧。

如果要進行簽章的話,可以加上 -S (大寫)。如果用小寫(-s)的話,commit的訊息會多出類似下面的訊息:

Signed-off-by: Weil Jimmer <me@weils.net>

加上 --allow-empty 可以允許沒有任何變更,卻能 commit。

git commit --allow-empty -m 'message'

git push

將本機的歷史紀錄推送到遠端儲存庫。

git push

如果要完整一點,比如指定遠端儲存庫,因為遠端可能有很多個,或是要指定分支。

git push <origin_name> <branch_name>

加上 -u 能夠修改預設的上游遠端儲存庫。

git push -u <origin_name> <branch_name>

如果被 reject 的話,建議可以下 git pull,更新一下歷史紀錄,然後再重新推送。

推送標籤。預設狀態下,標籤是不會跟著一起被推送出去。要推送標籤的話,加上 --tags。

git push --tags

預設狀況下,只會推送當前的分支,如果要推送全部分支,加上 --all。

git push --all

如果要刪除遠端儲存庫的分支或標籤,可以用 --delete 參數。

git push --delete origin <branch_name | tagname>

如果要鏡像儲存庫的話,可以使用 --mirror。

git push <repo-url> --mirror

下面是危險指令,強制推送(Force Push)本機儲存庫到遠端儲存庫,會覆蓋掉遠端儲存庫的歷史紀錄,即便遠端有最新的進度,仍然會被蓋成跟你本機一樣的紀錄。

使用這指令,有可能導致組員的工作進度被你清洗掉,也可能導致接下來團隊的歷史紀錄出現混亂、不同步。

要使用前,先清楚知道你自己在做什麼,先確定沒有別人在推送,而且你的進度是最新的,沒有分岔,別人能夠正常銜接上去。

git push -f

通常現代化的 Git Server 會有分支保護,會阻止強制推送。

git reset

reset 通常用於退版本用,如果要查看特定 commit 的內容會用 git checkout。

reset 有分三種狀態,soft、mixed、hard,預設值是 mixed。

--soft

這個指令,會把你的 HEAD 移到目標 commit,但是不會改變暫存區和工作目錄。如果較新的 commit (或預 commit) 有新的檔案或變更,仍然會在暫存區內。

git reset <commit_hash> --soft
--mixed

這是預設的模式,會把你的 HEAD 到目標 commit,但是不會改變工作目錄,會清空先前 commit 的暫存區,使得暫存區與目標 commit 一致。

git reset <commit_hash>
--hard

這是危險指令,它會把你的工作目錄(即便你有已經儲存到文件上的修改),全部重置到目標 commit,使得工作目錄與目標 commit 完全一致,會讓你已儲存但未 commit 的程式碼徹底丟失,並且無法通過 git reflog 恢復。

git reset <commit_hash> --hard

圖形介紹 git reset

尚未修改工作目錄的情況

已經修改過工作目錄並加入暫存的情況

git reflog

Git 的復原紀錄的大絕招,如果某些 commit 已經因為被刪除標籤或因為 reset 看不到歷史紀錄,可以嘗試使用它。

能夠找回之前的 commit,只要有找到 commit hash,就基本上能還原。

git reflog

如果你想要找回的東西並沒有 commit hash,而且使用了 git reset --hard 造成程式碼的丟失,是無法用這個指令復原的。

git tag

替當前 commit 加上標籤。

git tag <tagname>

指定 commit 加上標籤。

git tag <tagname> <commit_hash>

刪除本機儲存庫上的標籤。

git tag -d <tagname>

如果要把 Tag 也加上簽章,可以使用參數 -s。

Tag 名稱是不可以重複存在的,即使分支不同也不能重名。

git branch

Git 分支相比 SVN 很廉價的,不會複製很多個儲存庫,只佔幾個 bytes 而已,可以不用擔心空間問題。

同時,Git 分支開在本地工作,只要不 Push 回遠端,完全不會影響到別人。不需要擔心因為自己開了分支,別人是不是也能看到你開了分支,除非你上傳了分支,否則別人是不知道你在本地開了分支。

下面的命令能查看本機有哪些分支,並且查看現在在哪個分支。

git branch

可以查看遠端儲存庫有哪些分支。

git branch -r

建立分支。

git branch <branch_name>

刪除本機儲存庫的分支。

git branch -d <branch_name>

git checkout

切換分支到 branch_name。不建議使用 git checkout 來切分支,其功能太過含糊。建議改用 git switch <branch_name> 來進行分支切換。

git checkout <branch_name>

查看特定 commit 或 tag 的內容。

git checkout <commit_hash | tagname>

使用上面這個指令的話,HEAD 會移動到目標 commit,會進入斷頭狀態(detached HEAD),如果在這裡 commit 的話,會從這邊長出一個新的 commit。(但是沒有分支指向它。)

斷頭模式狀態的示例圖片:

下面這個指令是切換分支,如果沒有就創建一個分支 branch_name。

git checkout -b <branch_name>

git switch

Git 版本 2.23 後,這指令被推薦用來切換分支方式。因為 checkout 過於含糊不清、功能太多樣化。


git switch <branch_name>

git restore

Git 版本 2.23 後,這指令被推薦用來檢出文件。理由同上,因為 checkout 過於含糊不清、功能太多樣化。

下面的指令,能夠將工作目錄的特定檔案還原成暫存區的內容。如果沒有暫存,則會還原成當下 HEAD 紀錄中的內容。

git restore <filepath>

如果要從暫存區移除,需要加上參數 --staged,但這只會從暫存區移除,工作目錄仍然維持原本的修改。

git restore --staged <filepath>

如果要完全還原暫存區和工作目錄,要加上工作目錄的參數,如下。

git restore --staged --worktree <filepath>

如果要還原成某個版本的檔案,可以指定 --source=<tree> 參數,如下示範,將會還原成目標紀錄的檔案內容,包含暫存區和工作目錄。

git restore --staged --worktree --source=abcd1234 <filepath>

git stash

如果當前目錄已經正在修改,但是又還不能 commit,這時候無法使用 checkout,可以使用下面的指令先暫存起來。被暫存的這些程式碼,並不是存在「暫存區(staging area)」,此暫存非彼暫存,而是特別的區域,可以理解成本地(個人)的快取空間。

git stash

還原先前的草稿。

git stash pop

查看當前暫存起來的列表。

git stash list

清除所有暫存內容。

git stash clear

git clean

這個指令會強制移除所有未被追蹤的檔案或資料夾。假如有任何因編譯所產生的新檔案,都會被強制移除。


git clean -xdf

git gc

清除無用多餘的紀錄。基本上一個分歧的紀錄,如果沒有分支指向它並長達一段時間,就會被清除掉。

一個無法到達的 commit 也會被清除,例如:通過 reset 退版本,然後重新 commit 的狀態,先前 commit 的歷史紀錄都會是無法到達。

git gc

解決衝突 (Conflict)

相同分支的情況

如果在 git pull 之後出現類似下面的訊息:

CONFLICT (content): Merge conflict in xxx.txt
Automatic merge failed; fix conflicts and then commit the result.

通常情況下,那代表,別人修改了跟你相同檔案中的同一行,要先手動解決衝突。

如果使用 VSCode 之類的編輯器,會很貼心的幫你找出衝突的地方並給出比較。

像是這樣:

<<<<<<< HEAD
我的修改
=======
別人的修改
>>>>>>> 75f66a4b22c06e2526b9ab01689b3becfdbf6c93

編輯器會讓你選擇要套用哪種變更,或是你自行修改,修改完之後,使用 git add 重新 commit 一個紀錄後,即可再次 git push 推送上去。

合併請求衝突 Pull Request Conflict

現在有一個情境,你建立了一條分支 feature 進行你的工作,然而你的同事上傳了新代碼到 master 分支,他修改了與你在 feature 分支中相同一行的程式碼,導致發生衝突,你無法自動合併 feature 到 master。

這種情況,可以採取下面的步驟解決問題:

切换到 master 分支並更新
(feature) $ git checkout master
 (master) $ git pull origin master
切換回 feature 分支並合併 master 分支

 (master) $ git checkout feature
(feature) $ git merge master
手動解決衝突並提交
(feature) $ git add some/conflict/file
(feature) $ git commit -m 'Resolve conflict'
推送代碼回遠端分支
(feature) $ git push origin feature

完成這些步驟後,就可以在 Pull Request 中繼續自動合併。

按下建立合併提交後,線圖大概長這樣。

合併後,master 分支已經包含你在 feature 修改過的代碼,此時,通常的作法是刪除 feature 分支,因為可能不再需要了。

總結:

Git 最常用的指令不外乎是 git clone/pull/push/add/commit,其他的基本上不太會用到,只要把握好幾個基礎指令的用法,已經能應對大多數狀況了。

其他文章:
解決 Git 錯誤 fatal: repository http://example.com/repo.git not found 的問題
Git 儲存庫從 SHA256 降級為 SHA1 經驗

補充:

設定 Windows 上 GPG 執行檔位置

git config --global gpg.program "C:\Program Files\GnuPG\bin\gpg.exe"

設定 Windows 上 GCM 位置

git config --replace-all --global credential.helper "C:/Program Files/Git/mingw64/bin/git-credential-manager.exe"

解決暫存區無法重置的問題

目前遇到過很棘手的問題,使用 git stash 保存暫存但下 git status 仍然顯示狀態已修改, git restore 修改那個檔案,甚至是 git reset --hard 都無解,狀態都是已修改,導致我無法使用 git pull --rebase 更新進度,以致於無法 git push。

這種情況使用下面的方法可解:

git update-index --assume-unchanged /file/to/path/

這個方法會讓 git 會完全忽略這個檔案並認為這檔案沒有變更,如果要復原可以使用下面的指令。

git update-index --no-assume-unchanged /file/to/path/

By Weil Jimmer


This entry was posted in General, Git, Note By .