GitHub具体教程
Table of Contents
1 Git具体教程
1.1 Git简单介绍
1.1.1 Git是何方神圣?
Git是用C语言开发的分布版本号控制系统。版本号控制系统能够保留一个文件集合的历史记录,并能回滚文件集合到还有一个状态(历史记录状态)。还有一个状态能够是不同的文件,也能够是不同的文件内容。举个样例,你能够将文件集合转换到两天之前的状态,或者你能够在生产代码和实验性质的代码之间进行切换。文件集合往往被称作是“源码”。在一个分布版本号控制系统中,每一个人都有一份完整的源码(包含源码全部的历史记录信息),并且能够对这个本地的数据进行操作。分布版本号控制系统不须要一个集中式的代码仓库。
当你对本地的源码进行了改动,你能够标注他们跟下一个版本号相关(将他们加到index中),然后提交到仓库中来(commit)。Git保存了全部的版本号信息,所以你能够转换你的源码到不论什么的历史版本号。你能够对本地的仓库进行代码的提交,然后与其它的仓库进行同步。你能够使用Git来进行仓库的克隆(clone)操作,完整的复制一个已有的仓库。仓库的全部者能够通过push操作(推送变更到别处的仓库)或者Pull操作(从别处的仓库拉取变更)来同步变更。
Git支持分支功能(branch)。假设你想开发一个新的产品功能,你能够建立一个分支,对这个分支的进行改动,而不至于会影响到主支上的代码。
Git提供了命令行工具;这个教程会使用命令行。你也能够找到图形工具,譬如与Eclipse配套的EGit工具,可是这些都不会在这个教程中进行描写叙述。
1.1.2 重要的术语
Git 术语
术语 | 定义 |
---|---|
仓库 | 一个仓库包含了全部的版本号信息、全部的分支和标记信息. |
Repository | 在Git中仓库的每份拷贝都是完整的。仓库让你能够从中 |
取得你的工作副本。 | |
一个分支意味着一个独立的、拥有自己历史信息的代码线 | |
分支 | (code line)。你能够从已有的代码中生成一个新的分支 |
Branches | ,这个分支与剩余的分支全然独立。默认的分支往往是叫 |
master。用户能够选择一个分支,选择一个分支叫做 | |
checkout. | |
标记 | 一个标记指的是某个分支某个特定时间点的状态。通过标 |
Tags | 记,能够非常方便的切换到标记时的状态,比如2009年1月25 |
号在testing分支上的代码状态 | |
提交 | 提交代码后,仓库会创建一个新的版本号。这个版本号能够在 |
Commit | 兴许被又一次获得。每次提交都包含作者和提交者,作者和 |
提交者能够是不同的人 | |
URL | URl用来标识一个仓库的位置 |
用来表示代码的一个版本号状态。Git通过用SHA1 hash算法 | |
修订 | 表示的id来标识不同的版本号。每个 SHA1 id都是160位长 |
Revision | ,16进制标识的字符串.最新的版本号能够通过HEAD来获取. |
之前的版本号能够通过"HEAD~1"来获取,以此类推。 |
1.2 Git安装
在Ubuntu上,你能够通过apt来安装git命令行工具
sudo apt-get install git-core
对于其它的Linux版本号,请查看相关的软件包安装工具用法。msysgit项目提供了Windows版本号的Git,地址是http://code.google.com/p/msysgit/
1.3 Git配置
你能够在.gitconfig文件里防止git的全局配置。文件位于用户的home文件夹。上述已经提到每次提交都会保存作者和提交者的信息,这些信息都能够保存在全局配置中。兴许将会介绍配置用户信息、高亮显示和忽略特定的文件。
1.3.1 用户信息
通过例如以下命令来配置username和Email
git config --global user.name "Example Surname" 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
1.4 開始操作Git
兴许将通过一个典型的Git工作流来学习。在这个过程中,你会创建一些文件、创建一个本地的Git仓库、提交你的文件到这个仓库中。这之后,你会克隆一个仓库、在仓库之间通过pull和push操作来交换代码的改动。凝视(以#开头)解释了命令的详细含义,让我们打开命令行開始操作吧。
1.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
1.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
1.4.3 diff命令与commit更改
通过git diff命令,用户能够查看更改。通过改变一个文件的内容,看看gitdiff命令输出什么,然后提交这个更改到仓库中
# 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"
1.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
1.4.5 更正提交的信息 - git amend
通过git amend命令,我们能够改动最后提交的的信息。上述的提交信息中存在错误,以下会改动这个错误。
git commit --amend -m "More changes - now correct"
1.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 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"
1.5 远端仓库(remote repositories)
1.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
1.5.2 推送更改到其它的仓库
做一些更改,然后将这些更改从你的第一个仓库推送到一个远端仓库
cd ~/repo01
echo "Hello, hello. Turn your radio on" > test01echo "Bye, bye. Turn your radio off" > test02
git commit -a -m "Some changes"
git push ../remote-repository.git
1.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
1.5.5 克隆仓库
通过下面命令在新的文件夹下创建一个新的仓库
# Switch to home cd ~ # Make new directory mkdir repo02 # Switch to new directory cd ~/repo02 # Clone git clone ../remote-repository.git .
1.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
1.5.7 还原更改
假设在你的工作副本中,你创建了不想被提交的文件,你能够丢弃它。
# 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 resetfile 命令将这个文件从索引中删除
// 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
1.6 分支、合并
1.6.1 分支
通过分支,能够创造独立的代码副本。默认的分支叫master。Git消耗非常少的资源就能创建分支。Git鼓舞开发者多使用分支
以下的命令列出了全部的本地分支,当前所在的分支前带有*号
git branch
假设你还想看到远端仓库的分支,能够使用以下的命令
git branch -a
能够通过以下的命令来创建一个新的分支
# 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
1.6.2 合并
通过Merge我们能够合并两个不同分支的结果。Merge通过所谓的三路合并来完毕。分别来自两个分支的最新commit和两个分支的最新公共commit.能够通过例如以下的命令进行合并
# Syntax: git merge <branch-name> git merge testing
一旦合并发生了冲突,Git会标志出来,开发者须要手工的去解决这些冲突。解决冲突以后,就能够将文件加入�到索引中,然后提交更改
1.6.3 删除分支
删除分支的命令例如以下:
#Delete branch testing git branch -d testing # Check if branch has been deleted git branch
1.6.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
通过这样的方式,你能够确定哪些分支对于其它仓库是可见的,而哪些仅仅是本地的分支
1.7 解决合并冲突
假设两个不同的开发者对同一个文件进行了改动,那么合并冲突就会发生。而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 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"
1.8 变基(Rebase)
1.8.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信息(待理解)
1.8.2 Rebasing多个分支
你也能够对两个分支进行rebase操作。例如以下所述,merge命令合并两个分支的更改。rebase命令为一个分支的更改生成一个补丁,然后应用这个补丁到还有一分支中
使用merge和rebase,最后的源码是一样的,可是使用rebase产生的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
1.8.3 Rebase最佳实践
在push更改到其它的Git仓库之前,我们须要细致检查本地分支的commit历史
在Git中,你能够使用本地的commit。开发者能够利用这个功能方便的回滚本地的开发历史。可是在push之前,须要观察你的本地分支历史,是否当中有些commit历史对其它用户来说是无关的
假设全部的commit历史都跟同一个功能有关,非常多情况下,你须要rebase这些commit历史为一个commit历史。
交互性的rebase主要就是做重写commit历史的任务。这样做是安全的,由于commit还没有被push到其他的仓库。这意味着commit历史仅仅有在被push之前被改动。
假设你改动然后push了一个已经在目标仓库中存在的commit历史,这看起来就像是你实现了一些别人已经实现的功能
1.8.4 创建和应用补丁
一个补丁指的是一个包括对源码进行改动的文本文件。你能够将这个文件发送给某人,然后他就能够应用这个补丁到他的本地仓库。
以下会创建一个分支,对这个分支所一些改动,然后创建一个补丁,并应用这个补丁到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
1.9 定义同名命令
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中还没有支持。同名命令不能以!開始。
1.10 放弃跟踪文件
有时候,你不希望某些文件或者目录被包括在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命令
1.11 其它实用的命令
以下列出了在日常工作中很实用的Git命令
实用的Git命令
命令 | 描写叙述 |
---|---|
git blame filename | 谁创建了或者是改动了这个文件 |
git checkout -b mybranch | 以上上个commit信息为起点,创建一条 |
master~1 | 新的分支 |
1.12 安装Git服务
如上所述,我们的操作不须要Git服务。我能够仅仅使用文件系统或者是Git仓库的提供者,像Github或Bitbucket。可是,有时候,拥有一个自己的服务是比較方便的,在ubuntu下安装一个服务相对来说是比較easy的
确定你已经安装了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
1.13 在线的远端仓库
1.13.1 克隆远端仓库
Git支持远端的操作。Git支持多种的传输类型,Git自带的协议就叫做git。以下的的命令通过git协议从克隆一个仓库
git clone git@github.com:vogella/gitbook.git
相同的,你能够通过http协议来克隆仓库
# The following will clone via HTTP git clone http://vogella@github.com/vogella/gitbook.git
1.13.2 加入�远端仓库
假设你克隆了一个远端仓库,那么原先的仓库就叫做origin
你能够push改动到origin中,通过 git push origin 命令. 当然,push到一个远端的仓库须要对仓库的写权限
你能够通过git remote add name gitrepo 命令加入�多个仓库。比如,你能够通过http协议再次加入�之前clone过来的仓库:
// Add the https protocol git remote add githttp https://vogella@github.com/vogella/gitbook.git
1.13.3 通过http和代理server进行远端操作
假设你的防火墙屏蔽了出http以外的全部协议,那么使用http协议来获取仓库是很好的方法。.
Git相同支持通过代理server使用http协议。以下的Git命令会展示这一点。你能够为全部的程序设置代理server或者仅仅是为Git服务提供。
以下的样例用到了环境变量
# 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
1.14 Git服务提供商
除了如果自己的服务,你也能够使用Git服务提供商提供的服务。最流行的Git服务提供站点是GitHub和Bitbucket。它们都提供了有限制的免费服务
1.14.1 GitHub
能够通过 https://github.com/ 訪问GitHub. GitHub上全部的公开仓库都是免费的。假设你想在上面使用私有的仓库,那么就须要付费给GitHub
GitHub须要你创建ssh的公钥私钥。生成一份Ubuntu的公钥私钥能够訪问 sshkey creation in Ubuntu ,Windows环境能够訪问msysgit ssh key generation.
在GitHub上创建一个账户和一个仓库以后。你会收到怎样将你的项目上传到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
1.14.2 Bitbucket
能够通过 https://bitbucket.org/ 訪问Bitbucket. Bitbucket 提供了无限制了公共仓库和仅仅能有五个人訪问的私有仓库。假设你须要超过五个人訪问私有仓库,就须要付费给Bitbucket
1.15 Git的图形接口
这个教程主要说明Git命令行的使用。完毕了这个教程以后,你可能想要找到一个Git的图形工具
Git提供了两个图形工具。 gitk可以展示仓库的历史信息、git gui 让你可以通过编辑器来完毕Git操作
Eclipse EGit 项目提供了Git与Eclipse的集成,在最新的Eclipse版本号中能够找到
1.17 问题与讨论
在提出问题之前,请先查看 vogella FAQ. 假设你有不论什么的问题或者是从文章中找到错误,那么能够使用www.vogella.com Google Group. 我自己写了一个简短的列表 how to create good questions 可能会对你实用.
1.18 链接和文章
Git homepage
EGit - Teamprovider for Eclipse
Video with Linus Torwalds on Git
Progit book - Free Git book
Video casts about Git
http://code.google.com/p/msysgit/ Git on Windows
http://github.com/guides/git-cheat-sheet Git Cheat Sheets
Date: 2012-08-26 日
HTML generated by org-mode 6.33x in emacs 23