Git介紹及命令行使用

1. Git

1.1. Git是何方神圣?

Git是用C語(yǔ)言開(kāi)發(fā)的分布版本控制系統(tǒng)姥饰。版本控制系統(tǒng)可以保留一個(gè)文件集合的歷史記錄,并能回滾文件集合到另一個(gè)狀態(tài)(歷史記錄狀態(tài))。另一個(gè)狀態(tài)可以是不同的文件雁竞,也可以是不同的文件內(nèi)容簿寂。舉個(gè)例子漾抬,你可以將文件集合轉(zhuǎn)換到兩天之前的狀態(tài),或者你可以在生產(chǎn)代碼和實(shí)驗(yàn)性質(zhì)的代碼之間進(jìn)行切換常遂。文件集合往往被稱作是“源代碼”纳令。在一個(gè)分布版本控制系統(tǒng)中,每個(gè)人都有一份完整的源代碼(包括源代碼所有的歷史記錄信息)克胳,而且可以對(duì)這個(gè)本地的數(shù)據(jù)進(jìn)行操作平绩。分布版本控制系統(tǒng)不需要一個(gè)集中式的代碼倉(cāng)庫(kù)。

當(dāng)你對(duì)本地的源代碼進(jìn)行了修改毯欣,你可以標(biāo)注他們跟下一個(gè)版本相關(guān)(將他們加到index中)馒过,然后提交到倉(cāng)庫(kù)中來(lái)(commit)。Git保存了所有的版本信息酗钞,所以你可以轉(zhuǎn)換你的源代碼到任何的歷史版本腹忽。你可以對(duì)本地的倉(cāng)庫(kù)進(jìn)行代碼的提交,然后與其他的倉(cāng)庫(kù)進(jìn)行同步砚作。你可以使用Git來(lái)進(jìn)行倉(cāng)庫(kù)的克戮阶唷(clone)操作,完整的復(fù)制一個(gè)已有的倉(cāng)庫(kù)葫录。倉(cāng)庫(kù)的所有者可以通過(guò)push操作(推送變更到別處的倉(cāng)庫(kù))或者Pull操作(從別處的倉(cāng)庫(kù)拉取變更)來(lái)同步變更着裹。

Git支持分支功能(branch)。如果你想開(kāi)發(fā)一個(gè)新的產(chǎn)品功能米同,你可以建立一個(gè)分支骇扇,對(duì)這個(gè)分支的進(jìn)行修改,而不至于會(huì)影響到主支上的代碼面粮。

Git提供了命令行工具少孝;這個(gè)教程會(huì)使用命令行。你也可以找到圖形工具熬苍,譬如與Eclipse配套的EGit工具稍走,但是這些都不會(huì)在這個(gè)教程中進(jìn)行描述。

1.2. 重要的術(shù)語(yǔ)

表 1. Git 術(shù)語(yǔ)

術(shù)語(yǔ) 定義
倉(cāng)庫(kù)(Repository) 一個(gè)倉(cāng)庫(kù)包括了所有的版本信息柴底、所有的分支和標(biāo)記信息婿脸。在Git中倉(cāng)庫(kù)的每份拷貝都是完整的。倉(cāng)庫(kù)讓你可以從中取得你的工作副本柄驻。
分支(Branches) 一個(gè)分支意味著一個(gè)獨(dú)立的狐树、擁有自己歷史信息的代碼線(code line)。你可以從已有的代碼中生成一個(gè)新的分支鸿脓,這個(gè)分支與剩余的分支完全獨(dú)立褪迟。默認(rèn)的分支往往是叫master冗恨。用戶可以選擇一個(gè)分支,選擇一個(gè)分支叫做checkout.
標(biāo)記(Tags) 一個(gè)標(biāo)記指的是某個(gè)分支某個(gè)特定時(shí)間點(diǎn)的狀態(tài)味赃。通過(guò)標(biāo)記掀抹,可以很方便的切換到標(biāo)記時(shí)的狀態(tài),例如2009年1月25號(hào)在testing分支上的代碼狀態(tài)
提交(Commit) 提交代碼后心俗,倉(cāng)庫(kù)會(huì)創(chuàng)建一個(gè)新的版本傲武。這個(gè)版本可以在后續(xù)被重新獲得。每次提交都包括作者和提交者城榛,作者和提交者可以是不同的人
URL URl用來(lái)標(biāo)識(shí)一個(gè)倉(cāng)庫(kù)的位置
修訂(Revision) 用來(lái)表示代碼的一個(gè)版本狀態(tài)揪利。Git通過(guò)用SHA1 hash算法表示的id來(lái)標(biāo)識(shí)不同的版本。每一個(gè) SHA1 id都是160位長(zhǎng)狠持,16進(jìn)制標(biāo)識(shí)的字符串.疟位。最新的版本可以通過(guò)HEAD來(lái)獲取。之前的版本可以通過(guò)"HEAD~1"來(lái)獲取喘垂,以此類(lèi)推甜刻。

