博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

git 常见问题

Posted on 2021-01-15 20:30  心默默言  阅读(1017)  评论(0编辑  收藏  举报

1. Git推送遇到 Updates were rejected because the remote contains work that you do

hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., ‘git pull …’) before pushing again.

原因:新推送的的分支与项目分支没有进行关联。
解决方案;
在项目根目录中右键选择“Git Bash Here”进入Git命令终端:
输入:git branch --set-upstream-to=origin/<branch> master
回车。

 

 然后再次推送就可以了。

2. Git Bash终端中文输出显示乱码解决方案

1、打开自己的终端后,输入指令后,查看到显示中文出现乱码情况
在这里插入图片描述
2、在多终端的空白处,点击鼠标右键,弹出的菜单中选择【options…】
3、 弹出的菜单中找到【Text】->【Local】,下拉菜单中选择zh_CN
在这里插入图片描述
4、在【Character set】下拉菜单中选择【utf-8】,既是选择简体中文,最后点击apply
在这里插入图片描述
5、执行命令: git config --global core.quotepath false ,执行命令git status显示结果
在这里插入图片描述
6、执行命令git diff,显示中文信息
在这里插入图片描述

3. git commit后,如何撤销commit修改了本地的代码,然后使git add filegit commit -m '修改原因'执行commit后,还没执行push时,想要撤销这次的commit,该怎么办?解决方案:使用命令:git reset --soft HEAD^

这样就成功撤销了commit,如果想要连着add也撤销的话,--soft改为--hard(删除工作空间的改动代码)。

命令详解:

HEAD^ 表示上一个版本,即上一次的commit,也可以写成HEAD~1
如果进行两次的commit,想要都撤回,可以使用HEAD~2

--soft
不删除工作空间的改动代码 ,撤销commit,不撤销git add file

--hard
删除工作空间的改动代码,撤销commit且撤销add

另外一点,如果commit注释写错了,先要改一下注释,有其他方法也能实现,如:

git commit --amend
这时候会进入vim编辑器,修改完成你要的注释后保存即可。

 

使用git reset --head HEAD^误删了工作区的文件怎么办?

可以使用git reflog找回commit记录,然后再使用git reset --hard 提交记录

 

 

4.git rm 

1.如果文件添加到暂存区,想从暂存区删除且把工作区也删除,使用
git rm -f 文件

2.如果文件添加到暂存区,想从暂存区删除,但不删除工作区,使用

git rm --cached 文件

3.若果文件添加到暂存区,后又在工作区修改了该文件,如果本地工作区想回退到暂存区的版本,可以使用

git checkout -- 文件

 

5.跳过使用暂存区域

Git 提供了一个跳过使用暂存区域的方式,只要在提交的时候,给 git commit 加上 -a 选项,Git 就会自动把所有已经跟踪过的文件暂存起来一并提交,从而跳过 git add 步骤:

 

6.Git 别名

Git 并不会在你输入部分命令时自动推断出你想要的命令。如果不想每次都输入完整的 Git 命令,可以通过 gitconfig 文件来轻松地为每一个命令设置一个别名。

$ git config --global alias.co checkout
$ git config --global alias.br branch
$ git config --global alias.ci commit
$ git config --global alias.st status

这意味着,当要输入 git commit`时,只需要输入 `git ci。

7.分支

7.1分支创建

git branch testing

7.2分支切换

Git 又是怎么知道当前在哪一个分支上呢?也很简单,它有一个名为 HEAD 的特殊指针,指向当前所在的本地分支(译注:将 HEAD 想象为当前分支的别名)。

git branch 命令仅仅 创建 一个新分支,并不会自动切换到新分支中去。

使用 git log 命令查看各个分支当前所指的对象。提供这一功能的参数是 --decorate。

 

当前 “master” 和 “testing” 分支均指向校验和以 f30ab 开头的提交对象。

 

要切换到一个已存在的分支,需要使用 git checkout 命令。现在切换到新创建的 testing 分支去:

git checkout testing

