2011/10/21

Git == SVN 愛用者的快速入門

我想,很多人是 SVN  的愛用者,若有像我一樣要換到 git 的人,可以參考本文的原始文章: Git - SVN 快速入門。底下是翻譯

如果你只是想追蹤某人的專案的話,下面這樣就夠了:
git clone url
git pull
svn checkout url
svn update

在進一步閱讀前,你應該知道的事

  • Repositories.
    在 subversion 中,每個專案有一個單一的放置源碼的地方,英文叫 Repository,在 SVN 中它用來管理源碼、管理變動記錄、或是讓你上傳源碼
    但是在 Git 卻不一樣,它是分散式的,每個專案的複製品有它自己的專案倉庫,在做與 SVN 一樣的管理時,並不需要連線,你可以在本地端做完。也就是說,在本地端的分支進展,是可以與所謂的遠端分開的不同分支。雖然名詞上一樣,但是觀念上卻完全不同。
  • URL.在 SVN 中,URL 指的就是前面的 Repository的位址或其目錄樹位址,所以你必須對 Repository 做好目錄管理,譬如,最常見的 trunk/, branches/ 及tags/ 等。
    但是在 Git 中,URL 就只是 Repository 的位址而已,也就是說,你無法透過 URL 來指定分支什麼的。換句話說,Git 的倉庫要就整個被提取而 SVN 則可以從倉庫中提取個別的物品。看似 SVN 比較合理點,但是反過來思考二個問題,當對方的倉庫沒開門時,你就提取不到東西,而且若你想開分行時,將會占用另一個倉庫。我這樣說或許有人會說,Git 只是一開始就弄一個新倉庫,還不是一樣要占用一個倉庫?其實觀念上完全不同,你在本地端不管是 Git 或 SVN 本來也都一樣要占用完全的備份,而 SVN 則在新分支時又要重新占用一個新的備份。
  • Revisions.
    SVN 在版本的控管上是用 Revision, 而且會自動遞增。這在理論上或許很方便,實務上對 Repository 有人懶得管,或是分支的管理上,Revision 都反而增加了困擾。當然可以用 Tag 來稍微解決問題,但是常用 SVN 的人就知道,這確實是個很大的困擾。尤其到後期,你根本無法知道哪個 Revision 是你要的。若混用了 Repository 及 branch, 光是要記 Revision 就是一場災難。
    而 Git 則用 HEAD 來代表當前的版本,你可以搭配 HEAD^, HEAD^^ = HEAD~2 來表示更早的版本。而且 Git 在分支的管理上更是輕便,隨時可以切換分支,這一點是 SVN 比不上的。
  • Commits.
    首先一點是,SVN 的 commit 是丟到伺服器上,就是真的『提交』。而 Git 的 commit 則是丟到本地端的 Repository,跟 SVN 的 commit 相對應的反而是 push。
    第二點,Git 把每次的提交動作,分出 author, 及 committer, 也就是作者與提交者,兩個是不同的。底下的命令可以設定成全域值:
    git config --global user.name "Your Name Comes Here"
    git config --global user.email you@yourdomain.example.com
    
  • Commands.
    Git 有一個很特殊的用法,就是一般的用法是 "git command“ 你也可以用 “git-command” 的型式,這樣在 bash 下很容易用 tab 來找出你可以用的命令.
  • Colors.
    Git 很貼心的可以將命令的輸出著色,因為有些人討厭顏色,其實我也是,所以預設是關掉的。可以試著用下面的命令來打開:
    git config --global color.diff auto
    git config --global color.status auto
    git config --global color.branch auto
    
  • Visualize.
    Git 也有圖形界面可以用,最簡單的就是 gitk

Commiting

除了前面算是緒言的部份外,首先要介紹的是,如何讓你的專案交由 Git 來追蹤,並且看看在那之後每日必做的功課。先切換工作目錄到你的專案去吧,然後.....

git init
git add .
git commit
svnadmin create repo
svn import file://repo
git init 初始化 repository, 而 git add . 則會將目錄下所有東西加到 repository 中。事實上,與其相對應的 svn 是不存在的,因為 svn 沒有本地端的 repository 的觀念,所以上面的例子是用 svnadmin  來實作的,而這通常是在伺服器端。要注意的是,git commit 之後,才算真正的進入到 repository 中,不過貌似有個比較正式的名詞叫 staged.

git diffsvn diff | less
比對不同版本的差異。這邊講的版本,其實是每次的 commit 視為一個版本,跟實務上的版本是不一樣的。
git diff rev pathsvn diff -rrev path
Git embeds special information in the diffs about adds, removals and mode changes:
git applypatch -p0
That will apply the patch while telling Git about and performing those "meta-changes".
There is a more concise representation of changes available:
git statussvn status
This will show the concise changes summary as well as list any files that you haven't either ignored or told Git about. In addition, it will also show at the top which branch you are in.
While we are at the status command, over time plenty of the "Untracked files" will get in there, denoting files not tracked by Git. Wait a moment if you want to add them, run git clean if you want to get rid of all of them, or add them to the .gitignore file if you want to keep them around untracked (works the same as the svn:ignore property in SVN).
To restore a file from the last revision:
git checkout pathsvn revert path
You can restore everything or just specified files.
So, just like in SVN, you need to tell Git when you add, move or remove any files:
git add file
git rm file
git mv file
svn add file
svn rm file
svn mv file
You can also recursively add/remove whole directories and so on; Git's cool!
So, it's about time we commit our changes. Big surprise about the command:
git commit -asvn commit
to commit all the changes or, as with Subversion, you can limit the commit only to specified files and so on. A few words on the commit message: it is customary to have a short commit summary as the first line of the message, because various tools listing commits frequently show only the first line of the message. You can specify the commit message using the -m parameter as you are used, but you can pass several -m arguments and they will create separate paragraphs in the commit message:
If you don't pass any -m parameter or pass the -e parameter, your favorite $EDITOR will get run and you can compose your commit message there, just as with Subversion. In addition, the list of files to be committed is shown.
And as a bonus, if you pass it the -v parameter it will show the whole patch being committed in the editor so that you can do a quick last-time review.
By the way, if you screwed up committing, there's not much you can do with Subversion, except using some enigmatic svnadmin subcommands. Git does it better - you can amend your latest commit (re-edit the metadata as well as update the tree) using git commit --amend, or toss your latest commit away completely using git reset HEAD^, this will not change the working tree.

Browsing

Now that we have committed some stuff, you might want to review your history:
git log
git blame file
svn log | less
svn blame file
The log command works quite similar in SVN and Git; again, git log is quite powerful, please look through its options to see some of the stuff it can do.
The blame command is more powerful as it can detect the movement of lines, even with file copies and renames. But there is a big chance that you probably want to do something different! Usually, when using annotate you are looking for the origin of some piece of code, and the so-calledpickaxe of Git is much more comfortable tool for that job (git log -Sstring shows the commits which add or remove any file data matchingstring).
You can see the contents of a file, the listing of a directory or a commit with:
git show rev:path/to/file
git show rev:path/to/directory
git show rev
svn cat url
svn list url
svn log -rrev url
svn diff -crev url

Tagging and branching

Subversion marks certain checkpoints in history through copies, the copy is usually placed in a directory named tags. Git tags are much more powerful. The Git tag can have an arbitrary description attached (the first line is special as in the commit case), some people actually store the whole release announcements in the tag descriptions. The identity of the person who tagged is stored (again following the same rules as identity of the committer). You can tag other objects than commits (but that is conceptually rather low-level operation). And the tag can be cryptographically PGP signed to verify the identity (by Git's nature of working, that signature also confirms the validity of the associated revision, its history and tree). So, let's do it:
git tag -a namesvn copy http://example.com/svn/trunk http://example.com/svn/tags/name
To list tags and to show the tag message:
git tag -l
git show tag
svn list http://example.com/svn/tags/
svn log --limit 1 http://example.com/svn/tags/tag
Like Subversion, Git can do branches (surprise surprise!). In Subversion, you basically copy your project to a subdirectory. In Git, you tell it, well, to create a branch.
git branch branch
git checkout branch
svn copy http://example.com/svn/trunk http://example.com/svn/branches/branch
svn switch http://example.com/svn/branches/branch
The first command creates a branch, the second command switches your tree to a certain branch. You can pass an extra argument togit branch to base your new branch on a different revision than the latest one.
You can list your branches conveniently using the aforementioned git-branch command without arguments the listing of branches. The current one is denoted by an "*".
git branchsvn list http://example.com/svn/branches/
To move your tree to some older revision, use:
git checkout rev
git checkout prevbranch
svn update -r rev
svn update
or you could create a temporary branch. In Git you can make commits on top of the older revision and use it as another branch.

Merging

Git supports merging between branches much better than Subversion - history of both branches is preserved over the merges and repeated merges of the same branches are supported out-of-the-box. Make sure you are on one of the to-be-merged branches and merge the other one now:
git merge branchsvn merge -r 20:HEAD http://example.com/svn/branches/branch
(assuming the branch was created in revision 20 and you are inside a working copy of trunk)
If changes were made on only one of the branches since the last merge, they are simply replayed on your other branch (so-called fast-forward merge). If changes were made on both branches, they are merged intelligently (so-called three-way merge): if any changes conflicted, git mergewill report them and let you resolve them, updating the rest of the tree already to the result state; you can git commit when you resolve the conflicts. If no changes conflicted, a commit is made automatically with a convenient log message (or you can dogit merge --no-commit branch to review the merge result and then do the commit yourself).
Aside from merging, sometimes you want to just pick one commit from a different branch. To apply the changes in revision rev and commit them to the current branch use:
git cherry-pick revsvn merge -c rev url

Going Remote

So far, we have neglected that Git is a distributed version control system. It is time for us to set the record straight - let's grab some stuff from remote sites.
If you are working on someone else's project, you usually want to clone its repository instead of starting your own. We've already mentioned that at the top of this document:
git clone urlsvn checkout url
Now you have the default branch (normally master), but in addition you got all the remote branches and tags. In clone's default setup, the default local branch tracks the origin remote, which represents the default branch in the remote repository.
Remote branch, you ask? Well, so far we have worked only with local branches. Remote branches are a mirror image of branches in remote repositories and you don't ever switch to them directly or write to them. Let me repeat - you never mess with remote branches. If you want to switch to a remote branch, you need to create a corresponding local branch which will "track" the remote branch:
git checkout -b branchorigin/branchsvn switch url
You can add more remote branches to a cloned repository, as well as just an initialized one, using git remote add remote url. The command git remote lists all the remotes repositories and git remote show remote shows the branches in a remote repository.
Now, how do you get any new changes from a remote repository? You fetch them: git fetch. At this point they are in your repository and you can examine them using git log origin (git log HEAD..origin to see just the changes you don't have in your branch), diff them, and obviously, merge them - just do git merge origin. Note that if you don't specify a branch to fetch, it will conveniently default to the tracking remote.
Since you frequently just fetch + merge the tracking remote branch, there is a command to automate that:
git pullsvn update

Sharing the Work

Your local repository can be used by others to pull changes, but normally you would have a private repository and a public repository. The public repository is where everybody pulls and you... do the opposite? Push your changes? Yes! We do git push remote which will push all the local branches with a corresponding remote branch - note that this works generally only over SSH (or HTTP but with special webserver setup). It is highly recommended to setup a SSH key and an SSH agent mechanism so that you don't have to type in a password all the time.
One important thing is that you should push only to remote branches that are not currently checked out on the other side (for the same reasons you never switch to a remote branch locally)! Otherwise the working copy at the remote branch will get out of date and confusion will ensue. The best way to avoid that is to push only to remote repositories with no working copy at all - so called bare repositories which are commonly used for public access or developers' meeting point - just for exchange of history where a checked out copy would be a waste of space anyway. You can create such a repository. See Setting up a public repository for details.
Git can work with the same workflow as Subversion, with a group of developers using a single repository for exchange of their work. The only change is that their changes aren't submitted automatically but they have to push (however, you can setup a post-commit hook that will push for you every time you commit; that loses the flexibility to fix up a screwed commit, though). The developers must have either an entry in htaccess (for HTTP DAV) or a UNIX account (for SSH). You can restrict their shell account only to Git pushing/fetching by using the git-shell login shell.
You can also exchange patches by mail. Git has very good support for patches incoming by mail. You can apply them by feeding mailboxes with patch mails to git am. If you want to send patches use git format-patch and possibly git send-email. To maintain a set of patches it is best to use the StGIT tool (see the StGIT Crash Course).
If you have any questions or problems which are not obvious from the documentation, please contact us at the Git mailing list atgit@vger.kernel.org. We hope you enjoy using Git!

Git refs 參考文獻


Git Cheat Sheet

如您所見,轉貼一下有用的資訊而已

2011/10/20

git 基本概念 basic intro

主要是從這一篇簡報來寫的,因為我的網路慢,開簡報很麻煩,因此寫下來,直接看原簡報當然會清楚多了,我的這篇只是給自己看的。


Git 的目標或是特色有幾項:快、簡單(呃....)、非線性、分散式、可處理超大專案。

Git 對分支(Branch)的操作極快速,對複雜的合作開發模式也可以勝任。不過因為複雜開發模式也真的太複雜了,建議看看Git Flow 開發流程或是英文版的 A successful Git branching model

基本操作很簡單:
git init  /  git init --bare
git clone / git clone --bare
git add / git rm
git commit / git commit --amend
git status / git log / git diff
git checkout / git checkout -- file
// git clone 才像 svn checkout, 而 git checkout 是用來切換分支的命令
git pull origin == git fetch origin + git merge origin/master
































關於 rebase 與 merge, 其實我並沒有搞懂,但是這不妨礙我把它抄下來

指令 git pull --rebase 

rebase 的意思是
1. 把本地 repo. 從上次 pull 之後的變更暫存起來
2. 回覆到上次 pull 時的情況
3. 套用遠端的變更
4. 最後再套用剛暫存下來的本地變更。
所以如果將已經 push 出去的變動再來一次 rebase 的話,到底會怎樣?

git for windows 3 - 分散式之 client 端篇

在講下去之前,請見這篇git教學


ssh 需要公開金鑰與私鑰,公鑰是給別人的,放在 git server,而私鑰則是放自己家目錄中的 .ssh/ 目錄下



1. 產生 ssh key, 可以用下面的命令產生,此時你的 windows cmd 視窗應該可以執行 ssh-keygen 才對

這一步驟若是你有在別台機器上已經產生的 ssh key 的話,也是可以拿來用的,當然是要「信任的」。因此,若是你有別台安裝 Ubuntu 的電腦的話,也可以考慮使用該台電腦的 key, 這樣可以做到免密碼登入。

2. 把公開金鑰給 server
3. git server 的設定,請見這篇『簡易 git server 架設 或是這篇


git for windows 2 - 分散式之 server 端篇


在說明之前,先提一篇必看的文章,8 ways to share your git repository

先講一下基本觀念,因為要跟別人共用,所以要透過網路傳輸的協定,基本上有 git, ssh, http, https 等.....各有優缺,這邊以上面的教學來操作 ssh 的部份。

git 本身並沒有分 client 或是 server, 這邊講的 server 其實是指「連線功能」本身的,就好像要用 http protocol 的話,總要安裝 web server, ssh protocol 的話,就要安裝 ssh server. 而要用 git 的話,其實它也是用 ssh, 所以一樣要安裝 ssh server.

在 ubuntu 下的話,可以透過安裝 openssh-server 即可達標,windows 下我則建議使用 cygwin,當然其他套件也是非常多選擇啦,不過我並沒有打算在 windows 裝,所以這邊講的也都是指 ubuntu 下的。

$ sudo apt-get install openssh-server

接下來(至少)有兩種使用情境,只是要先提一下另外兩篇文章,只是因為與本文有點關係而已,跟我這邊要講的情境關係是有但是不大:請參考 Git Book, Setting a public repository 及 Git Book, Setting a private repository

在講server 端的操作的使用情境時,可以先了解一個 git 特有的概念,叫『bare git repository』,不管在 clone 或是 init 時,都可以加上 --bare。按照英文的意思,是叫「裸露」,也就是說並沒有內容,也就是沒有 project files, 只有 git repository 資料結構而已。請參考 push to only bare repository 或是 git bare v.s. none bare repository


server 端的操作的第一種情境是建立一個空的 repository ,此時可以用 git init --bare。這個情境通常是用來建立一個 public repository給自己用,也就是,如果你想在自己的機器上建立一個 git public repository 來給別人抓(pull)源碼的情況。

我知道這樣講也很模糊,這也是 git 讓人覺得複雜的地方,先用圖來說明, 在 git book, distributed workflows裡面有個圖:


                        you push
  your personal repo -----------------> your public repo
    ^                                     |
    |                                     |
    | you pull                            | they pull
    |                                     |
    |                                     |
    |               they push             V
  their public repo <------------------- their repo
左上角,也就是我之前貼的那篇 git for windows 單機版
而右上角,也就是第一個情境 git init --bare

同樣的,所謂的第二個情境,則是從遠端抓下來。由上圖可以很容易發現,就是把別人的 public repo 抓下來而已。用的是 git pull 或 git clone --bare 重新建立一個自己的 public repo

2011/10/19

GIT for windows - 單機版

一直以來都在用 svn 來做檔案管理,因為算是都自己在用,就算是團隊也是自己下面的,它方便之處在於使用與管理可以很簡單,不便之處則在於需要管理時反而不便。這邊講的管理,是指專案的控管上。還有一個 Git 的優點,就是它是分散式的,在團隊開發的情境中,若有人的檔案系統毀了也沒差,隨時可以回覆。

 首先介紹一些不錯的教學文章:
  寫給大家的 Git 教學 要想入門時有個清楚觀念的話,一定要看這一篇簡報
  Git community book  這篇是一定要看的書,不止是基礎那麼簡單而已,算是講的很清楚參考書+工具書
  Git for Windows with Central Server

  Git教學:初學者使用心得分享(Windows) 
  上一篇比較簡單,相對講的也只有一部份,完整請見下面三個:
  Git for Windows Part I
  Git for Windows Part II
  Git for Windows Part III

----PART I: Local User----
其實大部份版本控制的基本觀念都差不多,當然有其差異處,這邊就不比較了,直接講安裝。照著上面第一篇教學安裝就夠了,不過這邊提醒一下:
1. 我是先安裝 tortoisegit, 它只是 git 的 GUI 而已,別人的教學上寫的是反過來先安裝 msysgit, 想來兩種順序都可以。
2. 要搭配真正的 git 命令 for windows, 我是照文件寫的,安裝 msysgit,我相信有在用 cygwin 的人也可以用它
3. 安裝 msysgit 時,它會問 ssl client -- plink.exe, 有幾個選擇,一個是 putty, 一個是因為我自己也有安裝 tortoiseSVN, 或是前面的 tortoiseGIT 也有附這個東西

底下直接把我安裝時的照片貼上來

1. 安裝 msysgit, 注意我只勾選 Git Bash Here, 因為我的 GUI 用的是 tortoiseGIT
2. 環境變數,因為我沒在用 windows 內建的 find, sort 等,因此選擇用 msysgit 附的

3. 選擇 plink.exe,這是給要跟遠端的 git server 連線用的。若是個人自己要在自己的電腦上玩,這個就不是很重要。因為我有安裝 putty, 也可以選 tortoiseSVN 或是 tortoiseGIT 附的

4. 選擇 ending, 也就是 Windows 的換行與 Unix 的換行是不一樣的,若不瞭解的話,就選預設的就好了,否則出問題時很難解決。

5. 安裝好了之後,就開始新的專案,很簡單,第一個步驟是開啟一個「倉庫」放源碼。這邊有兩個方法,一個是產生一個 bare, 也就是一個 .git 檔,另一個是把某個目錄變成 git 的 repository, 我用的後面這個方法


6. 加檔案進去。若已經有很多源碼檔,可以用「加進整個目錄」或是只加一個檔案,底下的圖示範的是只加一個檔。就是在該檔按滑鼠右鍵,然後.....

  再選擇 TortoiseGit --> Add 即可加入。值得注意的是,此時並沒「push」到 server 的版本控制中,還需要 commit....後面會說


7. commit 也一樣簡單。不過也有兩種方式,或是說,有一種是不加『簽名」,一種加簽名,其實結果都差不多。在第一次使用 commit 時,TortoiseGit 會要求你設定 name & email, 就自己設一個吧。這一點也是跟 SVN 不一樣的地方,git 的使用者其實是很鬆散的,但是也是要自己負起責任的方式。



8. 取出。這部份有兩種,一個是在之前建立 repository 的目錄直接操作即可。另一個是你也可以到另一個目錄下取出之後來玩,這種需求比較少,可以自己玩玩看 git clone。

值得一提的是,TortoiseGIT 也支援從 svn server 取出 source code, 畫面如下



2011/10/12

plop boot manager

從光碟或是隨身碟開機,有些機型不見得能支援,有的有支援卻也不見得適用自己手邊的裝置。這邊介紹一個 boot manager 叫 plop, 功能強大,可以輕鬆解決這個問題,底下直接列其特性:

  • USB boot without BIOS support (UHCI, OHCI and EHCI)
  • CD/DVD boot without BIOS support (IDE)
  • PCMCIA CardBus support to enable boot from USB PC-Cards
  • Floppy boot
  • Different profiles for operating systems
  • Define up to 16 partitions
  • No extra partition for the boot manager
  • Hidden boot, maybe you have a rescue system installed and the user should not see that there is another system installed
  • Boot countdown
  • Hide partitions
  • Password protection for the computer and the boot manager setup
  • Backup of partition table data
  • Textmode user interface 80x50
  • Graphic user interface 640x480, 800x600, 1024x786, 1280x1024
  • MBR partition table edit
  • Start of the boot manager from harddisk, floppy, USB, CD, DVD
  • Starting from Windows boot menu
  • Starting from LILO, GRUB, Syslinux, Isolinux, Pxelinux (network)
  • It can be used as PCI option ROM
  • Access the whole USB hard disk (up to 2TB) even when the bios has a 128 GiB limit
  • You can run the boot manager over the network
  • Start the networkcard bootrom from the boot manager to boot from the network

2011/09/15

送信給加西亞 Send Message to Garcia

還記得我寫過這篇『態度決定一切摘要』嗎?現在回想,這篇是2004年寫的,因為當年陳水扁競選連任成功。裡面有一篇章叫「送信給加西亞」,當年我沒查到故事來源,此事我以為就從此沒下文了,誰知,今天開完會後,有個同仁竟然幫我查到了,底下錄下原文章,因為寫的比我要表達的還好:




在一切有關古巴的事情中,有一個常常從我記憶中冒出來讓我難以忘懷。
美西戰爭爆發時,美國必須立即與古巴的起義軍首領加西亞取得聯繫。加西亞在古巴廣闊的山脈裡──沒有人確切地知道他在哪裡,也沒有任何郵件或電報能夠送到他手上。而美國總統麥金菜又必須盡快地得到他的合作。
怎麼辦呢?
有人對總統說:”如果有人能夠找到加西亞的話,那麼這個人就是羅文”。於是總統把羅文找來,交給他一封寫信加西亞的信,關於那個名叫羅文的人,如何拿了信,用油紙袋包裝好,打封,放在胸口藏好;如何經過4天的船路到達古巴,再經過3個星期,徒步穿過一個危機四伏的國家,終於把那封信送給加西亞──這些細節不是我想說的。我要強調的重點是:美國總統把一封寫給加西亞的信交給羅文:而羅文接過信之後,並沒有問:”他在甚麼地方?”
像羅文這樣的人,我們應該為他塑造銅像,放在所有的大學裡,以表彰他的精神。年輕人所需要的不僅僅是從書本上學習來的知識,也不僅僅是他人的種種教誨,而是要加強一種敬業精神:忠於上級的托付,迅速地探取行動,全心全意地完成任務──”把信送給加西亞”。
加西亞將軍已經不在人世,但現在還有其他的”加西亞”。沒有人能夠經營好這樣的企業──在那裡雖然有眾多人手,但是令人驚訝的是,其中充滿了許多碌碌無為的人,這些人要麼沒有能力,要麼不情願去集中精力做好一件事。
懶懶散散﹑漠不關心﹑馬馬虎虎的做事態度,似乎已成常態;沒有人能夠成功,除非苦口心﹑威逼利誘地強迫他人幫忙。或者,除非奇跡出現,上派一名天使提供幫助,不然沒有人能把事情辦成。
不信的話,你可以做個試驗;此刻,你坐在辦公室裡──周圍有6名職員。把其中任何一名叫過來,對他說:”請幫我查一查百科全書,把克里吉奧的生平做成一篇摘錄。”
他會靜靜地說:”好的,先生。”
然後他會去執行嗎?
他敢說他絕對不會,他會用死魚般的眼睛盯著你,然後滿臉狐疑他提出一個或數個問題:他是誰呀?
哪套百科全書?
百科全書放在哪兒?
這是我的工作嗎?
為甚麼不叫喬治去做呢?
他死了嗎?
急不急?
需不需要我拿書過來,你自己查?
你為甚麼要查他?
我敢以十比一的賭注你打賭,在你回答了他提出的所有問題,解釋了怎樣去查那些資料,解釋了怎樣去查那些資料,以及你為甚麼要查的理由之後,那個職員會走開,吩咐另外一個職員去幫他查那些資料,然後,會回來告訴你,沒有這個人。當然,我可能會輸了這個賭注,但是根據平均概率法則,我不會輸。
現在,如果你夠聰明,你不會對你的助理”解釋”,克里吉奧編在甚麼,而不是甚麼類,你會滿臉笑容地說:”沒關係。”然後自己去查。
這種自主行動的無能,這種道德上的愚行,這種意志上的脆弱,這種惰性的風氣,這就是十來社會被帶到崩潰境地的根源。
如果人們都不能為了自己而自主行動,人們又怎麼可能心甘情願地為他人服務呢?
乍看起來,所有的公司都有許多可以委以任務的人選,但是事實真是如此嗎?你刊登廣告招聘一名速記員,應聘者中,十有八九不會拼也不會寫,他們甚至認為這些都無所謂。
這種人能夠寫一封給加西亞的信嗎?
“你看那個職員。”一家大工廠的主管對我說。
“我看到了,他怎麼樣?”
“他是個很好的會計,不過如果我讓他去城裡辦個小差事,他可能會完成任務,但很可能在途中走進酒吧,而到了鬧巿區,他還可能根本忘記了他的差事。”
這種人你能把給加西亞送信的任務交給他嗎?
近來,我們聽到了許多人對”那些薪水微薄而又無出頭之日的工人”以及”那些為了尋找一份舒適的工作而顏繁跳糟的人”表示同情,同時把那些僱主詛咒一通。
這是從來沒有人提到,那些年齡正在不斷變老僱主們白費了多少時間和精力去促使那些不求上進的懶蟲們勤奮起來;也沒有人提到,有些僱主持久而耐心地想感動些當他一轉身就投機取巧,敷衍了事的員工。
在每個商場和企業,都有一些常規性的整頓工作。僱主們經常送走那些不能對公司有所助益的員工,同時也接納一些新的成員。不論務怎麼忙碌,這種淘汰工作都要進行。只有當經濟形勢不景氣的時候,就業機會不多的時候,整頓才會有明顯的績效──那些不能勝任﹑沒有才能的人,都被擯棄於公司大門之外,只有最能干的人,才會被留下來。這是一個優勝劣汰的機制。僱主為了自己的利益,只會保留那些最佳的職員──那些能把信送給加西亞的人。
我認識一個有真才實學的人,他沒有獨自創業的能力,並且對他人也沒有絲毫的價值,因為他總是偏執地懷疑他僱主在壓榨他,或有壓榨他的傾向。他沒有能力指揮,也不願意被他人指揮。如果你要他去把信送給加西亞,他的回答很可能是:”你自己去吧﹗”
當然,我知道像這種道德不健全的人比那些肢體不健全的人更不值得同情;但是我們對那些用畢生精力去經營一個偉大企業的人也應該予以同情:下班的鈴聲不能夠停止他們的工作,他們因為努力維持那些漠不關心﹑偷懶被動﹑不知感激的員工的工作而白髮日增。那些員工從來不願想一想如果沒有僱主們付出的心血,他們是否將挨餓或者無家可歸?
我是否說得太嚴重了?可能如此。但是,就算整個世界變成貧民窟之時,我也要為成功者說幾句同情的話──這些人在成功機極小的情況下,承受巨大的壓力,導引眾人的力量,終於獲得了成功;但他從成功中所得到的是一片空虛,除了食物和衣服,其他甚麼也沒有。
我曾經為了衣食而他人工作,也曾經當過一些僱員的老板,我深知其中兩方面的種種甘苦。貧窮沒有甚麼優越之處,也不值得贊美;衣衫襤褸更不值得驕傲;並非所有的僱主都是探取高壓手段極力壓榨員工,並且我敢說大多數僱主都更富有美德。
我欽佩的是那些不論老板在還是不在都會努力工作的人,我也敬佩那些能夠把信交給加西亞的人,迅速地接受任務,不會提出任何愚蠢的問題,更不會隨手把信扔到水坑里,而是全力以地把信送到。這些人永遠不會被解僱,也永遠不會為加薪而罷工。

======= 分割線 ============
後來我又查到了一篇,也許是正牌的原文翻譯,不過這故事就如同我的那位同事說的,也許是美國家戶喻曉的故事吧。



2011/09/07

隨身碟多重開機又一章 Advanced for multi-OS on usb disk

寫過一篇 grub on usb disk, 再加上上一篇的從隨身碟開機, 後面這篇其實我沒表達的很完整,主要要講的是如何從隨身碟放進 liveCD 的 iso 檔,然後做多重開機。而前一篇則示範如何將 usb disk 放進 grub.....不過以現在的 Ubuntu 來說,你可以直接從 LiveDVD 安裝到 usb disk 也可以做到。

不過,grub on usb disk 這篇文章還示範了一個很有用的使用情境,你可以用 dd 來產生一個 usb disk image file, 然後再搭配從隨身碟開機,這樣可以得到另一個好處:

不必隨身碟,也可以用 VirtualBox 來虛擬隨身碟的多重開機,然後必要的時候,把它 dd 到隨身碟裡,你的隨身碟就有最新的多重開機環境。而且在製作多重開機隨身碟時,若使用這個方法,因為 image file 是在硬碟中,所以速度上會快很多。

底下以 16G 為例


1. $ dd if=/dev/zero of=16G.dd bs=262144 count=1 seek=61696
2. $ sudo losetup /dev/loop0 16G.dd
3. fdisk .... mkfs.....,用法上就跟硬碟/隨身碟一樣:
    $ sudo fdisk /dev/loop0
4. $ sudo VBoxManage internalcommands createrawvmdk -filename ~/.VirtualBox/usb-16G.vmdk -rawdisk /dev/loop0
......

快速產生特定大小的檔案 using dd fast create specified size file

dd 可以做很多事,這一點我想不必多說,它不止可以「複製」硬碟/隨身碟,還可以做轉換,網路上有人把它稱為瑞士刀。如果只會 dd if=/dev/zero of=my-dd-file bs=1M count=10 這樣的語法的話,那就遜掉了。以現代做嵌入式應用來說,dd 是個不可不學的指令,若你想要 remaster 自己的系統,似乎也離不開 dd.

這邊要提醒一個用法,可以「一瞬間」就產生特定大小。像我要產生一個 16G 大小的 image file,  以我手邊的隨身碟來看,原始大小是 16173498368, 我用的命令是 dd if=/dev/zero of=16G.dd bs=262144 count=1 seek=61696


其中 bs 是 block size, 這個大家都知道,因為一般的隨身碟或硬碟的 block size 都是 512, dd 的預設也是這麼大。上述 bs 也可以設計成 512, 這個是一次讀寫的量,因為記憶體都夠大,寫大一點照理會加速讀寫,所以我就設計成 512*512=262144,而 seek=61696 是計算來的,它等於 16173498368/512/512

這個命令的執行速度是
$ dd if=/dev/zero of=16G-2.dd bs=262144 count=1 seek=61696
1+0 records in
1+0 records out
262144 bytes (262 kB) copied, 0.00109749 s, 239 MB/s

2011/09/06

從隨身碟開機 raw disk image at virtualbox

這篇文章要寫的,主要是我把 Linux 安裝在我的隨身碟中,裝了幾個不同的系統,其中主要的就是 ubuntu, 加上幾個用 iso 檔的系統,例如 GeeXboX 2.0, TinyCore 等等,這當然能把作業系統隨身帶著走,不過有時找不到機器,那就可以考慮用 Virtualbox 來開機同樣的文章還可以參考這篇

先貼一下上面關於 GeeXboX 2.0, TinyCore 的 grub2 設定檔,這邊要提醒的是,Grub2 與 Grub1 的設定檔差很大。這個設定檔,按照 Ubuntu 的設定,只需要放在 /boot/grub/custom.cfg 即可「自動」生效。

menuentry "GeeXboX 2.0 alpha2" --class os {
  set isofile="/livecd/geexbox-2.0-alpha2-en.i386.eglibc.iso"
  loopback loop $isofile                          # 這個 loopback 設定,在硬碟中是 (hd1,msdos1)$isofile
                                                           # 請參考自己的環境適當修改
  linux (loop)/GEEXBOX/boot/vmlinuz root=/dev/ram0 rw rdinit=linuxrc boot=cdrom lang=en vga=788 video=vesafb:ywrap,mtrr hdtv quiet loglevel=3
  initrd (loop)/GEEXBOX/boot/initrd.gz
}
menuentry "Tinycore" --class os {
  set isofile="/livecd/tinycore.iso"
  loopback loop $isofile  # 同上
  linux (loop)/boot/bzImage
  initrd (loop)/boot/tinycore.gz
}
上面只是範例而已,要自己測試修改,其中 isofile 的目徑請務必自己修改。

上面 Virtualbox 來開機的教學是用 Windows(感謝微軟),相當簡單,若是想在 Linux Host 裡面用的話,反而要注意一件事,就是權限問題,若用 root 跑 virtualbox  當然不會有問題,若要用一般帳號的話,則要記得把隨身碟的 device 權限改成普通帳號可以存取的。至於命令很類似,參考文章改一下即可。

當然在 Linux 下命令與 windows 不太一樣,把兩者並列供大家參考:



-- Windows --
VBoxManage internalcommands createrawvmdk -filename "%USERPROFILE%"\.VirtualBox\usb.vmdk -rawdisk \\.\PhysicalDrive#
上面的 PhysicalDrive# 是透過 diskmgmt.msc 這個命令來查找的,主要就是隨身碟的「磁碟機編號」


-- Linux -- 
VBoxManage internalcommands createrawvmdk -filename ~/.VirtualBox/usb.vmdk -rawdisk /dev/sdb
上面的 /dev/sdb 相信大家都會,可以用 fdisk -l 命令來查隨身碟的編號

2011/08/15

套件管理 比較 package management

有一份文件叫『套件管理工具比較』,閱讀原文件比較易讀,作為備份,我轉載如下,以後有空也許也會分享心得:

比較一下現在市面上幾種套件管理工具
(debian - apt , gentoo - emerge , freebsd - prots)

其它參考: APT 用法、emerge 用法

深入內容中有 emerge, apt, ports 的語法比較(也可以說是語法教學吧)


以下轉載自: Gentoo/Debian/FreeBSD套件管理memo

以關鍵字搜尋軟體
Gentoo: emerge -s
輸出會有這個 pkg 的簡介 , 關鍵字都可以用正規表示式
Debian: apt-cache search
FreeBSD: make search name= 或 ports_glob -- need portupgrade

安裝軟體
Gentoo: emerge
Debian: apt-get install
FreeBSD: portinstall

移除軟體
Gentoo: emerge --unmerge 或 emerge -C
Debian: apt-get remove
FreeBSD: pkg_deinstall

升級單一軟體
Gentoo: emerge -u
Debian: apt-get install
FreeBSD: portupgrade

察看升級全系統會動到哪些套件:
Gentoo: emerge -puDv world
Debian: apt-get -u dist-upgrade
FreeBSD: portupgrade -arnv

升級全系統
Gentoo: emerge -u --deep world
Debian: apt-get dist-upgrade
FreeBSD: make world ; portupgrade -ar

查詢系統裝了哪些軟體
Gentoo: emerge -pe world 或 qpkg -I -v
Debian: dpkg --get-selections
FreeBSD: pkg_info

查詢某檔案屬於哪個軟體
Gentoo: qpkg -f
(need gentoolkit)
Debian: dpkg -S
FreeBSD: pkg_info -W

查詢某個套件安裝了什麼檔案
Gentoo: qpkg -l
Debian: dpkg -L
FreeBSD: pkg_info -L

查詢有沒有裝這個關鍵字的套件
Gentoo: qpkg -I | grep (qpkg再加上 -v 看版本號碼)
Debian: dpkg -qa | grep
FreeBSD: pkg_info | grep

找哪些 pkg "簡介" 裡含有你要找的關鍵字:
Gentoo: emerge -S <關鍵字>
輸出方式和前者一樣, 關鍵字都可以用正規表示式
Debian: apt-cache search
FreeBSD: make search key=

不管相依性強制移除某套件
Gentoo: emerge -C
Debian:
FreeBSD: pkg_delete -f

全系統重新編譯
Gentoo: emerge -e world
Debian: ?
FreeBSD: make world ; portupgrade -arf

========
補充:
qpkg -f
ps: emerge gentoolkit first.

--
gentoo 裡:
查詢某個套件安裝了什麼檔案:
qpkg -l
查詢有沒有裝這個關鍵字的套件:
qpkg -I (再加上 -v 看版本號碼)
不管相依性強制移除某套件:
emerge -C

--
仔細看一下 man emerge
要找一個 pkg 的 "名稱":
emerge -s <關鍵字>
輸出會有這個 pkg 的簡介

找哪些 pkg "簡介" 裡含有你要找的關鍵字:
emerge -S <關鍵字>
輸出方式和前者一樣

更厲害的是上面的關鍵字都可以用正規表示式!!

--
emerge -f (fetchonly)
好處在於當你emerge 兩個package以上的時候,可以先把source給抓回來,不過需要再emerge

emerge -p (pretend)
看要裝些什麼東西,

小弟認為這兩個指令對撥接使用者很重要,尤其 -f .一來可以大略知道下載時間,二來可以隨時中斷,然後在續傳(感謝偉大的wget)
--
升級單一軟體
Gentoo: emerge -u
Debian: apt-get install
FreeBSD: portupgrade

查詢某個套件安裝了什麼檔案
Gentoo: qpkg -l
credit to paar@gentoo.org.tw
Debian: dpkg -L
FreeBSD: pkg_info -L

全系統重新編譯
Gentoo: emerge -e world
Debian: apt-get update;apt-get upgrade
FreeBSD: make world ; portupgrade -arf

2011/08/11

Google Nexus S

先前把我的手機換成 Nexus S,......關於網路的使用,我一直是使用 usb....結果今天試著用 Wifi 分享,哪知....Wifi 的速度幾乎是 usb 的10倍!!!!而且不太會停頓........ 雖然說,用 usb 要多轉兩次,這也差太多了吧

2011/08/05

svn tag/branch

剛剛寫了一篇 svn on ubuntu,現在來談談對 release 的版本控制要怎麼進行。

版本控制有很多事要做,release 算是重要的一環。最簡單的就是自己在 commit 時加到註解中,然後日後自行讀 log 來判斷 release version

上面這種做法好處就是簡單,但是真正要做版本控制就有點複雜,因為必須從一堆 log 去找出來,當時間過去很久之後,這並不是一件簡單的事。因此比較正規的作法是用 svn copy 來完成。不過為了這個功能,一般書上會講一件事,就是目錄的擺放。我舉前面提到的 /home/svn/wade 來說....

首先,假如是用 log 來決定 release version 的話,大可以把所有 source code 都直接擺放 /home/svn/wade 下即可。但是若要用 svn copy 來做版本控制的話,依建議是.....
假設已經 checkout wade project 了,那麼在該工作目錄下執行底下兩個命令:
svn mkdir trunk
svn mkdir tags

然後,把所有 source code 都擺放在 trunk 目錄下,也就是真正的工作目錄是 /home/svn/wade/trunk
當你要 release source code 時,再用下面的命令:
svn copy http://localhost/svn/wade/trunk http://localhost/svn/wade/tags/release-1.0 -m "first release"

簡單講,svn 的 tag/branch 就是用 copy 來實現,而且是把工作目錄複製一份新的......當做了上面的命令之後,可以再接著用下面的命令來 release source code

svn export http://localhost/svn/wade/tags/release-1.0