Try   HackMD

git 練習場
git interview問題

Astro課程 0629-0701 git

使用brew 安裝

tingtinghsu@Hui-TingdeMacBook-Air  % which brew (這個指令在哪裡)
/usr/local/bin/brew

確認git版本

tingtinghsu@Hui-TingdeMacBook-Air % git --version
git version 2.24.0

初次設定git

git config --list
git config --global user.name "tingtinghsu"
git config --global user.email "tingtinghsu.tw[at]gmail.com"

注意:早期的時候寄email是不需要密碼的

也可以把以上指令中的global換成local,不同專案用不同公司/email
(因為不想發現是誰做的,統包商vs其他承包商)

cd /tmp (把資料放在/tmp,重開機就不見了)

git init

告訴git, 以後這個資料夾就是我管!

tingtinghsu@Hui-TingdeMacBook-Air projects % mkdir gitdemo
tingtinghsu@Hui-TingdeMacBook-Air projects % cd gitdemo 
tingtinghsu@Hui-TingdeMacBook-Air gitdemo % pwd 
/Users/tingtinghsu/Documents/projects/gitdemo
tingtinghsu@Hui-TingdeMacBook-Air gitdemo % git init
Initialized empty Git repository in /Users/tingtinghsu/Documents/projects/gitdemo/.git/

.git 所有紀錄都會在裡面

小技巧:不要給廠商 .git
(拿到肉體,不要給靈魂(對方歷史紀錄))
發案方(甲方)記得拿到歷史紀錄

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Reference

儲存庫(遠端)

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

CRUD 新增讀取修改刪除

git status

tingtinghsu@Hui-TingdeMacBook-Air gitdemo % touch first_day.rb
tingtinghsu@Hui-TingdeMacBook-Air gitdemo % git status
On branch master

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)
	first_day.rb

git add

tingtinghsu@Hui-TingdeMacBook-Air gitdemo % touch second_day.rb
tingtinghsu@Hui-TingdeMacBook-Air gitdemo % git status
On branch master

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)
#變成兩個檔案
first_day.rb
second_day.rb

tingtinghsu@Hui-TingdeMacBook-Air gitdemo % git add first_day.rb
    
tingtinghsu@Hui-TingdeMacBook-Air gitdemo % git status
On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
	new file:   first_day.rb

Untracked files:
  (use "git add <file>..." to include in what will be committed)
	second_day.rb

git rm -cached 復原staging的狀態

使用git rm -cached 檔案名稱將暫存區域的檔案移回工作目錄

tingtinghsu@Hui-TingdeMacBook-Air gitdemo % git rm --cached first_day.rb 
rm 'first_day.rb'
tingtinghsu@Hui-TingdeMacBook-Air gitdemo % git status
On branch master

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)
	first_day.rb
	second_day.rb

git commit -m "<寫入訊息>"

使用 git commit -m "簡述此次修改的內容" 將資料推入儲存庫,此語法是一個歸檔的動作,敘述修改內容有助於之後的閱讀
(如果只輸入git commit 會進入 vim畫面)

tingtinghsu@Hui-TingdeMacBook-Air gitdemo % git commit -m "first day in Astro"
[master (root-commit) 0eca0f5] first day in Astro
 2 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 first_day.rb
 create mode 100644 second_day.rb

什麼時候要commit?

  • 下班了
  • 功能做到一個段落

git log, git log --oneline

git log會顯示commit的作者、代碼及修改時間
git log --oneline將上述內容簡化成一行(不顯示作者)

tingtinghsu@Hui-TingdeMacBook-Air gitdemo % git log 
commit c3c15882363d0e28f0b9180a80094ad8e6eb396e (HEAD -> master)
Author: tingtinghsu <tingtinghsu.tw@gmail.com>
Date:   Mon Jun 29 15:56:24 2020 +0800

    edit file using vim

commit 0eca0f50a4d69facf96c5d395621b3f69e497ee4
Author: tingtinghsu <tingtinghsu.tw@gmail.com>
Date:   Mon Jun 29 15:42:31 2020 +0800

tingtinghsu@Hui-TingdeMacBook-Air gitdemo % git log --oneline
c3c1588 (HEAD -> master) edit file using vim
0eca0f5 first day in Astro

重要!git add .git add --all會將所有在工作目錄的檔案加入至暫存區域,範圍影響太大,盡量不要使用

Git 小劇場

git restore 檔名

可將刪掉之後的檔案拿回來

tingtinghsu@Hui-TingdeMacBook-Air projects % cd git-examples 
tingtinghsu@Hui-TingdeMacBook-Air git-examples % ls
git-branch1	git-branch3	git-rebase
git-branch2	git-conflict	git-stash

