翻译说明:个人出于兴趣爱好翻译这篇Git教程(google 搜索git tutorial排名第一的文章)。学习git最初的原因是为了了解GitHub,译者水平有限,有不足之处欢迎指正。希望这边译文对你能有帮助。转载请链接出处。
Git教程
本教程通过命令行来阐述分布版本控制系统Git的使用。演示系统选取的是Linux(Ubuntu),但是在其他系统上也能功能,例如Windows系统。
内容索引
- 1. Git
- 2. 安装
- 3. 配置
- 4. 开始操作Git
- 5. 远端仓库(remote repositories)
- 6. 还原更改
- 7. 标记
- 8. 分支和合并
- 9. 解决合并冲突
- 10. 变基(Rebase)
- 11. 创建和应用补丁
- 12. 定义同名命令
- 13. 放弃跟踪文件
- 14. 其他有用的命令
- 15. 安装Git服务
- 16. 在线的远端仓库
- 17. Git服务提供商
- 18. Git的图形接口
- 19. Kindle版本教程
- 20. 问题与讨论
- 21. 链接和文章
Git是用C语言开发的分布版本控制系统。版本控制系统可以保留一个文件集合的历史记录,并能回滚文件集合到另一个状态(历史记录状态)。另一个状态可以是不同的文件,也可以是不同的文件内容。举个例子,你可以将文件集合转换到两天之前的状态,或者你可以在生产代码和实验性质的代码之间进行切换。文件集合往往被称作是“源代码”。在一个分布版本控制系统中,每个人都有一份完整的源代码(包括源代码所有的历史记录信息),而且可以对这个本地的数据进行操作。分布版本控制系统不需要一个集中式的代码仓库。
当你对本地的源代码进行了修改,你可以标注他们跟下一个版本相关(将他们加到index中),然后提交到仓库中来(commit)。Git保存了所有的版本信息,所以你可以转换你的源代码到任何的历史版本。你可以对本地的仓库进行代码的提交,然后与其他的仓库进行同步。你可以使用Git来进行仓库的克隆(clone)操作,完整的复制一个已有的仓库。仓库的所有者可以通过push操作(推送变更到别处的仓库)或者Pull操作(从别处的仓库拉取变更)来同步变更。
Git支持分支功能(branch)。如果你想开发一个新的产品功能,你可以建立一个分支,对这个分支的进行修改,而不至于会影响到主支上的代码。
Git提供了命令行工具;这个教程会使用命令行。你也可以找到图形工具,譬如与Eclipse配套的EGit工具,但是这些都不会在这个教程中进行描述。
表 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"来获取,以此类推。 |
在Ubuntu上,你可以通过apt来安装git命令行工具
sudo apt-get install git-core
对于其他的Linux版本,请查看相关的软件包安装工具使用方法
msysgit项目提供了Windows版本的Git,地址是http://code.google.com/p/msysgit/
你可以在.gitconfig文件中防止git的全局配置。文件位于用户的home目录。 上述已经提到每次提交都会保存作者和提交者的信息,这些信息都可以保存在全局配置中。
后续将会介绍配置用户信息、高亮显示和忽略特定的文件
通过如下命令来配置用户名和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
可以配置Git忽略特定的文件或者是文件夹。这些配置都放在.gitignore文件中。这个文件可以存在于不同的文件夹中,可以包含不同的文件匹配模式。为了让Git忽略bin文件夹,在主目录下放置.gitignore文件,其中内容为bin。
同时Git也提供了全局的配置,core.excludesfile。
后续将通过一个典型的Git工作流来学习。在这个过程中,你会创建一些文件、创建一个本地的Git仓库、提交你的文件到这个仓库中。这之后,你会克隆一个仓库、在仓库之间通过pull和push操作来交换代码的修改。注释(以#开头)解释了命令的具体含义
让我们打开命令行开始操作吧
下面创建一些文件,它们会被放到版本控制之中
#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
每个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
通过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"
下面会向你展示仓库现有的状态以及过往的提交历史
# 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
通过git amend命令,我们可以修改最后提交的的信息
上述的提交信息中存在错误,下面会修改这个错误
git commit --amend -m "More changes - now correct"
如果你删除了一个在版本控制之下的文件,那么使用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 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"
我们将创建一个远端的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
做一些更改,然后将这些更改从你的第一个仓库推送到一个远端仓库
# 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
除了通过完整的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
通过以下命令在新的目录下创建一个新的仓库
# Switch to home cd ~ # Make new directory mkdir repo02 # Switch to new directory cd ~/repo02 # Clone git clone ../remote-repository.git .
通过拉取,可以从其他的仓库中获取最新的更改。在第二个仓库中,做一些更改,然后将更改推送到远端的仓库中。然后第一个仓库拉取这些更改
# 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
如果在你的工作副本中,你创建了不想被提交的文件,你可以丢弃它。
# 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
你可以提取老版本的代码,通过提交的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
命令将这个文件从索引中删除
//