1.3. 索引

Git 需要將代碼的變化顯示的與下一次提交進(jìn)行關(guān)聯(lián)。舉個(gè)例子正勒,如果你對(duì)一個(gè)文件繼續(xù)了修改得院,然后想將這些修改提交到下一次提交中,你必須將這個(gè)文件提交到索引中章贞,通過(guò)git add file命令祥绞。這樣索引可以保存所有變化的快照。

新增的文件總是要顯示的添加到索引中來(lái)鸭限。對(duì)于那些之前已經(jīng)提交過(guò)的文件蜕径,可以在commit命令中使用-a 選項(xiàng)達(dá)到提交到索引的目的。

2. 安裝

在Ubuntu上败京,你可以通過(guò)apt來(lái)安裝git命令行工具

sudo apt-get install git-core

對(duì)于其他的Linux版本丧荐,請(qǐng)查看相關(guān)的軟件包安裝工具使用方法
msysgit項(xiàng)目提供了Windows版本的Git,地址是http://code.google.com/p/msysgit/

3. 配置

你可以在.gitconfig文件中防止git的全局配置喧枷。文件位于用戶的home目錄。 上述已經(jīng)提到每次提交都會(huì)保存作者和提交者的信息弓坞,這些信息都可以保存在全局配置中隧甚。

后續(xù)將會(huì)介紹配置用戶信息、高亮顯示和忽略特定的文件

3.1. 用戶信息

通過(guò)如下命令來(lái)配置用戶名和Email

# Configure the user which will be used by git
# Of course you should use your name
git config --global user.name "Example Surname"
# Same for the email address
git config --global user.email "your.email@gmail.com"
# Set default so that all changes are always pushed to the repository
git config --global push.default "matching"

獲取Git配置信息渡冻,執(zhí)行以下命令:

git config --list

3.2. 高亮顯示

以下命令會(huì)為終端配置高亮

git config --global color.status auto
git config --global color.branch auto

3.3. 忽略特定的文件

可以配置Git忽略特定的文件或者是文件夾戚扳。這些配置都放在.gitignore文件中。這個(gè)文件可以存在于不同的文件夾中族吻,可以包含不同的文件匹配模式帽借。為了讓Git忽略bin文件夾珠增,在主目錄下放置.gitignore文件,其中內(nèi)容為bin砍艾。

同時(shí)Git也提供了全局的配置蒂教,core.excludesfile

3.4. 使用.gitkeep來(lái)追蹤空的文件夾

Git會(huì)忽略空的文件夾脆荷。如果你想版本控制包括空文件夾凝垛,根據(jù)慣例會(huì)在空文件夾下放置.gitkeep文件。其實(shí)對(duì)文件名沒(méi)有特定的要求蜓谋。一旦一個(gè)空文件夾下有文件后梦皮,這個(gè)文件夾就會(huì)在版本控制范圍內(nèi)。

4. 開(kāi)始操作Git

后續(xù)將通過(guò)一個(gè)典型的Git工作流來(lái)學(xué)習(xí)桃焕。在這個(gè)過(guò)程中剑肯,你會(huì)創(chuàng)建一些文件、創(chuàng)建一個(gè)本地的Git倉(cāng)庫(kù)观堂、提交你的文件到這個(gè)倉(cāng)庫(kù)中让网。這之后,你會(huì)克隆一個(gè)倉(cāng)庫(kù)型将、在倉(cāng)庫(kù)之間通過(guò)pull和push操作來(lái)交換代碼的修改寂祥。注釋?zhuān)ㄒ?開(kāi)頭)解釋了命令的具體含義

讓我們打開(kāi)命令行開(kāi)始操作吧

4.1. 創(chuàng)建內(nèi)容

下面創(chuàng)建一些文件,它們會(huì)被放到版本控制之中

#Switch to home
cd ~/
# Create a directory
mkdir ~/repo01
# Switch into it
cd repo01
# Create a new directory
mkdir datafiles
# Create a few files
touch test01
touch test02
touch test03
touch datafiles/data.txt
# Put a little text into the first file
ls >test01

4.2. 創(chuàng)建倉(cāng)庫(kù)七兜、添加文件和提交更改

每個(gè)Git倉(cāng)庫(kù)都是放置在.git文件夾下.這個(gè)目錄包含了倉(cāng)庫(kù)的所有歷史記錄丸凭,.git/config文件包含了倉(cāng)庫(kù)的本地配置。
以下將會(huì)創(chuàng)建一個(gè)Git倉(cāng)庫(kù)腕铸,添加文件倒倉(cāng)庫(kù)的索引中惜犀,提交更改。

# Initialize the local Git repository
git init
# Add all (files and directories) to the Git repository
git add .
# Make a commit of your file to the local repository
git commit -m "Initial commit"
# Show the log file
git log

4.3. diff命令與commit更改