tingtinghsu@Hui-TingdeMacBook-Air git-examples % cd git-branch1
tingtinghsu@Hui-TingdeMacBook-Air git-branch1 % ls
config		hello.html	index.html	welcome.html

tingtinghsu@Hui-TingdeMacBook-Air git-branch1 % rm index.html 
tingtinghsu@Hui-TingdeMacBook-Air git-branch1 % ls
config		hello.html	welcome.html

tingtinghsu@Hui-TingdeMacBook-Air git-branch1 % git restore index.html
tingtinghsu@Hui-TingdeMacBook-Air git-branch1 % ls
config		hello.html	index.html	welcome.html

git restoregit checkout 的不同

git checkout
=> 有可能是兩種選項
git restore (刪掉儲存的檔案)
git switch (切換分支)

tingtinghsu@Hui-TingdeMacBook-Air git-branch1 % git branch
* cat
  master
tingtinghsu@Hui-TingdeMacBook-Air git-branch1 % git help checkout
tingtinghsu@Hui-TingdeMacBook-Air git-branch1 % ls             
config		hello.html	index.html	welcome.html
tingtinghsu@Hui-TingdeMacBook-Air git-branch1 % touch cat
tingtinghsu@Hui-TingdeMacBook-Air git-branch1 % ls
cat		config		hello.html	index.html	welcome.html
tingtinghsu@Hui-TingdeMacBook-Air git-branch1 % git rm cat
fatal: pathspec 'cat' did not match any files
tingtinghsu@Hui-TingdeMacBook-Air git-branch1 % git checkout cat
Already on 'cat'
tingtinghsu@Hui-TingdeMacBook-Air git-branch1 % git checkout master
Switched to branch 'master'
tingtinghsu@Hui-TingdeMacBook-Air git-branch1 % ls  
cat		config		hello.html	index.html	welcome.html
tingtinghsu@Hui-TingdeMacBook-Air git-branch1 % git branch
  cat
* master

git help checkout 可以查詢指令

git checkout . (回歸到最近的一次commit狀態)
SL 大法: Save and load

git restore .

註:git checkoutgit reset也容易混淆!請參考細說git reset和git checkout的不同之處

git壞掉了,這行是誰寫的?

git blame 檔名

罵人之前先檢查,阿老師說吼通常會blame到自己

tingtinghsu@Hui-TingdeMacBook-Air git-branch1 % git blame index.html 
abb4f438 (Eddie Kao 2017-08-02 16:49:49 +0800  1) <!DOCTYPE html>
abb4f438 (Eddie Kao 2017-08-02 16:49:49 +0800  2) <html>
abb4f438 (Eddie Kao 2017-08-02 16:49:49 +0800  3)   <head>
abb4f438 (Eddie Kao 2017-08-02 16:49:49 +0800  4)     <meta charset="utf-8">
abb4f438 (Eddie Kao 2017-08-02 16:49:49 +0800  5)     <title>首頁</title>
abb4f438 (Eddie Kao 2017-08-02 16:49:49 +0800  6)   </head>
abb4f438 (Eddie Kao 2017-08-02 16:49:49 +0800  7)   <body>
657fce78 (Eddie Kao 2017-08-02 16:53:43 +0800  8)     <div class="container">
657fce78 (Eddie Kao 2017-08-02 16:53:43 +0800  9)     </div>
abb4f438 (Eddie Kao 2017-08-02 16:49:49 +0800 10)   </body>
abb4f438 (Eddie Kao 2017-08-02 16:49:49 +0800 11) </html>

git log -p 單一檔案的歷史紀錄

tingtinghsu@Hui-TingdeMacBook-Air git-branch1 % git log -p index.html
commit 657fce783a23e26721ec4f778b9e0e108253e92d
Author: Eddie Kao <eddie@5xruby.tw>
Date:   Wed Aug 2 16:53:43 2017 +0800

    add container

diff --git a/index.html b/index.html
index d1146e2..e90bdb3 100644
--- a/index.html
+++ b/index.html
@@ -5,5 +5,7 @@
     <title>首頁</title>
   </head>
   <body>
+    <div class="container">
+    </div>
   </body>
 </html>

commit abb4f43814af7bcf47afa9b779aaba63599e562b
Author: Eddie Kao <eddie@5xruby.tw>
Date:   Wed Aug 2 16:49:49 2017 +0800

git branch 分支

關鍵下一秒 (Next, 2007)
男主角可以看到不久之後的未來

未來 git master 可能會改成 git main (?)

