git踩坑指南
git踩坑指南
1.一些简介
git是一个分布式的代码管理仓库:
- 本地和远程上都有独立的库,可以用push命令远程提交
- 会保存完整的代码提交记录,每一次提交的都是文件快照
优势 | 劣势 |
---|---|
对团队合作非常友好 | 大文件的支持度不太好(可以用git-lfs补足),因为每一次git提交都占用库存 |
2.一些命令
2.1.初始化
# 本地项目初始化,在工作区根目录下
git init
[--initial-branch] 初始化的分支
[--bare] 创建一个裸仓库,只有git目录、无工作目录
[--template] 用模板创建提前构建好的自定义git目录
初始化会创建.git
配置文件夹,部分配置文件夹如下:
-
objects:存放加密文件快照(在暂存区)
git cat-file -p file_id
可以查看文件内容,file_id = 文件夹名+文件名(就是那一串字符)- 会有一个
目录树
文件,放着所有文件id、名字 - commit注释文件
- 查找顺序是:commit文件(会存储对应的tree id)->tree信息->code文件
-
refs:当做一个指针
-
heads:分支。文件夹
cat .git/refs/heads/master
,会看到当前ref版本下master对应的commit id -
tags:标签(意味着稳定版本)。通过
git tag tag_name
生成annotation tag:附注标签,说明这个版本的特色,`git tag -a v0.2 -m "add new function"
-
git的配置有三个级别:低级别的配置会覆盖高级别的配置
- --global,全局
- --system,系统
- --local,本地
2.2.remote
# 查看remote源
git remote -v
-
同一个origin设置不同的push和fetch url
git remote add git@url1.git git remote set-url --add --push origin git@url2.git
-
可以经常
cat .git/config
查看仓库remote配置
2.2.1.HTTP remote
免密配置:
# 内存
git config --global credential.helper `cache --timeout=3600`
# 硬盘,不指定则默认路径为~/.git-credentials
git config --global credential.helper "store --file /path_to_credential"
信息的格式:${scheme}://${user}:${password}@github.com
2.2.2.SSH remote
默认使用的rsa,但是安全问题的话,现在优先用ed25519
ssh-keygen -t ed25519 -C "your-github-email@com"
- 需要有
""
- [-t],选择秘钥类型
2.3.parent commit
更新文件后,tree会更新为最新版本,同时出现一个parent信息,指向之前的版本
2.3.1.修改历史版本
- commit --amend:修改后commit id会变
git rebase -i HEAD~3
修改最近三个commit:合并commit->修改具体的commit message->删除某个commit- filter --branch:指定删除已提交中的某个文件or全局修改邮箱地址……
2.4.垃圾回收
- git gc:删除没有ref指向的commit,还会对object进行一定的打包压缩->减少仓库体积
- reflog:(回收站)记录操作日志,可以找回丢失的数据。
git gc
也没完全删掉多的commit,用reflog把那些日志设置为过期才算 - git gc prune=now:指定修剪多久前的对象,默认为两周
2.5.pull & fetch
-
pull:把远程的分支拉取到本地,使远程的更新和本地同步(可能存在冲突,需要解决)
git pull = git fetch + git merge git pull --rebase = git fetch + git rebase
-
fetch:拉取远程分支到本地,不进行merge(意思是,把远端的分支拉取到本地了,但是没有进行分支合并,这时候查看历史记录会发现远程仓库的和本地的记录不一样)。会修改refs/remote里分支信息
关于冲突:
- 本地commit和远端commit历史记录不同,则产生冲突(
git commit --amend
或者git rebase
可能导致)- 某分支为个人使用,或者和同组的人确认过可以修改历史,就
git push origin master -f
强制推送(不推荐主分支搞这个,一般先解决冲突再push)
2.6.push
git push origin master
把本地origin源的master分支推送到远程仓库里
- origin,源的名字:
.git/refs/remotes/origin
3.关于报错
You've successfully authenticated, but GitHub does not provide shell access.
如果你是用仓库的http地址进行链接的,可以不管它!只要显示了Hi,bisa!
这种话就说明你远程链接仓库成功了,但你要是想push通过这个链接push代码上去,推荐采用ssh进行连接
采用ssh包括两个方面:
- 让你本地机生成ssh密钥,和github账号上new ssh(建立链接)<搜索关键词:“GitHub配置ssh”>
- 本地链接你remote的仓库时,用
git remote add origin git@github.com:巴拉巴拉
(也就是用仓库的ssh地址进行remote),这一步成功是不进行提示的
如果你已经设置了http的链接,现在执行git remote add origin git@...
报错error: remote origin already exists. 不要担心,这个意思是说你当前本地仓库中已经在链接一个远程仓库,重新设置就行。只要执行:
git rm remote origin
再git remote add origin git@...
就行
error: failed to push some refs to 'github.com:巴拉巴拉'
在执行git push -u origin master
时,报错提示:
! [rejected] master -> master (fetch first)
error: failed to push some refs to 'github.com:bisa42/learnOSTEP.git'
hint: 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.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
看到它推荐我们在push前先pull一遍代码,这很可能是因为当你与其他人合作共同写一份仓库的时候,其他人对这个仓库做了改动,但你的本地库没有更新其他人的操作,此时你直接将自己的本地库push到github上,就有几率损坏别人的更新。(当你用两个机子更新同一个仓库也会如此,即使这俩机子都由你本人操作&&机子中的本地库内容相同)
可以通过下面的命令来解决(这里的master只是仓库的分支名,请更换成你的分支):
git pull origin master
fatal: Need to specify how to reconcile divergent branches.
如果你跟我一样是个倒霉蛋,在执行了上面的命令后又出现了新的问题,那先喝口水冷静一下,查看报错信息:
* branch master -> FETCH_HEAD
* [new branch] master -> origin/master
hint: You have divergent branches and need to specify how to reconcile them.
hint: You can do so by running one of the following commands sometime before
hint: your next pull:
hint:
hint: git config pull.rebase false # merge (the default strategy)
hint: git config pull.rebase true # rebase
hint: git config pull.ff only # fast-forward only
hint:
hint: You can replace "git config" with "git config --global" to set a default
hint: preference for all repositories. You can also pass --rebase, --no-rebase,
hint: or --ff-only on the command line to override the configured default per
hint: invocation.
fatal: Need to specify how to reconcile divergent branches.
事实上,在这些报错出现之前,我能看到它还是成功更新了在缓存区中的文件,只不过还有点小问题罢了
报错信息的翻译:
提示:您有不同的分支,需要指定如何协调它们。
提示:您可以通过在之前某个时间运行以下命令之一来做到这一点
提示:你的下一招:
提示:
提示:git config pull.rebase false # 合并(默认策略)
提示:git config pull.rebase true # Rebase
提示:git config pull.ff only # 仅快进
提示:
提示:可以将“git config”替换为“git config——global”来设置默认值
提示:首选所有存储库。你也可以传递——rebase,——no-rebase,
提示:或命令行上的——ff-only,以覆盖配置的默认per
提示:调用。
fatal:需要指定如何协调不同的分支。
本来我要做的就是一个小仓库,并不需要考虑分支问题,所以我先尝试了提示中的默认策略:
git config pull.rebase false
结果此路不通。
当我再一次尝试git push -u origin master
时,得到下面的报错:
To github.com:bisa42/learnOSTEP.git
! [rejected] master -> master (non-fast-forward)
error: failed to push some refs to 'github.com:bisa42/learnOSTEP.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
翻译:
提示:更新被拒绝,因为您当前分支的尖端位于其远程分支的后面
提示:推荐在push代码前使用类似于git pull的命令
好吧,我们现在要恢复一下分支状态(估计是因为合并分支前pull的,但现在的分支已经被我合并<pull.rebase false
>了)
先查看一下最近3次的commit版本
git log -3
选择自己想回退到的commit
,执行:
git reset --hard yourcommit
fatal: refusing to merge unrelated histories
哈哈没想到吧,这是第三关!如果你进行了上面的操作,发现自己还是不能成功的git pull origin master
,并且报错形如这个小标题,那么可以执行
git pull origin master --allow-unrelated-histories
这个问题可能会被翻译成“拒绝合并不相关的历史”。其实它是说你的分支(或者是两个库)没有建立过关系,在push
/pull
/merge
的时候都可能会出现,但解决都是一个思路->加上--allow-unrelated-histories
退出编辑commit的界面
commit用的是nano文本编辑器,修改完成后按ctrl+x
,再敲个大写Y
,然后回车就能做到保存退出
切换成vim
什么?不想要这个编辑器?那就git config --global core.editor vim
来换成vim吧~
可怕的是这篇文竟然、、<未完待续>!