通過(guò)git diff命令狠裹,用戶可以查看更改虽界。通過(guò)改變一個(gè)文件的內(nèi)容,看看git diff命令輸出什么涛菠,然后提交這個(gè)更改到倉(cāng)庫(kù)中

# Make some changes to the file
echo "This is a change" > test01
echo "and this is another change" > test02

# Check the changes via the diff command 
git diff

# Commit the changes, -a will commit changes for modified files
# but will not add automatically new files
git commit -a -m "These are new changes"

4.4. Status, Diff 和 Commit Log

下面會(huì)向你展示倉(cāng)庫(kù)現(xiàn)有的狀態(tài)以及過(guò)往的提交歷史

# Make some changes in the file
echo "This is a new change" > test01
echo "and this is another new change" > test02

# See the current status of your repository 
# (which files are changed / new / deleted)
git status
# Show the differences between the uncommitted files 
# and the last commit in the current branch
git diff

# Add the changes to the index and commit
git add . && git commit -m "More chaanges - typo in the commit message"

# Show the history of commits in the current branch
git log
# This starts a nice graphical view of the changes
gitk --all

4.5. 更正提交的信息 - git amend

通過(guò)git amend命令莉御,我們可以修改最后提交的的信息
上述的提交信息中存在錯(cuò)誤,下面會(huì)修改這個(gè)錯(cuò)誤

git commit --amend -m "More changes - now correct"

4.6. 刪除文件

如果你刪除了一個(gè)在版本控制之下的文件俗冻,那么使用git add .不會(huì)在索引中刪除這個(gè)文件礁叔。需要通過(guò)帶-a選項(xiàng)的git commit命令和-A選項(xiàng)的git add命令來(lái)完成

# Create a file and put it under version control
touch nonsense.txt
git add . && git commit -m "a new file has been created"
# Remove the file
rm nonsense.txt
# Try standard way of committing -> will not work
 git add . && git commit -m "a new file has been created"
# Now commit with the -a flag
git commit -a -m "File nonsense.txt is now removed"
# Alternatively you could add deleted files to the staging index via
git add -A . 
git commit -m "File nonsense.txt is now removed"

5. 遠(yuǎn)端倉(cāng)庫(kù)(remote repositories)

5.1. 設(shè)置一個(gè)遠(yuǎn)端的Git倉(cāng)庫(kù)

我們將創(chuàng)建一個(gè)遠(yuǎn)端的Git倉(cāng)庫(kù)。這個(gè)倉(cāng)庫(kù)可以存儲(chǔ)在本地或者是網(wǎng)絡(luò)上迄薄。

遠(yuǎn)端Git倉(cāng)庫(kù)和標(biāo)準(zhǔn)的Git倉(cāng)庫(kù)有如下差別:一個(gè)標(biāo)準(zhǔn)的Git倉(cāng)庫(kù)包括了源代碼和歷史信息記錄琅关。我們可以直接在這個(gè)基礎(chǔ)上修改代碼,因?yàn)樗呀?jīng)包含了一個(gè)工作副本讥蔽。但是遠(yuǎn)端倉(cāng)庫(kù)沒(méi)有包括工作副本涣易,只包括了歷史信息画机。可以使用--bare選項(xiàng)來(lái)創(chuàng)建一個(gè)這樣的倉(cāng)庫(kù)新症。

為了方便起見(jiàn)步氏,示例中的倉(cāng)庫(kù)創(chuàng)建在本地文件系統(tǒng)上

# Switch to the first repository
cd ~/repo01
# 
git clone --bare . ../remote-repository.git
# Check the content, it is identical to the .git directory in repo01
ls ~/remote-repository.git

5.2. 推送更改到其他的倉(cāng)庫(kù)

做一些更改,然后將這些更改從你的第一個(gè)倉(cāng)庫(kù)推送到一個(gè)遠(yuǎn)端倉(cāng)庫(kù)

# Make some changes in the first repository
cd ~/repo01
# Make some changes in the file
echo "Hello, hello. Turn your radio on" > test01
echo "Bye, bye. Turn your radio off" > test02

# Commit the changes, -a will commit changes for modified files
# but will not add automatically new files
git commit -a -m "Some changes"

# Push the changes
git push ../remote-repository.git

5.3. 添加遠(yuǎn)端倉(cāng)庫(kù)

除了通過(guò)完整的URL來(lái)訪問(wèn)Git倉(cāng)庫(kù)外账劲,還可以通過(guò)git remote add命令為倉(cāng)庫(kù)添加一個(gè)短名稱戳护。當(dāng)你克隆了一個(gè)倉(cāng)庫(kù)以后,origin表示所克隆的原始倉(cāng)庫(kù)瀑焦。即使我們從零開(kāi)始腌且,這個(gè)名稱也存在。

# Add ../remote-repository.git with the name origin
git remote add origin ../remote-repository.git 

# Again some changes
echo "I added a remote repo" > test02
# Commit
git commit -a -m "This is a test for the new remote origin"
# If you do not label a repository it will push to origin
git push origin

5.4. 顯示已有的遠(yuǎn)端倉(cāng)庫(kù)