git head

  • HEAD 現在
    磁頭指的地方就是現在所在的分支上

分支指是一張貼在某個commit上的貼紙
分支往前移動,被HEAD(空心小圈圈)指的貼紙就往前貼

要先把權杖/令牌交給分身(HEAD,空心小圈圈),再叫分身去做事

tingtinghsu@Hui-TingdeMacBook-Air git-branch1 % git branch cat
tingtinghsu@Hui-TingdeMacBook-Air git-branch1 % git status
On branch master
nothing to commit, working tree clean

tingtinghsu@Hui-TingdeMacBook-Air git-branch1 % git branch
  cat
* master
tingtinghsu@Hui-TingdeMacBook-Air git-branch1 % git checkout cat
Switched to branch 'cat'

tingtinghsu@Hui-TingdeMacBook-Air git-branch1 % git status
On branch cat
nothing to commit, working tree clean
tingtinghsu@Hui-TingdeMacBook-Air git-branch1 % git branch
* cat
  master

圖形不一定會開叉,因為設計概念是貼貼紙

剛開完分支時並沒有感覺到特別的變化
(就像原地跳起來、原地落下)
(回到主要分支的時候,其他分支上建立的東西不會被刪掉)

本體master盡量留在原地,不要往前移動;
讓分支往前移。

Day2

狀況一:建立新分支,並將新分支的commit合併到主分支

重要:合併分支可以視為移動貼紙!

流程

  1. git branch cat
    建立新分支

  2. git checkout cat
    切換到新分支

  3. git commit -m "多一個commit" --allow-empty
    在新分支上commit --allow-empty內容不一定要有檔案(這指令不太有意義,只是為了教學用)

  4. git checkout master
    切回主分支

  5. git merge cat
    主分支合併新分支
    使用Fast-forward 快轉模式合併(收割成果)

練習:

tingtinghsu@Hui-TingdeMacBook-Air git-branch1 % git status
On branch cat
Untracked files:
  (use "git add <file>..." to include in what will be committed)
	cat

tingtinghsu@Hui-TingdeMacBook-Air git-branch1 % git add .
tingtinghsu@Hui-TingdeMacBook-Air git-branch1 % git commit -m "add cat"
[cat 454e202] add cat
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 cat


tingtinghsu@Hui-TingdeMacBook-Air git-branch1 % git branch    
  all
* cat
  master

tingtinghsu@Hui-TingdeMacBook-Air git-branch1 % git checkout master
Switched to branch 'master'

tingtinghsu@Hui-TingdeMacBook-Air git-branch1 % git merge cat
Updating e12d8ef..454e202
Fast-forward
 cat | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 cat

tingtinghsu@Hui-TingdeMacBook-Air git-branch1 % git branch
  all
  cat
* master

狀況二:複雜一點的分支

  • 開始跟別人合作
  • 如果要把cat分支和dog分支合併在一起
    (例如跟郭台銘合併家產)

