快捷搜索:

分布版本控制系统Git的使用教程

本教程经由过程敕令行来阐述散播版本节制系统Git的应用。演示系统拔取的是Linux(Ubuntu),然则在其他系统上也能功能,例如Windows系统。

转自:http://www.cnblogs.com/zhangjing230/archive/2012/05/09/2489745.html

内容索引

1. Git

1.1. Git是何方神圣?

1.2. 紧张的术语

1.3. 索引(stage)

2. 安装

3. 设置设置设备摆设摆设

3.1. 用户信息

3.2. 高亮显示

3.3. 轻忽特定的文件

3.4. 应用.gitkeep来追踪空的文件夹

4. 开始操作Git

4.1. 创建内容

4.2. 创建仓库、添加文件和提交变动

4.3. diff敕令和commit改动

4.4. Status, Diff和Commit Log

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

4.6. 删除文件

5. 远端仓库(remote repositories)

5.1. 设置一个远真个Git仓库

5.2. 推送改动到其他的仓库

5.3. 添加远端仓库

5.4. 显示已有的远端仓库

5.5. 克隆仓库

5.6. 拉取(Pull)改动

6. 还原变动

7. 标记

8. 分支和合并

8.1. 分支

8.2. 合并

8.3. 删除分支

8.4. 推送(Push)一个分支到远端仓库

9. 办理合并冲突

10. 变基(Rebase)

10.1. 在同一分支中利用Rebase Commit

10.2. Rebasing 多个分支

10.3. Rebase最佳实践

11. 创建和利用补丁

12. 定义同名敕令

13. 放弃跟踪文件

14. 其他有用的敕令

15. 安装Git办事

16. 在线的远端仓库

16.1. 克隆远端仓库

16.2. 添加远端仓库

16.3. 经由过程http和代理办事器进行远端操作

17. Git办事供给商

17.1. GitHub

17.2. Bitbucket

18. Git的图形接口

19. Kindle版本教程

20. 问题与评论争论

21. 链接和文章

1. Git

1.1. Git是何方神圣?

Git是用C说话开拓的散播版本节制系统。版本节制系统可以保留一个文件聚拢的历史记录,并能回滚文件聚拢到另一个状态(历史记录状态)。另一个状态可所以不合的文件,也可所以不合的文件内容。举个例子,你可以将文件聚拢转换到两天之前的状态,或者你可以在临盆代码和实验性子的代码之间进行切换。文件聚拢每每被称作是“源代码”。在一个散播版本节制系统中,每小我都有一份完备的源代码(包括源代码所有的历史记录信息),而且可以对这个本地的数据进行操作。散播版本节制系统不必要一个集中式的代码仓库。

当你对本地的源代码进行了改动,你可以标注他们跟下一个版真相关(将他们加到index中),然后提交到仓库中来(commit)。Git保存了所有的版本信息,以是你可以转换你的源代码到任何的历史版本。你可以对本地的仓库进行代码的提交,然后与其他的仓库进行同步。你可以应用Git来进行仓库的克隆(clone)操作,完备的复制一个已有的仓库。仓库的所有者可以经由过程push操作(推送变化到别处的仓库)或者Pull操作(从别处的仓库拉取变化)来同步变化。

Git支持分支功能(branch)。假如你想开拓一个新的产品功能,你可以建立一个分支,对这个分支的进行改动,而不至于会影响到主支上的代码。

Git供给了敕令行对象;这个教程会应用敕令行。你也可以找到图形对象,譬如与Eclipse配套的EGit对象,然则这些都不会在这个教程中进行描述。

1.2. 紧张的术语

表 1. Git 术语

术语

定义

仓库(Repository)

一个仓库包括了所有的版本信息、所有的分支和标记信息。在Git中仓库的每份拷贝都是完备的。仓库让你可以从中取得你的事情副本。

分支(Branches)

一个分支意味着一个自力的、拥有自己历史信息的代码线(code line)。你可以从已有的代码中天生一个新的分支,这个分支与残剩的分支完全自力。默认的分支每每是叫master。用户可以选择一个分支,选择一个分支叫做checkout.

标记(Tags)

一个标记指的是某个分支某个特准光阴点的状态。经由过程标记,可以很方便的切换到标记时的状态,例如2009年1月25号在testing分支上的代码状态

提交(Commit)

