使用GIT和GITHUB

URL Link //n.sfs.tw/10475

2016-12-24 22:21:53 By 張○○

有寫程式的人在網路上找資料時,常常會看到檔案是放在Github https://github.com/ 上,看起來很專業很高級,這是不是要花錢?是不是任何人都能放?答案是有免費的,而且是任何人都能放,這篇告訴你怎麼做。

安裝

請參考windows, linux, freebsd 下安裝git 這篇或官網[1]

一、註冊一個帳號

github 註冊一個帳號,並完成email的認證程序,這個步驟和大部分的站台註冊程序差不多。

二、建立一個儲存庫

登入後點選右上角新增一個repository(把他想像成一個db就好,外國人常簡寫成repos.)

填寫你的repos. name 名稱,不要用中文,未來會是一個連結,存取類別有public和private兩種,免費的只能使用public,private是付費版本:

public 你的所有的文件在網路上所有人都能看見和下載,但只有你授權的人能修改

private 只有你選擇的人能看見和修改你上傳的檔案,限付費帳號,1個月的費用是US$7

最下面的initialize the repository with a README 打勾後,系統會幫你建一個 README.md 檔,github會把他當成是此儲存庫的預設說明。如果你想把你現有的專案上傳的話,就不要勾,以免到時還要多處理這個檔。

這樣就會產生一個你專屬的git,https://github.com/[你的名稱]/[你的儲存庫].git,此例 https://github.com/AxerZ/TT.git

你會發現整個儲存庫會有一個README.md 下面會顯示他的內容。

如果是用WINDOWS版本,就會看到你建立的儲存庫了

三、Linux中操作

1. 假設我現在要開始在 /home/axer/public_html/TT/ 中寫一個專案,先要git初始化

  $ cd /home/axer/public_html/TT/
  $ git init
  Initialized empty Git repository in /home/axer/public_html/TT/.git/

2. 在本地設定自己的帳戶

  $ git config --global user.email "axer@tc.edu.tw"
  $ git config --global user.name "AxerZ"

3. 開始編輯檔案,例如新增的一個index.html (或是你可以從別的地方拷檔案到這個目錄來)

  $ touch index.html

  把index.html 加到你的舞台中(等於加入清單的意思)
  $ git add index.html

  要移出舞台用reset
  $ git reset HEAD index.html

  隨時用 status 查看舞台中的檔案
  $ git status

  把他送進 repos. 中,-m 參數後面帶的是此次更新的註解
  $ git commit index.html -m '加入索引檔'

  接下來如果不心心把index.html 刪掉,要回復的話就使用checkout ,後面那個 '.' 代表所有的檔案
  $ rm index.html
  $ git checkout .

  查看可以清除的untracked 的檔案

  $ git clean -n

  清除可以清除的untracked 的檔案

  $ git clean -f 檔案或目錄

  回覆原本的目錄,包括新增的檔案,清除所有未追蹤的(untracked)檔案[6]

  $ git clean -xdf

 其他的操作可以參考[2]的說明,非常的詳細

4. 到目前為止,都還只是本地端的操作,接下來要把檔案上傳到 github

加一個遠端 github repos. 名稱可以自取,此例myTT
$ git remote add myTT https://github.com/AxerZ/TT.git

可用下面的指令查看遠端的 git 資源
$ git remote -v
HeartTT ssh://axer@163.17.38.84/~/git/heart.git/ (fetch)
HeartTT ssh://axer@163.17.38.84/~/git/heart.git/ (push)
myTT    https://github.com/AxerZ/TT.git (fetch)
myTT    https://github.com/AxerZ/TT.git (push)

如果打錯了相要刪除,只要remove 就好,例如remove myTT
$ git remote rm myTT


$ git remote rm origin

把本地的檔案推到遠端的myTT中,master 這個分枝
$ git push myTT master

(gnome-ssh-askpass:2201): Gtk-WARNING **: cannot open display:
error: unable to read askpass response from '/usr/libexec/openssh/gnome-ssh-askpass'
Username for 'https://github.com': AxerZ

(gnome-ssh-askpass:2205): Gtk-WARNING **: cannot open display:
error: unable to read askpass response from '/usr/libexec/openssh/gnome-ssh-askpass'
Password for 'https://AxerZ@github.com':
To https://github.com/AxerZ/TT.git
 ! [rejected]        master -> master (non-fast-forward)
error: failed to push some refs to 'https://github.com/AxerZ/TT.git'

hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Merge the remote changes (e.g. 'git pull')
hint: before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

出現上面的錯誤,主要因為遠端repos.和本地的檔案清單不一致,還記得建repos.上面多一個README.md在本地的repos.是沒有的,因此要先把他拉回來合併:
$ git pull myTT master
From https://github.com/AxerZ/TT
 * branch            master     -> FETCH_HEAD
Merge made by the 'recursive' strategy.
 README.md |    4 ++++
 1 file changed, 4 insertions(+)
 create mode 100644 README.md

5. 把他推到 github

$ git push myTT master

(gnome-ssh-askpass:2339): Gtk-WARNING **: cannot open display:
error: unable to read askpass response from '/usr/libexec/openssh/gnome-ssh-askpass'
Username for 'https://github.com': AxerZ

(gnome-ssh-askpass:2341): Gtk-WARNING **: cannot open display:
error: unable to read askpass response from '/usr/libexec/openssh/gnome-ssh-askpass'
Password for 'https://AxerZ@github.com':
Counting objects: 6, done.
Delta compression using up to 16 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (5/5), 512 bytes, done.
Total 5 (delta 0), reused 0 (delta 0)
To https://github.com/AxerZ/TT.git
   39c84d4..cb106fe  master -> master

再去github 重新整理,就會發現你的 index.html已經上去了

四、建立分枝 branch

設定分枝 名稱"2nd"
$ git branch 2nd

切換到 "2nd" 這個分枝
$ git checkout 2nd
Switched to branch '2nd'

假設在這個分枝加入一個檔案 2ndtest.html,並送出

$ touch 2ndtest.html
$ ls
2ndtest.html  index.html  README.md

$ git add 2ndtest.html

$ git commit 2ndtest.html -m '2nd加入檔"

$ git push myTT 2nd

再查看github,檔案已經送過去,而且多了一個分枝可以選擇

查看分枝

git branch -a

建立一個新分枝note2,並使用其中第<commit hash>的commit

$ git branch note2 9b91107

移除一個branch note2[8]

$ git branch -d note2

更名branch [9]

$ git branch -m old_name new_name

五、使用github

已經上傳上去的檔案,如果要在另一個地方下載下來使用

$ git clone -b 2nd https://github.com/AxerZ/TT.git 2ndTT

這樣就會把https://github.com/AxerZ/TT.git 上分枝2nd的檔案,複製一份下載下來到 2ndTT的目錄中。

$ cd 2ndTT/

建立新檔 new.html
$ touch new.html

$ git add new.html
$ git commit new.html -m 'new'
[2nd 07fef1a] new
 0 files changed
 create mode 100644 new.html

刪除已加入的檔案
先刪除該檔
$ rm path/to/yourfile_or_dir

從git的索引中移除
$ git rm path/to/yourfile_or_dir

推到git hub
$ git push

如此就能隨時隨地更新你的github

六、在本地複製自己的repos.

上面教的是採用網路的GITHUB進行版本控制,但如果是要在local自己CLONE自己的repos要怎麼做:

很簡單只要指定另一個複本的位置即可
$ git clone /home/axer/public_html/TT/

七、在不使用GITHUB自建GIT server[3]

[SERVER端]
GIT可以使用SSH的協定更新,這樣提供了很大的彈性,假若SERVER檔案庫要建在自己家目錄中,則先在自己的家目錄下建一個目錄 git:
$ mkdir git
$ cd git

關於選定儲存庫的目錄
當然,如果你的專案是要給很多人同時編輯的話,就不建議放在家目錄,可以選擇採用以下方法:
1. 建立一個共同帳號,建在那個帳號的家目錄中。
2. 把會共同編輯的帳號設為同一個群組(group這是[3]採用的方法)
3. 建立一個權限777的目錄給大家用
4. 使用 setfacl 的指定建立例外權限

建立一個git的repos. 假設這個名稱叫 heart.git,記得加入參數 --bare 不建.git目錄,而把裡面的檔案直接放在目前目錄下[4],這樣才能當SERVER
$ git --bare init heart.git

[開發端]::把寫好的程式丟到server
client 端的作法就和三.4、三.5相同,先建遠端stage:

$ cd /path/to/your/project
$ git init
$ git remote add HeartTT ssh://axer@163.17.38.84/~/git/heart.git/

把本地端檔案加入清單
$ git add .
$ git commit -m '註解'