Eg. 如何用dog分支去合併cat分支?

  1. 長出一顆新的commit (合併用的節點)(公正的律師
  2. 被head指的dog貼紙往前移

註:git merge時盡量加上註解-m " ",不然會進入vim畫面

這次使用的git merge就不是fast-forward,而是'recursive' strategy

練習:

tingtinghsu@Hui-TingdeMacBook-Air git-examples % cd git-branch2

tingtinghsu@Hui-TingdeMacBook-Air git-branch2 % git status
On branch master
nothing to commit, working tree clean

tingtinghsu@Hui-TingdeMacBook-Air git-branch2 % git branch
  cat
  dog
* master

tingtinghsu@Hui-TingdeMacBook-Air git-branch2 % git checkout dog
Switched to branch 'dog'

tingtinghsu@Hui-TingdeMacBook-Air git-branch2 % git merge cat -m "dog branch merge cat" 

Merge made by the 'recursive' strategy.
 cat1.html | 0
 cat2.html | 0
 2 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 cat1.html
 create mode 100644 cat2.html

tingtinghsu@Hui-TingdeMacBook-Air git-branch2 % git branch
  cat
* dog
  master

不想要快轉合併,可以在指令加上--no-ff
(只是為了創造分支的存在感)

狀況三:刪掉已經合併過的分支

git branch -d cat
git branch -D

檔案沒有完全不見(所以可以救回來)

不管是FF合併或是Y型合併

  • 歷史紀錄並不會消失 (因為是沒有人看管的末端枝節)
  • 電腦多了40bytes (撕掉貼紙佔用的空間)

狀況四:忘記切換分支

只要想辦法把貼紙切換過來就可以
因為git的本體是commit (做了什麼事情),而不是貼紙的名字

名字互換:

git branch -m cat ccc (在master上改cat名字成ccc)
git checkout ccc 
git branch -m master cat
git checkout cat
git branch -m ccc master

狀況五:發生衝突 Conflict

  • 順利長出共同節點的前提是沒有衝突
  • git沒有辦法解決conflict,但會標出conflict的地方

練習:不管是誰合併誰,都會產生衝突

tingtinghsu@Hui-TingdeMacBook-Air git-examples % cd git-conflict 

tingtinghsu@Hui-TingdeMacBook-Air git-conflict % git status
On branch payment
nothing to commit, working tree clean

tingtinghsu@Hui-TingdeMacBook-Air git-conflict % git branch
  master
  member
* payment

tingtinghsu@Hui-TingdeMacBook-Air git-conflict % git merge member
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result.
  • 解決衝突並不一定代表解決問題
    => 如果沒有修好出現conflict的程式碼就直接commit,問題還是沒有解決
    => 去找同事討論該如何修改程式產生衝突的地方再commit
tingtinghsu@Hui-TingdeMacBook-Air git-conflict % git checkout member
index.html: needs merge
error: you need to resolve your current index first

tingtinghsu@Hui-TingdeMacBook-Air git-conflict % git status
On branch payment
You have unmerged paths.
  (fix conflicts and run "git commit")
  (use "git merge --abort" to abort the merge)

Changes to be committed:
	new file:   member.html

Unmerged paths:
  (use "git add <file>..." to mark resolution)
	both modified:   index.html

tingtinghsu@Hui-TingdeMacBook-Air git-conflict % git add .

tingtinghsu@Hui-TingdeMacBook-Air git-conflict % vim index.html              

tingtinghsu@Hui-TingdeMacBook-Air git-conflict % git commit -m "remove payment link"
[payment 031dc59] remove payment link
tingtinghsu@Hui-TingdeMacBook-Air git-conflict % git merge member
Already up to date.
tingtinghsu@Hui-TingdeMacBook-Air git-conflict % git status
On branch payment
nothing to commit, working tree clean

rebase

  • rebase:把Y型分支拉直(複製一份分支再嫁接的概念)
  • rebase發生衝突時,先解決衝突,再continue

rebase與merge的差別

優點

  • 省一顆commit的節點
  • 讓合併的歷史紀錄分支樹變得比較精簡

缺點

  • 比較麻煩
  • 歷史紀錄不會保留(但這可能也是優點)

練習:

tingtinghsu@Hui-TingdeMacBook-Air git-examples % cd git-branch2

tingtinghsu@Hui-TingdeMacBook-Air git-branch2 % git status
On branch dog
nothing to commit, working tree clean

tingtinghsu@Hui-TingdeMacBook-Air git-branch2 % git checkout cat
Switched to branch 'cat'

tingtinghsu@Hui-TingdeMacBook-Air git-branch2 % git status
On branch cat
nothing to commit, working tree clean

tingtinghsu@Hui-TingdeMacBook-Air git-branch2 % git rebase dog
First, rewinding head to replay your work on top of it...
Fast-forwarded cat to dog.

什麼時候適合用rebase?

  • 用來整理自己的commit
  • 分叉的地方對其他人不太有意義的時候

reset

當做好的commit不太滿意,想要砍掉

git reset "commit的id"
(reset有become的意思)

後面接的三種參數:
決定被砍掉的commit要被丟到哪裏

--soft (暫存區)
--mixed (預設值,放在工作目錄)(比soft多了git add指令)   
--hard (拋棄)

練習:

tingtinghsu@Hui-TingdeMacBook-Air git-branch1 % git log --oneline

454e202 (HEAD -> master, cat, all) add cat
e12d8ef add database.yml in config folder
85e7e30 add hello
657fce7 add container
abb4f43 update index page
cef6e40 create index page
cc797cd init commit

tingtinghsu@Hui-TingdeMacBook-Air git-branch1 % git reset 657fce7

tingtinghsu@Hui-TingdeMacBook-Air git-branch1 % git log --oneline

657fce7 (HEAD -> master) add container
abb4f43 update index page
cef6e40 create index page
cc797cd init commit

tingtinghsu@Hui-TingdeMacBook-Air git-branch1 % git status
On branch master
Untracked files:
  (use "git add <file>..." to include in what will be committed)
	cat
	config/
	hello.html

比較常用代名詞 (master, cat, HEAD)

git reset HEAD --hard

我想回到現在這個地方
(修改過但還沒commit的變化,全部都不要了)

^ = caret 卡洛特
~ = tilde 提爾達

^ 倒退一步
^^ 倒退二步
~10 倒退10步

git reset HEAD^ --hard

=> 類似ctrl Z
我想回到上一步 (但不能再回來了)

checkout

resetcheckout指令的差別?

git checkout: 我要去別的地方看一下
HEAD移動,master留在原地,所以分支的末端不會消失

git reset:
HEAD和master一起移動到之前的commit,分支的末端消失

練習:

  1. cat 合併 dog
tingtinghsu@Hui-TingdeMacBook-Air git-branch2 % git checkout cat
Switched to branch 'cat'

tingtinghsu@Hui-TingdeMacBook-Air git-branch2 % git status
On branch cat
nothing to commit, working tree clean

# Merge branch dog into cat
tingtinghsu@Hui-TingdeMacBook-Air git-branch2 % git merge dog
Merge made by the 'recursive' strategy.
 dog1.html | 0
 dog2.html | 0
 2 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 dog1.html
 create mode 100644 dog2.html
  1. 把cat貼紙撕起來,貼回上一步的commit

git reset HEAD^ hard (變回合併前的狀態)

tingtinghsu@Hui-TingdeMacBook-Air git-branch2 % git log --oneline

28f7314 (HEAD -> cat) Merge branch 'dog' into cat
053fb21 (dog) add dog 2
b69eb62 add dog 1
b174a5a add cat 2
c68537b add cat 1
e12d8ef (master) add database.yml in config folder
85e7e30 add hello
657fce7 add container
abb4f43 update index page
cef6e40 create index page
cc797cd init commit

tingtinghsu@Hui-TingdeMacBook-Air git-branch2 % git reset HEAD^ --hard
zsh: no matches found: HEAD^

tingtinghsu@Hui-TingdeMacBook-Air git-branch2 % git reset HEAD\^ --hard
HEAD is now at b174a5a add cat 2

tingtinghsu@Hui-TingdeMacBook-Air git-branch2 % git log --oneline      

b174a5a (HEAD -> cat) add cat 2
c68537b add cat 1
e12d8ef (master) add database.yml in config folder
85e7e30 add hello
657fce7 add container
abb4f43 update index page
cef6e40 create index page
cc797cd init commit

錯誤訊息:zsh: no matches found: HEAD^

狀況七:不小心用reset HARD模式刪掉commit

使用git reflog,然後hard reset回來

tingtinghsu@Hui-TingdeMacBook-Air git-examples % cd git-branch1

tingtinghsu@Hui-TingdeMacBook-Air git-branch1 % git reset HEAD~5 --hard
HEAD is now at cc797cd init commit

刪掉只剩一個commit該怎麼辦?

解法:找出HEAD的移動軌跡,包括
checkout
commit
rebase
reset
merge

tingtinghsu@Hui-TingdeMacBook-Air git-branch1 % git reflog 

cc797cd (HEAD -> master) HEAD@{0}: reset: moving to HEAD~5
e12d8ef HEAD@{1}: checkout: moving from cat to master
b174a5a HEAD@{2}: reset: moving to ORIG_HEAD
7243723 HEAD@{3}: rebase finished: returning to refs/heads/cat
7243723 HEAD@{4}: rebase: add cat 2
5b8f484 HEAD@{5}: rebase: add cat 1
053fb21 HEAD@{6}: rebase: checkout dog
b174a5a HEAD@{7}: checkout: moving from master to cat
e12d8ef HEAD@{8}: reset: moving to ORIG_HEAD
b174a5a HEAD@{9}: merge cat: Fast-forward
e12d8ef HEAD@{10}: reset: moving to ORIG_HEAD
...

找到e12d8ef HEAD@{1}的序號

git reset e12d --hard

tingtinghsu@Hui-TingdeMacBook-Air git-branch1 % git reset e12d --hard
HEAD is now at e12d8ef add database.yml in config folder

commit又全部長回來了!

註:rm -rf .git 才會砍掉所有紀錄

狀況八:不小心刪掉分支,如何復原?

刪掉dog分支的話,再把貼紙貼回去原來的commit就好

git branch -d dog
git branch -D dog
git branch new_dog 053fb21
(git branch 分支名稱 想賦予名稱的commit id)

tingtinghsu@Hui-TingdeMacBook-Air git-examples % cd git-branch2

tingtinghsu@Hui-TingdeMacBook-Air git-branch2 % git branch -d dog    
error: The branch 'dog' is not fully merged.
If you are sure you want to delete it, run 'git branch -D dog'.

tingtinghsu@Hui-TingdeMacBook-Air git-branch2 % git branch -D dog
Deleted branch dog (was 053fb21).

tingtinghsu@Hui-TingdeMacBook-Air git-branch2 % git reflog
e12d8ef (HEAD -> master) HEAD@{0}: checkout: moving from cat to master
b174a5a (cat) HEAD@{1}: reset: moving to ORIG_HEAD
...


tingtinghsu@Hui-TingdeMacBook-Air git-branch2 % git branch new_dog 053f

冷知識:HEAD移動到不同分支上的commit節點
git checkout HEAD12
= git checkout HEAD^^2

如何回到rebase之前的狀態?

  1. 先rebase:
    從cat分支:git rebase dog
    (rebase current branch onto dog)

  2. 再查詢當時分支存在的id:
    git reflog

  3. 然後用reset回復:
    git reset b174 --hard

註:還可以繼續用reset id結果又回到剛才rebase的狀態!(方唐鏡
=> 結論:reset可以用來做很多事!

tag

git tag 2.0
(類似git branch 2.0的意思)

git tag 1.0 abb4

cd -: 回到上一動(上次的目錄)
所以git checkout -: 也是回到上一次路徑的意思

tingtinghsu@Hui-TingdeMacBook-Air git-branch2 % git tag 2.0
tingtinghsu@Hui-TingdeMacBook-Air git-branch2 % git tag 1.0 abb4
tingtinghsu@Hui-TingdeMacBook-Air git-branch2 % git checkout 2.0
Note: switching to '2.0'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:

  git switch -c <new-branch-name>

Or undo this operation with:

  git switch -

Turn off this advice by setting config variable advice.detachedHead to false

HEAD is now at 053fb21 add dog 2

tingtinghsu@Hui-TingdeMacBook-Air git-branch2 % git checkout 1.0
Previous HEAD position was 053fb21 add dog 2
HEAD is now at abb4f43 update index page

tingtinghsu@Hui-TingdeMacBook-Air git-branch2 % git checkout -  
Previous HEAD position was abb4f43 update index page
HEAD is now at 053fb21 add dog 2

tag和branch有什麼不同?

branch會跟著commit走
tag會留下來

「留下來,或者我跟你走!」

修改commit -m 的訊息

git rebase bb0c -i (interactive模式)
或者使用git GUI軟體,在commit的點上按右鍵操作

做過修改後,之後的子分支會產生平行時空(序號改變)

整合太瑣碎零散的commit

把add cat1 和 add cat2拆掉
squash with previous commit


修改後的commit,之後的序號都改了

拆掉很大一包的commit

  1. 停下來: 先把HEAD指向需要修改的commit
  2. 倒退一步 git reset HEAD^
  3. 分別拆開檔案 git add
  4. git rebase --continue
    (但有接完壞掉的情況,取消 git rebase --abort)
tingtinghsu@Hui-TingdeMacBook-Air git-branch3 % cd ../git-rebase

tingtinghsu@Hui-TingdeMacBook-Air git-rebase % git status
interactive rebase in progress; onto bb0c9c2
Last commands done (2 commands done):
   pick 382a2a5 add database settings
   edit 3323ec7 All cat (+2 squashed commits) Squashed commits: [1de2076] add cat 2 [cd82f29] add cat 1
Next commands to do (5 remaining commands):
   pick 4c5255f add dog 1
   pick 1d68ddc add dog 2
  (use "git rebase --edit-todo" to view and edit)
You are currently editing a commit while rebasing branch 'master' on 'bb0c9c2'.
  (use "git commit --amend" to amend the current commit)
  (use "git rebase --continue" once you are satisfied with your changes)

nothing to commit, working tree clean

tingtinghsu@Hui-TingdeMacBook-Air git-rebase % git reset HEAD\^

tingtinghsu@Hui-TingdeMacBook-Air git-rebase % git status
interactive rebase in progress; onto bb0c9c2
Last commands done (2 commands done):
   pick 382a2a5 add database settings
   edit 3323ec7 All cat (+2 squashed commits) Squashed commits: [1de2076] add cat 2 [cd82f29] add cat 1
Next commands to do (5 remaining commands):
   pick 4c5255f add dog 1
   pick 1d68ddc add dog 2
  (use "git rebase --edit-todo" to view and edit)
You are currently editing a commit while rebasing branch 'master' on 'bb0c9c2'.
  (use "git commit --amend" to amend the current commit)
  (use "git rebase --continue" once you are satisfied with your changes)

Untracked files:
  (use "git add <file>..." to include in what will be committed)
	cat1.html
	cat2.html
	cat3.html
	cat4.html

nothing added to commit but untracked files present (use "git add" to track)

tingtinghsu@Hui-TingdeMacBook-Air git-rebase % git add cat1 cat2
fatal: pathspec 'cat1' did not match any files

tingtinghsu@Hui-TingdeMacBook-Air git-rebase % git add cat1.html cat2.html 

tingtinghsu@Hui-TingdeMacBook-Air git-rebase % git commit -m "cat1 cat2"
[detached HEAD aeff088] cat1 cat2
 2 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 cat1.html
 create mode 100644 cat2.html

tingtinghsu@Hui-TingdeMacBook-Air git-rebase % git add cat3.html cat4.html 
tingtinghsu@Hui-TingdeMacBook-Air git-rebase % git commit -m "add cat3 cat4"
[detached HEAD dce6353] add cat3 cat4
 2 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 cat3.html
 create mode 100644 cat4.html

tingtinghsu@Hui-TingdeMacBook-Air git-rebase % git rebase --continue
Successfully rebased and updated refs/heads/master.

成功把整包的貓拆成兩個cat1 cat2, cat 3 cat4兩個檔案!

問題:
source tree如何install command line?

然後直接在command line叫出source tree stree .

在GitHub建立新專案

New repository,網頁版右上角 +

全新專案

…or create a new repository on the command line
echo "# gitfile" >> README.md
git init
git add README.md
git commit -m "first commit"

git remote add origin https://github.com/tingtinghsu/gitfile.git
git push -u origin master

選擇httpshttps://github.com/tingtinghsu/gitfile.git
在推送的過程中會需要輸入帳號密碼

選擇SSH ,本地檔案會存一份公鑰和私鑰(不要在公用電腦上做)

git push origin master的解釋

Git push origin master
把master的進度推一份到origin

Git push origin master
Git push abc master
Git push xyz master

Git push heroku master
Git remote add heroku git@heroku.com:tingtinghsu

Git push piano master (把貓推到鋼琴上)

git push origin master其實是縮寫

git push origin master
=> 
git push origin master:master (遠端建立master branch的意思)

所以
git push origin master:cat (遠端建立cat branch的意思)

會用到git push origin master:cat的情境

git push heroku master
(heroku只能接受推master)
git push heroku dev
git push heroku dev:master
 (dev推上heroku遠端節點,再把遠端推成master branch的意思)

練習:

git push origin master:cat
Total 0 (delta 0), reused 0 (delta 0)
remote:
remote: Create a pull request for 'cat' on GitHub by visiting:
remote:      https://github.com/tingtinghsu/gitfile/pull/new/cat
remote:
To github.com:tingtinghsu/gitfile.git
 * [new branch]      master -> cat

在本地電腦產生SSH Key

  ssh-keygen

Generating public/private rsa key pair.
Enter file in which to save the key (/Users/tingtinghsu/.ssh/id_rsa):

Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /Users/tingtinghsu/.ssh/id_rsa.
Your public key has been saved in /Users/tingtinghsu/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:Iq4xYSKyLdY27bThg4cZM+RZTPb+BhYj9TOT8jbLl2s tingtinghsu@Hui-TingdeMacBook-Air.local
The key's randomart image is:
+---[RSA 3072]----+
|                 |
|     o .         |
|    + o . .      |
|   . + = *       |
|+ = + + S +      |
|o=.O.. = +       |
|o.++O+. = o .    |
|...B=oo  = E     |
|  . .+. . o..    |
+----[SHA256]-----+


 ~ cd /Users/tingtinghsu/           
 ~ ls
Applications Documents    Dropbox      Movies       Pictures
Desktop      Downloads    Library      Music        Public
~/.ssh                
 ~/.ssh  ls
id_rsa      id_rsa.pub  known_hosts
 ~/.ssh  code .        

 ~/.ssh  cat id_rsa.pub 

ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDVr2bi2kTesH5q1qbs0kx2rlWjCV5poV87HI5d8J0WQXXEt5oRCEi3+TP1UklablEGTD2zRjIBLkzN7AIZadALzkFMdfyLT7Y8b1ll5kDc3lNyb6mCHfqjUe5XAWit2oVUS1zqaCbcBdRUvEmxR0vprO3ksaCPbHbYDkaK7lkq/rPgfGwMXVz1FHjj7vD4x7v1NcQnAyw0ZyGgV9/VeYs7eCILHdRXpAbstmFDyXcHYJwVgnRbEh0B4cCJ4/489sVsucZNgH/FghAOYAdX864I0OtNu44xBGyafauU2hOFgkxcRaio4Y09eUUD8IoEDmErShL/QT64ZJnxdG3sfswik3TvKuQWmbWn4CKN9Vxx0+1esg9dUgY7wjfDvhPgssEDmLp5ZLDy1PLhNf7uflSWmzwhrfa9XmNPW+X8ijpHwJSmfaKDvPaB78yNg9O3avjV6IMJW7FaV1tqqQyp9XLDpOnH180KMTNZjV68yUE+Jd11n6IJR0xy8J8WK04XkfE= tingtinghsu@Hui-TingdeMacBook-Air.local

為GitHub設定SSH

  1. 確定該資料夾是否有設定遠端:
    git remote -v
fatal: not a git repository (or any of the parent directories): .git
(要選擇有.git檔案的資料夾才可推)
  1. 移除設定推送的遠端位置:
    git remote rm origin

  2. -u 設定預設的本地與推送的遠端位置配對
    (通常最近手邊在忙的專案)
    git push -u origin master

註:如果沒有-u,每次git push會出現
The current branch master has no upstream branch.

git push origin master

The authenticity of host 'github.com (140.82.114.3)' can't be established.
RSA key fingerprint is SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'github.com,140.82.114.3' (RSA) to the list of known hosts.
Enumerating objects: 9, done.
Counting objects: 100% (9/9), done.
Delta compression using up to 4 threads
Compressing objects: 100% (7/7), done.
Writing objects: 100% (9/9), 899 bytes | 299.00 KiB/s, done.
Total 9 (delta 1), reused 0 (delta 0)
remote: Resolving deltas: 100% (1/1), done.
To github.com:tingtinghsu/gitfile.git
 * [new branch]      master -> master

git push

fatal: The current branch master has no upstream branch.
To push the current branch and set the remote as upstream, use

    git push --set-upstream origin master

從GitHub把檔案pull下來

git fetch 抓線上有的、但是本機沒有的檔案

 ~/Documents/projects/gitdemo   master  git fetch


remote: Enumerating objects: 4, done.
remote: Counting objects: 100% (4/4), done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), done.
From github.com:tingtinghsu/gitfile
   2ad4ead..5f08c95  master     -> origin/master

git merge origin master 把本機的檔案跟上進度

 ~/Documents/projects/gitdemo   master  git merge origin/master
Updating 2ad4ead..5f08c95
Fast-forward
 origin.html | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 origin.html

git pull

git pull = git fetch + git merge

~/Documents/projects/gitdemo   master  git pull origin master
From github.com:tingtinghsu/gitfile
 * branch            master     -> FETCH_HEAD
Updating 5f08c95..a5feaf1
Fast-forward
 "\bpull.html" | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 "\pull.html"

git clone git網址

eg. 加入新專案、加入新團隊

在什麼都沒有的情況下,沒辦法fetch
必須先直接把整包下載下來

fetch是用來補上進度

一起合作專案的時候

策略一:先拉下來一份,再merge,然後再推上去
=> 但這樣會分支圖很醜

策略二:每個人建立新分支,在分支上做事情

注意:
git push -f使用前要先告訴同事!
因為其他同事之後還要先砍掉原有檔案再git clone
(因為歷史紀錄已經改變)

Pull Request

先fork其他人的專案到我自己的地方來
做完修改後再送PR

merge策略

  1. create a merge commit
    Y型合併,多一次commit(如果發PR的人落後orgin/master的專案進度,commit數還會再增加)

  2. squash and merge
    一次送了多個commit在同一個PR,但擠壓完只有增加一次commit

  3. rebase and merge
    直接加上發PR的人送的commit數

自己fork的專案落後原作專案的commit進度,如何跟上?

=> 想辦法同步

手冊:Syncing a fork
怎麼跟上當初 fork 專案的進度?

# 新加上原作的remote master (名稱為upstream)
git remote add upstream https://github.com/kaochenlong/dummy-git.git


# 拉一份下來,再合併 (讓本機master往前移動)
git pull upstream master

Git的世界觀

  1. git的物件有計算公式
    加密演算法:可以拿來驗證,但無法反推
    只要內容不變,數值就不變
    一樣的內容(就算都是空的內容),數值不變
    mkdir不會產生亂數

但是!commit本身的內容幾乎等於亂數

  1. git不在乎檔名是什麼,只在乎檔案內容的變化

cat index.html | grep title

| 的意思:把前面的東西丟給|的後面

cat index.html | git hash-object --stdin
會算出一個SHA1的一長串數值

git add (內容壓縮後,存在物件區)

git cat-file -t 看型態
git cat-file -p 看內容

切換branch時發生什麼事?

葡萄梗:從整串抽出來分支看

Git不是做差異備份!

git
即使只改一個字,都重新計算,產生一顆物件