提交卸码后,仓库会创建一个新的版本。这个版本可以在后续被从新得到。每次提交都包括作者和提交者,作者和提交者可所以不合的人

URL

URl用来标识一个仓库的位置

修订(Revision)

用来表示代码的一个版本状态。Git经由过程用SHA1 hash算法表示的id来标识不合的版本。每一个 SHA1 id都是160位长,16进制标识的字符串.。最新的版本可以经由过程HEAD来获取。之前的版本可以经由过程"HEAD~1"来获取,以此类推。

1.3. 索引

Git 必要将代码的变更显示的与下一次提交进行关联。举个例子,假如你对一个文件继承了改动,然后想将这些改动提交到下一次提交中,你必须将这个文件提交到索引中,经由过程git add file敕令。这样索引可以保存所有变更的快照。

新增的文件老是要显示的添加到索引中来。对付那些之前已经提交过的文件,可以在commit敕令中应用-a 选项达到提交到索引的目的。

2. 安装

在Ubuntu上,你可以经由过程apt来安装git敕令行对象

sudo apt-get install git-core

对付其他的Linux版本,请查看相关的软件包安装对象应用措施

msysgit项目供给了Windows版本的Git,地址是http://code.google.com/p/msysgit/

3. 设置设置设备摆设摆设

你可以在.gitconfig文件中防止git的全局设置设置设备摆设摆设。文件位于用户的home目录。 上述已经提到每次提交都邑保存作者和提交者的信息,这些信息都可以保存在全局设置设置设备摆设摆设中。

后续将会先容设置设置设备摆设摆设用户信息、高亮显示和轻忽特定的文件

3.1. 用户信息

经由过程如下敕令来设置设置设备摆设摆设用户名和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设置设置设备摆设摆设信息,履行以下敕令:

git config --list

3.2. 高亮显示

以下敕令会为终端设置设置设备摆设摆设高亮

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

3.3. 轻忽特定的文件

可以设置设置设备摆设摆设Git轻忽特定的文件或者是文件夹。这些设置设置设备摆设摆设都放在.gitignore文件中。这个文件可以存在于不合的文件夹中,可以包孕不合的文件匹配模式。为了让Git轻忽bin文件夹,在主目录下放置.gitignore文件,此中内容为bin。

同时Git也供给了全局的设置设置设备摆设摆设,core.excludesfile。

3.4. 应用.gitkeep来追踪空的文件夹

Git会轻忽空的文件夹。假如你想版本节制包括空文件夹,根据常规会在空文件夹下放置.gitkeep文件。着实对文件名没有特定的要求。一旦一个空文件夹下有文件后,这个文件夹就会在版本节制范围内。

4. 开始操作Git

