3. Git常见操作
init
git init [path] 初始化仓库
git init [path] --bare 初始化一个裸仓库
status
$ git status
经常检查当前文件状态是个好习惯
$ git help <command>
/ $ git <command> --help
获取帮助
add 跟踪新文件
这是个多功能命令,根据目标文件的状态不同,此命令的效果也不同:可以用它开始跟踪新文件,或者把已跟踪的文件放到暂存区,还能用于合并时把有冲突的文件标记为已解决状态等
git add [filename1] [filename2] ...
//可以一次提交很多文件
例如
$ git add AndroidManifest.xml
$ git add src/com/coolweather/app/MainActivity.java
$ git add src/
add单个文件夹
$ git add .
添加对应目录下所有文件和文件夹
rm 删除操作
$ git rm
从暂存区和工作区删除, 直接做了本地rm和add到暂存区的操作
$ git rm --cached readme.txt
从暂存区删除,但仍然希望保留在当前工作目录中。换句话说,仅是从跟踪清单中删除。比如一些大型日志文件或者一堆 .a 编译文件,不小心纳入仓库后,要移除跟踪但不删除文件,以便稍后在 .gitignore
文件中补上
$ git rm $(git ls-files --deleted)
: 删除所有被跟踪, 但是在工作区总被删除的文件
mv操作
$ git mv [oldFile] [newFile]
其实,运行 git mv 就相当于运行了下面三条命令:
$ mv README.txt README
$ git rm README.txt
$ git add README
commit 提交
$ git commit -m 'initial project version'
注意: Git 只不过暂存了你运行 git add 命令时的版本,而非当前工作目录中的版本。
每次修改,如果不add到暂存区,那就不会加入到commit中
跳过使用暂存区域
$ git commit -a/--all -m 'added new benchmarks'
Git 提供了一个跳过使用暂存区域的方式,只要在提交的时候,给git commit 加上 -a 选项,Git 就会自动把所有已经跟踪过的文件暂存起来一并提交,从而跳过 git add 步骤, 如果有未跟踪的文件还是需要先add
OPTIONS
-a
--all
Tell the command to automatically stage files that have been modified and deleted, but new files you have not told Git about are not affected.
小技巧: 修改最后一次提交的注释 $ git commit --amend -m "someMessage"
log 查看提交历史
-num 参数表示我们只想看到num行记录.
-p 按补丁格式显示每个更新之间的差异。
--stat 显示每次更新的文件修改统计信息, 包含增改行数统计
--shortstat 只显示 --stat 中最后的行数修改添加移除统计。
--name-only 仅在提交信息后显示已修改的文件清单。
--name-status 显示新增、修改、删除的文件清单。
--abbrev-commit 仅显示 SHA-1 的前几个字符,而非所有的 40 个字符。
--relative-date 使用较短的相对时间显示(比如,“2 weeks ago”)。
--graph 显示 ASCII 图形表示的分支合并历史。
--pretty 使用其他格式显示历史提交信息。可用的选项包括 oneline,short,full,fuller 和 format(后跟指定格式)。
reset
-
取消已经暂存的文件
$ git reset HEAD <file>...
to unstage 将文件内容才能够上次提交 复制到
暂存区, 由于 暂存区的修改回退到工作区 -
将当前分支回退到某个历史版本
$ git reset --mixed commit_id
【默认】它将重置HEAD到另外一个commit,并且重置index以便和HEAD相匹配,但是也到此为止。working copy不会被更改。
$ git reset --soft commit_id
$ git reset --hard commit_id
在Git中,用HEAD表示当前版本, 所以通常可以省略
上一个版本就是HEAD^
,上上一个版本就是HEAD^^
,当然往上100个版本写100个^比较容易数不过来,所以写成HEAD~100
。
例如:
$ git reflog
要重返未来,查看命令历史
例如回退到上个版本git reset --hard HEAD^
通常根据reflog命令查看hash后连用
$ git reset --hard commit_id
选择/回退历史版本
$ git checkout -- file
可以丢弃工作区的修改
git diff
$ git diff
查看尚未暂存的文件更新了哪些部分,不加参数直接输入 。
此命令比较的是工作目录中当前文件和暂存区域快照之间的差异,也就是修改之后还没有add暂存起来的变化内容。
$ git diff -- [filename]
查看工作区和版本库里面最新版本的区别
$ git diff --cached
(或 --staged
Git 1.6.1 及更高版本上还允许使用,效果是相同的,但更好记)
比较已经暂存起来的文件和上次提交时的快照之间的差异
$ git diff [<commit-id>] [<commit-id>]
比较两个commit-id之间的差异
checkout 撤销/检出
$ git checkout -- <file>...
(to discard changes in working directory)将文件内容从暂存区复制到工作目录
举例git checkout -- readme.txt
意思就是,把readme.txt文件在工作区的修改全部撤销,
这里有两种情况:
一种是readme.txt自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;
一种是readme.txt已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。
总之,就是让这个文件回到最近一次git commit或git add时的状态。
这条命令有些危险,所有对文件的修改都没有了,因为我们刚刚把之前版本的文件复制过来重写了此文件。所以在用这条命令前,请务必确定真的不再需要保留刚才的修改。
$ git checkout [branchName]
切换到分支
$ git checkout -
切换到上一个分支
$ git checkout [commit id]
HEAD指向某一个commit id
branch分支
Git 鼓励开发者频繁使用分支,正是因为有着这些特性作保障。Git 是如何知道你当前在哪个分支上工作的呢?其实答案也很简单,它保存着一个名为 HEAD 的特别指针. (译注:将 HEAD 想象为当前分支的别名。)
$ git branch [branch-name]
创建分支
$ git branch
查看所有分支
$ git branch -a
查看当前的版本库当中有哪些分支, 包含远程仓库的所有分支
$ git branch -v
要查看各个分支最后一个提交对象的信息 (译注:此为 --verbose 的简写,取首字母)
$ git branch --merge
查看哪些分支已被并入当前分支(译注:也就是说哪些分支是当前分支的直接上游。一般来说,列表中没有 * 的分支通常都可以用 git branch -d 来删掉。原因很简单,既然已经把它们所包含的工作整合到了其他分支,删掉也不会损失什么。
$ git branch --no-merged
查看尚未合并的工作,它会显示还未合并进来的分支。由于这些分支中还包含着尚未合并进来的工作成果,所以简单地用 git branch -d 删除该分支会提示错误,因为那样做会丢失数据, 过,如果你确实想要删除该分支上的改动,可以用大写的删除选项 -D 强制执行
创建并切换到该分支 git branch -b [branch-name]
相当于 git branch [branch-name]
git checkout [branch-name]
$ git branch -d <branch-name>
删除分支
$ git merge [branch-name]
合并某分支到当前分支
当合并分支时,如果可能,Git会用Fast forward模式,但这种模式下,删除分支后,会丢掉分支信息。
如果要强制禁用Fast forward模式,Git就会在merge时生成一个新的commit。
例如 $ git merge --no-ff -m "merge with no-ff" dev
远程仓库/分支
远程分支(remote branch)是对远程仓库中的分支的索引。它们是一些无法移动的本地分支;只有在 Git 进行网络交互时才会更新。远程分支就像是书签,提醒着你上次连接远程仓库时上面各分支的位置.
现在新建的目录成了 mygrit,其他的都和上边的一样。
$ git clone git://github.com/schacon/grit.git mygrit
(一次 Git 克隆会建立你自己的本地分支 master 和远程分支 origin/master,并且将它们都指向 origin 上的 master 分支)
查看当前配置有哪些远程仓库详细信息 //git remote -v
添加远程仓库 $ git remote add [remote-name] [url]
查看远程仓库信息 git remote show [remote-name]
远程仓库配置的重命名 git remote rename [old-name] [new-name]
远程仓库配置删除 git remote rm [remote-name]
fetch
$ git fetch [remote-name]
从远程仓库抓取数据同步到本地
有一点很重要,需要记住,fetch 命令只是将远端的数据拉到本地仓库,并不自动合并到当前工作分支,只有当你确实准备好了,才能手工合并。
将远程版本库上的修改同步到本地
git fetch origin master 会将远程版本库上的代码同步到本地,不过同步下来的代码并不会
合并到任何分支上去,而是会存放在到一个 origin/master分支上,这时我们可以通过 diff命令来查看远程版本库上到底修改了哪些东西:
$ git diff origin/master
之后再调用 merge 命令将 origin/master 分支上的修改合并到主分支上即可:
$ git merge origin/master
跟踪远程分支
$ git branch --set-upstream-to=<remote-name>/<branch> <local-branch-name>
除非是已有项目, 否则一般直接checkout命令新建branch以及跟踪一句话即可。
跟踪远程分支并新建切换到本地分支 git checkout -b [本地分支名] [远程名]/[分支名], 例如git checkout -b serverfix origin/serverfix
如果你有 1.6.2 以上版本的 Git,
还可以用 --track 选项简化:$ git checkout --track [远程名]/[分支名]
从远程分支 checkout 出来的本地分支,称为 跟踪分支 (tracking branch)。跟踪分支是一种和某个远程分支有直接联系的本地分支。在跟踪分支里输入 git push,Git 会自行推断应该向哪个服务器的哪个分支推送数据。同样,在这些分支里运行 git pull 会获取所有远程索引,并把它们的数据都合并到本地分支中来。
$ git checkout -b [分支名] [远程名]/[分支名]
, 这样你就可以在b继续开发了。
合并远程分支
如果要把该远程分支的内容合并到当前分支,可以运行 $ git merge origin/serverfix
$ git pull <remote> <branch>
从远程仓库抓取数据并merge到当前分支
相当于将 fetch 和 merge 这两个命令放在一起执行了
注:如果设置了某个分支用于跟踪某个远端仓库的分支, git pull,目的都是要从原始克隆的远端仓库中抓取数据后,合并到工作目录中的当前分支。
注:在跟踪分支里可直接输入 git push,Git 会自行推断应该向哪个服务器的哪个分支推送数据
*如果设置了跟踪, 可以直接git pull
git push [远程名] [本地分支]:[远程分支] //推送数据到远程仓库
例如:git push origin serverfix //简略写法
*如果设置了跟踪, 可以直接git push
git push (远程仓库名) (分支名) //表示 分支|同名远程分支
git push (远程仓库名) (本地分支:远程分支)
你可以把本地分支推送到某个命名不同的远程分支:若想把远程分支叫作 awesomebranch,可以用
推送数据git push origin serverfix:awesomebranch
推送删除远程分支 git push [远程名] :[分支名] (如果省略 [本地分支],那就等于是在说“在这里提取空白然后把它变成[远程分支]”)
例如git push origin :serverfix
tag标签
Git 使用的标签有两种类型:轻量级的(lightweight)和含附注的(annotated)。
- 轻量级标签, 就像是个不会变化的分支,实际上它就是个指向特定提交对象的引用。
- 附注标签,实际上是存储在仓库中的一个独立对象,它有自身的校验和信息,包含着标签的名字,电子邮件地址和日期,以及标签说明,标签本身也允许使用 GNU Privacy Guard (GPG) 来签署或验证。一般我们都建议使用含附注型的标签,以便保留相关信息;当然,如果只是临时性加注标签,或者不需要旁注额外信息,用轻量级标签也没问题。
$ git tag
列显已有的标签
$ git tag -l 'v1.4.2.*'
用特定的搜索模式列出符合条件的标签
创建轻量标签 git tag <name>用于新建一个标签,默认为HEAD,也可以指定一个commit id
例如指定commit id,为后期加注标签的:git tag v0.9 6d9ea3
创建一个含附注类型的标签 git tag -a v1.4 -m 'my version 1.4' (用 -a (译注:取 annotated 的首字母)指定标签名字即可,-m 选项则指定了对应的标签说明,Git 会将此说明一同保存在标签对象中)
用PGP签名标签 //git tag -s <tagname> -m "blablabla..."
查看相应标签的版本信息 git show <tagname>
删除一个本地标签 //git tag -d <tagname>
git push origin [tagname]
分享标签到远端仓库
git push origin --tags
如果要一次推送所有本地新增的标签
git push origin :refs/tags/<tagname>
删除一个远程标签,与删除远程仓库类似
可以简些为git push origin :<tagname> //只要命名不冲突,应该也是可以识别的
查看配置
- --local 默认级别: 只影响本仓库
.git/config
- --global 中级别: 影响到所有当前用户的git仓库
~/gitconfig
- --local 高级别: 影响全系统的git仓库
/etc/gitconfig
git config --list
查看当前所有配置信息
直接查阅某个环境变量的设定,只要把特定的名字跟在后面即可, 例如git config user.name
设置http代理
# 开启
$ git config --global http.proxy http://10.5.3.9:80
$ git config --global https.proxy https://10.5.3.9:80
# 取消
$ git config --global --unset http.proxy
$ git config --global --unset https.proxy
github新建空仓库后的操作
1.要关联一个远程库,使用命令
$ git remote add origin git@server-name:path/repo-name.git
2.关联后,使用命令$ git push -u origin master
[或者$ git push --set-upstream origin master
]第一次推送master分支的所有内容;
(加上了-u参数,Git不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令。
3.此后,每次本地提交后,只要有必要,就可以使用命令git push origin master推送最新修改;
…or create a new repository on the command line
echo "# MyProject" >> README.md
git init
git add README.md
git commit -m "first commit"
git remote add origin git@github.com:someone/MyProject.git
git push -u origin master
…or push an existing repository from the command line
git remote add origin git@github.com:someone/MyProject.git
push -u origin master