Git笔记

Git 教程 | 菜鸟教程 (runoob.com)

Git - Book (git-scm.com)

gitlab操作手册.pdf

本地操作

分为三个区:工作区,暂存区(stage/index),本地仓库(Repository)

一个文件在提交前共有四种状态:

四种状态

Git - 记录每次更新到仓库 (git-scm.com)

在上图中,通过add命令可将一个新的文件放入staged中(暂存区),之后通过commit提交至仓库(并变为unmodified)

1
2
git add 1.txt	//可直接git add .以添加所有文件(追踪)
git commit -m 'add new file 1.txt' //注释

如果在本地修改该文件,则将变为modified,此后要先通过add将之放入暂存区,才能commit

1
2
git add 1.txt
git commit -m 'modify 1.txt'

更便捷的方式直接提交:

1
git commit -am 'modify 1.txt'

可以省下add,但要保证该文件已被追踪(即,新文件不能用这种方式直接提交)


查看状态:git status

参数:

1
-s: 简要说明状态(用一个字母代指一个文件的状态)

比如??是未追踪,A是新添追踪,M是修改,AM是它添加到缓存之后又有改动


比较差异:git diff

  • 尚未缓存的改动(已写入暂存区和已经被修改但尚未写入暂存区文件):git diff
  • 查看已缓存的改动(缓存区和已提交): git diff --cached
  • 查看已缓存的与未缓存的所有改动(上面两者):git diff HEAD
  • 显示摘要而非整个 diff:git diff --stat

可接文件名以查看某个具体文件:git diff -- 文件名

Git基础-git diff 比较文件的差异_NorthCastle的博客-CSDN博客

git diff是工作区文件相比于缓存区

git diff HEAD是工作区文件相比于HEAD处提交

git diff --cached是缓存区文件相较于HEAD处提交

git diff 具体某版本是工作区相较于该次提交

git diff --cached 具体版本号是缓存区相较于该次提交


回退版本:git reset

参考:九、git reset详解_罗公子Coding的博客-CSDN博客

  • git reset:仅将index区回退至上次提交后(--mixed为默认参数)
  • git reset HEAD^:仅将index和repository回退至上次提交后
  • git reset --soft HEAD^:仅回退repository,适用于commit时有误想取消该commit
  • git reset --hard HEAD^:三个区域均回退(慎用!!!)

可以用多个^表示多个版本,也可以在~后跟数字(HEAD表示当前版本,git reset HEADgit reset效果一致)

可以通过版本号reset到未来版本(需通过git reflog获取之后的版本号)

git checkout -- filename可以将工作区的文件回退到上次git add 或者git commit时的状态


删除文件:git rm

比起直接rm,这样做的好处是删除后不需要再commit了

以下实例从暂存区和工作区中删除 runoob.txt 文件:

1
git rm runoob.txt 

如果删除之前修改过并且已经放到暂存区域的话,则必须要用强制删除选项 -f

如果想把文件从暂存区域移除,但仍然希望保留在当前工作目录中,换句话说,仅是从跟踪清单中删除,使用 --cached 选项


移动文件:git mv

好处是不需要add新建的文件。要删除要移动,在前面加git会方便很多


查看提交历史:git log

参数:

1
2
3
4
--oneline: 一条记录用一行显示
--graph: 用色彩表示分支关系
--reverse: 反过来显示(本来是早的在上,现在反过来)
--since, --before, --until, --after

git blame以列表形式显示修改记录


远程操作:关联Github

密钥

设置密钥参考:Github 简明教程 | 菜鸟教程 (runoob.com)

远程地址

成功收到欢迎界面后,添加远程地址:

1
git remote add origin git@github.com:yourName/yourRepo.git

上面命令中origin是对该地址的alias,可以用其他的,不过默认是这个(比如clone下来的本地仓库的remote就会被设置为origin)

Git 里面的 origin 到底代表啥意思? - 知乎 (zhihu.com)

remote其余命令:

显示所有远程仓库:git remote -v

显示某个远程仓库的信息:git remote show [remote]

