Mac Git的一站式学习

来源:互联网 发布:手机维棠软件 编辑:程序博客网 时间:2024/06/15 06:29

写在前面:Mac下git的一站式学习记录,目标熟练使用mac bash命令管理代码。(过程写的很粗糙 多是参考前辈的东西)

git 的远端仓库一般用两种github的或者bitbucket滴,但github没有免费的个人私有

repositories,这怎么行啊。果断用了bitbucket感觉还不错呦。

下载安装git,下载地址:https://git-scm.com/downloads 。(简单直接的办法)

git术语定义

仓库(Repository)         

一个仓库包括了所有的版本信息、所有的分支和标记信息。在Git中仓库的每份拷贝都是完整的。仓库让你可以从中取得你的工作副本。分支(Branches)一个分支意味着一个独立的、拥有自己历史信息的代码线(code line)。你可以从已有的代码中生成一个新的分支,这个分支与剩余的分支完全独立。默认的分支往往是叫master。用户可以选择一个分支,选择一个分支叫做checkout.

标记(Tags)

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

提交(Commit)

提交代码后,仓库会创建一个新的版本。这个版本可以在后续被重新获得。每次提交都包括作者和提交者,作者和提交者可以是不同的人URLURl用来标识一个仓库的位置

修订(Revision)

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

通过如下命令来配置(全局的)用户名和Email 

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

获取Git配置信息

git config --list

为终端配置高亮(optional)

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

如果你公司的项目是放在自建的gitlab上面, 如果你不进行配置用户名和邮箱的话, 则会使用全局的, 这个时候是错误的, 正确的做法////是针对公司的项目, 在项目根目录下进行单独配置(敲$后面的部分哈)

$ git config user.name "gitlab's Name"

$ git config user.email "gitlab@xx.com"

查看当前配置, 在当前项目下面查看的配置是全局配置+当前项目的配置, 使用的时候会优先使用当前项目的配置

$ git config --list

全局的用户名和邮箱啥的应该也可以自行更改,具体办法问度娘吧。

忽略特定的文件

可以配置Git忽略特定的文件或者是文件夹。这些配置都放在.gitignore文件中。这个文件可以存在于不同的文件夹中,可以包含不同的文件匹配模式。为了让Git忽略bin文件夹,在主目录下放置.gitignore文件,其中内容为bin。 

 同时Git也提供了全局的配置,core.excludesfile

使用.gitkeep来追踪空的文件夹

Git会忽略空的文件夹。如果你想版本控制包括空文件夹,根据惯例会在空文件夹下放置.gitkeep文件。其实对文件名没有特定的要求。一旦一个空文件夹下有文件后,这个文件夹就会在版本控制范围内。


命令行创建文件方法(以下绿色步骤都基于这里的操作示范)
#Switch to homecd ~/# Create a directorymkdir ~/repo01# Switch into itcd repo01# Create a new directorymkdir datafiles# Create a few filestouch test01touch test02touch test03touch datafiles/data.txt# Put a little text into the first filels >test01

创建仓库、添加文件和提交更改

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

以下将会创建一个Git仓库,添加文件到仓库的索引中,提交更改。(用git管理xcode工程,在还未将工程添加到git时,创建仓库应cd到工程的主目录下进行操作)

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

diff命令与commit更改

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

# Make some changes to the fileecho "This is a change" > test01echo "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 filesgit commit -a -m

Status, Diff 和 Commit Log

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

# Make some changes in the fileecho "This is a new change" > test01echo "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 branchgit diff# Add the changes to the index and commit
# words in quotes after -m is a introduction to describe your change git add . && git commit -m "More changes - typo in the commit message"# Show the history of commits in the current branchgit log

 

更正提交的信息 - git amend

通过git amend命令,我们可以修改最后提交的的信息

git commit --amend -m 

删除文件

