2014年6月28日 星期六

自己犯的錯自己刪,使用git-gc

最近我修改了我的ADS2Origin,因為使用者回饋表示,有時候資料區塊長度不同是無可避免的,比如說遇到loadpull的圖形,因此我把輸出改為csv格式,程式只會提醒使用者資料區塊長度不同,而不會自動切掉長度過長的部分;這個東西其實也不難改,反正資料就在那裡,只是改一下寫出的方式。
倒是寫這個讓我想起data mining的名言:「做data mining的,用了70%的時間在處理資料,30%的時間在靠北處理資料」

與此同時,很高興6/25號晚上我又推了一位同學當使用者,使用者人數++。
為了方便使用者,把下載連結換到dropbox的公開連結上:
https://dl.dropboxusercontent.com/u/3192346/ADS2Origin.zip

--

另外,最近我發現到一個問題,因為我的git project把windows下的執行檔都包進去,git又是每記錄一個版本就把檔案都複製一份,看一下我的git repository已經14 MB(唔…跟某些project用幾十G在算的比起來其實還是很小),不過恁爸保留exe的commit好像也沒啥用,就趁這個機會研究一下怎麼刪掉舊記錄裡面的執行檔。
不能用git rm ,這是不夠的,git歷史資料還是會保留著,因此需要一些特別的方法,主要的參考資料是參考資料一的:「Git 內部原理 - 維護及資料復原」,其實大部分的內容它都講完了,我只是照做而已。

其實理論上是不能這麼做的啦,這樣的行為會改變整個有大檔案存在的歷史,在有協作時需要你的團隊重新拉你的commit,會如此麻煩是因為git的設計理念就是不讓你輕易的丟失資料。
不過不管啦,我有幾個理由:
一、這個project根本沒人理
二、恁北我看windows不爽,就是要把windows的執行檔幹掉
三、跳脫舒適圈

首先看一下project的狀況,在執行完git gc後,再用git count-objects -v看看project有多大:
得到size-pack為: 3350 KB
我們的目標是一個名為dist的資料夾,裡面放滿了py2exe產生的巨量檔案。
用git log找出所有有加入該檔的歷史資料:
git log --pretty=oneline --branches --abbrev-commit -- dist
這個的會列出所有head下,match到dist 這個路徑裡的log,使用縮短的sha來顯示,結果如下:
5f9f3dc output in csv format, allow various length data
23f8633 windows executable file of 0.3.1 version
bb1107f Merge branch 'master' of github.com:lc85301/ADSToOrigin
e891091 update ADSToOrigin.exe version
acbeb1d fix duplicate tital bug
5343e5c add data length different detect, multifile sup
9ff12b9 multi variable parser support add
c989cc4 allow drag in windows
b21d5c1 windows distribution
的確,第一次把dist這個資料夾加進來就是從這個windows distribution開始的,這個commit的SHA值為b21d5c1。

好的,讓我們動手,這個要使用git filter-branch的命令,基本上這是一個…破壞性有點高的指令,建議是把manpage好好讀過一遍之後再來使用,不然GG了我不負責。
Filter-branch可以傳入一個filter,然後基於這個filter上,把所有的commit重寫一篇
這裡要用的是--index-filter或--tree-filter,這個會改變commit的內容,另外還有像--env-filter改寫每個commit的環境設定,msg-filter用來改寫commit message等等。

每一個filter後面要接一個command,用來操作你的git倉庫,拿最簡單的來說,msg-filter會把目前的commit message送到你的command的stdin,然後以command stdout的內容當作新的commit message,例如我有一個倉庫依序加入abc三個檔案,現在長這樣:
b0b79d5 add c
f09a9d6 add b
2eee4d4 add a
如果我下:git filter-branch --msg-filter 'echo XDD' -- master
結果就會變成這樣:
075cdd6 XDD
44fe70f XDD
ec1e435 XDD
所有的commit message都被改寫成XDD,這簡直比改歷史教科書還要簡單

現在我們要移除掉dist資料夾,就使用--index-filter
git filter-branch --index-filter 'git rm -r --cached dist' -- b21d5c1^..
最後這個-- b21d5c1^..,是送到git rev-list的內容
git rev-list會把從某個branch往前回溯(嚴格來說是reachable)的每個branch寫出來,然後可以加上各種條件對這個群集進行操作,這裡我用例子來說明:
git rev-list master //master往前的所有commit
git rev-list master ^branch //master 往前,但不是branch往前的commit
git rev-list branch..master //與上一行等價
另外還有...的用法,只是那個我還沒搞懂,搞懂了再另外寫一篇XDD
前面提到,windows的東西第一次是出現在 b21d5c1這個commit
因此我們做的,就是從master往前所有commit裡面,把 b21d5c1前一個commit再往前的排除掉,因此只會更改到 b21d5c1這個commit之後的東西,不然filter-branch就會重寫這個歷史,會花比較多的時間(這個垃圾project算了,請想像你有幾千個commit要修正的話?)。
指令是移除掉dist下的東西,就是個rm。

output大概會像這樣:
Rewrite b21d5c1abbaf39e02b817b0ccb7efdc54dbf6090 (1/14)rm 'dist/ADSToOrigin_win.exe'
rm 'dist/_hashlib.pyd'
rm 'dist/bz2.pyd'
rm 'dist/library.zip'
rm 'dist/python27.dll'
rm 'dist/select.pyd'
rm 'dist/unicodedata.pyd'
rm 'dist/w9xpopen.exe'

以下類似的東西重複14次,無非就是刪掉exe, pyd 巴啦巴啦,可以看見我到底存了多少exe垃圾在我的project裡面lol。

另外,我有些commit是針對windows distribution去commit的,這個指令一下這個commit就變成empty commits,因此我們再來:
git filter-branch --prune-empty -- b21d5c1^.. 註:這裡的SHA應該要換掉,只是我忘了是多少了。
這個參數可以在上面就下,一次做完比較痛快,這時候像windows distribution這個commit就不見了。

這樣我們已經讓記錄中不再記錄這個檔案,最後把它從.git裡面記錄刪掉,因為git reflog跟branch-filter本身都有對它的引用(你看看從git裡面刪東西是有多機車……)。
rm -Rf .git/refs/original //刪除branch-filter的引用
rm -Rf .git/logs/ //刪除reflog
git gc

最後,強制把你修改的分枝樹,把遠端的東西蓋掉。
git push origin master -f

這樣應該就差不多了,雖然說我弄完之後好像沒變小很多,不過我不是很清楚問題在哪...

參考資料:

1. Git 內部原理 - 維護及資料復原
2. ignoring doesn't remove a file

2014年6月25日 星期三

用word寫論文的一些技巧

站長最近都在忙論文,blog就這樣荒廢了,不過今天心血來潮,把幾個寫論文時用word+mathtype寫的技巧整理一下,分享給大家。
不過先聲明,個人還是認為用LaTeX寫才是真高手,只是站長小孬孬就用word寫,不像強者我同學們都用LaTeX。

其實我覺得大部分的技巧,我在前面三篇office中都整理的差不多了,主要就是:
第一:設定好階層
第二:使用樣式庫
第三:弄懂段落
第四:管理好參考資料
詳細請參考:
http://yodalee.blogspot.tw/2013/04/office-word1.html
http://yodalee.blogspot.tw/2013/05/office-word2.html
http://yodalee.blogspot.tw/2013/07/office-word3.html

文章到這邊就可以結束了當然,我還是把大略的流程整理一下,看情況隨機插入一些技巧:

1. 設定樣式庫:
一開始就先把大部分的樣式設好,這樣以後比較方便,我遇到大部分要設定的樣式總計為:

內文,標題,標題1-4(論文能寫到更多層我也覺得滿厲害的),目錄1-4,圖片,表格系列包括標題列格式、表格內文、表格註記,圖片標號,表格標號,reference樣式。

一些細節的設定等等再談,這裡先把大略的字體、大小都設定好了。

