Git基础常用功能

一、安装

具体查看 安装Git

 windows下git bash坑

不能使用上/下键切换选项

参考:https://blog.csdn.net/csdn_yudong/article/details/86613435

推荐直接使用数字代替,从1开始

 

 

二、使用

基础知识

  • 工作区(Workspace):就是你在电脑里能看到的项目目录。
  • 暂存区(Index / Stage):临时存放更改的地方,使用命令"git add <.|file>"就是把文件加入暂存区。一般存放在 ".git目录下" 下的index文件(.git/index)中,所以我们把暂存区有时也叫作索引(index)。
  • 版本库(Repository):管理版本的文件,使用"git commit -m 'description'"就是把暂存区的文件提交到版本库。工作区有一个隐藏目录.git,这个不算工作区,而是Git的版本库。
  • 远程仓库(Remote):托管代码的服务器。可以简单的认为是你项目组中的一台电脑用于远程数据交换

一张图描述git的文件如何在各个区域之前流转:

origin:远程仓库库默认别名

master:  仓库默认分支的名称
 

本地项目初始化/和远程仓库操作

git init,把当前文件夹初始化位git工程
git remote add [<options>] <name> <url>  把当前文件夹关联远程仓库并命名,比如git remote add origin git@server-name:path/repo-name.git;
git remote -v 查看远程仓库地址
git push <远程主机名> <本地分支名>  <远程分支名>,比如 git push origin dev dev
git push -u origin master 如果当前分支与多个主机存在追踪关系,则可以使用 -u 参数指定一个默认主机,这样后面就可以不加任何参数使用git push
git remote set-url origin git@your.server:new-name.git // 修改远程仓库名称。要确保新的仓库已经再远程存在才行
git clone <repo> // 克隆远程仓库到本地(各种分支/历史记录一并克隆),当从github上克隆时可能非常慢,有几种方式减少克隆量
git clone --depth <depth> <repo> // 只克隆最新depth层副本。比如git clone --depth 1  https://github.com/vuejs/vue.git,只拷贝vue最新的一条提交。包含这条提交对应的分支和tag
git pull  // 拉取并合并最新的远程数据,其中 --unshallow可以将历史的commit都拉取过来。--depth方式的clone看log只能看到设置的条数。
git clone -b <branch> <repo> // 只拷贝指定的分支
 

基本操作:添加/提交/查看记录

"git add ."或者"git add <file>",将所有文件或指定文件从工作区添加到暂存区
git commit -m "description",将暂存区的所有文件提交到版本库
git commit --amend -m "xxxx"修改上一次的提交信息
git show <commitId> <filename> :查看提交详情
git status,查看当前工作区和暂存区的文件状态
git diff,查看当前工作区对比暂存区的更改
git diff HEAD -- readme.txt命令可以查看工作区和版本库里面最新版本的区别
“git log”或"git log <file>",查看版本库或者指定文件的提交记录
git log --graph命令可以看到分支合并图。
git log --pretty=oneline --graph --abbrev-commit展示效果如下

 git cherry-pick <commitId>,复制一个特定的提交到当前分支,比如master分支的bug修复提交复制到dev分支

 git cherry-pick commitId1..commitId100,复制两个commit之间的提交到当前分支,注意:不包括commitId1

若要合并某个分支上的一系列提交,还有另一种方式。
需要使用rebase指令进行合并操作
具体操作步骤:
// 以**最后一次提交**为节点, 创建一个新的分支<newbranch 是新分支的名字>
1. git checkout -b newbranch 最后一次提交的id
// 再 rebase 这个新分支的commit到目标分支上<--onto 目标分支>。<start_id> 指明你想从哪个特定的commit开始。
2. git rebase --onto 目标分支 start_id
 两个操作一样,都是重新生产commit副本。不是移动从A分支移动commit到B分支(移动之后,移出的分支的commit将消失)

仓库分支管理

查看分支:git branch
创建分支:git branch <name>
切换分支:git checkout <name>或者git switch <name>
如果本地有多个remote,切换到指定remote的分支:git checkout --track <remote_name>/<name>
创建+切换分支:git checkout -b <name>或者git switch -c <name>
 
