Git 保存的不是文件的变化或者差异,而是一系列不同时刻的 快照!
在Git中文件在本地有三个阶段:没有被track的,放在暂存中的,提交的:当一个文件没有使用git add时,它就是untrack的,当使用git add之后,文件被track且被放入暂存。
一:配置
当安装完Git工具后,最先做的工作应该就是进行配置工作了。
1.1查看配置
git config --list --show-origin
git config --list
1.2配置全局用户信息
安装完Git之后的第一步操作就是配置用户信息,因为每一次的Git提交都会使用这些信息,它们会写入到你的每一次提交中,不可更改:
git config --global user.name "pjsong"
git config --global user.email 1832****65@163.com
1.3配置默认的文本编辑器:
git config --global core.editor gedit
1.4编辑配置:
git config --global --edit
1.5删除某项全局配置:
git config --global --unset core.editor/user.name 等等
二:获取帮助文档
git help config // 简短的help: git add -h
三:clone仓库
3.1描述:
如果你想获得一份已经存在了的 Git 仓库的拷贝,比如说,你想为某个开源项目贡献自己的一份力,这时就要用到 git clone 命令。 如果你对其它的 VCS 系统(比如说 Subversion)很熟悉,请留心一下你所使用的命令是"clone"而不是"checkout"。 这是 Git 区别于其它版本控制系统的一个重要特性,Git 克隆的是该 Git 仓库服务器上的几乎所有数据,而不是仅仅复制完成你的工作所需要文件。 当你执行 git clone 命令的时候,默认配置下远程 Git 仓库中的每一个文件的每一个版本都将被拉取下来。 事实上,如果你的服务器的磁盘坏掉了,你通常可以使用任何一个克隆下来的用户端来重建服务器上的仓库 (虽然可能会丢失某些服务器端的钩子(hook)设置,但是所有版本的数据仍在。
3.2命令:
git clone https://github.com/****/t2
3.3解释:
这会在当前目录下创建一个名为 “t2” 的目录,并在这个目录下初始化一个 .git 文件夹, 从远程仓库拉取下所有数据放入 .git 文件夹,然后从中读取最新版本的文件的拷贝。 如果你进入到这个新建的 t2 文件夹,你会发现所有的项目文件已经在里面了,准备就绪等待后续的开发和使用。
一 else:
如果你想在克隆远程仓库的时候,自定义本地仓库的名字,你可以通过额外的参数指定新的目录名:
git clone https://github.com/****/t2 mylocalt2
Git 支持多种数据传输协议。 上面的例子使用的是 https:// 协议,不过你也可以使用 git:// 协议或者使用 SSH 传输协议,比如 user@server:path/to/repo.git 。
四:命令
git add
git add命令会将文件变为track跟踪状态,一个文件变为跟踪状态之后才可以commit,一个track状态的文件在多次修改后,可能同时存在暂存区和非暂存区,因为之前的在暂存区的版本是通过git add时的那个版本,在修改后,工作目录中的版本需要使用git add将最新的版本重新暂存起来。
git status -s
可以以更紧凑的形式展现。新添加的未跟踪文件前面有 ?? 标记,新添加到暂存区中的文件前面有 A 标记,修改过的文件前面有 M 标记。
.gitignore
忽略文件:.gitignore文件存放在项目根目录下,每个目录都可以有一个,作用域为当前目录。
文件 .gitignore 的格式规范如下:
所有空行或者以 # 开头的行都会被 Git 忽略。
可以使用标准的 glob 模式匹配,它会递归地应用在整个工作区中。
匹配模式可以以(/)开头防止递归。
匹配模式可以以(/)结尾指定目录。
要忽略指定模式以外的文件或目录,可以在模式前加上叹号(!)取反。
rm移除文件
要从 Git 中移除某个文件,就必须要从已跟踪文件清单中移除(确切地说,是从暂存区域移除),然后提交。 可以用 git rm 命令完成此项工作,并连带从工作目录中删除指定的文件,这样以后就不会出现在未跟踪文件清单中了。
如果只是简单地从工作目录中手工删除文件,运行 git status 时就会在 “Changes not staged for commit” 部分(也就是 未暂存清单),需要再运行git rm 记录此次移除文件的操作。下一次提交时,该文件就不再纳入版本管理了。 如果要删除之前修改过或已经放到暂存区的文件,则必须使用强制删除选项 -f(译注:即 force 的首字母)。 这是一种安全特性,用于防止误删尚未添加到快照的数据,这样的数据不能被 Git 恢复。
另外一种情况是,我们想把文件从 Git 仓库中删除(亦即从暂存区域移除),但仍然希望保留在当前工作目录中。 换句话说,你想让文件保留在磁盘,但是并不想让 Git 继续跟踪。 当你忘记添加 .gitignore 文件,不小心把一个很大的日志文件或一堆 .a 这样的编译生成文件添加到暂存区时,这一做法尤其有用。 为达到这一目的,使用 --cached 选项:
git rm --cached 待删除文件 //该行语句可以删除git上的保留工作区的
git restore --staged 文件 //改行测试时发现不能删除git上的
git rm 命令后面可以列出文件或者目录的名字,也可以使用 glob 模式。比如:
git rm log/\*.log
注意到星号 * 之前的反斜杠 \, 因为 Git 有它自己的文件模式扩展匹配方式,所以我们不用 shell 来帮忙展开。 此命令删除 log/ 目录下扩展名为 .log 的所有文件。 类似的比如:
git rm \*~ //该命令会删除所有名字以 ~ 结尾的文件。
mv重命名文件
要在 Git 中对文件改名,可以这么做:
git mv file_from file_to
它会恰如预期般正常工作。 实际上,即便此时查看状态信息,也会明白无误地看到关于重命名操作的说明:
$ git mv README.md README
$ git status
On branch master
Your branch is up-to-date with ‘origin/master’.
Changes to be committed:
(use “git reset HEAD …” to unstage)
renamed: README.md -> README
其实,运行 git mv 就相当于运行了下面三条命令:
$ mv README.md README
$ git rm README.md
$ git add README
如此分开操作,Git 也会意识到这是一次重命名,所以不管何种方式结果都一样。 两者唯一的区别是,mv 是一条命令而非三条命令,直接用 git mv 方便得多。 不过有时候用其他工具批处理重命名的话,要记得在提交前删除旧的文件名,再添加新的文件名。
git log
不传入参数的默认情况下,git log会按时间先后顺序列出所有提交,最近的更新排在最上面。
按每次提交所引入的差异显示:-p或–patch
git log -p -2 //数字是控制显示条目,-2表示只显示最近两次提交。
查看每次提交的简略统计信息:
git log --stat
正如你所看到的,–stat 选项在每次提交的下面列出所有被修改过的文件、有多少文件被修改了以及被修改过的文件的哪些行被移除或是添加了。 在每次提交的最后还有一个总结。
另一个非常有用的选项是 --pretty。 这个选项可以使用不同于默认格式的方式展示提交历史。 这个选项有一些内建的子选项供你使用。 比如 oneline 会将每个提交放在一行显示,在浏览大量的提交时非常有用。 另外还有 short,full 和 fuller 选项,它们展示信息的格式基本一致,但是详尽程度不一。
最有意思的是 format ,可以定制记录的显示格式。 这样的输出对后期提取分析格外有用——因为你知道输出的格式不会随着 Git 的更新而发生改变:
$ git log --pretty=format:"%h - %an, %ar : %s"
ca82a6d - Scott Chacon, 6 years ago : changed the version number
085bb3b - Scott Chacon, 6 years ago : removed unnecessary test
a11bef0 - Scott Chacon, 6 years ago : first commit
查找添加或删除了某个字符串的提交:
git log -S asdf
git diff
git diff是查看工作目录中的文件和暂存区域快照之间的差异,也就是修改后还没有暂存起来的变化的内容。
查看已暂存的将要添加到下次提交里的内容:
git diff --staged
这条命令将比对已暂存的文件与最后一次提交的文件的差异
撤销操作amend
注意:撤销操作可能会导致之前的工作丢失!
假设1:commit提交信息写错了想更改提交信息,可以使用:
//该命令会将暂存区中的文件提交,如果自上次提交以后未做任何修改,仅改变提交信息,那么快照会保持不变,而仅仅修改提交信息。
git commit --amend
假设2:在一次提交过后,发现还有一个文件忘记了放入暂存(没有使用git add操作),可以使用下面的操作,避免因为一个文件生成一个提交版本:
git commit -m 'initial commit'
git add forgotten_file
git commit --amend
最终你会发现只有一次提交(效果就像第二次提交的更新会插进之前的版本上)。
撤销操作reset / restore
有这样一种情况,假如你修改了两个文件AB,但是你只想在这次提交中提交A文件,B文件留待下次提交。但是你不小心执行了git add *命令,暂存了AB两个文件,如何取消B文件呢?可以使用reset命令:
git reset HEAD B
撤销操作checkout
假如在工作区中修改了A文件,但是后面发现不需要修改了,如何抛弃当前工作区中A文件的修改恢复到上一次版本提交时的A文件呢?
git status 告诉我们可以这样:
git checkout -- A //目前最新版是使用git restore 文件
五:远程仓库
- git remote列出指定的每一个远程服务器的简写,git remote -v会显示所有需要读写远程仓库使用的git保存的简写与对应的URL。
- git clone命令会拉取并自动添加远程仓库。
手动添加:
添加一个新的远程Git仓库,并指定一个方便使用的简写。
git remote add <shortname> <url>
如:git remote add pb https://github.com..git
拉取fetch / pull:
指定简写的名称之后就可以使用fetch命令来拉取代码了:
git fetch pb
从远程仓库拉取的命令就是:git fetch remoteurl or shortname:
这个命令会访问远程仓库,从中拉取所有你还没有的数据。 执行完成后,你将会拥有那个远程仓库中所有分支的引用,可以随时合并或查看。
如果你使用 clone 命令克隆了一个仓库,命令会自动将其添加为远程仓库并默认以 “origin” 为简写。 所以,git fetch origin 会抓取克隆(或上一次抓取)后新推送的所有工作。 必须注意 git fetch 命令只会将数据下载到你的本地仓库——它并不会自动合并或修改你当前的工作。 当准备好时你必须手动将其合并入你的工作。
由于git fetch命令不会自动合并,git pull可以:git pull 命令来自动抓取后合并该远程分支到当前分支。 这或许是个更加简单舒服的工作流程。默认情况下,git clone 命令会自动设置本地 master 分支跟踪克隆的远程仓库的 master 分支(或其它名字的默认分支)。 运行 git pull 通常会从最初克隆的服务器上抓取数据并自动尝试合并到当前所在的分支
推送:
当你想分享你的项目时,必须将其推送到上游。
git push <remote> <branch>
当你想要将 master 分支推送到 origin 服务器时(再次说明,克隆时通常会自动帮你设置好那两个名字), 那么运行这个命令就可以将你所做的备份到服务器:
git push origin master
只有当你有所克隆服务器的写入权限,并且之前没有人推送过时,这条命令才能生效。 当你和其他人在同一时间克隆,他们先推送到上游然后你再推送到上游,你的推送就会毫无疑问地被拒绝。 你必须先抓取他们的工作并将其合并进你的工作后才能推送。
查看某个远程仓库:
git remote show <remote> //如:git remote show origin
修改某个远程仓库的简写名:
git remote rename <old name> <new name>
如果因为一些原因想要移除一个远程仓库——你已经从服务器上搬走了或不再想使用某一个特定的镜像了, 又或者某一个贡献者不再贡献了——可以使用:
git remote remove 或 git remote remove abc
六:分支
介绍:
Git在进行提交操作时,Git会保存一个提交对象。该提交对象会包含一个只想暂存内容快照的指针,作者的姓名邮箱,提交时的输入信息
以及指向它的父对象的指针。首次提交产生的提交对象没有父对象,普通提交操作产生的提交对象有一个父对象,而由多个分支合并产生的
提交对象有多个父对象。假设现在有一个工作目录,里面包含了三个将要被暂存和提交的文件,暂存操作会为每一个文件计算校验和,然后会把当前版本的文件快照保存到Git仓库中(Git使用blob对象来保存他们),最终的校验和加入到暂存区域等待提交。
当使用 git commit 进行提交操作时,Git 会先计算每一个子目录(本例中只有项目根目录)的校验和, 然后在 Git 仓库中这些校验和保存为树对象。随后,Git 便会创建一个提交对象, 它除了包含上面提到的那些信息外,还包含指向这个树对象(项目根目录)的指针。 如此一来,Git 就可以在需要的时候重现此次保存的快照。
注意:HEAD永远指向当前所在的分支
查看各个分支所指的对象,提供这一功能的参数是:–decorate:
git log --oneline --decorate
创建分支:
git branch iss53
切换分支:
git checkout iss53
创建+切换:
git checkout -b iss53
创建分支并切换之后可以在那个分支进行那个分支的操作,不影响主分支。
合并分支
- 先切换到master主分支,然后进行分支合并:git merge <分支名称>。当合并完一个分支后,该分支应该删除:
git branch -d <分支名称>
- 当AB两个分支都从master分出之后,如果A合并后,B分支并不包含A分支的内容,这时可以将master分支合并到B分支,但是不要删除master,等完成之后再合并到master。或者直接等B分支完成再合并到master。合并后在删除B分支。
- 在AB两个分支都对同一个文件中的内容做了修改之后,合并将产生冲突,通过git status命令展示的Unmerged paths下面会提示冲突未合并的文件,需要手动去解决这些冲突。当冲突解决了对每个冲突文件使用git add命令来标记为冲突已解决。(一旦暂存这些原本有冲突的文件,Git就会将它们标记为冲突已解决。)解决冲突后使用commit提交。
分支管理
查看哪些分支已经被合并,哪些没有被合并:
git branch --merged //在这个列表中前面没有带*号的分支都可以删除git branch -d <名称>,表示已经合并。
git branch --no-merged //在这个列表中的分支表示没有被合并,正在开发。如果使用git branch -d <分支名称>删除将会失败,如果
//想要删除正在开发未合并的分支可以使用:git branch -D <名称>。
查看尚未合并到master分支的有哪些:
git branch --no-merged master
推送分支:
git push origin <分支名称> //可以是master dev ..
将本地分支推送到远程命名不相同的分支:
git push origin localBranchName:originBranchName
抓取远程新分支到本地:
这种情况本地不会自动生成一份可编辑的拷贝副本。换一句话说这种情况不会有一个新的分支,只有一个不可以修改的指针。解决这种情况
可以合并到当前所在的分支git merge origin/<远程分支名称>;或者放在本地跟远程分支相同的名称的分支上:
//这会给我们一个用于工作的本地分支,并且起点位于origin/branchname
git checkout -b branchname origin/branchname
删除远程分支:
git push origin --delete branchname