顯示具有 git 標籤的文章。 顯示所有文章
顯示具有 git 標籤的文章。 顯示所有文章

2019年2月18日 星期一

Gitlab+Jenkins實現自動部署

1. 安裝(使用yum安裝,略)

jenkins 2.150.1
gitlab ( GitLab Community Edition 11.5.0 )

2. 配置gitlab

打開project、配置SSH密鑰、上傳code(略)

3. 配置Jenkins

a. 新增插件

Manage Jenkins => Manage Plugins => 安裝以下插件
Gitlab Hook
Build Authorization Token Root
Publish Over SSH
Gitlab Authentication
Gitlab

添加完插件重啟jenkins,開始添加要部署代碼的主機,注意一定是要能夠ssh登陸的用户

b. 添加主機

Manage Jenkins => Configure System => Publish over SSH

c. 新建任務

New Item => (填寫任務名字)Freestyle project => Source Code Management
Build Triggers
Build
Exec command:
# 重啟nginx
/usr/local/nginx/sbin/nginx -s reload
# 同步.git 目錄(git log)
rsync -r /var/lib/jenkins/workspace/test/.git /path/test/jenkins_cd
# 切到develop分支
git --git-dir=/path/test/jenkins_cd/.git remote update
git --git-dir=/path/test/jenkins_cd/.git branch -D develop
git --git-dir=/path/test/jenkins_cd/.git checkout -b develop remotes/origin/develop

4. 配置gitlab,當有代碼提交時,觸發jenkins的部屬操作


出現Hook executed successfully: HTTP 200 => 說明配置成功

5. 加入git-flow

test-release (預發佈分支的jenkins item)

Source Code Management
Branches to build - Branch Specifier (blank for 'any'): */master => 從master生release分支
Build Triggers
Allowed branches - Filter branches by regex - Target Branch Regex: .*master
Build
SSH Publishers - Transfers - Remote directory: /path/test/jenkins_release
SSH Publishers - Transfers - Exec command:
/usr/local/nginx/sbin/nginx -s reload
# 同步 release worksapce的git log 到release項目路徑上
rsync -r /var/lib/jenkins/workspace/test-release/.git /path/test/jenkins_release
# 切換到release 分支
git --git-dir=/path/test/jenkins_release/.git remote update
git --git-dir=/path/test/jenkins_release/.git branch -D release
git --git-dir=/path/test/jenkins_release/.git checkout -b release remotes/origin/master
# 配置.git目录权限
chmod 777 -R /path/test/jenkins_release/.git/


test-master(線上分支的jenkins item)

Source Code Management
Branches to build - Branch Specifier (blank for 'any'): */master
Build Triggers
Allowed branches - Filter branches by regex - Target Branch Regex: .*master
Build
SSH Publishers - Transfers - Remote directory: /path/test/jenkins_master
SSH Publishers - Transfers - Exec command:
/usr/local/nginx/sbin/nginx -s reload
# 同步 master worksapce的git log 到master項目路徑上
rsync -r /var/lib/jenkins/workspace/test-master/.git /path/test/jenkins_master
# 可以使用一些jenkins中的變量
echo "$PWD bear $JOB_NAME-$BUILD_NUMBER $GIT_COMMIT $GIT_PREVIOUS_COMMIT $GIT_PREVIOUS_SUCCESSFUL_COMMIT start" >> /tmp/bear2
# 可以使用bash的條件判斷
if [ "$GIT_COMMIT" = "$GIT_PREVIOUS_COMMIT" ]
then
    echo "var is 123"  >> /tmp/bear2
else
    echo "var is 456"  >> /tmp/bear2