通過(guò)以下命令查看已經(jīng)存在的遠(yuǎn)端倉(cāng)庫(kù)

# Show the existing defined remote repositories
git remote

5.5. 克隆倉(cāng)庫(kù)

通過(guò)以下命令在新的目錄下創(chuàng)建一個(gè)新的倉(cāng)庫(kù)

# Switch to home
cd ~
# Make new directory
mkdir repo02

# Switch to new directory
cd ~/repo02

# Clone
git clone ../remote-repository.git .

5.6. 拉乳晃汀(Pull)更改

通過(guò)拉取铺董,可以從其他的倉(cāng)庫(kù)中獲取最新的更改。在第二個(gè)倉(cāng)庫(kù)中禀晓,做一些更改精续,然后將更改推送到遠(yuǎn)端的倉(cāng)庫(kù)中。然后第一個(gè)倉(cāng)庫(kù)拉取這些更改

# Switch to home
cd ~

# Switch to second directory
cd ~/repo02
# Make changes
echo "A change" > test01
# Commit
git commit -a -m "A change"
# Push changes to remote repository
# Origin is automatically maintained as we cloned from this repository
git push origin
# Switch to the first repository and pull in the changes
cd ~/repo01
git pull ../remote-repository.git/
# Check the changes
less test01

6. 還原更改

如果在你的工作副本中粹懒,你創(chuàng)建了不想被提交的文件重付,你可以丟棄它。

# Create a new file with content
touch test04
echo "this is trash" > test04

# Make a dry-run to see what would happen
# -n is the same as --dry-run 
git clean -n

# Now delete
git clean -f

你可以提取老版本的代碼凫乖,通過(guò)提交的ID确垫。git log命令可以查看提交ID

# Switch to home
cd ~/repo01
# Get the log
git log

# Copy one of the older commits and checkout the older revision via 

//譯者注:checkout 后加commit id就是把commit的內(nèi)容復(fù)制到index和工作副本中 
git checkout commit_name

如果你還未把更改加入到索引中,你也可以直接還原所有的更改

#Some nonsense change
echo "nonsense change" > test01
# Not added to the staging index. Therefore we can 
# just checkout the old version
#譯者注:checkout后如果沒(méi)有commit id號(hào)帽芽,就是從index中拷貝數(shù)據(jù)到工作副本删掀,不涉及commit部分的改變
git checkout test01
# Check the result
cat test01
# Another nonsense change
echo "another nonsense change" > test01
# We add the file to the staging index
git add test01
# Restore the file in the staging index
#譯者注:復(fù)制HEAD所指commit的test01文件到index中
git reset HEAD test01
# Get the old version from the staging index
#譯者注:復(fù)制index中test01到工作副本中g(shù)it checkout test01
#譯者注,以上兩條命令可以合并為git checkout HEAD test01

也可以通過(guò)revert命令進(jìn)行還原操作

# Revert a commit
git revert commit_name

即使你刪除了一個(gè)未添加到索引和提交的文件导街,你也可以還原出這個(gè)文件

# Delete a file
rm test01
# Revert the deletion
git checkout test01

如果你已經(jīng)添加一個(gè)文件到索引中披泪,但是未提交“峁澹可以通過(guò)git reset file
命令將這個(gè)文件從索引中刪除

// Create a file
touch incorrect.txt
// Accidently add it to the index
git add .
// Remove it from the index
git reset incorrect.txt
// Delete the file
rm incorrect.txt

如果你刪除了文件夾且尚未提交款票,可以通過(guò)以下命令來(lái)恢復(fù)這個(gè)文件夾 。譯者注:即使已經(jīng)提交泽论,也可以還原

git checkout HEAD -- your_dir_to_restore

譯者注:checkout和reset這兩個(gè)命令的含義是不同的艾少,可以參閱這篇文章http://marklodato.github.com/visual-git-guide/index-en.html

7. 標(biāo)記

Git可以使用對(duì)歷史記錄中的任一版本進(jìn)行標(biāo)記。這樣在后續(xù)的版本中就能輕松的找到佩厚。一般來(lái)說(shuō),被用來(lái)標(biāo)記某個(gè)發(fā)行的版本

可以通過(guò)git tag命令列出所有的標(biāo)記说订,通過(guò)如下命令來(lái)創(chuàng)建一個(gè)標(biāo)記和恢復(fù)到一個(gè)標(biāo)記

git tag version1.6 -m 'version 1.6' 
git checkout <tag_name>

8. 分支抄瓦、合并

8.1. 分支

通過(guò)分支潮瓶,可以創(chuàng)造獨(dú)立的代碼副本。默認(rèn)的分支叫master钙姊。Git消耗很少的資源就能創(chuàng)建分支毯辅。Git鼓勵(lì)開(kāi)發(fā)人員多使用分支

下面的命令列出了所有的本地分支,當(dāng)前所在的分支前帶有*號(hào)

git branch