比如git checkout -b dev,切换并创建dev分支,相当于
$ git branch dev
$ git checkout dev
从某个commit切出分支:git checkout commitId -b 本地新branchName 
合并某分支到当前分支:git merge <name>
正常合并如果能用fast-forward就会使用, 但这种模式下,删除分支后,会丢掉分支信息。可以使用--no-ff强制禁用ff模式
git merge --no-ff -m "merge with no-ff" dev
因为本次合并要创建一个新的commit,所以加上-m参数,把commit描述写进去。
git branch -d <name>,删除本地分支:
git push origin --delete 分支名,删除远程分支
git push origin :分支名,删除远程分支,同上
git branch -m old_branch new_branch,本地分支更名/重命名
git fetch -p, fetch之后删除掉没有与远程分支对应的本地分支

例1. git远程分支已经删除,本地还能看到解决办法

当我们删除远程分支后执行git branch -a本地却依然能看到远程分支

这个时候我们只需要执行git remote prune origin清理一下就可以了

然后再次执行git branch -a就看不到啦

 

代码回退

看上面的几个区域的图基本就能明白

 "git reset HEAD" 或者"git reset HEAD <file>"命令,暂存区的目录树或文件会被重写,被 master 分支指向的目录树或文件所替换,但是工作区不受影响。

git reset --hard HEAD^/git reset --hard 1094a,强制回退上一个版本/回退到指定版本号的版本,版本库会直接回退(远程仓库不会回退),需要特别谨慎。删除工作空间改动代码,撤销commit,撤销git add . 
git reset --soft HEAD^/git reset --soft 1094a,不删除工作空间改动代码,撤销commit,不撤销git add . 

 "git rm --cached <file>" 命令,会直接从暂存区删除文件,工作区则不做出改变。

 "git checkout ." 或者 "git checkout -- <file>" 命令,会用暂存区全部或指定的文件替换工作区的文件。这个操作很危险,会清除工作区中未添加到暂存区的改动。

"git checkout HEAD ." 或者 "git checkout HEAD <file>" 命令时,会用 HEAD 指向的 master 分支中的全部或者部分文件替换暂存区和以及工作区中的文件。这个命令也是极具危险性的,因为不但会清除工作区中未提交的改动,也会清除暂存区中未提交的改动。

“git revert HEAD/git revert commitID”: 放弃已经push的指定版本的修改,会新增一条记录,版本会递增
"git reflog" , 用来查看你的每一条命令,用来配合上面的命令恢复你的误操作
 
例1:将单个文件(a.js)回退到某一版本
  1. git  log a.js查看a.js的更改记录
  2. git reset   fcd2093  a.js 先将暂存区中的该文件回退到历史版本fcd2093
  3. git checkout -- a.js 暂存区中该文件的历史版本(fcd2093)覆盖工作区中对应的文件,此时(工作区、暂存区的文件a.js是fcd2093版本)。
【注】git reset [选项]  [版本号]  [回退对象]命令,当回退对象是文件时选项不能为hard
【注】2、3步可以合并成一步git checkout fcd2093 a.js
此时,如果git commit 提交暂存区的数据到版本库,则会重新生成一条记录
 
例2:将整个项目(远程仓库和本地仓库当前版本一致)回退到某个版本,并push到远程仓库,让远程仓库也回退。
  例如,版本库最新的几条提交记录是:aaaa -> bbbb -> cccc;cccc是最新的提交记录,要回退到aaaa并push
  1. git reset --hard aaaa 强制将版本库回退到aaaa,但是远程仓库还是cccc
  2. git reset cccc 将head移到最新的版本(和远程的head保持一致,实际就是将远程暂存区的内容更新到最新版本cccc,工作区的内容还是保持在aaaa),此时aaaa和cccc的差异便作为本次更改的内容。
  3. git add / git commit / git push 提交后生成新的版本号dddd

此时git log 看到的最近的提交记录就是:aaaa -> bbbb -> cccc -> dddd

【注】也可以使用git revert cccc 和 git revert bbbb来实现,不过会新增两条回滚记录

 
例3: 将整个项目(远程仓库和本地仓库当前版本一致)回退到某个版本,并push到远程仓库,让远程仓库也回退(并且不保留已经被撤销的提交)

如果删除远程仓库的最后一次提交的时候不需要保留历史记录的话,可以使用reset,命令如下:

    git reset --hard HEAD^
    git push origin master -f

保留半成品现场(存储临时现场)

