前言
最近本人将一些代码放到了github上,顺便总结了一下git的用法;经过了各种百度,最终形成了以下这篇文章。
个人感觉追求效率的话,只看最后一条git常用命令即可。
前面的似乎有用,又似乎没用......
Git使用方法
- 简介
Git 是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目。
Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。
Git 与常用的版本控制工具 CVS, Subversion 等不同,它采用了分布式版本库的方式,不必服务器端软件支持。
- 安装
Git 各平台安装包下载地址为:http://git-scm.com/downloads
- Git工作流程
一般工作流程如下:
1.克隆 Git 资源作为工作目录。
2.在克隆的资源上添加或修改文件。
3.如果其他人修改了,你可以更新资源。
4.在提交前查看修改。
5.提交修改。
6.在修改完成后,如果发现错误,可以撤回提交并再次修改并提交。
下图展示了 Git 的工作流程:
- Git 工作区、暂存区和版本库
工作区:就是你在电脑里能看到的目录。
暂存区:英文叫stage, 或index。一般存放在 ".git目录下" 下的index文件(.git/index)中,所以我们把暂存区有时也叫作索引(index)。
版本库:工作区有一个隐藏目录.git,这个不算工作区,而是Git的版本库。
下面这个图展示了工作区、版本库中的暂存区和版本库之间的关系:
图中左侧为工作区,右侧为版本库。在版本库中标记为 "index" 的区域是暂存区(stage, index),标记为 "master" 的是 master 分支所代表的目录树。
图中我们可以看出此时 "HEAD" 实际是指向 master 分支的一个"游标"。所以图示的命令中出现 HEAD 的地方可以用 master 来替换。
图中的 objects 标识的区域为 Git 的对象库,实际位于 ".git/objects" 目录下,里面包含了创建的各种对象及内容。
当对工作区修改(或新增)的文件执行 "git add" 命令时,暂存区的目录树被更新,同时工作区修改(或新增)的文件内容被写入到对象库中的一个新的对象中,而该对象的ID被记录在暂存区的文件索引中。
当执行提交操作(git commit)时,暂存区的目录树写到版本库(对象库)中,master 分支会做相应的更新。即 master 指向的目录树就是提交时暂存区的目录树。
当执行 "git reset HEAD" 命令时,暂存区的目录树会被重写,被 master 分支指向的目录树所替换,但是工作区不受影响。
当执行 "git rm --cached <file>" 命令时,会直接从暂存区删除文件,工作区则不做出改变。
当执行 "git checkout ." 或者 "git checkout -- <file>" 命令时,会用暂存区全部或指定的文件替换工作区的文件。这个操作很危险,会清除工作区中未添加到暂存区的改动。
当执行 "git checkout HEAD ." 或者 "git checkout HEAD <file>" 命令时,会用 HEAD 指向的 master 分支中的全部或者部分文件替换暂存区和以及工作区中的文件。这个命令也是极具危险性的,因为不但会清除工作区中未提交的改动,也会清除暂存区中未提交的改动。
- Git基本操作
1.git init
(1) 使用当前目录做为git仓库:
git init
该命令执行完毕后会在当前目录生成一个.git目录。
(2) 使用指定目录做为git仓库:
git init newrepo
该命令执行完毕后会在newrepo下生成.git目录。
2.将文件纳入版本控制:
$ git add *.c
$ git add README
$ git commit -m '初始化项目版本'
以上命令将当前目录下以 .c 结尾及 README 文件提交到仓库中。
3.git clone
(1)比如,要克隆代码仓库 Grit,可以用下面的命令:
$ git clone git://github.com/schacon/grit.git
执行该命令后,会在当前目录下创建一个名为grit的目录,其中包含一个 .git 的目录,用于保存下载下来的所有版本记录。
(2)如果要自己定义要新建的项目目录名称,可以在上面的命令末尾指定新的名字:
$ git clone git://github.com/schacon/grit.git mygrit
Git 与常用的版本控制工具 CVS, Subversion 等不同,它采用了分布式版本库的方式,不必服务器端软件支持。
4.git status
git status 以查看在你上次提交之后是否有修改。
使用 -s 参数,获得简短的结果输出。如果没加该参数会详细输出内容。
5.git diff
执行git diff来查看执行 git status 的结果的详细信息。
git diff 命令显示已写入缓存与已修改但尚未写入缓存的改动的区别。git diff 有两个主要的应用场景。
尚未缓存的改动:git diff
查看已缓存的改动: git diff --cached
查看已缓存的与未缓存的所有改动:git diff HEAD
显示摘要而非整个 diff:git diff --stat以查看在你上次提交之后是否有修改。
6.git commit
使用 git add 命令将想要快照的内容写入缓存区, 而执行 git commit 将缓存区内容添加到仓库中。
Git 为你的每一个提交都记录你的名字与电子邮箱地址,所以第一步需要配置用户名和邮箱地址。
$ git config --global user.name 'runoob'
$ git config --global user.email test@runoob.com
接下来我们写入缓存,并提交对 hello.php 的所有改动。在首个例子中,我们使用 -m 选项以在命令行中提供提交注释。
$ git add hello.php
$ git commit -m '第一次版本提交'
如果你没有设置 -m 选项,Git 会尝试为你打开一个编辑器以填写提交信息。
如果你觉得 git add 提交缓存的流程太过繁琐,Git 也允许你用 -a 选项跳过这一步。如下:
git commit -am '修改 hello.php 文件'
7.git reset HEAD
git reset HEAD 命令用于取消已缓存的内容。
$ git add .
$ git reset HEAD hello.php
现在你执行 git commit,就不会提交hello.php了。
8.git rm
如果只是简单地从工作目录中手工删除文件,运行 git status 时就会在 Changes not staged for commit 的提示。
要从 Git 中移除某个文件,就必须要从已跟踪文件清单中移除,然后提交。可以用以下命令完成此项工作
git rm <file>
如果删除之前修改过并且已经放到暂存区域的话,则必须要用强制删除选项 -f
git rm -f <file>
如果把文件从暂存区域移除,但仍然希望保留在当前工作目录中,换句话说,仅是从跟踪清单中删除,使用 --cached 选项即可
git rm --cached <file>
可以递归删除,即如果后面跟的是一个目录做为参数,则会递归删除整个目录中的所有子目录和文件:
git rm –r *
进入某个目录中,执行此语句,会删除该目录下的所有文件和子目录。
9.git mv
git mv 命令用于移动或重命名一个文件、目录、软连接。
然后对其重名:
$ git mv README README.md
- Git分支管理
1.基本命令:
创建分支命令:
git branch (branchname)
切换分支命令:
git checkout (branchname)
当你切换分支的时候,Git 会用该分支的最后提交的快照替换你的工作目录的内容, 所以多个分支不需要多个目录。
合并分支命令:
git merge
你可以多次合并到统一分支, 也可以选择在合并之后直接删除被并入的分支。
2.列出分支:
列出分支基本命令:
git branch
没有参数时,git branch 会列出你在本地的分支。
当你执行 git init 的时候,默认情况下 Git 就会为你创建 master 分支。
用 git checkout (branch) 切换到我们要修改的分支。
也可以使用 git checkout -b (branchname) 命令来创建新分支并立即切换到该分支下,从而在该分支中操作。
3.删除分支:
删除分支命令:
git branch -d (branchname)
4.分支合并:
一旦某分支有了独立内容,你终究会希望将它合并回到你的主分支。 你可以使用以下命令将任何分支合并到当前分支中去:
git merge
例如:
git merge newtest
将 newtest 分支合并到主分支去,test.txt 文件被删除。
合并完后就可以删除分支(也可以不删):
$ git branch -d newtest
删除后, 就只剩下 master 分支了。
5.合并冲突:
当分支中的文件发生了修改,并且主分支中同一个文件也发生了修改,此时将分支合并到主分支,就会发生冲突。
此时,需要手动修改这个文件:
$ vim runoob.php
$ cat runoob.php
<?php
echo 1;
echo 'runoob';
?>
之后,可以用 git add 要告诉 Git 文件冲突已经解决
$ git add runoob.php
- Git查看提交历史
在使用 Git 提交了若干更新之后,又或者克隆了某个项目,想回顾下提交历史,我们可以使用 git log 命令查看。
可以用 --oneline 选项来查看历史记录的简洁的版本。
$ git log --oneline
还可以用 --graph 选项,查看历史中什么时候出现了分支、合并。
也可以用 --reverse 参数来逆向显示所有日志。
$ git log --reverse --oneline
如果只想查找指定用户的提交日志可以使用命令:git log --author。
$ git log --author=Linus --oneline -5
如果你要指定日期,可以执行几个选项:--since 和 --before,但是你也可以用 --until 和 --after。
$ git log --oneline --before={3.weeks.ago} --after={2010-04-18} --no-merges
- Git标签
如果你达到一个重要的阶段,并希望永远记住那个特别的提交快照,你可以使用 git tag 给它打上标签。
比如说,我们想为我们的 runoob 项目发布一个"1.0"版本。 我们可以用 git tag -a v1.0 命令给最新一次提交打上(HEAD)"v1.0"的标签。
-a 选项意为"创建一个带注解的标签"。
$ git tag -a v1.0
当你执行 git tag -a 命令时,Git 会打开你的编辑器,让你写一句标签注解,就像你给提交写注解一样。
现在,当我们执行 git log --decorate 时,就可以看到我们的标签了。
如果我们忘了给某个提交打标签,又将它发布了,我们可以给它追加标签。
例如,假设我们发布了提交 85fc7e7(上面实例最后一行),但是那时候忘了给它打标签。 我们现在也可以:
$ git tag -a v0.9 85fc7e7
如果我们要查看所有标签可以使用以下命令:
$ git tag
指定标签信息命令:
git tag -a <tagname> -m "runoob.com标签"
PGP签名标签命令:
git tag -s <tagname> -m "runoob.com标签"
- Git 远程仓库(Github)
Git 并不像 SVN 那样有个中心服务器。
目前我们使用到的 Git 命令都是在本地执行,如果你想通过 Git 分享你的代码或者与其他开发人员合作。你就需要将数据放到一台其他开发人员能够连接的服务器上。
1.添加远程库
要添加一个新的远程仓库,可以指定一个简单的名字,以便将来引用,命令格式如下:
git remote add [shortname] [url]
本例以 Github 为例作为远程仓库,如果你没有 Github 可以在官网 https://github.com/注册。
由于你的本地 Git 仓库和 GitHub 仓库之间的传输是通过SSH加密的,所以我们需要配置验证信息:
使用以下命令生成 SSH Key:
$ ssh-keygen -t rsa -C "youremail@example.com"
后面的 your_email@youremail.com 改为你在 Github 上注册的邮箱,之后会要求确认路径和输入密码,我们这使用默认的一路回车就行。成功的话会在 ~/ 下生成 .ssh 文件夹,进去,打开 id_rsa.pub,复制里面的 key。
回到 github 上,进入 Account => Settings(账户配置)。
左边选择 SSH and GPG keys,然后点击 New SSH key 按钮,title 设置标题,可以随便填,粘贴在你电脑上生成的 key。
为了验证是否成功,输入以下命令:
$ ssh -T git@github.com
Hi tianqixin! You've successfully authenticated, but GitHub does not provide shell access.
以下命令说明我们已成功连上 Github。
之后登录后点击" New repository " 。
之后在在Repository name 填入 runoob-git-test(远程仓库名) ,其他保持默认设置,点击"Create repository"按钮,就成功地创建了一个新的Git仓库。
我们可以从这个仓库克隆出新的仓库,也可以把本地仓库的内容推送到GitHub仓库。
现在,我们根据 GitHub 的提示,在本地的仓库下运行命令:
$ mkdir runoob-git-test # 创建测试目录
$ cd runoob-git-test/ # 进入测试目录
$ echo "# 菜鸟教程 Git 测试" >> README.md # 创建 README.md 文件并写入内容
$ ls # 查看目录下的文件
README
$ git init # 初始化
$ git add README.md # 添加文件
$ git commit -m "添加 README.md 文件" # 提交并备注信息
[master (root-commit) 0205aab] 添加 README.md 文件
1 file changed, 1 insertion(+)
create mode 100644 README.md
# 提交到 Github
$ git remote add origin git@github.com:tianqixin/runoob-git-test.git
$ git push -u origin master
以上命令请根据你在Github成功创建新仓库的地方复制,而不是根据我提供的命令,因为我们的Github用户名不一样,仓库名也不一样。
接下来我们返回 Github 创建的仓库,就可以看到文件已上传到 Github上。
2.查看当前的远程库
要查看当前配置有哪些远程仓库,可以用命令:
git remote
执行时加上 -v 参数,你还可以看到每个别名的实际链接地址。
$ git remote -v
3.提取远程仓库
Git 有两个命令用来提取远程仓库的更新。
(1)从远程仓库下载新分支与数据:
git fetch
该命令执行完后需要执行git merge 远程合并到你所在的分支。
(2)从远端仓库提取数据并尝试合并到当前分支:
git merge
该命令就是在执行 git fetch 之后紧接着执行 git merge 远程分支到你所在的任意分支。
例:
$ git fetch origin
$ git merge origin/master
4.推送到远程仓库
推送你的新分支与数据到某个远端仓库命令:
git push [alias] [branch]
以上命令将你的 [branch] 分支推送成为 [alias] 远程仓库上的 [branch] 分支,实例如下。
$ touch runoob-test.txt # 添加文件
$ git add runoob-test.txt
$ git commit -m "添加到远程"
master 69e702d] 添加到远程
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 runoob-test.txt
$ git push origin master # 推送到 Github
5.删除远程仓库
删除远程仓库你可以使用命令:
git remote rm [别名]
实例
# 添加仓库 origin2
$ git remote add origin2 git@github.com:tianqixin/runoob-git-test.git
# 删除仓库 origin2
$ git remote rm origin2
$ git remote -v
origin git@github.com:tianqixin/runoob-git-test.git (fetch)
origin git@github.com:tianqixin/runoob-git-test.git (push)
- 命令行中github的用法
1.使用命令
ssh-keygen -t rsa -C "youremail@example.com"
参数为github邮箱;输入文件保存地址,输入github密码;之后生成pub文件
2.回到 github 上,进入 Account => Settings(账户配置),选择 SSH and GPG keys,然后点击 New SSH key 按钮,title 设置标题,可以随便填,粘贴在你电脑上生成的 pub文件的内容。
3.输入以下命令测试:ssh -T git@github.com;如果失败,则搜索.ssh文件夹(C:UsersAdmin.ssh),将第一步生成的两个文件粘贴到此处,并重命名为id_rsa与id_rsa.pub
4.在github中点击New respository,之后在Repository name 填入 runoob-git-test(远程仓库名) ,其他保持默认设置,点击"Create repository"按钮,就成功地创建了一个新的Git仓库。
5.按照提示信息创建一个测试文件并上传到git仓库:
echo "# 菜鸟教程 Git 测试" >> README.md
git init
git add README.md
git commit -m "123"
git remote add origin https://github.com/BlackHoleSeventh/gitest.git
git push -u origin master
之后需要输入用户名与密码,之后就上传成功了。
6.将一个已有的项目上传到github:
(1) cd到已有项目的目录中,使用git init;命令初始化
(2) 使用git add * ;将所有项目添加到git
(3) 使用git commit -m “任意信息”将添加后的文件提交
(4) 使用git remote add myStore https://github.com/UserName/storeName.git添加一个远程仓库地址;其中myStore是自己起的仓库名,对应后面的地址;使用git remote -v即可查看自己有哪些仓库地址。
(5) 使用git push -u myStore master将代码推送到远程仓库的master分支中,其中myStore是自己起的仓库名,master是分支名。(可以任意起,如果远程仓库没有这个分支,则会创建一个)
7.将一个github项目更新到本地:
(1) cd到目标目录中,使用git fetch myStore命令拉到本地(没有参数,从远程master拉到了本地master目录中);其中myStore是自己起的仓库名(对应url用)。
(2) 使用git merge myStore/master命令将内容同步。其中myStore是自己起的仓库名,master是同步到本地master分支。
8.将一个github项目下载到本地空文件夹:
(1) cd到目标空文件夹中,使用git clone https://github.com/UserName/storeName.git name命令,其中url为github仓库的网址,name为自己起的文件夹名,也可以不加,则会使用storeName为文件夹名。clone操作是一个从无到有的克隆操作,不需要git init初始化。
(2) 也可以使用git pull,相当于从远程仓库获取最新版本,然后再与本地分支merge(合并)。
举例:将远程主机origin的master分支拉取过来,与本地的branchtest分支合并。
$ git pull origin master:branchtest
(3) 以上的git pull操作也可以用git fetch来表示:
$ git fetch origin master:brantest
$ git merge brantest
将远程master分支下载到本地brantest分支;
将brantest分支合并入主分支master。
使用fetch可以先查看代码不同,再决定是否合并。
git fetch更新本地仓库的两种用法:
# 方法一
$ git fetch origin master #从远程的origin仓库的master分支下载代码到本地的origin master
$ git log -p master.. origin/master #比较本地的仓库和远程参考的区别
$ git merge origin/master #把远程下载下来的代码合并到本地仓库,远程的和本地的合并
# 方法二
$ git fetch origin master:temp #从远程的origin仓库的master分支下载到本地并新建一个分支temp
$ git diff temp #比较master分支和temp分支的不同
$ git merge temp #合并temp分支到master分支
$ git branch -d temp #删除temp
9.Git回滚:
(1) 使用git log --pretty=oneline查看历史版本
(2) 使用git reset --hard 9e4a2468e8ecb8d763b7e53549bd982c3370d00d回退到指定版本
10.git上传大文件:
(1) 在项目目录下,使用git lfs install命令
(2) 使用命令:git lfs track “* .gif” --这里的 “ *.gif "就是你要上传的大文件的路径
(3) 使用命令:git add .gitattributes
(4) 先提交:git commit -m "123";
(5) 先上传:git push -u orgin master
(6) 之后再上传大文件。注意,一定要先上传.gitattributes文件才可以!
11.git撤销add命令:
git reset HEAD //可以全部恢复未提交状态
git reset --hard HEAD //把全部更改的文件都恢复(小心使用,不然辛辛苦苦写的全没了)
- Idea中git的用法
1.cd到指定目录,使用命令
git init
git add *
git commit -m “msg”
git remote add orgin https://github.com/UserName/UserStore.git
git push -u orgin master
将代码同步到远程仓库
2.或者使用
git clone git://github.com/UserName/UserStore.git
将代码下载到本地
3.使用idea打开项目,会出现提示是否要用git管理项目,选“yes”
4.或者,上方vcs菜单中有checkout from version control子菜单,其中可以设置git地址。
5.在右下角“Git:master”处,点击选择“New Branch”可以添加新分支
6.在右下角选择“check out”选择目标分支
7.上方有update按钮与commit按钮,commit按钮可以选择commit and push;之后会要求输入用户名密码,即可push到远程仓库。
8.下方“version control”中可以查看正在修改的文件,可以选择commit或revert。
9.上方vcs菜单中有git子菜单,可以选择revert、clone、fetch、pull、push等操作。
10.分支代码更新后,可以回到主分支,选择另一个分支的merge,即可将分支代码同步到主分支;主分支代码更新后,也可以先进入从分支,选择主分支的merge,即可将代码同步到当前分支。
11.当一个分支的代码push后,可以进入其它分支merge此分支的代码,如果此时merge其余分支的代码,则不会有反应,因为git只保存一个提交对象。
12.当两个以上从分支push后,主分支想merge其中一个分支,则会发生冲突,需要选择接受哪一个分支。
- TortoiseGit的用法
1.安装
2.安装好后,右键可以发现TortoiseGit的相关菜单
3.选择git clone从仓库下载代码,或者选择git create repository here...创建.git文件夹
4.可以使用commit、push、revert操作代码
5.可以使用create branch创建分支,使用Switch/Checkout切换分支。
6.先进入目标分支,然后选择merge,再选择另一个分支,就可以将代码合并到目标分支上。
7.删除分支:点击“Switch/Checkout”打开对话框,点击Switch to区域中Branch条目后面的更多按钮,打开分支列表对话框,右键点击要删除的分支,选择delete branch进行删除。
- Git冲突与解决方法
1、git冲突的场景
情景一:多个分支代码合并到一个分支时;
情景二:多个分支向同一个远端分支推送代码时;
实际上,push操作即是将本地代码merge到远端库分支上。
关于push和pull其实就分别是用本地分支合并到远程分支 和 将远程分支合并到本地分支
所以这两个过程中也可能存在冲突。
git的合并中产生冲突的具体情况:
(1)两个分支中修改了同一个文件(不管什么地方)
(2)两个分支中修改了同一个文件的名称
两个分支中分别修改了不同文件中的部分,不会产生冲突,可以直接将两部分合并。
2、冲突解决方法
情景一:在当前分支上,直接修改冲突代码--->add--->commit。
情景二:在本地当前分支上,修改冲突代码--->add--->commit--->push
注:借用vim或者IDE或者直接找到冲突文件,修改。
- 个人总结:Git常用命令
--------------------------------------------
//git上传本地项目以及上传大文件
git init
git remote add orgin https://github.com/UserName/UserStore.git
git lfs install
git lfs track "*.*"
git add .gitattributes
git commit -m "LFS上传大文件"
git push -u orgin master
git add *
git commit -m "上传已存在项目"
git push -u orgin master
--------------------------------------------
//git从仓库下载项目(还有clone与pull,不过只用fetch也可以)
git init
git remote add orgin https://github.com/UserName/UserStore.git
git fetch orgin
git merge orgin/master
--------------------------------------------
//git查看提交历史
git log --pretty=oneline
--------------------------------------------
//git revert,生成一个新的提交来撤销某次提交,此次提交之前的commit都会被保留
git revert HEAD #撤销倒数第一次提交
git revert HEAD^ #撤销倒数第二次提交
git revert HEAD~2 #撤销倒数第三次提交
git revert c011eb3c20ba6fb38cc94fe5a8dda366a3990c61
--------------------------------------------
//git reset,回到某次提交,提交及之前的commit都会被保留,但是此次之后的修改都会被退回到暂存区,用法与revert类似
//git取消add操作
git reset HEAD
//只回退某个指定文件到指定版本
git reset a4e215234aa4927c85693dca7b68e9976948a35e MainActivity.java
--------------------------------------------