如果你還想看到遠(yuǎn)端倉(cāng)庫(kù)的分支煞额,可以使用下面的命令

git branch -a

可以通過(guò)下面的命令來(lái)創(chuàng)建一個(gè)新的分支

# Syntax: git branch <name> <hash>
# <hash> in the above is optional 
# if not specified the last commit will be used
# If specified the corresponding commit will be used
git branch testing
# Switch to your new branch
git checkout testing
# Some changes
echo "Cool new feature in this branch" > test01
git commit -a -m "new feature"
# Switch to the master branch
git checkout master
# Check that the content of test01 is the old one
cat test01

8.2. 合并

通過(guò)Merge我們可以合并兩個(gè)不同分支的結(jié)果思恐。Merge通過(guò)所謂的三路合并來(lái)完成。分別來(lái)自兩個(gè)分支的最新commit和兩個(gè)分支的最新公共commit

可以通過(guò)如下的命令進(jìn)行合并

# Syntax: git merge <branch-name>
git merge testing

一旦合并發(fā)生了沖突膊毁,Git會(huì)標(biāo)志出來(lái)胀莹,開(kāi)發(fā)人員需要手工的去解決這些沖突。解決沖突以后婚温,就可以將文件添加到索引中描焰,然后提交更改

8.3. 刪除分支

刪除分支的命令如下:

#Delete branch testing
git branch -d testing
# Check if branch has been deleted
git branch

8.4. 推送(push)一個(gè)分支到遠(yuǎn)端倉(cāng)庫(kù)

默認(rèn)的,Git只會(huì)推送匹配的分支的遠(yuǎn)端倉(cāng)庫(kù)栅螟。這意味在使用git push命令默認(rèn)推送你的分支之前荆秦,需要手工的推送一次這個(gè)分支。

# Push testing branch to remote repository
git push origin testing

# Switch to the testing branch
git checkout testing

# Some changes
echo "News for you" > test01
git commit -a -m "new feature in branch"

# Push all including branch
git push

通過(guò)這種方式力图,你可以確定哪些分支對(duì)于其他倉(cāng)庫(kù)是可見(jiàn)的步绸,而哪些只是本地的分支

9. 解決合并沖突

如果兩個(gè)不同的開(kāi)發(fā)人員對(duì)同一個(gè)文件進(jìn)行了修改,那么合并沖突就會(huì)發(fā)生吃媒。而Git沒(méi)有智能到自動(dòng)解決合并兩個(gè)修改

在這一節(jié)中瓤介,我們會(huì)首先制造一個(gè)合并沖突,然后解決它晓折,并應(yīng)用到Git倉(cāng)庫(kù)中

下面會(huì)產(chǎn)生一個(gè)合并沖突

# Switch to the first directory
cd ~/repo01
# Make changes
touch mergeconflict.txt
echo "Change in the first repository" > mergeconflict.txt
# Stage and commit
git add . && git commit -a -m "Will create merge conflict 1"

# Switch to the second directory
cd ~/repo02
# Make changes
touch mergeconflict.txt
echo "Change in the second repository" > mergeconflict.txt
# Stage and commit
git add . && git commit -a -m "Will create merge conflict 2"
# Push to the master repository
git push

# Now try to push from the first directory
# Switch to the first directory
cd ~/repo01
# Try to push --> you will get an error message
git push
# Get the changes
git pull origin master

Git將沖突放在收到影響的文件中惑朦,文件內(nèi)容如下:

<<<<<<< HEAD
Change in the first repository
=======
Change in the second repository
>>>>>>> b29196692f5ebfd10d8a9ca1911c8b08127c85f8

上面部分是你的本地倉(cāng)庫(kù),下面部分是遠(yuǎn)端倉(cāng)庫(kù)±旄牛現(xiàn)在編輯這個(gè)文件漾月,然后commit更改。另外的胃珍,你可以使用git mergetool命令

# Either edit the file manually or use 
git mergetool
# You will be prompted to select which merge tool you want to use
# For example on Ubuntu you can use the tool "meld"
# After merging the changes manually, commit them
git commit -m "merged changes"

10. 變基(Rebase)

10.1. 在同一分支中應(yīng)用Rebase Commit

通過(guò)rebase命令可以合并多個(gè)commit為一個(gè)梁肿。這樣用戶push更改到遠(yuǎn)端倉(cāng)庫(kù)的時(shí)候就可以先修改commit歷史

接下來(lái)我們將創(chuàng)建多個(gè)commit,然后再將它們r(jià)ebase成一個(gè)commit

# Create a new file
touch rebase.txt

# Add it to git
git add . && git commit -m "rebase.txt added to index"

# Do some silly changes and commit
echo "content" >> rebase.txt
git add . && git commit -m "added content"
echo " more content" >> rebase.txt
git add . && git commit -m "added more content"
echo " more content" >> rebase.txt
git add . && git commit -m "added more content"
echo " more content" >> rebase.txt
git add . && git commit -m "added more content"
echo " more content" >> rebase.tx
tgit add . && git commit -m "added more content"
echo " more content" >> rebase.txt
git add . && git commit -m "added more content"