如果你删除了一个在版本控制之下的文件,那么使用git add .不会在索引中删除这个文件。需要通过带-a选项的git commit命令和-A选项的git add命令来完成

# Create a file and put it under version controltouch no.txtgit add . && git commit -m "##你自己的文件提交说明##"# Remove the filerm no.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 flaggit commit -a -m "File no.txt is now removed"# Alternatively(或者) you could add deleted files to the staging index viagit add -A . git commit -m "File

远端仓库(remote repositories)

设置(创建)一个远端的Git仓库,这个仓库可以存储在本地或者是网络上。

远端Git仓库和标准的Git仓库有如下差别:一个标准的Git仓库包括了源代码和历史信息记录。我们可以直接在这个基础上修改代码,因为它已经包含了一个工作副本。但是远端仓库没有包括工作副本,只包括了历史信息。可以使用--bare选项来创建一个这样的仓库。(在这里如果还没有设立网络远端仓库,请关注紫色字。如果已经有网络远端仓库就看橘黄的字喽(一直往下滑呀滑~),PS:设置远端仓库这里用的bitbucket,如何创建就又去某度上学习了,官网介绍就很详细了)

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

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

推送更改到其他的仓库

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

# Make some changes in the first repositorycd ~/repo01# Make some changes in the fileecho "Hello, hello. Turn your radio on" > test01echo "Bye, bye. Turn your radio off" > test02# Commit the changes, -a will commit changes for modified files# but will not add automatically new filesgit commit -a -m "Some changes"# Push the changesgit push ../remote-repository.git

添加远端仓库

除了通过完整的URL来访问Git仓库外,还可以通过git remote add命令为仓库添加一个短名称。当你克隆了一个仓库以后,origin表示所克隆的原始仓库。即使我们从零开始,这个名称也存在。 

# Add ../remote-repository.git with the name origingit remote add origin ../remote-repository.git # Again some changesecho "I added a remote repo" > test02# Commitgit commit -a -m "This is a test for the new remote origin"# If you do not label a repository it will push to origingit push origin

显示已有的远端仓库

通过以下命令查看已经存在的远端仓库 

# Show the existing defined remote repositoriesgit remote

 

克隆仓库

通过以下命令在新的目录下创建一个新的仓库 

# Switch to homecd ~# Make new directorymkdir repo02# Switch to new directorycd ~/repo02# Clonegit clone ../remote-repository.git .


拉取(Pull)更改

通过拉取,可以从其他的仓库中获取最新的更改。在第二个仓库中,做一些更改,然后将更改推送到远端的仓库中。然后第一个仓库拉取这些更改 

# Switch to homecd ~# Switch to second directorycd ~/repo02
# Make changesecho "A change" > test01# Commitgit commit -a -m "A change"# Push changes to remote repository# Origin is automatically maintained as we cloned from this repositorygit push origin# Switch to the first repository and pull in the changescd ~/repo01git pull ../remote-repository.git/# Check the changesless test01

还原更改

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

# Create a new file with contenttouch test04echo "this is trash" > test04# Make a dry-run to see what would happen# -n is the same as --dry-run git clean -n# Now deletegit clean -f

 

你可以提取老版本的代码,通过提交的ID。git log命令可以查看提交ID 

# Switch to homecd ~/repo01# Get the loggit log# Copy one of the older commits and checkout the older revision via  译者注:checkout 后加commit id就是把commit的内容复制到index和工作副本中 git checkout commit_name

 

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

#Some nonsense changeecho "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 resultcat test01# Another nonsense changeecho "another nonsense change" > test01# We add the file to the staging indexgit 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 commitgit revert commit_name

 

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

# Delete a filerm test01# Revert the deletiongit checkout test01

 

如果你已经添加一个文件到索引中,但是未提交。可以通过git reset file 命令将这个文件从索引中删除 

// Create a filetouch incorrect.txt// Accidently add it to the indexgit add .// Remove it from the indexgit reset incorrect.txt// Delete the filerm incorrect.txt

 

如果你删除了文件夹且尚未提交,可以通过以下命令来恢复这个文件夹 。译者注:即使已经提交,也可以还原

git checkout HEAD -- your_dir_to_restore

综上可以看出,只要文件使用了git 包括add到索引 commit到仓库 git里有文件的内容了 就可以做基于保存内容的回滚操作。

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



 标记

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

可以通过git tag命令列出所有的标记,通过如下命令来创建一个标记和恢复到一个标记

 

git tag version1.6 -m 'version 1.6'      

git checkout <tag_name>

 

分支、合并

分支

通过分支,可以创造独立的代码副本。默认的分支叫masterGit消耗很少的资源就能创建分支。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


合并

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

可以通过如下的命令进行合并 

# Syntax: git merge <branch-name>

git merge testing

一旦合并发生了冲突,Git会标志出来,开发人员需要手工的去解决这些冲突。解决冲突以后,就可以将文件添加到索引中,然后提交更改


删除分支

删除分支的命令如下: 

#Delete branch testing

git branch -d testing

# Check if branch has been deleted

git branch

 

推送(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


通过这种方式,你可以确定哪些分支对于其他仓库是可见的,而哪些只是本地的分支  


解决合并冲突

如果两个不同的开发人员对同一个文件进行了修改,那么合并冲突就会发生。而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"

 

 变基(Rebase

在同一分支中应用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信息(待理解)


Rebasing多个分支

你也可以对两个分支进行rebase操作。如下所述,merge命令合并两个分支的更改。rebase命令为一个分支的更改生成一个补丁,然后应用这个补丁到另一分支中

使用mergerebase,最后的源代码是一样的,但是使用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

 

Rebase最佳实践

push更改到其他的Git仓库之前,我们需要仔细检查本地分支的commit历史

Git中,你可以使用本地的commit。开发人员可以利用这个功能方便的回滚本地的开发历史。但是在push之前,需要观察你的本地分支历史,是否其中有些commit历史对其他用户来说是无关的

如果所有的commit历史都跟同一个功能有关,很多情况下,你需要rebase这些commit历史为一个commit历史。

交互性的rebase主要就是做重写commit历史的任务。这样做是安全的,因为commit还没有被push到其它的仓库。这意味着commit历史只有在被push之前被修改

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


创建和应用补丁

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

下面会创建一个分支,对这个分支所一些修改,然后创建一个补丁,并应用这个补丁到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

 


定义同名命令

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中还没有支持。同名命令不能以!开始。


放弃跟踪文件

有时候,你不希望某些文件或者文件夹被包含在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命令


其他有用的命令

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

Table 2. 有用的Git命令

命令描述

git blame filename谁创建了或者是修改了这个文件

git checkout -b mybranch master~1以上上个commit信息为起点,创建一条新的分支



安装Git服务

如上所述,我们的操作不需要Git服务。我可以只使用文件系统或者是Git仓库的提供者,像GithubBitbucket。但是,有时候,拥有一个自己的服务是比较方便的,在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

  

在线的远端仓库

克隆远端仓库

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


添加远端仓库

如果你克隆了一个远端仓库,那么原先的仓库就叫做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

 

 通过http和代理服务器进行远端操作

如果你的防火墙屏蔽了出http以外的所有协议,那么使用http协议来获取仓库是非常好的方法。.

Git同样支持通过代理服务器使用http协议。下面的Git命令会展示这一点。你可以为所有的程序设置代理服务器或者只是为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

 

Git的图形接口

这个教程主要说明Git命令行的使用。完成了这个教程以后,你可能想要找到一个Git的图形工具

Git提供了两个图形工具。 gitk能够展示仓库的历史信息、git gui 让你可以通过编辑器来完成Git操作

Eclipse EGit项目提供了GitEclipse的集成,在最新的Eclipse版本中可以找到





原创粉丝点击