fi
# 切換到master分支
git --git-dir=/path/test/jenkins_master/.git remote update
git --git-dir=/path/test/jenkins_master/.git branch -D master
git --git-dir=/path/test/jenkins_master/.git checkout -b master remotes/origin/master
# 合併release分支內容
git --git-dir=/path/test/jenkins_master/.git --work-tree=/path/test/jenkins_master/ merge remotes/origin/release
# 更新到倉庫的master分支
git --git-dir=/path/test/jenkins_master/.git push origin master:master
# 删除release远程分支
git --git-dir=/path/test/jenkins_master/.git push origin --delete release
# 删除release环境
rm -rf /path/test/jenkins_release/*
rm -rf /path/test/jenkins_release/.git//

ps. test-release、test-master皆需配gitlab webhook

6. 流程

開發在本地環境開發完+自測後更新到develop分支,jenkins會自動部屬測試環境給測試測,測試測完build test-release環境(從master分支分出來的),release環境只有一個,兩人同時要上時必須等待,開發上release環境將develop分支中的commit cherry-pick到release分支中,測試測完release後更新到release分支,線上發佈時build test-master,部屬完更新到master分支、刪除倉庫release分支、release環境

7. Jenkins 建置狀態回寫gitlab

a. 安裝gitlab、jenkins安裝gitlab plugin


b. Gitlab 使用者設定

GitLab 主畫面開啟帳號圖像下拉選單,依序點選「Settings」 → 「Access Tokens」
產生一個Personal Access Tokens
然後你就可以用這個token存取gitlab api
ex. http://gitlab.server.com/api/v4/projects?private_token=xxx

c. Jenkins 設定

Manage Jenkins => Configure System => Gitlab
Gitlab區塊輸入「Connection name」與「Gitlab host URL」
於「Credentials」旁按下【Add】 → 【Jenkins】,開啟「新增 Credentials」頁面
然後填入以下欄位(API token為你剛剛在gitlab生成的access tokens)

d. 工作組態設定

test item => Configure
General
GitLab Connection: 選擇 Gitlab
Post-build Actions
按下【Build Now】,此時此項工作會進行建置並使用 GitLab connection 將建置狀態發送至 GitLab 上。

8. 可能的報錯

a. Gitlab webhook 報錯: 500 Internal Server Error - URI::InvalidURIError

使用root登入gitlab => Admin area => Settings => Network => Outbound requests => 勾選「Allow requests to the local network from hooks and services」
ps. 可能會因為gitlab 版本不同,而菜單位置有差異

b. 永遠使用英文介面

因為jenkins 預設文字為用戶瀏覽器語言,但是網路上查到的資料都是英文的,如何使介面為英文?
i. Jenkins安裝 Locale Plugin
ii. Jenkins configuration => Locale => Default Language: en

參考資料:

https://hk.saowen.com/a/286fcee36ef6c80c697b392adeb8249047a9c282b50fe82b42526af3f673562a  Gitlab+Jenkins實現自動部署(主要)
https://dotblogs.com.tw/echo/2018/04/29/jenkins_plugin_gitlab_publishbuildstatus  【Jenkins】外掛套件:GitLab(Jenkins 建置狀態回寫)(次要)
https://linuxize.com/post/how-to-install-jenkins-on-centos-7/  How To Install Jenkins on CentOS 7
https://web.devdon.com/archives/10  GitLab搭配Jenkins實現可持續集成開發
https://blog.csdn.net/u010947098/article/details/61922969  jenkins使用publishover ssh插件连接应用机器时,报Message [Auth fail]的问题(jenkins.plugins.publish_over.BapPublisherException: Failed to connect and initialize SSH connection. Message: [Failed to connect session for config [测试机]. Message [Auth fail]])
https://stackoverflow.com/questions/49626860/gitlab-webhook-get-error-500-internal-server-error-uriinvalidurierror  Gitlab webhook get error: 500 Internal Server Error - URI::InvalidURIError
https://stackoverflow.com/questions/1386291/git-git-dir-not-working-as-expected  git --git-dir not working as expected
https://stackoverflow.com/questions/12350707/jenkins-in-windows-shows-ui-in-russian-language  Jenkins in Windows shows UI in russian language
https://alexbilbie.com/2015/04/setting-up-jenkins/  Setup Jenkins and test a PHP project


2018年8月6日 星期一

git revert merge commit心得

情境
developer_c 將未測過的分支merge到主分支上,然而要如何處理此情況?
(下圖中 developer_c 所有的提交都是沒測過的,線上git log沒有的)

$ git log --graph --decorate
* commit 17d7378fbc6158ba78dda5bee3888946262dae00 (origin/v/1.0)
| Author: developer_c <you@example.com>
| Date:   Wed Aug 1 14:27:36 2018 +0800
|
|     developer_c commit 2
|
*   commit 343d7522c01f0a23694c23bf100e64c73fd564ac
|\  Merge: 11a53f7 d785818
| | Author: developer_c <you@example.com>
| | Date:   Wed Aug 1 14:26:41 2018 +0800
| |
| |     Merge branch 'v/1.0' of www.gitlab.com:root/admin into v/1.0.cy
| |
| *   commit d7858187c1047c3070b7cf22e8ecc73662fa36ff
| |\  Merge: 3152999 3aa9df2
| | | Author: developer_y <developer_y@example.com>
| | | Date:   Mon Jul 30 16:43:21 2018 +0800
| | |
| | |     Merge branch 'v/1.0' of www.gitlab.com:root/admin into v/1.0
| | |
| | * commit 3aa9df2a1bce8a2140dbdc284c99281101d13c28
| | | Author: developer_k <developer_k@developer_k-VirtualBox>
| | | Date:   Sat Jul 28 14:39:24 2018 +0800
| | |
| | |     developer_k commit 3
| | |
| | * commit 5613362f2dd3f880dd51e93490674b09ad002658
| | | Author: developer_k <developer_k@developer_k-VirtualBox>
| | | Date:   Sat Jul 28 13:42:34 2018 +0800
| | |
| | |     developer_k commit 2
| | |
| | * commit c1c959dff6814d3265f83a74abe7ada284d1fcd4
| | | Author: developer_k <developer_k@developer_k-VirtualBox>
| | | Date:   Fri Jul 27 18:44:38 2018 +0800
| | |
| | |     developer_k commit 1
| | |
| | * commit 061a2e49e399a52fa9750f6ac283f00bdfdbc839
| | | Author: developer_b <developer_b@example.com>
| | | Date:   Thu Jul 26 16:55:41 2018 +0800
| | |
| | |     developer_b commit 1
| | |
| * | commit 315299970b9e47c35e1f5b623fbfc063a9f2f2b7
| |/  Author: developer_y <developer_y@example.com>
| |   Date:   Mon Jul 30 16:43:01 2018 +0800
| |
| |       developer_y commit 4
| |
| * commit ea2d0d563cfd576a59d174d684411d3d7209f7c4
| | Author: developer_y <developer_y@example.com>
| | Date:   Thu Jul 26 10:03:13 2018 +0800
| |
| |     developer_y commit 3
| |
* |   commit 11a53f77caf39dc0444852d97e7e647cf1a2227c
|\ \  Merge: daa70a6 67528e6
| |/  Author: developer_c <you@example.com>
| |   Date:   Wed Jul 25 18:49:01 2018 +0800
| |
| |       Merge branch 'v/1.0' of www.gitlab.com:root/admin into v/1.0.cy
| |
| * commit 67528e6cd2e20c128637f23adb9672d7eddfbca4
| | Author: developer_y <developer_y@example.com>
| | Date:   Tue Jul 24 15:27:15 2018 +0800
| |
| |     developer_y commit 2
| |
| * commit 24ea51e72478735b03a86e9beab9d49036d62278
| | Author: developer_y <developer_y@example.com>
| | Date:   Mon Jul 23 13:51:06 2018 +0800
| |
| |     developer_y commit 1
| |
* | commit daa70a6a8514ee0ff790b15433f92d0d2f58d6c7 (origin/v/1.0.cy)
|/  Author: developer_c <you@example.com>
|   Date:   Fri Jul 20 10:27:21 2018 +0800
|
|       developer_c commit 1
|

developer_c commit 2 ( 17d7378 ) 因為是合併後再提交的,所以直接revert就好
$ git revert 17d7378fbc6158ba78dda5bee3888946262dae00

Merge branch 'v/1.0' of www.gitlab.com:root/admin into v/1.0.cy ( 343d752 ) 因為是merge 的commit ,必須指名 -m 參數才能revert。然而這分支中間又合併了一次 Merge branch 'v/1.0' of www.gitlab.com:root/admin into v/1.0.cy (11a53f7
所以必須 -m 2343d752 分支上的  11a53f7daa70a6 回復
$ git revert -m 2 343d7522c01f0a23694c23bf100e64c73fd564ac

使用git log -p file_name、 git show commit 檢查中間commit(如 3aa9df2、3152999)的修改沒有受影響

參考資料:
https://stackoverflow.com/questions/7099833/how-to-revert-a-merge-commit-thats-already-pushed-to-remote-branch  How to revert a merge commit that's already pushed to remote branch?


2016年5月17日 星期二

gitlab 自動custom hook佈署到server上

gitlab和web server現在放在同一台機器上,想要本地測試完git push到機器上後自動佈署到web服務上
因為懶得搞另一套 jenkins,所以打算用hook做

方案
git本身的hook
gitlab的 custom hook   http://docs.gitlab.com/ee/hooks/custom_hooks.html
gitlab的 web hook   http://docs.gitlab.com/ee/web_hooks/web_hooks.html

這裡選用gitlab的 custom hook

步驟:
0. 切換到git使用者,因為gitlab文件的使用者權限都是git
# sudo su git
1. 假設root使用者的test專案需要hook
2. 找server上test.git庫的位置,我的放在 /var/opt/gitlab/git-data/repositories/root/test.git ,但也有可能放在 /home/git/repositories/<group>/<project>.git ,依你安裝的方式不同而不同
3. 進入該資料夾後新建 custom_hooks 資料夾
4. 進入 custom_hooks 資料夾,在這邊新增原git hook類型的檔案,ex. pre-receive。這邊新增 post-receive這個鉤子文件,當push完成後這個文件就會被調用
post-receive
#!/bin/sh
git --work-tree=/var/www/test.localhost/html --git-dir=/var/opt/gitlab/git-data/repositories/root/test.git checkout -f
--git-dir git庫所在位置
--work-tree 實際文件被存放的位置
5. 別忘了賦予 post-receive 可執行權限
$ chmod +x post-receive
6. /var/www/test.localhost/html 路徑也必須是git權限
# chown git:git -R /var/www/test.localhost/html

最後在本地端測試push後,機器上web服務也馬上更新了,
如果 /var/www/test.localhost/html 上面原本有內容的檔案不會清空,只會被覆蓋

參考資料:
http://sumyblog.me/2015/11/02/use-git-hooks-for-hexo-automatic-deployment/  使用git hooks进行hexo博客自动化部署


2015年3月11日 星期三

將別的repository的commit合併到svn上

情境:
有兩個同專案的程式,因網路關係,其中一個有一陣子被放生到一個新的git上(因為git沒有網路也能用),現在要把git(程式較新)的commit移回svn上(git分出去後無提交新的commit)
假設svn倉庫在 http://svn.domain/trunk/project/
git倉庫在 ssh://bear@192.168.0.115:/srv/http/git_repo
本機端git svn 操作在git_svn_repo
本機端保留的git本地倉庫在 /your/git_repo/path

解法:
You'll need to add the other repository as a remote, then fetch its changes. From there you see the commit and you can cherry-pick it.

使用git svn 拉回svn的程式
$ git svn clone http://svn.domain/trunk/project/ git_svn_repo
$ cd git_svn_repo
新增git的遠端倉庫,並命名git_repo
$ git remote add git_repo file:///your/git_repo/path #我在本地端另外目錄有pull git倉庫的東西,先用他的commit 去merge
抓回git_repo
$ git fetch git_repo
檢查branch
$ git branch -a
查git倉庫的log
$ git log remotes/git_repo/master
將git倉庫你要合併的commit cherry-pick到master(他將會推上svn)
$ git cherry-pick commit_id
上傳到svn
$ git svn dcommit


將git_svn_repo的更新推到git
$ git remote rm git_repo #因為前面用本機保留的git本地倉庫,所以刪掉重新把remote設成git遠端倉庫
$ git remote add origin ssh://bear@192.168.0.115:/srv/http/git_repo
直接推送會報錯:
$ git push origin master
lman@192.168.0.115's password:
To ssh://bear@192.168.0.115:/srv/http/git_repo
 ! [rejected]        master -> master (non-fast-forward)
error: failed to push some refs to 'ssh://bear@192.168.0.115:/srv/http/git_repo'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
解法:
$ git pull origin master # 這會多一個merge的commit
(編輯修改後)
$ git push origin master
即可將git_svn_repo的修改內容推送到遠端git倉庫

不過上面那段是錯的,原因:這樣git_svn_repo的修改就送不到svn上了



參考資料:
http://stackoverflow.com/questions/5120038/is-it-possible-to-cherry-pick-a-commit-from-another-git-repository

2015年1月29日 星期四

git-ftp心得

git-ftp有兩種解法
https://github.com/ezyang/git-ftp ( 可搭配hook,只傳新檔案和移除舊檔案 )
https://github.com/git-ftp/git-ftp ( 傳tracked的檔案 )

https://github.com/git-ftp/git-ftp
安裝:
# apt-get install git-ftp
使用(在 client repository):
$ git ftp init -u username -p password - ftp://your.ftp.domain/htdocs/  #第一次要用init
or
$ git ftp push -u username -p password - ftp://your.ftp.domain/htdocs/

https://github.com/ezyang/git-ftp ( 搭配hooks的 post-receive )
安裝:
# apt-get install python-setuptools ( 如果沒有easy_install,就先裝這個 )
# easy_install gitpython
在remote repository上根目錄建立 ftpdata ( 與config, HEAD同一層 ):
[master]
username=ftp_username
password=ftp_password
hostname=your.ftp.domain
remotepath=/htdocs  #你的ftp上傳路徑
ssl=no  #如果ftp 不支援https ,要改no

在hooks下建立 post-receive(權限775,直接複製github上的內容):
#!/bin/bash
# You may install this post-receive hook in your remote git repository
# to have automatic file upload when pushing to the repository.
while read OLD_COMMIT NEW_COMMIT REFNAME; do
    BRANCH=${REFNAME#refs/heads/}

    if [[ `grep "^\[$BRANCH\]$" ftpdata` ]]; then
        echo "Uploading $BRANCH..."
        $(dirname $(readlink -f "$0"))/git-ftp.py -b "$BRANCH" -c "$NEW_COMMIT" || exit $?
    fi  
done
true

在hooks下建立 git-ftp.py(權限775,直接複製github上的內容):


然後在client repository,git push後 就會更新程式到ftp上去

參考資料:
http://stackoverflow.com/questions/2950107/git-push-into-production-ftp

2015年1月28日 星期三

使用git hooks管理網站

本地倉庫
$ cd ~/test/
$ mkdir website && cd website
$ git init
$ echo 'Hello, world!' > index.html
$ git add index.html
$ git commit -q -m "The humble beginnings of my web site."
註: git commit -q  是--quiet ,抑制commit 時的訊息

遠端倉庫 ( 我在同一個file system下測試,沒用ssh )
$ cd ~/test/
$ mkdir website.git && cd website.git
$ git init --bare

在website.git 資料夾下繼續操作:
$ mkdir ~/test/www.example.org
$ cat > hooks/post-receive
#!/bin/sh
GIT_WORK_TREE=/home/bear/test/www.example.org git checkout -f
$ chmod +x hooks/post-receive
註:
post- 是 "後" 的意思,遠端倉庫在收到commit後所作的動作
chmod +x 把檔案權限變成755

回到本地倉庫繼續操作
$ cd ~/test/
$ git remote add web file:///home/bear/test/website.git
$ git push web +master:refs/heads/master

簡化push的動作
$ git push --set-upstream web master #設定一次就可以了
$ git push web

檢查
在 /home/bear/test/website.git 中檢查push上來的檔案有沒有被更新

hook 有分 用戶端掛鉤 和 伺服器端掛鉤
用戶端掛鉤
位置在 ~/test/website/.git/hooks ,sample檔是bash寫的,可以用其他語言,如perl寫,只需要在第一行指定 #!/usr/bin/perl ,記得把權限改成755 ,script最後只要exit 1 就會被中止,
執行順序:
pre-commit  => commit-msg => post-commit ( 我沒測 prepare-commit-msg,但我想應該是在 pre-commit和commit-msg之間 )
以 commit-msg 為例:
commit-msg 掛鉤接收一個參數,此參數是包含最近提交資訊的暫存檔路徑( .git/COMMIT_EDITMSG )。
bash 收這個參數是 $1,perl 是 $ARGV[0]

有了這些掛鉤就能客製化開發者們在commit 時限制commit message的格式,外掛jslint檢查程式碼,檢查行尾有無空白,沒有錯誤才push到伺服器上

伺服器端掛鉤
pre-receive
post-receive # 上面的例子有用到這個
update

參考資料:
http://toroid.org/ams/git-website-howto
http://git-scm.com/book/zh-tw/v1/Git-%E5%AE%A2%E8%A3%BD%E5%8C%96-Git-Hooks #hook相關屬性

2015年1月19日 星期一

git合併兩個現有repos的紀錄到同一個repos

假設要把mp3合併到mp2(主要)
下載兩個repos並進入其中主要的branch
$ git clone git@your.domain:bear/mp2.git
$ git clone git@your.domain:bear/mp3.git
$ cd mp2
把mp3加入mp2的remote
$ git remote add mp3 ../mp3
$ git fetch mp3
$ git branch mp3 mp3/master
$ git merge mp3
合併後的git log圖如下:
*   0f54c78 2015-01-19 | fix conflict merge [bear]
|\
| * dc09a26 2015-01-19 | add mp3.txt (mp3/master, mp3) [bear]
| * d6b0993 2015-01-19 | mp3 test commit 2 [bear]
| * 9d89949 2015-01-19 | mp3 first commit [bear]
*   4fea708 2014-11-23 | Merge branch 'master' of your.domain:bear/mp2 (origin/master, origin/HEAD) [b
|\
| * fdc6ced 2014-11-23 | gitlab [bear]
* 719d8ef 2014-11-23 | gitlab [bear]
* a66d115 2014-11-23 | Initial commit [kalecgos0616]
( ~/.bashrc:設定 alias glog='git log --pretty=format:"%h %ad | %s%d [%an]" --graph --date=short')
要重新回到mp2 被merge前的 commit( 4fea708 ) 並保留log,因為 0f54c78 中混合了4fea708 和 dc09a26 的code,有衝突的檔案要手動解決conflict,要回到最原本的4fea708
方法1. ( 會多3個revert的commit )
$ git revert dc09a26 d6b0993 9d89949
方法2. ( 只會多一個commit,並回到 4fea708 的狀態)
$ git revert -m 1 0f54c78

下面這方法試不出來,可能是我的0f54c78 是兩個repos merge的node
$ git revert HEAD~2..HEAD

ps. 把本地端某個branch推到gitlab上
$ git checkout -b branch_name remote_name/branch_name
$ git push -u origin branch_name

參考資料:
http://stackoverflow.com/questions/4114095/revert-to-a-previous-git-commit
http://blog.caplin.com/2013/09/18/merging-two-git-repositories/
http://stackoverflow.com/questions/2765421/push-a-new-local-branch-to-a-remote-git-repo-and-track-it-too

2015年1月16日 星期五

git 搬移log到svn下

需求:
git下的所有log資料搬到svn 某新資料夾下(svn其他資料夾已有log)

過程照參考資料做基本上就可以了...
1. Create Subversion-aware Git clone ( 首先你要安裝git-sv )
 $ git svn clone http://svn.localhost/svn/trunk/company
 $ cd trunk
 $ git fetch git@your.domain:username/project.git # 我是抓我gitlab上的git

 $ git branch tmp $(cut -b-40 .git/FETCH_HEAD)
$(cut -b-40 .git/FETCH_HEAD) 是原本gitlab最後一個commit id
 $ git tag -a -m "Last fetch" last tmp

2. Apply initial commit
 $ INIT_COMMIT=$(git log tmp --pretty=format:%H | tail -1)
$(git log tmp --pretty=format:%H | tail -1)是tmp branch log的最後一個 commit id
 $ git checkout $INIT_COMMIT .  #注意最後要有點(.)
 $ git commit -C $INIT_COMMIT

3. Rebase and submit
 $ git rebase master tmp
 $ git branch -M tmp master

 $ git svn dcommit

4. Update Google Code
 ...
 $ mv .git/refs/tags/newlast .git/refs/tags/last #這步我沒做



參考資料:
http://code.google.com/p/support/wiki/ImportingFromGit

2014年11月23日 星期日

git同時push到兩個repo

情境:
以github和gitlab為例,假設他們各自有不同的內容要整合在一起

模擬環境
分別在github和gitlab建立新專案(ex 專案名稱mp),gitlab為master的pull
master 更新檔案 pull從gitlab
master 上傳檔案push到 gitlab和github(github純備份用,因為gitlab上是和其他人共同開發)

(分別在github和gitlab的mp.git新增不同的內容,我們之後要整合在一起)

拉下gitlab檔案
$ git clone git@xxx.tw:bear/mp.git gitlab_mp #用ssh要在gitlab設定keys,用https不用,但要輸入gitlab的帳號密碼
新增remote
$ git remote add github git@github.com:bear/mp.git
更新remote(remote branch會多remotes/github/master,用git branch -a 查詢)
$ git remote update

更新特定的remote

$ git remote update github

(這邊假設github和gitlab裡面各自有不同內容要整合,如果備份的repo為新開的repo可以略過a.b.c這三步)
a. 開github的branch
$ git checkout -b github remotes/github/master
b. 切回master
$ git checkout master
c. 將github整合進gitlab
$ git rebase github


git pull(做這步之後才能push,中間有conflict就手動改)
$ git pull #這步會多一個git merge的 commit
設定origin remote的url
$ git remote set-url origin --push --add git@xxx.tw:bear/mp2.git
$ git remote set-url origin --push --add git@github.com:bear/mp.git
檢查remote 會push到哪裡
$ git remote -v
github  git@github.com:bear/mp.git (fetch)
github  git@github.com:bear/mp.git (push)
origin  git@xxx.tw:bear/mp2.git (fetch)  # 因為git push預設是git push origin master,所以master會抓自架gitlab的repo
origin  git@xxx.tw:bear/mp2.git (push) # master會push到 gitlab
origin  git@github.com:bear/mp.git (push) # master也會push到 github
最後git push就能同時推到兩個不同的repo去了
$ git push

刷新gitlab和github頁面檢查

要更改預設master pull的repo
修改 .git/config 的
[remote "origin"]
    url = git@xxx.tw:bear/mp2.git #改成你要pull的repo

參考資料:
http://stackoverflow.com/questions/849308/pull-push-from-multiple-remote-locations 採用Malvineous的答案

關於刪除branch
移除gitlab上多餘的branch
$ git push origin --delete alt(多餘的branch名字)
本地的branch要分開刪,沒辦法一起刪
$ git branch -D alt
把本地remote的branch( git branch -a )也刪
# git branch --delete --remotes origin/alt

push新的branch到remote repository
$ git push origin exhibition:exhibition3
這樣遠端倉庫就會新建exhibition3分支,內容是本地端exhibition的內容,另外origin是你remote的名字

將遠端master branch拉到本地端exhibition branch
$ git pull origin master:exhibition
語法:
git pull <remote_name> <remote_branch>:<local_branch>

將本地端exhibition branch推到遠端master branch
$ git push origin exhibition:master
語法:
git push <remote_name> <local_branch>:<remote_branch>







2014年10月26日 星期日

使用Markdown在github上排版README.md

只針對github專案上README.md顯示有效

參考資源:
http://markdown.tw/
https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet

主標題
==========
副標題
--------------

#your word =>H1大小的your word
...
######your word =>H6大小的your word

有序的list => "1. " 數字+點+空白
1. ordered list one
2. ordered list two
...

無順序的list => "* "星號+空白
* list
* list

巢狀list => 用兩個空白縮排,可用有序或無序的list
1. ordered list one
  * nested list
  * nested list
2. ordered list two

斜體 => 一個*星號包住字
*斜體字*

粗體 => 兩個**星號包住字
**粗體字**

粗體斜體混合使用
**粗體字_粗體和斜體字_**

引言
> 一層引言 ("> "一個大於+空白)
> > 兩層引言("> "兩個大於+空白)

分隔線 => 三個*星號
***

超連結 => 直接打網址
http://tw.yahoo.com

刪除線 => 兩個~~引號包住字
~~文字上會有刪除線~~

寫程式碼 => 三個"`"(esc下面那個鍵) 包起來
```perl
use Data::Dumper;
print Dumper $bear;
```

表格 => 直接寫HTML的table(我常試過github table的寫法,但預覽時一直無效)
<table>
    <tr>
        <th>TO_BASE64('abc')</th>
        <th>FROM_BASE64(TO_BASE64('abc'))</th>
    </tr>
    <tr>
        <td>YWJj</td>
        <td>abc</td>
    </tr>
</table>


圖片連結
[Imgur](http://i.imgur.com/your_image.jpg)
註:imgur.com上傳圖片後可以直接選Markdown的圖片語法

2012年6月19日 星期二

[git] 查歷史紀錄 ( git常見問題 )

Unable to diff files in two separate branches in Git
http://stackoverflow.com/questions/916822/unable-to-diff-files-in-two-separate-branches-in-git


git diff branch:UNREADME master:README
git difftool somebranch:UNREADME otherbranch:README  (用vim比較工具查看)

View the change history of a file using Git versioning
http://stackoverflow.com/questions/278192/view-the-change-history-of-a-file-using-git-versioning
git log -p filename ( to let git generate the patches for each log entry )
git show HEAD ( get just the diff for a specific commit )

將所有新增的檔案加入:
$ git add .
http://stackoverflow.com/questions/572549/difference-of-git-add-a-and-git-add

將檔案移除
$ git rm filename

將整個資料夾移除
$ git clean -f -d
http://stackoverflow.com/questions/61212/removing-untracked-files-from-your-git-working-copy

讓某個目錄不再追蹤
$ git rm -r --cached <your directory>
http://stackoverflow.com/questions/1329291/ignoring-an-already-checked-in-directorys-contents

git移除所有刪除的檔案
Removing multiple files from a Git repo that have already been deleted from disk
http://stackoverflow.com/questions/492558/removing-multiple-files-from-a-git-repo-that-have-already-been-deleted-from-disk
http://stackoverflow.com/questions/1402776/how-do-i-commit-all-deleted-files-in-git
$ git add -u
OR
$ git add -A

在本地端還原成某個commitID狀態
$ git reset --soft HEAD^

查哪個紀錄改了什麼檔案
http://stackoverflow.com/questions/2557564/how-do-i-identify-files-directories-that-were-added-or-removed-in-a-git-commit
$ git whatchanged -n 1


http://kevyu.blogspot.tw/2011/10/git-stash.html
使用 $ git stash 暫存現在改的狀態再checkout 其他branch 繼續做其他事

查這個commit是哪個branch
How to list branches that contain a given commit?
http://stackoverflow.com/questions/1419623/how-to-list-branches-that-contain-a-given-commit
$ git branch -a --contains commit_tag

查git commit是否含有該文字
$ git log --all --grep='XXX'
--all 會查所有branch

查專案中檔案是否含有該文字(比直接grep快)
$ git grep -e XXX -e OOO

http://stackoverflow.com/questions/215718/how-do-i-reset-revert-a-specific-file-to-a-specific-revision-using-git
取出某個版本的某個檔案
Assuming the commit you want is abcde:
$ git checkout abcde file/to/restore

20130717
在checkout另個branch時,因為用ctrl+c中斷掉了,使得git reset --hard後留下一堆untracked files
如何刪除這些untracked files和資料夾:
http://stackoverflow.com/questions/61212/removing-untracked-files-from-your-git-working-copy
git clean -f -d to be sure that also directories are gone! you can check with git status if they are really gone.

顯示這個commit有哪些檔案被改過
http://stackoverflow.com/questions/424071/list-all-the-files-for-a-commit-in-git
$ git diff-tree --no-commit-id --name-only -r bd61ad98
$ git show --pretty="format:" --name-only bd61ad98
但無法顯示是新增、修改還是刪除,也無法像git pull時顯示+++-- 的示意符號

只移除某commit的修改(不是把該commit之後的commit改變都移除)
$ git revert commmitId

GIT複製別人本地端的branch
http://www.ptt.cc/bbs/Linux/M.1387124688.A.38A.html
方法1:
    $ git remote add jack ssh://jack.s.ip/home/jack/repo # 使用git remote rm jack 移除jack這個remote
    $ git fetch jack
    $ git checkout -b local_branch jack/local_branch # 在本地開local_branch,內容為jack/local_branch
    若jack和master裡面有同樣名字的branch(ex. dev_branch),在git pull時pull到master(之前加入)的dev_branch
方法2:
    $ git diff master local_branch > local_branch.diff # git diff commitId_old commitId_new
    $ git checkout -b local_branch master
    $ git apply local_branch.diff
    $ git commmit -am "Apply patch from Jack's local_branch" # -am 自動add且commit


復原 'git add .' 在提交(commit)之前
http://stackoverflow.com/questions/348170/undo-git-add-before-commit
$ git reset .
復原某個已經被git add的檔案
$ git reset HEAD <file>

讓git diff 有顏色
http://stackoverflow.com/questions/10998792/how-to-color-the-git-console-in-ubuntu
$ git config --global color.ui auto

git push時需要輸入帳號密碼
Git push requires username and password ( github )
http://stackoverflow.com/questions/6565357/git-push-requires-username-and-password
解:把remote的url設成ssh
$ git remote set-url origin git@github.com:username/repo.git
git remote set-url origin xxx 也是設定fetch網址的方法

查某兩個版本之間改過(新增)了哪些檔案
http://stackoverflow.com/questions/6879501/filter-git-diff-by-type-of-change
$ git diff 8702591419104918304ea46dc02ec65e3a8830a4 0136fef0d24d2fd3f1a8c83633e3cef7e7fdcaab --diff-filter=A

git diff時忽略空白(如用tab和space縮排方式改變不顯示出來)
$ git diff -w

被.gitignore的檔案已經被commit了,如何讓他真的被ignore
http://stackoverflow.com/questions/1139762/ignore-files-that-have-already-been-committed-to-a-git-repository
$ git rm -r --cached .
$ git add .
$ git commit -m ".gitignore is now working"
如果是配置文件被git rm --cached,線上更新時該commit會把該文件刪掉

忽略檔案模式(chmod)改變
如果chmod 檔案權限而不改內容,git status仍然會列出差異
http://stackoverflow.com/questions/1580596/how-do-i-make-git-ignore-file-mode-chmod-changes
$ git config core.fileMode false
這樣只改變權限就不會被列出來了

列出所有被刪除過的檔案
http://stackoverflow.com/questions/6017987/is-there-a-way-in-git-to-list-all-deleted-files-in-the-repository
列出log中哪個commit刪除了哪些檔案
$ git log --diff-filter=D --summary

git diff 只列出某檔名的差異
http://stackoverflow.com/questions/8554776/what-option-should-be-used-restrict-the-git-diff-to-a-given-set-of-file-extensio
列出html檔差異
$ git diff -w commit_old commit_new -- *.html
只列出index.html檔差異
$ git diff -w commit_old commit_new -- *index.html

git diff 忽略新增和刪除的檔案
http://stackoverflow.com/questions/6894322/how-to-make-git-diff-and-git-log-ignore-new-and-deleted-files
$ git diff -w commit_old commit_new --diff-filter=M

revert多個commit
http://stackoverflow.com/questions/1463340/revert-multiple-git-commits
假設 log 是 A -> B -> C -> HEAD
要回復到A
$ git revert --no-commit D    # commit由新到舊
$ git revert --no-commit C
$ git commit -m 'revert B and C commit'

git diff 顯示方法名稱而不是class名稱
http://stackoverflow.com/questions/7344577/is-there-a-way-to-ask-git-diff-to-show-the-method-name-instead-of-the-class-name
新增 .gitattributes(放到你家目錄下即可)或 .git/info/attributes 的倉庫中,並加入下面這行
*.php diff=php
( git version >= 1.4 )
1. 將  這行放到 ~/.gitattributes
2. 執行 git config --global core.attributesfile "~/.gitattributes"
如果你想要讓他便全局,將上面那行放到 /etc/gitattributes ( 未測 )
最後git diff 結果就會顯示修改的部份是在哪個function內,而不是在哪個class內

新增空資料夾在git倉庫
http://stackoverflow.com/questions/115983/how-can-i-add-an-empty-directory-to-a-git-repository
因為git存放的是檔案,在.gitignore中寫下
tmp/
忽略整個tmp/資料夾下的檔案同時也忽略了tmp資料夾,但是不想忽略tmp資料夾又想忽略tmp資料夾下檔案,要怎麼做呢?
在每個你要忽略的資料夾下寫下 .gitignore ,內容為
# Ignore everything in this directory
*
# Except this file
!.gitignore
!test/  # 不忽略tmp下的test資料夾,但同時test資料夾下也必須新增同樣的.gitignore檔案
或是使用.gitkeep
https://stackoverflow.com/questions/7229885/what-are-the-differences-between-gitignore-and-gitkeep
.gitkeep 不是git的特性,因為git不能新增空目錄,所以人們通常將.gitkeep放到空目錄使得能將該目錄加到版本庫

修改commit內容
http://stackoverflow.com/questions/179123/edit-an-incorrect-commit-message-in-git
$ git commit --amend
$ git commit --amend -m "New \`commit\` message"
反引號 grave/backticks( ` ) 必須要跳脫
設定git預設編輯器為vim
http://stackoverflow.com/questions/6098742/using-git-commit-a-with-vim
$ git config core.editor "vim"

合併兩個不同repos但code 類似的專案
http://stackoverflow.com/questions/13040958/merge-two-git-repositories-without-breaking-file-history/20974621#20974621
因為code管控,手上的較舊的code (old_project)改動,現在要依功能(如:留言板)分批合併到另一個repos(new_project)上正式的code上面
先在 old_project 上回復到比較舊的版本後開一個branch(guestbook),將留言板功能的commit從master 分批cherry-pick到guestbook分支上,並commit成一個記錄
先將舊的old_project加入新new_project庫的remote上
$ git remote add old_project file:///var/www/html/old_project
fetch
$ git fetch old_project
old_project的guestbook分支在new_project上生成
$ git branch guestbook old_project/guestbook
old_project/guestbook 的留言板功能commit cherry-pick到new_project 的master上
$ git cherry-pick commit_id
這時候已經成功一半了,但仍有少部分檔案會有衝突,在git status的 Unmerged paths中,此時要手動解決,我的方法是:保留舊版本衝突的檔案,然後參考 old_project/guestbook 上留言板功能的git diff分別進去手動加入更動

只將有實際更改(不含空白差異)的檔案做git add
http://stackoverflow.com/questions/3515597/add-only-non-whitespace-changes
$ git diff -U0 -w --no-color | git apply --cached --ignore-whitespace --unidiff-zero -

git add untracked 的檔案
http://stackoverflow.com/questions/7446640/adding-only-untracked-files
$ git add -i
第一個詢問選 a ( add untracked )
第二個詢問選* ( 全選 )
地三個詢問選q ( quit )

push 到gerrit的庫失敗
http://stackoverflow.com/questions/16586642/git-unpack-error-on-push-to-gerrit
$ git push origin master
Counting objects: 1, done.
Writing objects: 100% (1/1), 199 bytes | 0 bytes/s, done.
Total 1 (delta 0), reused 0 (delta 0)
error: unpack failed: error Missing tree 2d0d7370fe441e2c2439c0e5a523ad55bc5a0731
fatal: Unpack error, check server log
To ssh://bear@gerrit.test.com:29418/project.git
 ! [remote rejected] master -> master (n/a (unpacker error))
error: failed to push some refs to 'ssh://bear@gerrit.test.com:29418/project.git'
解法:
$ git push --no-thin origin master

cherry-pick 後出現both added的檔案
http://stackoverflow.com/questions/9823692/resolving-a-both-added-merge-conflict-in-git
使用原本的檔案
$ git checkout --ours src/MyFile.cs
使用commit-id新的檔案
$ git checkout --theirs src/MyFile.cs

從比較舊的commit id 開始,開一個新的分支
http://stackoverflow.com/questions/18054057/git-checkout-commit-id-is-changing-branch-to-no-branch
$ git checkout -b <new_branch_name> commit_id

僅打包兩個commit id之間更改的檔案
http://stackoverflow.com/questions/4541300/export-only-modified-and-added-files-with-folder-structure-in-git
http://tosbourn.com/using-git-to-create-an-archive-of-changed-files/
http://stackoverflow.com/questions/424071/how-to-list-all-the-files-in-a-commit
假設git log 是這樣 A -> B -> C
列出B,C 一共改了哪些檔案
$ git diff --name-only A C

$ git diff-tree --no-commit-id --name-only -r A C
將B,C 改的檔案打包
$ git archive -o update.zip HEAD $( git diff-tree --no-commit-id --name-only -r A C)

$ git archive -o update.zip C $( git diff-tree --no-commit-id --name-only -r A C) =>如果不是打包最新版的內容的話
或 如果只打包新增(A)和修改(M)的檔案(打包刪除的發生錯誤)
$ git archive -o update.zip HEAD $( git diff-tree --diff-filter=AM --no-commit-id --name-only -r A C)

新建檔案其內容為某版本檔案的內容
https://stackoverflow.com/questions/888414/git-checkout-older-revision-of-a-file-under-a-new-name
$ git show HEAD^:main.cpp > old_main.cpp
ex.
$ git show commit_id:test.php > test2.php

無法開新分支
$ git checkout -b test
fatal: Unable to write new index file
https://stackoverflow.com/questions/16064513/git-fatal-unable-to-write-new-index-file
原因:主機硬碟滿了,刪不必要的檔案

git diff 的tab使用4個空白
https://stackoverflow.com/questions/10581093/setting-tabwidth-to-4-in-git-show-git-diff
$ git config --global core.pager 'less -x1,5'

統計所有開發者某段時間內commit數量
https://stackoverflow.com/questions/9839083/git-number-of-commits-per-author-on-all-branches
$ git shortlog -s -n --all --no-merges --since="10 Feb 2019" --before="01 Sept 2099"

git pull報錯 There are no candidates for merging among the refs that you just fetched.
https://stackoverflow.com/questions/13799108/git-wildcard-refspec-with-no-match-on-remote-when-pulling
$ git pull
There are no candidates for merging among the refs that you just fetched.
Generally this means that you provided a wildcard refspec which had no
matches on the remote end.
原因:硬碟滿了。清硬碟就好

git log -p /path/file 或git show時搜尋忽略大小寫
https://stackoverflow.com/questions/16666009/how-do-i-use-vim-as-git-log-editor
https://serverfault.com/questions/11736/gnu-less-how-can-i-search-while-ignoring-case-sensitivity-without-using-less-i
git log 使用的是 linux 的 less, less 忽略大小寫是 -I -i
所以
$ git config --global core.pager 'less -I'
千萬不要用vim去看,會有亂碼
$ git config --global core.pager 'vim -'

用正則刪除多個分支
https://medium.com/@rajsek/deleting-multiple-branches-in-git-e07be9f5073c
$ git branch | grep "<pattern>" | xargs git branch -D

revert多個commit

https://stackoverflow.com/a/1470452  How to revert multiple git commits?
A -> B -> C -> D -> HEAD
一次revert  D+C+B的commit,回到A
$ git reset --hard A
$ git reset --soft @{1}  # (or ORIG_HEAD), which is D
$ git commit