# Check the git log message
git log

我們合并最后的七個(gè)commit觅彰。你可以通過(guò)如下的命令交互的完成

git rebase -i HEAD~7

這個(gè)命令會(huì)打開(kāi)編輯器讓你修改commit的信息或者 squash / fixup最后一個(gè)信息

Squash會(huì)合并commit信息而fixup會(huì)忽略commit信息(待理解)

10.2. Rebasing多個(gè)分支

你也可以對(duì)兩個(gè)分支進(jìn)行rebase操作吩蔑。如下所述,merge命令合并兩個(gè)分支的更改填抬。rebase命令為一個(gè)分支的更改生成一個(gè)補(bǔ)丁烛芬,然后應(yīng)用這個(gè)補(bǔ)丁到另一分支中

使用merge和rebase,最后的源代碼是一樣的,但是使用rebase產(chǎn)生的commit歷史更加的少赘娄,而且歷史記錄看上去更加的線性

# Create new branch 
git branch testing
# Checkout the branch
git checkout testing
# Make some changes
echo "This will be rebased to master" > test01
# Commit into testing branch
git commit -a -m "New feature in branch"
# Rebase the master
git rebase master

10.3.Rebase最佳實(shí)踐

在push更改到其他的Git倉(cāng)庫(kù)之前仆潮,我們需要仔細(xì)檢查本地分支的commit歷史

在Git中,你可以使用本地的commit遣臼。開(kāi)發(fā)人員可以利用這個(gè)功能方便的回滾本地的開(kāi)發(fā)歷史性置。但是在push之前,需要觀察你的本地分支歷史揍堰,是否其中有些commit歷史對(duì)其他用戶來(lái)說(shuō)是無(wú)關(guān)的

如果所有的commit歷史都跟同一個(gè)功能有關(guān)鹏浅,很多情況下,你需要rebase這些commit歷史為一個(gè)commit歷史屏歹。

交互性的rebase主要就是做重寫(xiě)commit歷史的任務(wù)隐砸。這樣做是安全的,因?yàn)閏ommit還沒(méi)有被push到其它的倉(cāng)庫(kù)西采。這意味著commit歷史只有在被push之前被修改

如果你修改然后push了一個(gè)已經(jīng)在目標(biāo)倉(cāng)庫(kù)中存在的commit歷史凰萨,這看起來(lái)就像是你實(shí)現(xiàn)了一些別人已經(jīng)實(shí)現(xiàn)的功能

11. 創(chuàng)建和應(yīng)用補(bǔ)丁

一個(gè)補(bǔ)丁指的是一個(gè)包含對(duì)源代碼進(jìn)行修改的文本文件。你可以將這個(gè)文件發(fā)送給某人械馆,然后他就可以應(yīng)用這個(gè)補(bǔ)丁到他的本地倉(cāng)庫(kù)

下面會(huì)創(chuàng)建一個(gè)分支胖眷,對(duì)這個(gè)分支所一些修改,然后創(chuàng)建一個(gè)補(bǔ)丁霹崎,并應(yīng)用這個(gè)補(bǔ)丁到master分支

# Create a new branch
git branch mybranch
# Use this new branch
git checkout mybranch
# Make some changes
touch test05
# Change some content in an existing file
echo "New content for test01" >test01
# Commit this to the branch
git add .
git commit -a -m "First commit in the branch"

# Create a patch --> git format-patch master
git format-patch origin/master
# This created patch 0001-First-commit-in-the-branch.patch

# Switch to the master
git checkout master

# Apply the patch
git apply 0001-First-commit-in-the-branch.patch
# Do your normal commit in the master 
git add .
git commit -a -m "Applied patch"
# Delete the patch 
rm 0001-First-commit-in-the-branch.patch

12. 定義同名命令

Git允許你設(shè)定你自己的Git命令珊搀。你可以給你自己常用的命令起一個(gè)縮寫(xiě)命令,或者合并幾條命令道一個(gè)命令上來(lái)尾菇。

下面的例子中境析,定義了git add-commit 命令,這個(gè)命令合并了git add . -Agit commit -m命令派诬。定義這個(gè)命令后劳淆,就可以使用git add-commit -m "message"了.

git config --global alias.add-commit '!git add . -A && git commit'

但是非常不幸,截止寫(xiě)這篇文章之前默赂,定義同名命令在msysGit中還沒(méi)有支持沛鸵。同名命令不能以!開(kāi)始缆八。

13. 放棄跟蹤文件

有時(shí)候曲掰,你不希望某些文件或者文件夾被包含在Git倉(cāng)庫(kù)中。但是如果你把它們加到.gitignore文件中以后奈辰,Git會(huì)停止跟蹤這個(gè)文件栏妖。但是它不會(huì)將這個(gè)文件從倉(cāng)庫(kù)中刪除。這導(dǎo)致了文件或者文件夾的最后一個(gè)版本還是存在于倉(cāng)庫(kù)中奖恰。為了取消跟蹤這些文件或者文件夾吊趾,你可以使用如下的命令

