發表文章

目前顯示的是有「Git」標籤的文章

Git Submodule 除錯

圖片
前言:   網路上已經有很多關於 Git Submodule 的介紹,使用方式 、使用時機等等,都有很可靠的資訊可以參考,因此本篇文章並不會再贅述使用方法,而是著重在泰勞之前遇到的問題,經驗分享以及解決的辦法。   前情提要: 我們先依照下列步驟製造出一個類似的場景,先新增一個 Submodule,然後 接著將 Submodule 裡面的 .git 刪除! $ git submodule add <repository> submodule $ git commit -m "Add submodule" $ cd  submodule $ rm -rf .git 這麼做當然是為了要模擬問題,但是為什麼要這麼做?原因是泰勞曾經拿過一個 Patch,它只是一個目錄,並非 Git Patch,因此我用 cp 將其複製到工作區裡面,並且加入至 Git Stage,就在此時,問題發生了,是我從來沒有看過的錯誤訊息! fatal: Pathspec 'xxx' is in submodule 不管我怎麼做,submodule 目錄都無法被加入!就如同上圖,錯誤訊息顯示此目錄底下的檔案在 Submodule 裡面,泰勞可以合理推測當時那個 Patch,原先在別人手上時,是以 Submodule 的方式做管理,而發出  Patch 的步驟是直接將目錄複製出來給我們,並沒有選擇 Git Patch,才會導致這樣的問題。 解決方式並不複雜,透過 Git 將其刪除,然後再加回來即可。 $ git rm -rf --cached submodule $ git add submodule/ $ git commit -m "Add folder" 這個問題應該不會太常遇到,復現此現象也只是想讓大家知道有這種款式的錯誤訊息,不過,上網查詢資料時,也是有蠻多人表示他們是不小心刪除 .git 造成的 XD 參考資料: [StackOverflow]Git: fatal: Pathspec is in submodule

還原遺失的 Git Commit

圖片
前言: 在 Git 裡頻繁且大量的新增或刪除 Commit 是常有的事,也難免會有些疏失,如果是不小心加入不相關的 Commit,還算是好解決,但萬一不小心刪除,或是不小心遺失了某個重要的 Commit,該怎麼辦呢?除了重新上一個內容一樣的 Commit之外,有沒有其他補救方法呢? 前情提要: 我們 先依照下列步驟製造出一個類似的場景 $ touch abc.txt $ vim abc.txt    ==>  加入字串 defdef $ git add . $ git commit -m "defdef" $ vim abc.txt    ==>  加入字串 ghighi $ git add . $ git commit -m "ghighi" 接著我們將捨棄最新的一個 Commit,並將修改還原為上一個 Commit 的狀態 $ git reset HEAD~    ==>  捨棄最新一個 Commit $ git checkout -- abc.txt    ==>  取消修改 如上圖所示,此時的 abc.txt 裡面沒有字串"ghighi",如果我們想再一次加入字串"ghighi",或者說我想更精準的要求,必須找回剛剛捨棄的那個 Commit 並且將它還原呢? Git Reflog: 答案是使用 git reflog 指令,其實大部分透過 Git 指令的操作,都會紀錄在本地端的倉庫裡,其中包含了 Commit 歷史紀錄,因此 git reflog 非常適用於現在的情況,它會列出本地端目前紀錄過的 Commit,從中找到你想還原的 Commit,透過 Reset 或 Cherry-Pick 將其還原即可! $ git reflog    ==>  找到欲還原的 Commit ID $ git reset --hard <commit-id>    or git cherry-pick <commit-id> 按照上面步驟完成之後,...

Git 還原特定檔案

圖片
前言: Git 可以透過 Revert 還原某一次的修改,但是以 Commit 為單位去做復原的動作,假如這一次的 Commit 裡面包含了五個檔案的修改,而你只想要復原其中一個檔案,要怎麼做呢? 前情提要: 先依照下列步驟製造出一個類似的場景 $ touch abc.txt $ git add abc.txt $ git commit -m "Add abc.txt" $ touch def.txt $ git add def.txt $ git commit -m "Add def.txt" $ vim abc.txt    ==> 加入字串 $ vim def.txt     ==> 加入字串 $ git add . $ git commit -m "Modify all files" 目前有三個 Commit,其中最新的一個 Commit 同時修改了 abc.txt. 和 def.txt。   假設現在我要還原稍早對於 def.txt 檔案的修改,可以怎麼做呢?我們先來看一個比較不好的操作方式,為什麼不好?稍後會做說明。 $ git reset HEAD~    ==> 復原至上一個 Commit $ git checkout -- def.txt    ==> 取消 def.txt 的修改 $ git add . $ git commit -m "Revert def.txt" 此時 def.txt 已經被還原為原本的樣子,而最新的 Commit 也只有修改 abc.txt,但是,此時的 Commit 歷史紀錄也已經不一樣了 !如果在多人共同開發的情況之下,修改已經 Push 至遠端的歷史紀錄是不被允許的,因此需要特別強調,此方法只能用於本地端,在你還沒將舊的修改 Push 至遠端之前,才可以這麼做喔! 再來要說明的是我比較推薦的操作方式,此方法背後的原理就類似於新增一個新的 Commit,而這 Commit 的內容就是將先前的修改給復原回去,如果修改的內容只有一兩行,直接手動去修改也是沒有問題的,但既然 Git 有提供更方便簡潔的指令,何不嘗試看看呢! ...