主要用在目前还不想提交的但是已经修改的内容进行保存至堆栈中,后续可以在某个分支上恢复出堆栈中的内容
git stash 存储临时现场
git stash list 查看工作临时现场
一是用git stash apply恢复,但是恢复后,stash内容并不删除,你需要用git stash drop来删除;
另一种方式是用git stash pop,恢复的同时把stash内容也删了
你可以多次stash,恢复的时候,先用git stash list查看,然后恢复指定的stash,用命令:
git stash apply stash@{0}
 
git stash drop stash@{0} ,删除第一个队列
 

子模块

有时工程太过庞大想要分出子工程单独管理,或者纳入一个子工程到当前工程来,就可能用到子模块功能。

git子模块配置处理(即git的B仓库被作为A仓库的子目录),两个仓库可以各自管理和提交
git submodule add <path> <name>:将<path>对应的仓库作为当前仓库A的<name>子目录
git status:在A中查看发现多了<name>和 .gitmodules(这个文件中是子模块的相关配置)
git diff --cached <name>:在A中看到无法查询子模块的提交记录, 取而代之的是,Git 将它记录成来自B仓库的一个特殊的提交(这个提交在克隆的该项目时,进入子模块就是进入到这个提交)
例如,子模块B的名称为subproject_demo:
$ git diff --cached subproject_demo
diff --git a/subproject_demo b/subproject_demo
new file mode 160000
index 0000000..aa1eeb0
--- /dev/null
+++ b/subproject_demo
@@ -0,0 +1 @@
+Subproject commit aa1eeb06e67608d7a2af179a7dfd9e594777e90f
git commit -m 'first commit with submodule xxx': 结果中注意 subproject_demo条目的 160000 模式。这在Git中是一个特殊模式,基本意思是你将一个提交记录为一个目录项而不是子目录或者文件。
当你使用clone克隆该项目(父工程A)时,会发现子模块的文件夹内容为空,需要做:
git submodule init: 初始化你的本地配置文件
git submodule update:从子模块B拉取所有数据并检出你上层项目里所列的合适的提交(保持子模块是最新的那个)
进入子模块,发现子模块是那个项目的 你先前提交的确切状态的分支
chen_@DESKTOP-TJKEMKG MINGW64 /c/works/demo/subproject_demo  ((aa1eeb0...))
// 发现没:aa1eeb0就是之前的哪个提交

如果你在项目中改了子模块的代码,准备提交到对应的分支(add和commit已经执行过),使用:

git push origin HEAD:<branch>   这样就把代码提交到对应的分支 ,和 git push origin <localBranch> <remoteBranch>类似

如果其他人有修改这个子模块并提交到A工程,你可以重新pull A项目分支,然后执行git submodule update保证子模块也是最新的
git clone --recurse-submodules <repositary> ,他就会自动初始化并更新仓库的每一个子模块
 
【注】使用时要注意,最好保证在父工程A中来自B的提交永远来自同一个B的分支,比如master分支。所以B的分支代码更改完毕并测试完毕合并到master后,再在A提交来自B的master分支的提交

【注】引入私有git工程还可以又其他方式,比如和npm配合:《2018 年了,你还是只会 npm install 吗》查看“私有 git 共享 package”部分

 

打标签

你可以使用 阿里的AoneFlow模式 使用Git做分支管理,每次发完版本之后需要给当前的master打一个tag,表示发布的一个版本,以便追溯。

git tag,展示所有已经打过的标签

git tag -l 'v1.8.5*',匹配特定的标签查看

git tag -a v1.4 -m "my version 1.4",打附注标签

git tag -a v1.4 932cab, 后期给932cab提交补打上标签

git tag v1.4-lw,打轻量标签,没有标签信息

git tag -d v1.4,删除标签按【谨慎】

git git push origin :refs/tags/v1.4,删除远程v1.4这个标签

git show v1.4,命令可以看到标签信息与对应的提交信息

git push origin v1.4,共享标签,默认情况下,git push 命令并不会传送标签到远程仓库服务器上。 在创建完标签后你必须显式地推送标签到共享服务器上

git push origin --tags,一次性把所有标签push到远程


【注】:更详细查看https://git-scm.com/book/zh/v2/Git-%E5%9F%BA%E7%A1%80-%E6%89%93%E6%A0%87%E7%AD%BE

 

https和ssh使用

查看链接:https://blog.csdn.net/qq_42108192/article/details/90168968

 

https模式下添加git账号到项目,push不用每次输入账号密码

打开.git文件的下的 vim .git/config新增以下内容