# Remove directory .metadata from git repo
git rm -r --cached .metadata
# Remove file test.txt from repo
git rm --cached test.txt

這樣做不會(huì)將這些文件從commit歷史中去掉宛裕。如果你想將這些文件從commit歷史中去掉,可以參考git filter-branch
命令

14. 其他有用的命令

下面列出了在日常工作中非常有用的Git命令
Table 2. 有用的Git命令

命令 描述
git blame filename 誰(shuí)創(chuàng)建了或者是修改了這個(gè)文件
git checkout -b mybranch master~1 以上上個(gè)commit信息為起點(diǎn)论泛,創(chuàng)建一條新的分支

15. 安裝Git服務(wù)

如上所述续滋,我們的操作不需要Git服務(wù)。我可以只使用文件系統(tǒng)或者是Git倉(cāng)庫(kù)的提供者孵奶,像Github或Bitbucket。但是蜡峰,有時(shí)候了袁,擁有一個(gè)自己的服務(wù)是比較方便的,在ubuntu下安裝一個(gè)服務(wù)相對(duì)來(lái)說(shuō)是比較容易的

確定你已經(jīng)安裝了ssh

apt-get install ssh

如果你還沒(méi)有安裝Git服務(wù)湿颅,安裝它

sudo apt-get install git-core

添加一個(gè)名為git的用戶

sudo adduser git

然后使用git用戶進(jìn)行登陸载绿,創(chuàng)建一個(gè)空的倉(cāng)庫(kù)

# Login to server
# to test use localhost
ssh git@IP_ADDRESS_OF_SERVER

# Create repository
git init --bare example.git

現(xiàn)在你就可以向遠(yuǎn)端的倉(cāng)庫(kù)提交變更了

mkdir gitexample
cd gitexample
git init
touch README
git add README
git commit -m 'first commit'
git remote add origin git@IP_ADDRESS_OF_SERVER:example.git
git push origin master

16. 在線的遠(yuǎn)端倉(cāng)庫(kù)

16.1. 克隆遠(yuǎn)端倉(cāng)庫(kù)

Git支持遠(yuǎn)端的操作。Git支持多種的傳輸類(lèi)型油航,Git自帶的協(xié)議就叫做git崭庸。下面的的命令通過(guò)git協(xié)議從克隆一個(gè)倉(cāng)庫(kù)

git clone git@github.com:vogella/gitbook.git

同樣的,你可以通過(guò)http協(xié)議來(lái)克隆倉(cāng)庫(kù)

# The following will clone via HTTP git clone 
http://vogella@github.com/vogella/gitbook.git

16.2. 添加遠(yuǎn)端倉(cāng)庫(kù)

如果你克隆了一個(gè)遠(yuǎn)端倉(cāng)庫(kù)谊囚,那么原先的倉(cāng)庫(kù)就叫做origin

你可以push修改到origin中怕享,通過(guò) git push origin 命令
. 當(dāng)然,push到一個(gè)遠(yuǎn)端的倉(cāng)庫(kù)需要對(duì)倉(cāng)庫(kù)的寫(xiě)權(quán)限

你可以通過(guò)git remote add name gitrepo命令添加多個(gè)倉(cāng)庫(kù)镰踏。例如函筋,你可以通過(guò)http協(xié)議再次添加之前clone過(guò)來(lái)的倉(cāng)庫(kù):

// Add the https protocol 
git remote add githttp https://vogella@github.com/vogella/gitbook.git

16.3. 通過(guò)http和代理服務(wù)器進(jìn)行遠(yuǎn)端操作

如果你的防火墻屏蔽了出http以外的所有協(xié)議,那么使用http協(xié)議來(lái)獲取倉(cāng)庫(kù)是非常好的方法奠伪。

Git同樣支持通過(guò)代理服務(wù)器使用http協(xié)議跌帐。下面的Git命令會(huì)展示這一點(diǎn)。你可以為所有的程序設(shè)置代理服務(wù)器或者只是為Git服務(wù)提供绊率。

下面的例子用到了環(huán)境變量

# Linux
export http_proxy=http://proxy:8080
# On Windows
# Set http_proxy=http://proxy:8080 
git clone http://dev.eclipse.org/git/org.eclipse.jface/org.eclipse.jface.snippets.git
# Push back to the origin using http
git push origin

下面的例子只是用到了Git的配置

// Set proxy for git globally 
git config --global http.proxy http://proxy:8080
// To check the proxy settings
git config --get http.proxy
// Just in case you need to you can also revoke the proxy settings
git config --global --unset http.proxy

17. Git服務(wù)提供商

除了假設(shè)自己的服務(wù)谨敛,你也可以使用Git服務(wù)提供商提供的服務(wù)。最流行的Git服務(wù)提供網(wǎng)站是GitHub和Bitbucket滤否。它們都提供了有限制的免費(fèi)服務(wù)

