文章目录
Git
安装Git
- git --version
- yum install -y git
用户信息
- git config --global user.name “XXX”
- git config --global user.email XX@.XXX
检查配置信息
git config --list
在现有目录中初始化仓库
- git init
- git add *.c
- git add LICENSE
- git commit -m “XXXX”
克隆现有的仓库
git clone url 别名
检查当前文件状态
现在我们手上有了一个真实项目的 Git 仓库,并从这个仓库中取出了所有文件的工作拷贝。接下来,对这些文件做些修改,在完成了一个阶段的目标之后,提交本次更新到仓库。
请记住,你工作目录下的每一个文件都不外乎这两种状态:已跟踪
或 未跟踪
。 已跟踪的文件是指那些被纳入了版本控制的文件,在上一次快照中有它们的记录,在工作一段时间后,它们的状态可能处于未修改,已修改或已放入暂存区。 工作目录中除已跟踪文件以外的所有其它文件都属于未跟踪文件,它们既不存在于上次快照的记录中,也没有放入暂存区。 初次克隆某个仓库的时候,工作目录中的所有文件都属于已跟踪文件,并处于未修改状态。
编辑过某些文件之后,由于自上次提交后你对它们做了修改,Git 将它们标记为已修改文件。我们逐步将这些修改过的文件放入暂存区,然后提交所有暂存了的修改,如此反复。所以使用 Git 时文件的生命周期如下:
git status
-
On branch master
nothing to commit, working directory clean 工作目录相当干净
-
On branch master
(use "git add <file>..." to include in what will be committed) README nothing added to commit but untracked files present (use "git add" to track) 在状态报告中可以看到新建的 README 文件出现在 Untracked files 下面。 然后git add README 就开启跟踪一个文件```
-
On branch master
(use "git reset HEAD <file>..." to unstage) new file: README 文件已被跟踪```
-
On branch master
(use "git reset HEAD <file>..." to unstage)
new file: README
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: contribution.md 修改的文件需要再次提交
状态简览
git status -s
M README
MM Rakefile
A lib/git.rb 新添加到暂存区中的文件前面有 A 标记
M lib/simplegit.rb 修改过的文件前面有 M 标记
?? LICENSE.txt 新添加的未跟踪文件前面有 ?? 标记
你可能注意到了 M 有两个可以出现的位置,出现在右边的 M 表示该文件被修改了但是还没放入暂存区,出现在靠左边的 M 表示该文件被修改了并放入了暂存区。 例如,上面的状态报告显示:
README 文件在工作区被修改了但是还没有将修改后的文件放入暂存区
Rakefile 在工作区被修改并提交到暂存区后又在工作区中被修改了,所以在暂存区工 作区都有该文件被修改了的记录
lib/simplegit.rb 文件被修改了并将修改后的文件放入了暂存区
忽略文件
cat .gitignore
文件 .gitignore 的格式规范如下:
- 所有空行或者以 # 开头的行都会被 Git 忽略。
- 可以使用标准的 glob 模式匹配。
- 匹配模式可以以( / )开头防止递归。
- 匹配模式可以以( / )结尾指定目录。
- 要忽略指定模式以外的文件或目录,可以在模式前加上惊叹号( ! )取反。
Java.gitignore
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
提交更新
git commit
-m 提交信息与命令放在同一行
-a 自动把所有跟踪过的文件暂存起来一起提交,从而跳过git add步骤
查看提交历史
git log
-p 显示每次提交的内容差异
-2 显示最近2次提交
-stat 每次提交的简略统计信息
–pretty=format:"%h - %an,%ar :%s" 定制显示的记录格式
示例:
查看2008年10月期间,cyj提交的但未合并的测试文件
git log --pretty="%h - %s" --author=cyj–since=“2008-10-01”
–before=“2008-11-01” --no-merges – t/
撤销操作
- 有时候我们提交完了才发现漏掉了几个文件没有添加,或者提交信息写错了。 此时,可以运行带有 --amend 选项的提交命令尝试重新提交:
git commit --amend
- 取消暂存文件
git reset HEAD 文件名
远程仓库的使用
查看远程仓库
git remote
git remote -v
添加远程仓库
git remote add
从远程仓库中抓取与拉取
git fetch [remote-name] 访问远程仓库,从中拉取所有你还没有的数据。
推送到远程仓库
git push origin[remote-name] master[branch-name]
查看远程仓库
git remote show origin
远程仓库的移除与重命名
git remote rename pb[name] paul[rename]
git remote 查看
git remote rm paul 移除远程仓库
打标签
列出标签
git tag
创建标签
git tag -a v1.4 -m “XXX” 创建一个附注标签
git show v1.4 可以看到标签信息与对应的提交信息
后期打标签
git log --pretty=oneline 一行打印出提交信息
git tag -a v1.2 校验和(或部分校验和)9fceb02
共享标签
git push origin v1.5[tagname]
检出标签
在 Git 中你并不能真的检出一个标签,因为它们并不能像分支一样来回移动。 如果你想要工作目录与仓库中特定的标签版本完全一样,可以使用 git checkout -b [branchname][tagname] 在特定的标签上创建一个新分支:
$ git checkout -b version2 v2.0.0
Switched to a new branch 'version2'
当然,如果在这之后又进行了一次提交, version2 分支会因为改动向前移动了,那么
version2 分支就会和 v2.0.0 标签稍微有些不同,这时就应该当心了。
Git别名
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.ci commit git commit=git ci
git config --global alias.st status
git config --global alias.unstage ‘reset HEAD --’
git config --global alias.last ‘log -1 HEAD’
Git分支
分支简介
当使用 git commit 进行提交操作时,Git 会先计算每一个子目录的校验和,然后在 Git 仓库中这些校验和保存为树对象。 随后,Git 便会创建一个提交对象,它除了包含上面提到的那些信息外,还包含指向这个树对象(项目根目录)的指针。如此一来,Git 就可以在需要的时候重现此次保存的快照。
现在,Git 仓库中有五个对象:三个 blob 对象(保存着文件快照)、一个树对象(记录着目录结构和 blob 对象索引)以及一个提交对象(包含着指向前述树对象的指针和所有提交信息)
Figure 1. 首次提交对象及其树结构
做些修改后再次提交,那么这次产生的提交对象会包含一个指向上次提交对象(父对象)的指针。
Figure 2. 提交对象及其父对象
Git 的分支,其实本质上仅仅是指向提交对象的可变指针。 Git 的默认分支名字是 master 。在多次提交操作之后,你其实已经有一个指向最后那个提交对象的 master 分支。 它会在每次的提交操作中自动向前移动。
Figure 3. 分支及其提交历史
分支创建
git branch testing 创建一个testing分支
git log --oneline --decorate 查看各个分支当前所指的对象
Figure 4. 两个指向相同提交历史的分支 + Figure 5. HEAD 指向当前所在的分支
分支切换
git checkout testing 将
HEAD
指针指向testing分支
分支切换会改变你工作目录中的文件
在切换分支时,一定要注意你工作目录里的文件会被改变。 如果是切换到一个较旧的分支,你的工作目录会恢复到该分支最后一次提交时的样子。 如果 Git 不能干净利落地完成这个任务,它将禁止切换分支
新建分支
git checkout -b XXX 新建一个分支并同时切换到那个分支上
合并分支
git merge XXX 合并分支【合并操作没有需要解决的分歧叫做 “快进(fast-forward)】
删除分支
git branch -d XXX 删除分支
分支的合并
git checkout master 合并其他分支到master分支,先切换到master分支
git merge XXX 开始合并
遇到冲突时的分支合并
有时候合并操作不会如此顺利。 如果你在两个不同的分支中,对同一个文件的同一个部分进行了不同的修改,Git 就没法干净的合并它们。 如果你对 #53 问题的修改和有关 hotfix 的修改都涉及到同一个文件的同一处,在合并它们的时候就会产生合并冲突:
$ git merge iss53
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result
此时 Git 做了合并,但是没有自动地创建一个新的合并提交。 Git 会暂停下来,等待你去解决合并产生的冲突。 你可以在合并冲突后的任意时刻使用 git status 命令来查看那些因包含合并冲突而处于未合并(unmerged)状态的文件:
$ git status
On branch master
You have unmerged paths.
(fix conflicts and run "git commit")
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: index.html
no changes added to commit (use "git add" and/or "git commit -a")
分支管理
git branch 获取当前所有分支列表
git branch --no-merged 查看所有包含未合并工作的分支
远程分支
git fetch origin 同步工作,抓取origin本地中没有的数据,并且更新本地数据库
推送
git push origin master
拉取
git pull 在大多数情况下它的含义是一个 git fetch 紧接着一个 git merge 命令。
删除远程分支
git push origin --delete 分支名 基本上这个命令做的只是从服务器上移除这个指针。 Git 服务器通常会保留数据一段时间直到垃圾回收运行,所以如果不小心删除掉了,通常是很容易恢复的。
变基
git checkout experiment
git rebase master
它的原理是首先找到这两个分支(即当前分支 experiment 、变基操作的目标基底分支master )的最近共同祖先 C2 ,然后对比当前分支相对于该祖先的历次提交,提取相应的修改并存为临时文件,然后将当前分支指向目标基底 C3 , 最后以此将之前另存为临时文件的修改依序应用。
-
变基操作的实质是丢弃一些现有的提交,然后相应地新建一些内容一样但实际上不同的提交。
-
变基比较复杂,根据具体情况来进行学习会有更好的效果。
-
现在,让我们回到之前的问题上来,到底合并还是变基好?希望你能明白,并没有一个简单的答案。 Git 是一个非常强大的工具,它允许你对提交历史做许多事情,但每个团队、每个项目对此的需求并不相同。 既然你已经分别学习了两者的用法,相信你能够根据实际情况作出明智的选择。
-
总的原则是,只对尚未推送或分享给别人的本地修改执行变基操作清理历史,从不对已推送至别处的提交执行变基操作,这样,你才能享受到两种方式带来的便利。
生成密钥
cd ~/.ssh 查看公钥位置
ssh -keygen 生成密钥
GitHub学习
派生(Fork)项目
- 通过这种方式,项目的管理者不再需要忙着把用户添加到贡献者列表并给予他们推送权限。人们可以派生这个项目,将修改推送到派生出的项目副本中,并通过创建
合并请求(Pull Request)
来让他们的改动进入源版本库。创建了合并请求后,就会开启一个可供审查代码的板块,项目的拥有者和贡献者可以在此讨论相关修改,直到项目拥有者对其感到满意,并且认为这些修改可以被合并到版本库。
GitHub流程
- 从master分支中创建一个新分支
- 提交一些修改来改进项目
- 将这个分支推动到GitHub上
- 创建一个合并请求
- 讨论,根据实际情况继续修改
- 项目的拥有者合并或关闭你的合并请求
Git命令
设置与配置
git config
: 显示git的一系列的配置
git help
: 显示任何命令的Git自带文档
获取与创建项目
git init
: 可以将一个目录变成一个Git仓库
git clone
: 实际上是一个封装了其他几个命令的命令
快照基础
git add
: 将内容从工作目录添加到暂存区,以备下次提交
git status
: 展示工作区及暂存区域中不同状态的文件
git diff
: 查看任意两棵树的差异;查看你工作环境与你的暂存区的差异;你暂存区域与最后提交之间的差异;两个提交记录的差异
git difftool
: 简单地启动一个外部工具来展示两棵树之间的差异
git commit
: 将所有通过git add暂存的文件内容在数据库中创建一个持久的快照,然后将当前分支上的分支指针移到其之上
git reset
: 主要用来根据你传递给动作的参数来执行撤销操作
git rm
: Git用来从工作区,或者暂存区移除文件的命令
git mv
: 用于移到一个文件并且在新文件上执行git add命令及在来文件上执行git rm命令
git clean
: 用来从工作区中移除不想要的文件的命令
分支与合并
git branch
: 列出你所有的分支,创建新分支,删除分支及重命名分支
git checkout
: 用来切换分支或者检出内容到工作目录
git merge
: 合并一个或者多个分支到你已经检出的分支中,然后将当前分支指针移动到合并结果上
git mergetool
: 启动一个外部的合并帮助工具
git log
: 展示一个项目的可达历史记录,从最近的提交快照起
git stash
: 临时地保存一些还没有提交的工作,在分支上不需要提交未完成工作就可以清理工作目录
git tag
: 为代码历史记录中的某一个点指定一个永久的书签
项目分享与更新
git fetch
: 将远程仓库中有但在当前仓库中没有的所有信息拉取下来然后存储在你的本地数据库中
git pull
: git fetch+git merge的组合体
git push
: 与另一个仓库通信,计算你本地数据库与远程仓库的差异,然后将差异推送到另一个仓库中
git remote
: 允许将一个长URL保存成一个简写的句柄 git remote add
git archive
: 创建一个指定快照的归档文件
git submodule
: 用来管理一个仓库的其他外部仓库
检查与比较
git show
: 以一种简单的人类可读的方式来显示一个Git对象
git shortlog
: 归纳git log
的输出的命令
git describe
: 接受任何可以解析成一个提交的东西,然后生成一个人类可读的字符串且不可变
调试
git bisect
: 它通过自动进行一个二分查找来找到哪一个特定的提交是导致 bug 或者问题的第一个提交
git blame
: 标注任何文件的行,指出文件的每一行的最后的变更的提交及谁是那一个提交的作者
git grep
: 帮助在源代码中,甚至是你项目的老版本中的任意文件中查找任何字符串或者正则表达式
补丁
git cherry-pick
: 获得在单个提交中引入的变更,然后尝试将作为一个新的提交引入到你当前分支上
git rebase
: 一个自动化的 cherry-pick 命令。 它计算出一系列的提交,然后再以它们在其他地方以同样的顺序一个一个的 cherry-picks 出它们。即所谓的变基操作
git revert
: 本质上就是一个逆向的 git cherry-pick 操作。 它将你提交中的变更的以完全相反的方式的应用到一个新创建的提交中,本质上就是撤销或者倒转
邮件
git apply
: 应用一个通过 git diff 或者甚至使用 GNU diff 命令创建的补丁
git am
: 应用来自邮箱的补丁。特别是那些被 mbox 格式化过的
git format-patch
: 以 mbox 的格式来生成一系列的补丁以便你可以发送到一个邮件列表中
git imap-send
: 将一个由 git format-patch 生成的邮箱上传至 IMAP 草稿文件夹
git send-eamil
: 通过邮件发送那些使用 git format-patch 生成的补丁
git request-pull
: 简单的用来生成一个可通过邮件发送给某个人的示例信息体
外部系统
git svn
: 可以使 Git 作为一个客户端来与 Subversion 版本控制系统通信
git fast-import
: 对于其他版本控制系统或者从其他任何的格式导入,你可以使用 git fast-import 快速地将其他格式映射到 Git 可以轻松记录的格式
管理
git gc
: 在你的仓库中执行garbage collection
,删除数据库中不需要的文件和将其他文件打包成一种更有效的格式
git fsck
: 检查内部数据库的问题或者不一致性
git reflog
: 分析你所有分支的头指针的日志来查找出你在重写历史上可能丢失的提交
git filter-branch
: 根据某些规则来重写大量的提交记录,例如从任何地方删除文件,或者通过过滤一个仓库中的一个单独的子目录以提取出一个项目
底层命令
ls-remote
: 查看服务端的原始引用
ls-files
: 查看暂存区的更原始的样子
rev-parse
: 可以接受任意字符串,并将其转成一个对象的 SHA-1 值
参考书籍
ProGit2
下载链接 提取码:w48j