1
2
git remote rm name  # 删除远程仓库
git remote rename old_name new_name # 修改仓库名

获取代码

从远程获取代码库:git fetch

1
git fetch origin		//有多种写法

fetch后面的仓库名,分支名写法详见git命令之git fetch的用法_苦咖啡-bit的博客-CSDN博客

会将获取的版本记录到FETCH_HEAD

合并代码

1
git merge [alias]/[branch]

在fetch后可以直接执行git merge,此时默认将FETCH_HEAD合并至本地的当前分支

git命令之git fetch的用法_苦咖啡-bit的博客-CSDN博客

合并代码的方法:

第一种,传统标准的做法:
git fetch origin 目标分支名 // fetch到远程仓库目标分支的最新commit记录到 ./git/FETCH_HEAD文件中
git checkout 要被合并的分支名 // 切换到要合并的分支
git merge FETCH_HEAD // 将目标分支最新的commit记录合并到当前分支

举例说明:将远程origin仓库的xx分支合并到本地的yy分支。
git fetch origin xx
git checkout yy
git merge FETCH_HEAD
完成。

如果关联了xx和yy(即git push -u),则没必要在merge后加那个

另一种方式是pull,但不推荐:

1
git pull <远程主机名> <远程分支名>:<本地分支名>

如果远程分支是与当前分支合并,则冒号后面的部分可以省略。

第二种,直接使用pull命令,将远程仓库的目标分支合并到本地的分支:
git pull <remote_repository_name> <branch_name>

举例说明:将远程origin仓库的xx分支合并到本地的yy分支:
git checkout yy
git pull origin xx
完成。

git pull 后不加参数的时候,跟git push 一样,默认就是git pull origin 当前分支名,当然远程仓库没有跟本地当前分支名一样的分支的话,肯定会报错。
本地master分支执行git pull的时候,其实就是git pull origin master。

这两种方法的具体细节:Git fetch、pull以及merge之间的区别_pull和merge的区别_飞!!!的博客-CSDN博客

冲突解决:

©当在 git merge 过程中遇到冲突时,Git 会停止合并,并将冲突的文件标记为未解决的冲突状态。你需要手动解决这些冲突,然后继续合并的过程。

以下是解决合并冲突的一般步骤:

  1. 停止合并: 如果合并中途遇到冲突,Git 会告诉你合并已经暂停,需要手动解决冲突。你可以使用以下命令查看当前合并的状态:

    1
    git status

    这将显示有冲突的文件以及冲突的状态。

  2. 手动解决冲突: 打开包含冲突的文件,你将看到 Git 在冲突的地方插入了标记,通常是 <<<<<<<, =======, 和 >>>>>>>。这个部分是 Git 找到的两个不同版本的冲突的地方。

    你需要手动编辑文件,删除标记并选择保留你需要的代码。解决冲突后,将文件保存。

  3. 标记文件为已解决: 在解决冲突后,使用以下命令标记文件为已解决:

    1
    git add path/to/conflicted/file

    替换 path/to/conflicted/file 为实际冲突文件的路径。

  4. 继续合并: 一旦你标记了所有冲突文件为已解决,使用以下命令继续合并:

    1
    git merge --continue

    或者:

    1
    git commit

    这将完成合并过程并创建一个新的合并提交。

  5. 中止合并: 如果在解决冲突的过程中你决定放弃合并,可以使用以下命令中止合并:

    1
    git merge --abort

    或者,如果使用 git commit 继续合并时出现问题,你也可以使用:

    1
    git reset --merge

这些步骤可以帮助你在 git merge 过程中解决冲突并完成合并。确保在执行合并操作之前备份重要的更改,以免出现问题时能够恢复到先前的状态。


Github 简明教程 | 菜鸟教程 (runoob.com)

搞了半天终于明白上面这些fetch, pull, merge是获取最新的仓库,仅在远程版本领先时会生效。如果本地版本与其一致或者更新,则该命令无效。(不知道这里在写啥?可能当时是刚fetch过又fetch,此时远程还无其他更改,因此无效?)