[user]
name = XXXX05@qq.com
email = XXXX05@qq.com
[credential]
helper=store

 

 合并commit/修改历史commit

合并commit用到git rebase,参考:https://www.cnblogs.com/laphome/p/11309834.html https://www.jianshu.com/p/964de879904a

需要注意的是,如果只是squash中间的部分节点。保存之后可能后面的pick执行会执行不了,提示如下

hint: Could not execute the todo command
hint: 
hint:     pick 4d45xxxx918364 xxxx
hint: 
hint: It has been rescheduled; To edit the command before continuing, please
hint: edit the todo list first:
hint: 
hint:     git rebase --edit-todo
hint:     git rebase --continue

明显后面的pick没有执行(导致漏掉),按提示先执行--edit-todo,然后--continue就OK

注意:然后要将修改过后的commit提交到远程(在提交之前不要使用git pull。这回导致之前合并之前的commit记录会被再次下载下来)。使用:git push -f 【需要特别注意,这个动作将不可回退,建议使用一个拷贝的分支来做这些动作】 

修改历史commit查看:https://blog.csdn.net/jbj6568839z/article/details/102797968

注意:为了确保edit后面的pick继续执行,一定要执行“git rebase --continue”    。修改历史commit这个操作会在一个副本上进行。完毕只有需要将记录push到对应的分支上:

git push origin HEAD:<name-of-remote-branch>  如果失败,加 -f 强制覆盖(要特别小心,强制覆盖会导致之前的记录消失)

 

Enter passphrase for key '/c/Users/Administrator/.ssh/id_rsa'

https://www.jianshu.com/p/b6545f4cd317

  1. ssh-agent bash
  2. ssh-add ~/.ssh/id_rsa

 

 

更新一组依赖包 

 

1.npm-check-updates

// 先下载

yarn global add npm-check-updates

// 更新包(@kant @rousseau @alice)下的所有子包

ncu \"/@(kant|rousseau|alice)\\/\\S+/\" -u 

 

2.upgrade-interactive

yarn upgrade-interactive --latest
// 需要手动选择升级的依赖包,按空格键选择,a 键切换所有,i 键反选选择

 

3.upgrade
yarn upgrade package@version
// yarn.lock和package.json都会更新,但是会进行版本锁定 "echarts": "4.2.0-rc.2"

 


三、.gitignore 

# 忽略文件夹,下面两种写法都可,会递归匹配所有的子文件夹
lib
types/
# 忽略根目录下的文件夹
/.husky
#忽略文件夹内容,但是其中某些文件不忽略,**表示递归,*表示只匹配最近的一层
packages/svg/**
!packages/svg/index.d.ts
# 忽略文件夹中的子文件推荐只用一个*。此时达到的效果和两个*是一样的
.vscode/*
!.vscode/extensions.json
!.vscode/settings.json
*.suo
*.ntvs*
*.sw?

# Logs
logs
*.log
yarn-debug.log*
yarn-error.log* 

如果设置了.gitignore但是却没有生效,原因是 .gitignore 只能忽略那些原来没有被track的文件,如果某些文件已经被纳入了版本管理中,则修改.gitignore是无效的。
那么解决方法就是先把本地缓存删除(改变成未track状态),然后再提交。

git rm -r --cached .
git add .
git commit -m 'update .gitignore'

  

 

四、踩坑

[remote rejected]  (hook declined)

完整日志:

$ git push
Enumerating objects: 25, done.
Counting objects: 100% (24/24), done.
Delta compression using up to 8 threads
Compressing objects: 100% (13/13), done.
Writing objects: 100% (13/13), 1.20 KiB | 1.20 MiB/s, done.
Total 13 (delta 11), reused 0 (delta 0)
remote: git: 'refs/heads/web2.0' is not a git command. See 'git --help'.
remote: error: hook declined to update refs/heads/web2.0
To https://e.coding.net/tops/front-www.git
 ! [remote rejected] web2.0 -> web2.0 (hook declined)
error: failed to push some refs to 'https://e.coding.net/tops/front-www.git'

百度查看帮助,找到类似的问题:https://blog.csdn.net/weixin_39278265/article/details/102248258

本人的问题解决办法

git config --global --unset branch.web2.0.merge

然后再push就OK

 

 

posted @ 2020-02-05 10:16  chua1989  阅读(1935)  评论(0编辑  收藏  举报