这样 HEAD 就指向 testing 分支了。

 

 

 这样的实现方式会带来什么好处呢?现在不妨再提交一次:

如图所示, testing 分支向前移动了,但是 master 分支却没有,它仍然指向运行 git checkout 时所指的对象。这就有意思了,现在切换回 master 分支看看:

这条命令做了两件事。一是使 HEAD 指回 master 分支,二是将工作目录恢复成 master 分支所指向的快照内容。也就是说,现在做修改的话,项目将始于一个较旧的版本。本质上来讲,这就是忽略 testing 分支所做的修改,以便于向另一个方向进行开发。

注意:分支切换会改变当前工作目录中的文件
 
不妨再稍微做些修改并提交:

现在,这个项目的提交历史已经产生了分叉(参见 项目分叉历史)。因为刚才创建了一个新分支,并切换过去进行了一些工作,随后又切换回 master 分支进行了另外一些工作。上述两次改动针对的是不同分支:可以在不同分支间不断地来回切换和工作,并在时机成熟时将它们合并起来。

可以简单地使用 git log 命令查看分叉历史。运行 git log --oneline --decorate --graph --all,它会输出你的提交历史、各个分支的指向以及项目的分支分叉情况。

8.分支的新建与合并示例

 

 8.1新建分支

首先,假设你正在你的项目上工作,并且已经有一些提交。
 
现在,你已经决定要解决你的公司使用的问题追踪系统中的 #53 问题。想要新建一个分支并同时切换到那个分支上,你可以运行一个带有 -b 参数的 git checkout 命令:
 

 

你继续在 #53 问题上工作,并且做了一些提交。在此过程中,iss53 分支在不断的向前推进,因为你已经检出到该分支(也就是说,你的 HEAD 指针指向了 iss53 分支)

 

现在你接到那个电话,有个紧急问题等待你来解决。有了 Git 的帮助,你不必把这个紧急问题和 iss53 的修改混在一起,你也不需要花大力气来还原关于 53#问题的修改,然后再添加关于这个紧急问题的修改,最后将这个修改提交到线上分支。你所要做的仅仅是切换回master 分支。

 

但是,在你这么做之前,要留意你的工作目录和暂存区里那些还没有被提交的修改,它可能会和你即将检出的分支产生冲突从而阻止 Git 切换到该分支。最好的方法是,在你切换分支之前,保持好一个干净的状态。有一些方法可以绕过这个问题(即,保存进度(stashing) 和 修补提交(commit amending))。现在,假设你已经把你的修改全部提交了,这时你可以切换回 master分支了:

 

 

这个时候,你的工作目录和你在开始 #53 问题之前一模一样,现在你可以专心修复紧急问题了。请牢记:当你切换分支的时候,Git 会重置你的工作目录,使其看起来像回到了你在那个分支上最后一次提交的样子。Git 会自动添加、删除、修改文件以确保此时你的工作目录和这个分支最后一次提交时的样子一模一样。接下来,你要修复这个紧急问题。让我们建立一个针对该紧急问题的分支(hotfix branch),在该分支上工作直到问题解决:

 

你可以运行你的测试,确保你的修改是正确的,然后将其合并回你的 master 分支来部署到线上。你可以使用git merge 命令来达到上述目的:

 

 在合并的时候,你应该注意到了"快进(fast-forward)"这个词。由于当前 master 分支所指向的提交是你当前提交(有关 hotfix 的提交)的直接上游,所以 Git 只是简单的将指针向前移动。换句话说,当你试图合并两个分支时,如果顺着一个分支走下去能够到达另一个分支,那么 Git 在合并两者的时候,只会简单的将指针向前推进(指针右移),因为这种情况下的合并操作没有需要解决的分歧——这就叫做 “快进(fast-forward)”。

现在,最新的修改已经在 master 分支所指向的提交快照中,你可以着手发布该修复了。

 