这种情况下,如果想要回退本地版本至远程版本,可以使用
git checkout -- <filename>
此命令会使用 HEAD 中的最新内容替换掉你的工作目录中的文件。已添加到暂存区的改动以及新文件都不会受到影响。

假如你想丢弃你在本地的所有改动与提交,可以到服务器上获取最新的版本历史,并将你本地主分支指向它:
git fetch origin
git reset --hard origin/master

fetch获得最新的版本,origin/master是FETCH_HEAD(reset必须跟HEAD名而不是仓库名)

Git 远程仓库(Github) | 菜鸟教程 (runoob.com)

  • 执行 git fetch origin master 时,它的意思是从名为 origin 的远程上拉取名为 master 的分支到本地分支 origin/master 中。既然是拉取代码,当然需要同时指定远程名与分支名,所以分开写。
  • 执行 git merge origin/master 时,它的意思是合并名为 origin/master 的分支到当前所在分支。既然是分支的合并,当然就与远程名没有直接的关系,所以没有出现远程名。需要指定的是被合并的分支。
  • 执行 git push origin master 时,它的意思是推送本地的 master 分支到远程 origin,涉及到远程以及分支,当然也得分开写了。
  • 还可以一次性拉取多个分支的代码:git fetch origin master stable oldstable
  • 也还可以一次性合并多个分支的代码:git merge origin/master hotfix-2275 hotfix-2276 hotfix-2290

在合并改动之前,你可以使用如下命令预览差异:
git diff <source_branch> <target_branch>

如:git diff master origin/master

HEAD代指当前分支,FETCH_HEAD代指远程分支,因此也可以git diff HEAD FETCH_HEAD,只是记得要先fetch到最新版本

另一个命令是git rebase,其与git merge的区别:Git:Rebase和Merge之间的区别,看完这篇文章你就懂了!_IT技术分享社区的博客-CSDN博客


推送代码

git push 命令用于从将本地的分支版本上传到远程并合并

1
git push <远程主机名> <本地分支名>:<远程分支名>

如果本地分支名与远程分支名相同,则可以省略冒号:

1
git push <远程主机名> <本地分支名>

如果本地版本与远程版本有差异,但又要强制推送可以使用 --force 参数:

1
git push --force origin master

删除主机的分支可以使用 --delete 参数,以下命令表示删除 origin 主机的 master 分支:

1
git push origin --delete master

另外使用-u可以关联本地分支和远程分支

© git push -u是将本地分支的更新推送到远程仓库,并将本地分支与远程分支关联的命令。其中,-u选项表示将本地分支与远程分支进行关联,这样在以后的推送和拉取操作中就可以省略分支名和远程仓库名,直接使用git pushgit pull命令即可。

例如,如果要将本地分支main的更新推送到远程仓库originmain分支,并与远程分支进行关联,可以使用以下命令:

1
git push -u origin main

这样,在以后的推送和拉取操作中,就可以直接使用以下命令:

1
2
git push
git pull

而不需要再指定分支名和远程仓库名。

如果本地版本低于远程版本,有如下方法:

  1. push前先将远程repository修改pull下来,然后再推送:
1
2
3
git pull origin master 
... //做修改
git push -u origin master
  1. 使用强制push的方法:
1
git push -u origin master -f 

这样会使远程修改丢失,一般是不可取的,尤其是多人协作开发的时候。

  1. 若不想merge远程和本地修改,可以先创建新的分支:
1
2
git branch [name] 
git push -u origin [name]

git push报错:Updates were rejected because the tip of your current branch is behind - 知乎 (zhihu.com)


分支

创建分支命令:

1
git branch (branchname)

切换分支命令:

1
git checkout (branchname)

也可以使用 git checkout -b (branchname) 命令来创建新分支并立即切换到该分支下,从而在该分支中操作

切换分支会影响工作区的文件,比如一个分支有1.txt,另一个没有,于是切换时会发现工作目录会变化。

列出分支命令:

1
git branch

删除分支命令:

1
git branch -d (branchname)

使用以下命令将任何分支合并到当前分支中去:

1
git merge	//不跟分支名则默认跟FETCH_HEAD,其他则要加上想要合并的分支名