后续将经由过程一个范例的Git事情流来进修。在这个历程中,你会创建一些文件、创建一个本地的Git仓库、提交你的文件到这个仓库中。这之后,你会克隆一个仓库、在仓库之间经由过程pull和push操作来互换代码的改动。注释(以#开首)说清楚明了敕令的详细含义

让我们打开敕令行开始操作吧

4.1. 创建内容

下面创建一些文件,它们会被放到版本节制之中

#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. 创建仓库、添加文件和提交变动

每个Git仓库都是放置在.git文件夹下.这个目录包孕了仓库的所有历史记录,.git/config文件包孕了仓库的本地设置设置设备摆设摆设。

以下将会创建一个Git仓库,添加文件倒仓库的索引中,提交变动。

# 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变动

经由过程git diff敕令,用户可以查看变动。经由过程改变一个文件的内容,看看git diff敕令输出什么,然后提交这个变动到仓库中

# 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

下面会向你展示仓库现有的状态以及过往的提交历史

# 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

经由过程git amend敕令,我们可以改动着末提交的的信息

上述的提交信息中存在差错,下面会改动这个差错

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

4.6. 删除文件

假如你删除了一个在版本节制之下的文件,那么应用git add .不会在索引中删除这个文件。必要经由过程带-a选项的git commit敕令和-A选项的git add敕令来完成

# 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 workgit 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. 远端仓库(remote repositories)

5.1. 设置一个远真个Git仓库

我们将创建一个远真个Git仓库。这个仓库可以存储在本地或者是收集上。

远端Git仓库和标准的Git仓库有如下区别:一个标准的Git仓库包括了源代码和历史信息记录。我们可以直接在这个根基上改动代码,由于它已经包孕了一个事情副本。然则远端仓库没有包括事情副本,只包括了历史信息。可以应用--bare选项来创建一个这样的仓库。

为了方便起见,示例中的仓库创建在本地文件系统上

# 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. 推送变动到其他的仓库

做一些变动,然后将这些变动从你的第一个仓库推送到一个远端仓库

# 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. 添加远端仓库

除了经由过程完备的URL来造访Git仓库外,还可以经由过程git remote add敕令为仓库添加一个短名称。当你克隆了一个仓库今后,origin表示所克隆的原始仓库。纵然我们从零开始,这个名称也存在。

# 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

显示已有的远端仓库

经由过程以下敕令查看已经存在的远端仓库

# Show the existing defined remote repositories git remote

5.5. 克隆仓库

经由过程以下敕令在新的目录下创建一个新的仓库

# Switch to home cd ~ # Make new directory mkdir repo02# Switch to new directorycd ~/repo02 # Clone git clone ../remote-repository.git .

5.6. 拉取(Pull)变动

经由过程拉取,可以从其他的仓库中获取最新的变动。在第二个仓库中,做一些变动,然后将变动推送到远真个仓库中。然后第一个仓库拉取这些变动

# 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. 还原变动

假如在你的事情副本中,你创建了不想被提交的文件,你可以丢弃它。

# 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-rungit clean -n# Now delete git clean -f

你可以提取老版本的代码,经由过程提交的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的内容复制到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后假如没有commit id号,便是从index中拷贝数据到事情副本,不涉及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 #译者注:复制HEAD所指commit的test01文件到index中 git reset HEAD test01 # Get the old version from the staging index #译者注:复制index中test01到事情副本中 git checkout test01 #译者注,以上两条敕令可以合并为git checkout HEAD test01

也可以经由过程revert敕令进行还原操作

# Revert a commit git revert commit_name

纵然你删除了一个未添加到索引和提交的文件,你也可以还原出这个文件

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

假如你已经添加一个文件到索引中,然则未提交。可以经由过程git reset file 敕令将这个文件从索引中删除

// 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

假如你删除了文件夹且尚未提交,可以经由过程以下敕令来规复这个文件夹 。译者注:纵然已经提交,也可以还原

git checkout HEAD -- your_dir_to_restore

译者注:checkout和reset这两个敕令的含义是不合的,可以参阅这篇文章http://marklodato.github.com/visual-git-guide/index-en.html

7. 标记

Git可以应用对历史记录中的任一版本进行标记。这样在后续的版本中就能轻松的找到。一样平常来说,被用来标记某个发行的版本

可以经由过程git tag敕令列出所有的标记,经由过程如下敕令来创建一个标记和规复到一个标记

git tag version1.6 -m 'version 1.6'git checkout

8. 分支、合并

8.1. 分支

经由过程分支,可以创造自力的代码副本。默认的分支叫master。Git耗损很少的资本就能创建分支。Git鼓励开拓职员多应用分支

下面的敕令列出了所有的本地分支,当前所在的分支前带有*号

git branch

假如你还想看到远端仓库的分支,可以应用下面的敕令

git branch -a

可以经由过程下面的敕令来创建一个新的分支

# Syntax: git branch#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. 合并

经由过程Merge我们可以合并两个不合分支的结果。Merge经由过程所谓的三路合并来完成。分手来自两个分支的最新commit和两个分支的最新公共commit

可以经由过程如下的敕令进行合并

# Syntax: git merge

git merge testing

一旦合并发生了冲突,Git会标志出来,开拓职员必要手工的去办理这些冲突。办理冲突今后,就可以将文件添加到索引中,然后提交变动

8.3. 删除分支

删除分支的敕令如下:

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

8.4. 推送(push)一个分支到远端仓库

默认的,Git只会推送匹配的分支的远端仓库。这意味在应用git push敕令默认推送你的分支之前,必要手工的推送一次这个分支。

# 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

经由过程这种要领,你可以确定哪些分支对付其他仓库是可见的,而哪些只是本地的分支

9. 办理合并冲突

假如两个不合的开拓职员对同一个文件进行了改动,那么合并冲突就会发生。而Git没有智能到自动办理合并两个改动

在这一节中,我们会首先制造一个合并冲突,然后办理它,并利用到Git仓库中

下面会孕育发生一个合并冲突

# 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将冲突放在收到影响的文件中,文件内容如下:

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

上面部分是你的本地仓库,下面部分是远端仓库。现在编辑这个文件,然后commit变动。别的的,你可以应用git mergetool敕令

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

10. 变基(Rebase)

10.1. 在同一分支中利用Rebase Commit

经由过程rebase敕令可以合并多个commit为一个。这样用户push变动到远端仓库的时刻就可以先改动commit历史

接下来我们将创建多个commit,然后再将它们rebase成一个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.txt git 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

我们合并着末的七个commit。你可以经由过程如下的敕令交互的完成

git rebase -i HEAD~7

这个敕令会打开编辑器让你改动commit的信息或者 squash/ fixup着末一个信息

Squash会集并commit信息而fixup会轻忽commit信息(待理解)

10.2. Rebasing多个分支

你也可以对两个分支进行rebase操作。如下所述,merge敕令合并两个分支的变动。rebase敕令为一个分支的变动天生一个补丁,然后利用这个补丁到另一分支中

应用merge和rebase,着末的源代码是一样的,然则应用rebase孕育发生的commit历史加倍的少,而且历史记录看上去加倍的线性

# Create new branchgit 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最佳实践

在push变动到其他的Git仓库之前,我们必要仔细反省本地分支的commit历史

在Git中,你可以应用本地的commit。开拓职员可以使用这个功能方便的回滚本地的开拓历史。然则在push之前,必要察看你的本地分支历史,是否此中有些commit历史对其他用户来说是无关的

假如所有的commit历史都跟同一个功能有关,很多环境下,你必要rebase这些commit历史为一个commit历史。

交互性的rebase主要便是做重写commit历史的义务。这样做是安然的,由于commit还没有被push到其它的仓库。这意味着commit历史只有在被push之前被改动

假如你改动然后push了一个已经在目标仓库中存在的commit历史,这看起来就像是你实现了一些别人已经实现的功能

11. 创建和利用补丁

一个补丁指的是一个包孕对源代码进行改动的文本文件。你可以将这个文件发送给某人,然后他就可以利用这个补丁到他的本地仓库

下面会创建一个分支,对这个分支所一些改动,然后创建一个补丁,并利用这个补丁到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 mastergit add . git commit -a -m "Applied patch"# Delete the patchrm 0001-First-commit-in-the-branch.patch

12. 定义同名敕令

Git容许你设定你自己的Git敕令。你可以给你自己常用的敕令起一个缩写敕令,或者合并几条敕令道一个敕令上来。

下面的例子中,定义了git add-commit 敕令,这个敕令合并了git add . -A 和git commit -m 敕令。定义这个敕令后,就可以应用git add-commit -m "message" 了.

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

然则异常不幸,截止写这篇文章之前,定义同名敕令在msysGit中还没有支持。同名敕令不能以!开始。

13. 放弃跟踪文件

无意偶尔候,你不盼望某些文件或者文件夹被包孕在Git仓库中。然则假如你把它们加到.gitignore文件中今后,Git会竣事跟踪这个文件。然则它不会将这个文件从仓库中删除。这导致了文件或者文件夹的着末一个版本照样存在于仓库中。为了取消跟踪这些文件或者文件夹,你可以应用如下的敕令

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

这样做不会将这些文件从commit历史中去掉落。假如你想将这些文件从commit历史中去掉落,可以参考git filter-branch敕令

14. 其他有用的敕令

下面列出了在日常事情中异常有用的Git敕令

Table 2. 有用的Git敕令

敕令

描述

git blame filename

谁创建了或者是改动了这个文件

git checkout -b mybranch master~1

以上上个commit信息为动身点,创建一条新的分支

15. 安装Git办事

如上所述,我们的操作不必要Git办事。我可以只应用文件系统或者是Git仓库的供给者,像Github或Bitbucket。然则,无意偶尔候,拥有一个自己的办事是对照方便的,在ubuntu下安装一个办事相对来说是对照轻易的

确定你已经安装了ssh

apt-get install ssh

假如你还没有安装Git办事,安装它

sudo apt-get install git-core

添加一个名为git的用户

sudo adduser git

然后应用git用户进行登岸,创建一个空的仓库

# Login to server # to test use localhost ssh git@IP_ADDRESS_OF_SERVER# Create repository git init --bare example.git

现在你就可以向远真个仓库提交变化了

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

您可能还会对下面的文章感兴趣: