# 假設你已經從 A 站 clone 下來,這時 origin 指向 A 站
git remote rename origin upstream
# 新增 B 站的遠端儲存庫
git remote add origin [B 站的 Repository URL]
# 之後你就可以 push 到 B 站了
git push -u origin main
# 如果需要,也可以從 A 站拉取更新
git pull upstream main
# 假設你已經從 A 站 clone 下來,這時 origin 指向 A 站
git remote rename origin upstream
# 新增 B 站的遠端儲存庫
git remote add origin [B 站的 Repository URL]
# 之後你就可以 push 到 B 站了
git push -u origin main
# 如果需要,也可以從 A 站拉取更新
git pull upstream main
git config --global credential.helper wincred關於 timeout 的設定就沒有看到了。
hg bookmark -r default master(4) 在原來的 hg 的目錄下,執行以下命令,把歷史推上去:
hg push git+https://bitbucket.org/username/hg-projectname-git(5) 用 git clone 新路徑。之後就用這個新的 git clone 目錄工作。
You don’t have to get fancy to get most of your work done with Git; start with these essential commands
用 git 工作你不需要趕流行用什麼特技,只要用這些基本指令就好。
大多數公司都用 git,不只為了開發商業或消費性 app。科學與政府組織也有好理由,所以這些技術越來越常被使用。
git 允許漸進式合作,快速散佈,為程式碼建立信心,三個都是很重要的目標,所以很多團隊納為 devops 的手法。為了要達成這些目標,許多 git 平台包含整合工具支援程式碼測試與團隊管理。
就算 git 變得無所不在,仍有一些在觀望。 GitLab 最近有個調查,發現 40% 的開發團隊憂心 git 的學習曲線。自然地,在 GitLab,我每天用它工作,我了解 git 對新使用者的挑戰。
幸運的是,有大量的資源可以幫助新使用者克服他們的焦慮。許多公司,包含我們自己,都有免費資源給想要學習的開發者。除了公司主導的資源外,git 也有很多社群技援,分享許多常見問題的解法。
要了解 git,最好要知道它是從命令列來的。但是,有經驗的 git 使用者喜歡客戶端有簡易介面讓易用性提高。Git Tower 與 Tortoise Git 就是非常好的客戶端程式。
好消息是,多數開發者可以只學幾個基本指令就可以處理大多數的工作。與 repo 同步、建立新分支、建立新增與提交,把改變推回遠端等,這幾個工作,使用以下會提到的七個命令就可以做到。git 不需要搞得太複雜。
git checkout master
這個 git checkout 讓你在分支間移動,並回復檔案。git checkout master 會切換到主線,這是你要改東西之前最好的出發點。
git pull origin master
一但你切到主線,你可以用 git pull origin master 保證你的分支裡的東西是repo的裡最新的。這是通常在合併上游改變之後要做的事。git pull實際上是合併了git fetch(這是把最後資訊抓回來) 與git merge(這把兩個歷史合併)這兩個命令。基本上,git pull origin master讓你一次做兩個命令,這非常省時間。
在一個 repo 開始工作前,執行一次 git pull origin master 是個好主意。畢竟,在協作過程中,你會想要確定你的 repo 跟遠端最新的是一樣的內容。
git checkout -b branchname
這個命令用來建立新的分支,分支名是 “branchname”,然後移動過去。
分支是 git 的基礎功能。想要開個新功能嗎?輸入git checkout -b new-feature,建立一個新分支叫做”new-feature”,然後開啟它。這個新分支讓你平行開發,與你的同事之間是一個,你自己是另一個分支,程式碼分開,不會互相干擾。
當你準備好要分享你的工作成果,你可以把分支推去遠端或是合併到新分支(通常是主線),這些指令馬上來說明…。
git status
讓 git 告訴你現在你的 repo 的狀況。例如,git 會指出哪些檔案有改變過或是你的分支新增的。然後 git 會給予建議該怎麼做,提供指令如何 stage 或 commit 這些檔案。
git add
這個指令會在工作目錄加入一個改變,使得它放到台面(也就是標記為改變的一部份)。這個改變可以是移除或新增一個檔案或目錄。這是提交改變的準備步驟。實際的動作已經做完了,但這個命令只是正式申明這些改變要被提交。
如果你對所有改變都很滿意,你可以加上 -all選項,git add -all會標明所有這個工作目錄與子目錄的改變,包含目錄的移除。
git commit
這個命令會記下你的改變,放在本地端 repo。不要與git push搞混,接下來會解釋。你也可以使用git commit刪除檔案,用些迂迴的方式來做。
git 是個整包的提交,也就是說提交是個改變(裡面會包含此次所有的新增、刪除、更新)。git commit 會把之前用git add記為改變的提交出去。這個改變是記在本地 repo。要分享出去就一定要推到遠端。
git push
執行這個命令會推送你的改變到遠端,有數個方式你可以調整。單純git push這個指令,會改變 repo 與它的所有相關。
git push <remote> <branchname> 這指令會推送本地端 的改變到,它通常是你協作同事的伺服器。預設,第一個 remote 叫做 “origin”,如果你在 “new-feature” 分支有改變,你可以下 git push origin new-feature,把改變(提交)送到你協作同事的地方。
你完全可以用以上的指令把 git 相關工作搞定。通常開發者會遇到困難是因為他們想用複雜指令像是git rebase而把事情搞得太複雜,而導致不清楚自己在做什麼以及是否有必要搞這些。
當有疑問的時候,執行git status,讓 git 告訴你。
前一陣子試著使用 dulwich 來操作 .git 裡面的資料,例如上傳到 changeset 到 remote、下載 changeset 到 local。看起來都很正常。但是,把檔案從 .git 裡面拿出來放,就會判定某些檔案被改變,我去檢查內容,自己使用 sha,md5 對兩個檔案檢查,結果顯示兩個檔案內容完全一樣。我想,dulwich 這麼多人用,難道我又遇到「沒人會遇到」的問題嗎?
另外我使用 tortoisegit 來檢查其內容,一樣也是說相同,但是用 dulwich 拉回來的 .git,跟 tortoisegit 拉回來的 .git 對於相同檔案,卻是一個說相同,一個說有改變。這可搞死我了,難道要放棄使用 dulwich 嗎?
後來翻到一個舊的 tortoisegit 的 issue:https://code.google.com/p/tortoisegit/issues/detail?id=812
Allow to change git file permission mask / attributes (especially executable bit)
才知道,dulwich 可能也是中同一個招數。git 是有檢查 Read, Write, Execute vs User, Group, Other 的。於是就可以解釋,為何只要是 script 或是 linux 的執行檔才會出現內容相同,但被判定有改變。在 windows 的檔案權限是 666,跟原來的不一樣了,也沒辦法改成 755。不曉得 tortoisegit 怎麼解決這問題的…。我這裡暫時停止研究了。
原本有在用 hg,還以為會很順利地就會使用 git。
結果,等到真正開始管專案,第一個遇到的就是,revert 呢?
因為原本很習慣地,只要有臨時改過某個檔,要回到原狀,就很簡單地「指」著那個檔按右鍵,選revert
在下圖按下 revert 就解決了。
但是,在 tortoisegit 我眼花啦~~~~~!!
我找了兩天啊!可說是上天下海用 google 去找,怎麼沒有人會有這種問題呢?
大概沒有人跟我一樣眼睛被蚵仔擋到,就在這兒啊,怎麼會有人要問這種問題呢?
其實還真有…
http://stackoverflow.com/questions/8011538/git-pulling-only-certain-files
https://github.com/jelmer/dulwich
安裝…找不到說明,BUT!
出奇的簡單,用 git 從 github 下載回來,使用 setup.py install 就搞定。
操作…
操作的文件在這 http://www.samba.org/~jelmer/dulwich/docs/tutorial/index.html,真的是RTFM,不注意還找不到文件在哪裡。我太嫩了。
已經知道細節的人,可以直接跳 http://www.samba.org/~jelmer/dulwich/docs/tutorial/repo.html 開始!但是,不知道細節的人,一定要從頭到尾看清楚每個字,尤其是 Introduction,它把這個軟體的功能說的很清楚。就是「它有寫的就是它能做的」。我原先以為他能像 git command line 工具一樣操作,結果不是。文章中,介紹了 .git 裡面的三個物件,commit, tree, blob,dulwich 軟體主要就是讓你操作這三個物件來達成你想要的動作。於是經過了嘗試、失敗、掙扎、又嘗試別的程式,失敗,掙扎,又回來嘗試這程式…的循環,我得到了我想要的結果。
我這裡整理一下我知道的跟我不知道的對應表。
| git init myrepo | from dulwich.repo import Repo |
| git --bare init | 不知道該怎辦。因為我只是把 dulwich 當 client 端,應該不會用到這個指令。 |
| git add foo.txt | repo.stage(["foo.txt"]) |
| git commit | commit_id = repo.do_commit("The first commit", committer="your name <name@example.com>") |
| git clone | 說明:這個大家最常用來抓新專案的指令,沒辦法直接對應,要先使用 fetch,再自行把檔案內容從 stores 裡面抓出來,寫到本地端的檔案系統。 例: repo = Repo("myrepo") 這是我不小心在亂晃的時候發現的 https://lists.launchpad.net/dulwich-users/msg00116.html 藏得很隱密 |
| git fetch | 目前到 github 我都是用 https:// 的,所以就試了一個用 https:// 的。git:// 的我沒試。 server_address = 'https://github.com/' client = HttpGitClient(server_address) local = Repo.init("local", mkdir=True) remote_refs = client.fetch("/jelmer/dulwich.git", local, determine_wants=local.object_store.determine_wants_all, progress=sys.stdout.write) local["HEAD"] = remote_refs["HEAD"] #這個很重要,不然會沒有HEAD! |
https://github.com/qrpike/NodeJS-Git-Server
在照該網站上的步驟進行,到了要用 git 測試,就會出現
events.js:72
throw er; // Unhandled 'error' event
^
Error: spawn ENOENT
at errnoException (child_process.js:980:11)
at Process.ChildProcess._handle.onexit (child_process.js:771:34)
不曉得為什麼,已經在那裡留 issue 了。
但是在 ubuntu 就沒問題…。
後續:
後來不死心,用了最笨的方法,就是在 source code 裡到處加 console.log,看看程式怎麼跑。
後來知道了兩點,就把它修好了。
一、啟動新 server 需要指定 repoLocation。因為預設是 /tmp/repo,這目錄在 windows 下一定不存在。
二、git-server 其實是執行 git 指令,所以,一定要安裝 git,以 windows 來說,我安裝了 msysgit 的 Git-1.8.1.2-preview20130201.exe。
三、git-server 其實是執行 git 指令,又不會自帶路徑,所以要在環境變數 path,加入以下路徑:
C:\Program Files (x86)\Git\bin;C:\Program Files (x86)\Git\libexec\git-core
這樣,就可以啟動 git-server 了。
因為有人說,因為大家都是 *nix like,只有 windows 不是,所以有問題會很慢才解決,我當場就把作業系統給換成 ubuntu。
gitteh 是一個讓 nodejs 可以用程式的方式來執行 git 指令,因為我想要自動偵測新檔案出現,就自動 commit,所以腦筋就動到這東西來了。也有人說,只要會用 shell 指令,把 stdout 導出來,再做一些文字解析的工作,也就完成一樣的事,不過,就是怕改版文字會跑掉。所以,有人就寫了 libgit2 的 C 語言函式庫讓人使用,再由各語言呼叫 C 函式庫來滿足大家的需求,例如 nodejs、python。而 nodejs 的 bindings 就叫做 gitteh。
libgit2 的網站 http://libgit2.github.com/
gitteh 的網站 https://github.com/libgit2/node-gitteh
在 github 這裡,就只有說 npm install gitteh 就好,看了就很高興。
BUT! 人生就怕這個字。
執行 npm install gitteh 遇到
hadoop@ubuntu:~/nodejs/myapp/src$ npm install gitteh
npm http GET https://registry.npmjs.org/gitteh
npm http 304 https://registry.npmjs.org/gitteh> gitteh@0.1.0 preinstall /home/hadoop/nodejs/myapp/src/node_modules/gitteh
> node-waf configure --use-bundled-libgit2sh: 1: node-waf: not found
npm ERR! weird error 127
npm ERR! not ok code 0
以為是少 node-waf,於是下指令 npm install node-waf
結果
hadoop@ubuntu:~/nodejs/myapp/src$ npm install node-waf
npm http GET https://registry.npmjs.org/node-waf
npm http 404 https://registry.npmjs.org/node-waf
npm ERR! 404 'node-waf' is not in the npm registry.
npm ERR! 404 You should bug the author to publish it
npm ERR! 404
npm ERR! 404 Maybe try 'npm search waf'
npm ERR! 404
npm ERR! 404 Note that you can also install from a
npm ERR! 404 tarball, folder, or http url, or git url.npm ERR! System Linux 3.5.0-17-generic
npm ERR! command "/home/hadoop/.nvm/v0.10.7/bin/node" "/home/hadoop/.nvm/v0.10.7/bin/npm" "install" "node-waf"
npm ERR! cwd /home/hadoop/nodejs/myapp/src
npm ERR! node -v v0.10.7
npm ERR! npm -v 1.2.21
npm ERR! code E404
npm ERR!
npm ERR! Additional logging details can be found in:
npm ERR! /home/hadoop/nodejs/myapp/src/npm-debug.log
npm ERR! not ok code 0
唉~~
試了 http://stackoverflow.com/questions/13784551/how-to-install-node-gitteh-module-from-npm-nodejs-0-8-x
npm install git://github.com/jmendeth/node-gitteh.git
失敗再試 https://github.com/libgit2/node-gitteh/issues/21 還是失敗我想試試先安裝 libgit2,npm install libgit2,結果找不到。npm search libgit2 有找到一個 nodegit,就來試試,npm install nodegit。跑了一大串之後得到> nodegit@0.0.79 install /home/hadoop/nodejs/myapp/src/node_modules/nodegit
> node install.js[nodegit] Downloading libgit2 dependency.
[nodegit] Building libgit2 dependency.
/usr/bin/env: cmake: No such file or directory
npm ERR! weird error 127
npm ERR! not ok code 0
於是 sudo apt-get install cmake 後,再一次,結果換 g++ 找不到。依稀記得有個 build-essential,就裝它吧。 sudo apt-get install build-essential 。再一次安裝 nodegit。好像成功了,雖然有 WARN
npm WARN package.json cli-table@0.2.0 No repository field.
nodegit@0.0.79 node_modules/nodegit
├── async@0.2.8
├── request@2.9.203
├── tar@0.1.17 (inherits@1.0.0, block-stream@0.0.6, fstream@0.1.22)
├── fs-extra@0.6.0 (jsonfile@0.0.1, ncp@0.4.2, mkdirp@0.3.5, rimraf@2.1.4)
└── node-gyp@0.8.5 (which@1.0.5, osenv@0.0.3, graceful-fs@1.2.1, rimraf@2.1.4, semver@1.1.4, mkdirp@0.3.5, glob@3.2.1, fstream@0.1.22, npmlog@0.0.2, nopt@2.1.1, minimatch@0.2.12)
又回到執行 npm install gitteh,登登!
> gitteh@0.1.0 preinstall /home/hadoop/nodejs/myapp/src/node_modules/gitteh
> node-waf configure --use-bundled-libgit2sh: 1: node-waf: not found
npm ERR! weird error 127
npm ERR! not ok code 0
此路不通啊。
下載 git clone https://github.com/libgit2/node-gitteh.git 來安裝試試
hadoop@ubuntu:~/nodejs/myapp/src/node-gitteh$ node install.js
module.js:340
throw err;
^
Error: Cannot find module 'async'
at Function.Module._resolveFilename (module.js:338:15)
at Function.Module._load (module.js:280:25)
at Module.require (module.js:364:17)
at require (module.js:380:17)
at Object.<anonymous> (/home/hadoop/nodejs/myapp/src/node-gitteh/install.js:1:75)
at Module._compile (module.js:456:26)
at Object.Module._extensions..js (module.js:474:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
at Function.Module.runMain (module.js:497:10)
看來是 async 找不到,就裝一下,
hadoop@ubuntu:~/nodejs/myapp/src/node-gitteh$ npm install async -g
npm http GET https://registry.npmjs.org/async
npm http 304 https://registry.npmjs.org/async
npm WARN package.json github-url-from-git@1.1.1 No repository field.
npm WARN package.json assert-plus@0.1.2 No repository field.
npm WARN package.json ctype@0.5.2 No repository field.
async@0.2.8 /home/hadoop/.nvm/v0.10.7/lib/node_modules/async
再試發現裝到 global 好像沒反應,就改裝在工作目錄。
hadoop@ubuntu:~/nodejs/myapp/src/node-gitteh$ node install.js
module.js:340
throw err;
^
Error: Cannot find module 'async'
at Function.Module._resolveFilename (module.js:338:15)
at Function.Module._load (module.js:280:25)
at Module.require (module.js:364:17)
at require (module.js:380:17)
at Object.<anonymous> (/home/hadoop/nodejs/myapp/src/node-gitteh/install.js:1:75)
at Module._compile (module.js:456:26)
at Object.Module._extensions..js (module.js:474:10)
at Module.load (module.js:356:32)
at Function.Module._load (module.js:312:12)
at Function.Module.runMain (module.js:497:10)
hadoop@ubuntu:~/nodejs/myapp/src/node-gitteh$ npm install async
npm http GET https://registry.npmjs.org/async
npm http 304 https://registry.npmjs.org/async
async@0.2.8 node_modules/asynchadoop@ubuntu:~/nodejs/myapp/src/node-gitteh$
npm install async
npm http GET https://registry.npmjs.org/async
npm http 304 https://registry.npmjs.org/async
async@0.2.8 node_modules/asynchadoop@ubuntu:~/nodejs/myapp/src/node-gitteh$
hadoop@ubuntu:~/nodejs/myapp/src/node-gitteh$
hadoop@ubuntu:~/nodejs/myapp/src/node-gitteh$
hadoop@ubuntu:~/nodejs/myapp/src/node-gitteh$
hadoop@ubuntu:~/nodejs/myapp/src/node-gitteh$ node install.js
[gitteh] Downloading libgit2 dependency.
Submodule 'deps/libgit2' (git://github.com/libgit2/libgit2.git) registered for path 'deps/libgit2'
Cloning into 'deps/libgit2'...中間省略
[gitteh] Building native module.
/bin/sh: 1: ./node_modules/.bin/node-gyp: not found
又少 node-gyp。再來 npm install node-gyp
hadoop@ubuntu:~/nodejs/myapp/src/node-gitteh$ npm install node-gyp
npm http GET https://registry.npmjs.org/node-gyp
npm http 304 https://registry.npmjs.org/node-gyp
npm http GET https://registry.npmjs.org/tar
npm http GET https://registry.npmjs.org/fstream
npm http GET https://registry.npmjs.org/graceful-fs
npm http GET https://registry.npmjs.org/minimatch
npm http GET https://registry.npmjs.org/mkdirp
npm http GET https://registry.npmjs.org/nopt
npm http GET https://registry.npmjs.org/npmlog
npm http GET https://registry.npmjs.org/osenv
npm http GET https://registry.npmjs.org/request
npm http GET https://registry.npmjs.org/rimraf
npm http GET https://registry.npmjs.org/semver
npm http GET https://registry.npmjs.org/which
npm http GET https://registry.npmjs.org/glob
npm http 304 https://registry.npmjs.org/graceful-fs
npm http 304 https://registry.npmjs.org/minimatch
npm http 304 https://registry.npmjs.org/fstream
npm http 304 https://registry.npmjs.org/nopt
npm http 304 https://registry.npmjs.org/npmlog
npm http 304 https://registry.npmjs.org/osenv
npm http 304 https://registry.npmjs.org/request
npm http 200 https://registry.npmjs.org/tar
npm http 304 https://registry.npmjs.org/rimraf
npm http 304 https://registry.npmjs.org/semver
npm http 304 https://registry.npmjs.org/which
npm http 304 https://registry.npmjs.org/glob
npm http 304 https://registry.npmjs.org/mkdirp
npm http GET https://registry.npmjs.org/ansi
npm http GET https://registry.npmjs.org/abbrev
npm http GET https://registry.npmjs.org/lru-cache
npm http GET https://registry.npmjs.org/sigmund
npm http GET https://registry.npmjs.org/inherits
npm http GET https://registry.npmjs.org/inherits
npm http GET https://registry.npmjs.org/inherits
npm http GET https://registry.npmjs.org/block-stream
npm http 304 https://registry.npmjs.org/abbrev
npm http 304 https://registry.npmjs.org/sigmund
npm http 304 https://registry.npmjs.org/lru-cache
npm http 304 https://registry.npmjs.org/ansi
npm http 304 https://registry.npmjs.org/inherits
npm http 304 https://registry.npmjs.org/inherits
npm http 304 https://registry.npmjs.org/block-stream
npm http 304 https://registry.npmjs.org/inherits
node-gyp@0.8.5 node_modules/node-gyp
├── which@1.0.5
├── osenv@0.0.3
├── graceful-fs@1.2.1
├── rimraf@2.1.4
├── semver@1.1.4
├── mkdirp@0.3.5
├── request@2.9.203
├── nopt@2.1.1 (abbrev@1.0.4)
├── fstream@0.1.22 (inherits@1.0.0)
├── minimatch@0.2.12 (sigmund@1.0.0, lru-cache@2.3.0)
├── npmlog@0.0.2 (ansi@0.1.2)
├── tar@0.1.17 (inherits@1.0.0, block-stream@0.0.6)
└── glob@3.2.1 (inherits@1.0.0)
再試 node install.js
/home/hadoop/.node-gyp/0.10.7/deps/uv/include/uv.h:1411:15: error: initializing argument 4 of ‘int uv_queue_work(uv_loop_t*, uv_work_t*, uv_work_cb, uv_after_work_cb)’ [-fpermissive]
make: *** [Debug/obj.target/gitteh/src/repository.o] Error 1
make: Leaving directory `/home/hadoop/nodejs/myapp/src/node-gitteh/build'
gyp ERR! build error
gyp ERR! stack Error: `make` failed with exit code: 2
gyp ERR! stack at ChildProcess.onExit (/home/hadoop/nodejs/myapp/src/node-gitteh/node_modules/node-gyp/lib/build.js:256:23)
gyp ERR! stack at ChildProcess.EventEmitter.emit (events.js:98:17)
gyp ERR! stack at Process.ChildProcess._handle.onexit (child_process.js:789:12)
gyp ERR! System Linux 3.5.0-17-generic
gyp ERR! command "node" "/home/hadoop/nodejs/myapp/src/node-gitteh/node_modules/.bin/node-gyp" "build"
gyp ERR! cwd /home/hadoop/nodejs/myapp/src/node-gitteh
gyp ERR! node -v v0.10.7
gyp ERR! node-gyp -v v0.8.5
gyp ERR! not ok
還是失敗。等等,會不會忘了 preinstall?結果沒用…。
於是我就放棄了,試試看 http://www.pygit2.org/
作業環境:ubuntu 12.10
由於,node-gitteh 實在太難裝了。於是,我換到 pygit2 這裡。
按照 http://www.pygit2.org/install.html 一樣我也遭遇到問題。
例如,要安裝 python-dev 之類的 ( sudo apt-get install python-dev)
最後,我還是安裝成功了。
過程如下:
先下載 libgit2 的 git source,要記得,使用下列指令拿到的才行,不然之後有可能會出現錯誤(註一),據說是 libgit2 v0.18 之後的才不會有問題。
git clone git://github.com/libgit2/libgit2.git -b master
然後,使用 cmake 安裝至系統中
mkdir libgit2/build
cd libgit2/build
cmake ..
cmake --build .
sudo cmake --build . --target install
之後,下載 pygit2,並使用 setup.py 安裝
$ git clone git://github.com/libgit2/pygit2.git
$ cd pygit2
$ python setup.py install
$ python setup.py test
註一:錯誤訊息為:error: too many arguments to function ‘git_reference_list’