2. 把文章的幾個標題都打好:
什麼大綱、Contents,chapter 1什麼的,套用好格式。
接著,因為遇到標題、標題一應該要開新頁,因此在這兩個格式的「分行與分頁設定」中,選擇「段落前分頁」,沒事別亂加分頁符號,那會讓文件變得難以排版。
這時候,基本的文章架構應該已經有了,頁數也變得至少十頁,雖然說內容都是空的

3. 建標號:
把該用的標號建好:兩個基本款應該是Fig 跟Table,在「參考資料」-「插入標號」裡新增它們。
建立時可以選擇「編號方式」,讓標號的數字會依照章節數字跳動。

4. 打文章:
好啦這才是最花時間的地方,但這沒啥技巧,全是硬功夫,再好的排版軟體要是沒內容排也排不出東西。

5. 插圖片:
個人會在文件旁建立一個fig資料夾,依章節把圖片分好,就算圖片還沒畫,也可以先複製隨便一張圖片放著,然後在插入的視窗中選擇「插入與連結」,之後只要改動插入的圖片,選擇圖片按F9即會自動更新了。
插入圖片之後,記得選取圖片該行,將樣式改為「圖片」樣式。

6. 插標號:
每插入一張圖片、表格後就用參考資料-插入標號,選用已建好的標籤
在內文的地方就選交互參照,選適當的標籤,插入參照類型的「段落編號(部分顯示)」
內文就會自動變成Fig. xx
插入新圖片後只要全選後按「更新功能變數」或F9,所有編號都會自動更新。
另外因為標號跟它的內容要在同一頁,因此在「圖片」樣式的落段「分行與分頁設定」中,選擇「與下段同樣」,表格標號也如此設定,這樣表格、圖片和它的標號才會在同一頁。

7. 表格:
其實表格在2007後也有自己的樣式,不過我是覺得沒什麼設定的必要。
不過表格是有不少需要設定的內容:
* 在左上方M$的符號-「 word選項」-「進階」最後的「版面配置選項」,把「不要將跨頁的換行表格切斷」選起來,這樣一般大小的表格才不會在表格中間換頁,而是直接跳下一頁。
註:藏這麼深誰找得到啦!( ̄▽ ̄)╭∩╮
* 如果有一個非常長的表格(依我的論文22列以上大概都會超出一頁),那麼請把整個表格選起來,在「表格內容」-「列」-「允許列跨越頁分隔線」取消掉,才不會出現一列的內容被分到兩頁去。
* 同時把「跨頁標題重複」勾起來,讓word自動重複標題。
* 在「表格內容」的「表格」,設定為「文繞圖」,然後在「位置」中設定下方的邊界值,這樣表格後的文字才不會離表格太近。

8. 方程式:
好了我們說到word最WTF的地方了,基本上作者試了很多方式之後,還是無法自動的產生靠右的方程式編號,最後還是靠MathType來解決,反正word爛也不是一天兩天的事,同學說 LaTeX is the ultimate solution 或許真有幾分道理。

補:後來強者我同學為中大神在FB上面嗆我說,用word也是能正常為方程式編號的,方法如影片所示:
https://www.youtube.com/watch?v=JcB4nQ2AYts
我是還沒試過啦,不過既然是為中大神開示,應該就是正確無誤了。

9. 插目錄:
差不多有點內容就可以插入目錄了,在該插入的地方選「參考資料」-「目錄」,要圖表目錄還是一般目錄就自己選。
視狀況調整目錄1-4的樣式,只有一個靠右的定位點是必要的,如果發生目錄文字太長讓頁碼沒有靠右,請設定該樣式段落的「縮排」為「第一排」並設定適當縮排值。

10. 檢視技巧:
在上方的檢視裡:
* 選用Web 版面配置,可以盡情放大文件,橫軸的捲軸會消失,文件的內文會自動換行,這在寫太久眼睛很累的時候很好用
* 打開文件引導模式:左邊會有標題列的列表,點一下可以直接跳過去。
* 開新視窗:同一份文件開一個新的視窗,我的習慣是多開一個,一個用來打內文,另一份停在Reference的地方,要reference什麼Alt+Tab切到另一個視窗去找,就不需要用滑鼠一直滾來滾去。

結論:這篇文章只是出來騙文章數的。