17.1. GitHub

可以通過(guò) https://github.com/ 訪問(wèn)GitHub. GitHub上所有的公開(kāi)倉(cāng)庫(kù)都是免費(fèi)的脸狸。如果你想在上面使用私有的倉(cāng)庫(kù),那么就需要付費(fèi)給GitHub

GitHub需要你創(chuàng)建ssh的公鑰私鑰顽聂。生成一份Ubuntu的公鑰私鑰可以訪問(wèn) ssh key creation in Ubuntu肥惭,Windows環(huán)境可以訪問(wèn)msysgit ssh key generation.

在GitHub上創(chuàng)建一個(gè)賬戶和一個(gè)倉(cāng)庫(kù)以后。你會(huì)收到如何將你的項(xiàng)目上傳到GitHUb的指南紊搪,其中的命令大致如下:

Global setup: 
Set up git 
git config --global user.name "Your Name" 
git config --global user.email your.email@gmail.com 

Next steps: 
mkdir gitbook 
cd gitbook 
git init 
touch README 
git add README 
git commit -m 'first commit' 
git remote add origin git@github.com:vogella/gitbook.git
git push -u origin master 

Existing Git Repo? 
cd existing_git_repo 
git remote add origin 
git@github.com:vogella/gitbook.git 
git push -u origin master 

17.2. Bitbucket

可以通過(guò) https://bitbucket.org/ 訪問(wèn)Bitbucket. Bitbucket 提供了無(wú)限制了公共倉(cāng)庫(kù)和只能有五個(gè)人訪問(wèn)的私有倉(cāng)庫(kù)蜜葱。如果你需要超過(guò)五個(gè)人訪問(wèn)私有倉(cāng)庫(kù),就需要付費(fèi)給Bitbucket


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末爸黄,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子揭鳞,更是在濱河造成了極大的恐慌炕贵,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,194評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件野崇,死亡現(xiàn)場(chǎng)離奇詭異称开,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)乓梨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門(mén)鳖轰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人扶镀,你說(shuō)我怎么就攤上這事蕴侣。” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,780評(píng)論 0 346
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)靠瞎。 經(jīng)常有香客問(wèn)我,道長(zhǎng)狞膘,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,388評(píng)論 1 283
  • 正文 為了忘掉前任什乙,我火速辦了婚禮客冈,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘稳强。我一直安慰自己场仲,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布退疫。 她就那樣靜靜地躺著渠缕,像睡著了一般。 火紅的嫁衣襯著肌膚如雪褒繁。 梳的紋絲不亂的頭發(fā)上亦鳞,一...
    開(kāi)封第一講書(shū)人閱讀 49,764評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音棒坏,去河邊找鬼燕差。 笑死,一個(gè)胖子當(dāng)著我的面吹牛坝冕,可吹牛的內(nèi)容都是我干的徒探。 我是一名探鬼主播,決...
    沈念sama閱讀 38,907評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼喂窟,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼测暗!你這毒婦竟也來(lái)了央串?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,679評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤碗啄,失蹤者是張志新(化名)和其女友劉穎质和,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體稚字,經(jīng)...
    沈念sama閱讀 44,122評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡饲宿,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了胆描。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片褒傅。...
    茶點(diǎn)故事閱讀 38,605評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖袄友,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情霹菊,我是刑警寧澤剧蚣,帶...
    沈念sama閱讀 34,270評(píng)論 4 329
  • 正文 年R本政府宣布,位于F島的核電站旋廷,受9級(jí)特大地震影響鸠按,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜饶碘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評(píng)論 3 312
  • 文/蒙蒙 一目尖、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧扎运,春花似錦瑟曲、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,734評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至负拟,卻和暖如春烦衣,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背掩浙。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,961評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工花吟, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人厨姚。 一個(gè)月前我還...
    沈念sama閱讀 46,297評(píng)論 2 360
  • 正文 我出身青樓衅澈,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親谬墙。 傳聞我的和親對(duì)象是個(gè)殘疾皇子矾麻,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容

  • git常用命令 GIT常用命令備忘:http://stormzhang.com/git/2014/01/27/gi...
    新篇章閱讀 8,458評(píng)論 1 26
  • Git是目前最流行的版本管理系統(tǒng)纱耻,也是最先進(jìn)的分布式版本控制系統(tǒng)(distributed version cont...
    pro648閱讀 5,682評(píng)論 1 17
  • 1. 安裝 Github 查看是否安裝git: $ git config --global user.name "...
    Albert_Sun閱讀 13,644評(píng)論 9 163
  • 你不必每天早晚刷牙,說(shuō)忘記了就好 你不必記得字里行間险耀,看書(shū)只是時(shí)光消耗 你不必關(guān)燈睡覺(jué)弄喘,你真的不想現(xiàn)在睡著 你不必...
    快慢書(shū)閱讀 137評(píng)論 0 0