最後,把client端的檔案推到server中吧
$ git push HeartTT master
axer@163.17.38.84's password:
Counting objects: 8, done.
Delta compression using up to 16 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (8/8), 729 bytes, done.
Total 8 (delta 0), reused 0 (delta 0)
To ssh://axer@163.17.38.84/~/git/heart.git/
 * [new branch]      master -> master

[客戶端CLIENT]::把server端的程式拿來來用

$ git clone ssh://axer@163.17.38.84/~/git/heart.git/ /path/to/

這樣就能直接用了

未來更新

$ git pull HeartTT master

八、移除及記錄

如果一個目錄已經 git init過,要怎麼移除它?很簡單,只要到根目錄把那個 .git 的隱藏檔刪掉即可。

查看更新記錄

$ git log

commit f09a149382b74d021f8abf0488d18f94e9f57117
Author: AxerZ <root@pid1.sso.edu.tw>
Date:   Mon Jul 17 00:16:34 2017 +0800

    mod ReadME

commit ee690dbb72bb979b20aa39f5be20e99c0326614c
Author: AxerZ <root@pid1.sso.edu.tw>
Date:   Mon Jul 17 00:06:25 2017 +0800

    add main files

...

查看異動記錄

$ git show <COMMIT_ID>

# git show 2a877b0a506ad0d0ce3e3486b6143f292f30e99b

 

回復

回復到其中的第X次更新,後面接著checkout 上的流水號

$ git checkout f09a149382b74d021f8abf0488d18f94e9f57117

只回復某一個檔案到某一個流水號

$ git checkout  b0f50343bb911b59e30156729104cac2c80cb657 Management.php

回復不小心刪除的某目錄

$ git checkout path/

放棄最後一次更新

$ git revert HEAD

如果要強制遠端放棄最後一個版號,下指令

$ git git push logTT +ad7679ef33aff2230d3a413db0376a08b55e266b^:master

其中ad7679ef33aff2230d3a413db0376a08b55e266b是最後一個commit hash號,要被放棄的,而logTT是達端的repos.,請參考上面三、5的說明

如果本地有回復到某一個commit hash,要遠端也同步的話,下指令

$ git reset HEAD^ --hard

$ git push logTT -f

 

錯誤

出現無法操作錯誤,刪除 index.lock 後重試

fatal: Unable to create '/home/ddns/.git/index.lock': File exists.

似乎另外一個 git 進程在這個版本庫中執行,例如:'git commit' 指令打開了一個編輯器。請確認所有進程都已經關閉然後重試。如果仍然報錯,可能之前有一個 git 進程在這個版本庫中異常離開:手動刪除這個檔案再繼續。[11]

# rm -f .git/index.lock

 

The following untracked working tree files would be overwritten by merge

試著清除本地的未追蹤檔

Git 2.11 and newer versions:

git clean -d -f .

Older versions of Git:

git clean -d -f ""

-x ignored files are also removed as well as files unknown to Git.

-d remove untracked directories in addition to untracked files.

-f is required to force it to run.

 

結語

與其說 git是分散式的版本控制,不如說他是集中式+分散式的,和subversion比起來,sv可以建立免費的私人的server,為client-server架構,反而比較像分散式的。但是git對於分枝的支援,及集中的空間讓大家分享檔案,是相當不錯的特色。

感謝

台中教網中心陳瑩光提出的需求和指導

參考資料

[1] https://help.github.com/articles/set-up-git

[2] http://blog.gogojimmy.net/2012/01/17/how-to-use-git-1-git-basic/
    http://blog.gogojimmy.net/2012/02/29/git-scenario/

[3] http://littlebmix.blogspot.tw/2011/02/git-server-ubuntu-linux.html

[4] http://blog.xuite.net/yctseng/notes/35377315-git-init

[5] GITHUB API V3 http://developer.github.com/v3/

[6] http://stackoverflow.com/questions/1090309/git-undo-all-working-dir-changes-including-new-files

[7] http://christoph.ruegg.name/blog/git-howto-revert-a-commit-already-pushed-to-a-remote-reposit.html

[8] https://makandracards.com/makandra/621-git-delete-a-branch-local-or-remote

[9] https://stackoverflow.com/questions/6591213/how-do-i-rename-a-local-git-branch

[10] https://stackoverflow.com/questions/17404316/the-following-untracked-working-tree-files-would-be-overwritten-by-merge-but-i

[11] https://stackoverflow.com/questions/16602544/fatal-unable-to-create-git-index-lock-file-exists


原文 2013-04-13 12:53:33