Git 如何不再追蹤 Tracked Files

圖片
今天的例子比較特殊,因為 Android 的原始碼在 「 編譯的過程中 修改 」 了一些檔案,這些檔案不能被刪除,它們屬於原始碼的一部分,但是我們必須避免因為編譯而被修改的部份進入到 Git 歷史裡面。換句話說,這些檔案在原始碼裡面是永遠不能改變的,每次從遠端 repo sync 下來都必須是 「 原版 」 ,只有編譯之後才會依編譯情況而改變,這要怎麼解決呢? 參考資料: [Git-Scm]Git-Hooks [DigitalOcean]How To Use Git Hooks To Automate Deployment Tasks   需求: 讓 Tracked files 存在於目錄,但任何修改都不再被 Git 追蹤。 Android 原始碼本身就是由 Repo 和 Git 來管理,剛好在這兩個工具相互合作的情況下,找到了一個方法,就是 Git Hook 加上 Repo 的 Linkfile 功能,可以達到上方描述的需求,如此一來可以避免我們不小心將不必要的修改 Commit 進去。 方法: 設定 Repo 參數,使其 Sync 完成的同時,觸發 Git hook: post-checkout 執行特定指令。 步驟1: 將不想再被追蹤的檔案加入 .gitignore。 疑?.gitignore不是僅適用於尚未被追蹤的檔案嗎?沒錯,如果是 Tracked files,必須再執行 git update-index --assume-unchanged 這行指令,在本地端才會生效,為什麼說本地端呢?因為只要刪除整個目錄,重新 repo sync 一次,那些被加入 .gitignore 的 Tracked files 仍然會被追蹤!所以我們需要繼續下面步驟。  Untracked file => 加入即生效  Tracked file => git update-index --assume-unchanged 步驟2: 在專案裡新增目錄 hooks,在 hooks 目錄內新增檔案 post-checkout,然後 git add; git commit; git push......,post-checkout 內容如下所示。 #!/bin/sh exec...

Git 衝突處理

圖片
當一個專案同時有許多人在進行開發與維護時,時常會遇到兩個人修改同樣的文件甚至是同樣的地方,此時就必須決定該使用誰的版本,或是將兩種版本融合在一起。 在Git的架構裡,當進行Merge 、 Pull 、Rebase 、Cherry-Pick 甚至是Revert 時,發現有兩筆Commit同時修改了相同位置,就會被判定為衝突(Conflict),意味著Git系統無法自動處理這樣的改變,必須由開發者手動解決。今天就來看看Git有哪些常見的衝突形式,以及處理衝突的方法與指令吧! 參考資料: [GitHowTo]Resolving Conflicts [Git Docs]git checkout 常見的衝突形式大致上分成下列三種: 1.檔案內容衝突 <<<<<HEAD int a = 5; int b = 10; ========== int a = 6; int b = 15; >>>>>branchB 此為最常見的形式,只要發生衝突的檔案是可以直接用文字編輯器打開(並且一般人能夠閱讀),你就會看到檔案裡出現這些標記符號。 從<<<<<HEAD到=====之間是你當前所指向的分支,從=====到>>>>>branchB之間是你準備要合併進來的分支或Commit,選擇你想使用的版本,或是自行修改成你要的內容,並且將 「 標記符號刪除 」 才算解決衝突,最後進行add與commit的動作以完成這次的合併。 2.檔案版本衝突 Unmerged paths: (use "git add <file>..." to mark resolution) both modified: libtest.so both added    : taiwan.bin 與第一種非常相似,差別在於檔案內容是無法直接編輯的,例如:函式庫(副檔名.so 或.a ) 、映像檔(副檔名.bin或.iso),因為無法比較內容,因此只能選擇版本,可以透過Git指令來操作。 $ git checkout --theirs FileName => checkout 至準備...