当要合并的两个文件发生冲突时(比如master中1.txt和new中1.txt内容不同),需手动解决。

(Chat) 手动解决代码冲突通常需要执行以下步骤:

  1. 打开你的代码编辑器,并切换到包含冲突的文件。
  2. 找到冲突的代码块,通常会有类似于 <<<<<<< HEAD=======>>>>>>> branch-name 的标记,分别表示你当前分支的代码、两个分支的代码合并点和另一个分支的代码。
  3. 仔细检查冲突的代码块,并决定要保留哪些代码。你可以选择保留当前分支的代码、两个分支的代码合并点或另一个分支的代码,也可以将它们组合起来以创建新的代码。
  4. 一旦你决定了如何解决冲突,就可以手动编辑代码并删除冲突标记。
  5. 保存文件并提交你的更改。(实际上直接保存提交即可,但这样会多出些标记,因此还是删了后再提交)

以下是一个示例代码冲突的解决方法:

1
2
3
4
5
<<<<<<< HEAD
print("Hello, world!")
=======
console.log("Hello, there!");
>>>>>>> other-branch

在这个示例中,冲突的代码块包含两个 printconsole.log 语句。你可以选择保留其中一个或两个,或者创建一个新的语句。例如,你可以将这些语句组合成一个输出:

1
console.log("Hello, world! Hello, there!");

一旦你完成了解决冲突的代码块,就可以提交你的更改并继续合并分支。

新建分支并将其push到origin去,需要添加--set-upstream参数

©--set-upstream 是一个Git命令行选项,通常用于与远程仓库关联本地分支,并设置本地分支与远程分支的跟踪关系。这通常用于将本地分支推送到远程仓库的新分支,或者将本地分支与现有的远程分支进行关联。

下面是一些常见的情景和如何使用 --set-upstream 选项的示例:

  1. 创建新的本地分支并与远程分支关联

    假设你要创建一个新的本地分支并将其与远程仓库的分支关联。你可以使用以下命令:

    1
    2
    git checkout -b my-feature-branch
    git push --set-upstream origin my-feature-branch

    这将创建一个名为 my-feature-branch 的本地分支,并将其推送到远程仓库(origin)的 my-feature-branch 分支上。--set-upstream 选项会自动建立跟踪关系。

  2. 将本地分支与远程分支关联

    如果你已经有一个本地分支,但希望将其与远程分支关联,可以使用以下命令:

    1
    git branch --set-upstream-to=origin/my-feature-branch my-feature-branch

    这将将本地的 my-feature-branch 分支与远程的 origin/my-feature-branch 分支关联起来。

  3. 查看分支关联关系

    要查看本地分支与远程分支的关联关系,可以使用以下命令:

    1
    git branch -vv

    这会列出所有本地分支,并显示它们与远程分支的关联情况。

总之,--set-upstream 选项是Git中用于建立本地分支与远程分支之间跟踪关系的有用工具,它使你能够更轻松地管理分支和与团队协作。

之后在Github上会出现pull request, 同意即可在github上添加该分支

此外,合并时加与不加--no-ff的区别:Git 合并时 --no-ff 的作用_git no-ff_zombres的博客-CSDN博客

标签

希望记住某个特别的快照,使用git tag打标签

-a 选项意为"创建一个带注解的标签"。 不用 -a 选项也可以执行的,但它不会记录这标签是啥时候打的,谁打的,也不会让你添加个标签的注解

1
git tag -a v1.0 

假设我们发布了提交 85fc7e7(上面实例最后一行),但是那时候忘了给它打标签。 我们现在也可以追加:

1
git tag -a v0.9 85fc7e7

commit后会生成一段哈希值,其前7位就可以作为唯一标识符。写完整版的也行。

查看已有标签:

1
2
3
4
5
6
[root@Git git]# git tag
v1.0
[root@Git git]# git tag v1.1
[root@Git git]# git tag
v1.0
v1.1

删除:

1
2
3
4
[root@Git git]# git tag -d v1.1
Deleted tag ‘v1.1’ (was 91388f0)
[root@Git git]# git tag
v1.0