连接问题

参考:https://v2ex.com/t/843383#reply47

远程仓库有两种连接方式:https 和 ssh:

https://github.com/xxx.git
git@github.com:xxx.git

可以使用 git config -l 来看当前仓库对应的远程仓库的链接来分辨使用的是 ssh 连接,还是 https 链接。

我一般使用ssh key来完成身份验证,基本流程是,将公钥id.rsa.pub存储到GitHub账户上,私钥放到~/.ssh/id_rsa中,这样每次git push的时候,就会自动验证身份.

设置 Http Proxy

git config --global http.proxy socks5://127.0.0.1:7890

事实上使用 socks5h 更佳,即

git config --global http.proxy socks5h://127.0.0.1:7890

h 代表 host ,包括了域名解析,即域名解析也强制走这个 proxy 。另外不需要配置 https.proxy,git 不认的(关于这一点我认识不是很清晰,希望有人解惑)。

推荐使用 socks5 代理,因为 socks5 包含 http(s)。而且 socks5 代理工作在 osi 七层模型中的会话层(第五层),https/http 代理工作在 osi 七层模型的应用层(第七层), socks 代理更加底层。所以就没必要配置 git config --global http.proxy http://127.0.0.1:7890 了。

这样配置的话会使本机所有的 git 服务都走了代理,假如你在良心云上(国内主机)部署了自己的 gitea ,域名 https://gitea.example.com,那么可以只配置 GitHub 的 http proxy ,即

git config --global http.https://github.com.proxy socks5://127.0.0.1:7890

当你访问 https://github.com 这个地址时,请使用 SOCKS5 代理 127.0.0.1:7890

设置 SSH Proxy

Linux & macOS

配置文件在用户家目录下的 .ssh/config 其中 nc 程序位于 /usr/bin/nc

$ cat ~/.ssh/config

Host github.com
Hostname ssh.github.com
IdentityFile /xxx/.ssh/github_id_rsa
User git
Port 443
ProxyCommand nc -v -x 127.0.0.1:7890 %h %p

nc 就是 netcat,是一个简单的 unix 实用程序,它使用 TCP 或 UDP 协议跨网络连接读取和写入数据。 它被设计成一个可靠的“后端”工具,可以直接使用或由其他程序和脚本轻松驱动。 同时,它还是一个功能丰富的网络调试和探索工具,因为它几乎可以创建您需要的任何类型的连接,并且具有几个有趣的内置功能。Netcat ,或实际程序命名的“nc”,早就应该作为另一种神秘但标准的 Unix 工具提供。

Windows

Win 下与之对应的 netcat 程序是 connect.exe,程序位于 Git 安装路径 C:\Program Files\Git\mingw64\bin,win 下推荐使用 Git Bash ,路径也是 Linux style

$ cat ~/.ssh/config

Host github.com
Hostname ssh.github.com
IdentityFile /c/users/xxx/.ssh/github_id_rsa
User git
Port 443
ProxyCommand connect -S 127.0.0.1:7890 %h %p

补充信息

为什么 hostname 是 ssh.github.com,为什么要用 443 端口,ssh 默认不是 22 端口么?

因为有些木弟子对于 22 端口做了限制,要么禁止了,要么有些抽风,这时经常会遇到如下错误

kex_exchange_identification: Connection closed by remote host

所以如果 22 端口不畅就使用 443 ,安全可靠。ps: 22 端口时 hostname 请填 github.com。这部分请扩展阅读 此文

使用 ssh -T git@github.com 来验证连接是否成功:

ssh -T git@github.com

Connection to ssh.github.com port 443 [tcp/https] succeeded!
Hi Shawn-Summer! You've successfully authenticated, but GitHub does not provide shell access.

连接远程仓库和设置远程分支

git remote add origin <远程仓库地址> #添加名为origin的远程仓库

然后给本地分支绑定一个上游分支(远程分支)

git branch -u origin/main #给当前的head分支关联远程的main分支

然后就可以使用 git push来推送本地仓库了.

回退到某次提交,并删除后续提交记录

使用reset命令将 Git 仓库的当前分支的 HEAD 指针、索引(暂存区)和工作目录都重置到指定的提交(commit)状态。

git reset --hard commit-hash

或者采用soft来保留修改,意思就是说,工作区代码不变,head回退到某次提交。

git reset --soft commit-hash

然后使用git push force来将本地HEAD指向的分支,推送到origin(远程仓库)上的同名分支,并且直接覆盖掉.

git push origin HEAD --force

例如,HEAD指向demo分支,origin为GitHub仓库,则上面这段代码会直接在,GitHub上对应仓库中,创建一个demo分支,用本地的分支copy过去.

删除一些提交记录

可以使用git rebase来完成这个操作,下面指令使用交互式指令,来处理最近5次提交.

git rebase -i HEAD~5

或者使用下面指令,处理所有提交

git rebase -i --root

然后会看到类似这样的交互界面:

# Rebase 628acfa..ba99949 onto 628acfa (3 commands)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup [-C | -c] <commit> = like "squash" but keep only the previous
# commit's log message, unless -C is used, in which case
# keep only this commit's message; -c is same as -C but
# opens the editor
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# create a merge commit using the original merge commit's
# message (or the oneline, if no original merge commit was
# specified); use -c <commit> to reword the commit message
# u, update-ref <ref> = track a placeholder for the <ref> to be updated
# to this position in the new commits. The <ref> is
# updated at the end of the rebase
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.

常用操作是:squashreword,即合并提交和重新编辑提交日志.

然后可能需要处理一些冲突,处理完毕之后就可以使用git rebase --continue指令,后续可能还有编辑日志等操作,最后完成rebase操作.

git reflog回溯到以前的状态

有时候使用git rebase或者git reset后,一些提交记录直接消失了,这时候可以调用git reflog来查看HEAD的引用记录,

1a2b3c4 HEAD@{0}: commit: Some commit message
2b3c4d5 HEAD@{1}: rebase: Some other commit message
3c4d5e6 HEAD@{2}: commit: Yet another commit

然后使用下面指令恢复之前的状态

git reset --hard HEAD@{2}