关于这个紧急问题的解决方案发布之后,你准备回到被打断之前时的工作中。然而,你应该先删除 hotfix 分支,因为你已经不再需要它了 —— master 分支已经指向了同一个位置。你可以使用带 -d 选项的 git branch命令来删除分支:

 

 

现在你可以切换回你正在工作的分支继续你的工作,也就是针对 #53 问题的那个分支(iss53 分支)。

 

 

你在 hotfix 分支上所做的工作并没有包含到 iss53 分支中。如果你需要拉取 hotfix 所做的修改,你可以使用 git merge master 命令将 master 分支合并入 iss53 分支,或者你也可以等到 iss53 分支完成其使命,再将其合并回 master 分支。

 

8.2分支的合并

假设你已经修正了 #53 问题,并且打算将你的工作合并入 master 分支。为此,你需要合并 iss53 分支到master 分支,这和之前你合并 hotfix 分支所做的工作差不多。你只需要检出到你想合并入的分支,然后运行git merge 命令:

 

这和你之前合并 hotfix 分支的时候看起来有一点不一样。在这种情况下,你的开发历史从一个更早的地方开始分叉开来(diverged)。因为,master 分支所在提交并不是 iss53 分支所在提交的直接祖先,Git 不得不做一些额外的工作。出现这种情况的时候,Git 会使用两个分支的末端所指的快照(C4 和 C5)以及这两个分支的工作祖先(C2),做一个简单的三方合并。

 

和之间将分支指针向前推进所不同的是,Git 将此次三方合并的结果做了一个新的快照并且自动创建一个新的提交指向它。这个被称作一次合并提交,它的特别之处在于他有不止一个父提交。

 

需要指出的是,Git 会自行决定选取哪一个提交作为最优的共同祖先,并以此作为合并的基础;这和更加古老的CVS 系统或者 Subversion (1.5 版本之前)不同,在这些古老的版本管理系统中,用户需要自己选择最佳的合并基础。Git 的这个优势使其在合并操作上比其他系统要简单很多。

既然你的修改已经合并进来了,你已经不再需要 iss53 分支了。现在你可以在任务追踪系统中关闭此项任务,并删除这个分支。

 

8.3遇到冲突时的分支合并

有时候合并操作不会如此顺利。如果你在两个不同的分支中,对同一个文件的同一个部分进行了不同的修改,Git 就没法干净的合并它们。如果你对 #53 问题的修改和有关 hotfix 的修改都涉及到同一个文件的同一处,在合并它们的时候就会产生合并冲突:

 

此时 Git 做了合并,但是没有自动地创建一个新的合并提交。Git 会暂停下来,等待你去解决合并产生的冲突。你可以在合并冲突后的任意时刻使用 git status 命令来查看那些因包含合并冲突而处于未合并

(unmerged)状态的文件:

任何因包含合并冲突而有待解决的文件,都会以未合并状态标识出来。Git 会在有冲突的文件中加入标准的冲突解决标记,这样你可以打开这些包含冲突的文件然后手动解决冲突。出现冲突的文件会包含一些特殊区段,看起来像下面这个样子:

 

 这表示 HEAD 所指示的版本(也就是你的 master 分支所在的位置,因为你在运行 merge 命令的时候已经检出到了这个分支)在这个区段的上半部分(======= 的上半部分),而 iss53 分支所指示的版本在 ======= 的下半部分。为了解决冲突,你必须选择使用由 ======= 分割的两部分中的一个,或者你也可以自行合并这些内容。例如,你可以通过把这段内容换成下面的样子来解决冲突:

 

上述的冲突解决方案仅保留了其中一个分支的修改,并且 <<<<<<< , ======= , 和 >>>>>>> 这些行被完全删除了。在你解决了所有文件里的冲突之后,对每个文件使用 git add 命令来将其标记为冲突已解决。

一旦暂存这些原本有冲突的文件,Git 就会将它们标记为冲突已解决。如果你想使用图形化工具来解决冲突,你可以运行 git mergetool,该命令会为你启动一个合适的可视化合并工具,并带领你一步一步解决这些冲突: