虚机ubuntu下局网搭建gitlab服务器

部署过程:

  • 坑一:当安装了postfix后,发现需要重新配置成internet,使用命令

sudo apt-get install gitlab-ce

然后就是参考过程:

https://blog.csdn.net/discoverer100/article/details/51814171

  • 坑二:本人禁用了先前安装的nginx,把external_url改成了“http://192.168.23.128:8010”,才顺利OK。否则看到的界面有问题,是CSS等资源不完整的显示。此时虽然能有改密码的界面,但不会成功的。如果是想和即有的nginx配合,请参考:https://jingyan.baidu.com/article/6525d4b1b5d89dac7c2e944a.html
  • 坑三:腾讯云把gitlab做起生意了,如果想在上面搞,域名和证书都要理顺,而且会对外界资源有排斥。

用户数据设计:

以下基于本人环境,不用参考。

root下面有codera,coderb,coderc

codera下面建立一个标准项目:bgsvc4hbw

grp4task1下面指定codera是owner(负责人),由root创建组,再邀请codera

此后,codera又建立了一个仓库flowshow用于研究git工作流。

进阶应用:

管理员密码重置

https://blog.csdn.net/weixin_30687051/article/details/97273880

工作流学习链接:

https://blog.csdn.net/qq_32452623/article/details/78905181?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1.control

小结一下,gitflow的心得:

1)feature都是起止于develop分支(回归develop时使用:git merge –no-ff)

2)hotfixs是起于master,止于同时推给master(打tag且尾号加1)和develop(回归方式cherry-pick)

3)realse是起于develop,和hotfixs永远不发生关系,止于性质与hotfixs相同,但区别tag是前一位版本号加1。同样不使用merge来回归develop

4)对于master外的发布,可以根据环境灵活建立分支,比如一平台一分支。

5)tag一般不会隐式推送到远端,所以,可以只选择大版本来显示手工命令推送。

https://blog.csdn.net/github_27263697/article/details/79563949

备份和迁移

https://blog.csdn.net/qq_40907977/article/details/106756999

go与qt的新酒老瓶

前言

只所以说是新酒老瓶而不是新瓶老酒是有用意的。

因为QT是器,老瓶,出来时配合着C++的。而如今go来势凶凶,自然英雄所见略同。

两大开源神器,跨平台开发,终将双剑合璧了,让你如虎添翼。

过程记录如下

安装QT

→参考指导:

https://www.cnblogs.com/haijian/p/12417129.html

本人使用/usr/local/qt为QTDIR。5.12.10

安装go

→参考指导:

https://blog.csdn.net/icanx/article/details/91438450

→配置go env国内源

liteide源码编译安装

→参考指导:

https://www.cnblogs.com/7explore-share/p/5838281.html?utm_source=debugrun&utm_medium=referral

出现了模板路径报错,于是使用tarena环境,但是root账户,先安装两个包,再改脚本后,编译方成功。

https://www.cnblogs.com/liaojiafa/p/12798025.html

实在是经典解说:

→针对windows平台

在此时需要安装mingw64做为前提,不然liteide就是水土不服的。必要时关闭360吧!

mingw64实是难搞,换了几个工具,如mingw installation manager,最后用mingw-w64-install.exe
启动后选择版本,posix和seh,这就生成了安装目录。
在安装过程中,把此前下载的源码包压缩包“mingw-w64-v8.0.0.zip”重新命名为“x86_64-8.1.0-release-posix-seh-rt_v6-rev0.7z”,放置在默认的目录中“x86_64-8.1.0-posix-seh-rt_v6-rev0”
最后,把安装的路径
C:\Program Files\mingw-w64\x86_64-8.1.0-posix-seh-rt_v6-rev0\mingw64\bin
放到系统环境变量中。万事大吉。gcc,g++一应具全,随处可用。

GO111MODULE在windows上是没有auto可设置的,即便你使用liteide设置了,但go env中实际还是当它为on。

所以,系统底层仍设置为on,GOPATH目录内的源码编译成功,无论是否有go.mod。但要是GOPATH目录外的拥有go.mod文件(这是通过go mod init src生成的)可以编译成功。

当设置为off时,同时也得让GOPROXY为空,这时GOPATH和有go.mod的外部目录都可在命令行编译成功。所以,建议你还是使用命令行吧,因为,同一代码在命令行和liteide中结果不同,并且,保持on状态,保持代码不在GOPATH中。相信,go的发展也是会弃掉它。

→针对linux平台

GO111MODULE可以被liteide设置成auto.

这样设置的好处是模糊使用GOPATH(任何设置都OK)。而无论要编译的源码在任何目录都可以,且不用设置go.mod。

前台qt后台go起步

→参考指导:

环境:https://github.com/therecipe/qt/wiki

→therecipe/qt包的安装

先go get -u -v 不行就先下载,然后改名适配到代码中包引用的相应GOPATH中,然后再安装命令工具即cmd中的…。

重要是认清go get的本质就是一种git clone的包装。

go install  /home/tarena/code4DN/learn_gopath/src/github.com/therecipe/qt/cmd/...

不出意外是报错的,但看下面的解决问题内容。

→解决go端的环境的问题

https://blog.csdn.net/wzw_mzm/article/details/77618922

出现“找不到 golang.org/x/mod/module”问题,后来手工下载了golang.org/x/下面系列仓库,就是 git clone.

git clone https://github.com/golang/mod.git 
git clone https://github.com/golang/xerrors.git 
这是两个新加入的,一般没有它,已经可以运行demo.最终的完整支持包如下图

原始网上下载运行demo的命令如下,

go get -ldflags="-w" github.com/therecipe/examples/basic/widgets && $(go env GOPATH)/bin/widgets

它会直接运行一个弹出窗口,相应后台的操作是拷贝了代码并编译放在GOPATH/bin中,再运行。
本人已经下载过therecipe/qt包了,就是对应GOPATH下的

github.com/therecipe/examples/basic/widgets/main.go

→解决QT端的环境问题

以上集齐了龙珠。这里是锦上添花,因为,要充分使用QT的伎俩,就需要一套工具。
这时再次执行命令

go install  /home/tarena/code4DN/learn_gopath/src/github.com/therecipe/qt/cmd/...

命令成功使用之后

goqtuic的安装

go get -u -v github.com/stephenlyu/goqtuic

事实上没有这些工具也可以运行demo或QT库的代码。只要thericipe/qt包具备了就行。

总结跨平台

不管是windows还是linux下,都要在GOPATH/src下具备github.com和golang.org。前者里面有therecipe后者里面有x。同样的代码,都用Liteide编译,本地化成各自系统的风格。

静态库的go调用:(用GO来唤醒C的各种沉睡资源吧)
https://www.jianshu.com/p/b3fb41d7c33f

附录:

  • qtsetup会把qt的相应源码下载放置在go源码旁边,如果你有了mingw和gcc,它都会编译成静态库(.a的文件)给你。go帮你丰富环境真是全方位的。如果你是单独完全安装的qt环境,此处可以省略。很久以前,静态编译成window平台的QT库让你累疯,但现在mingw和go,让你永远不碰那个步骤了。
  • 翻墙参考:https://www.cnblogs.com/hupeng1234/p/9727170.html
  • qt如果要调试或用其它QT版本,有几个需要的环境变量比如QT_DIR。

云上git服务器

使用gitosis用户管理

→安装

首先,切换python2来安装
yum install -y python-setuptools 
git clone git://github.com/res0nat0r/gitosis.git 
cd gitosis 
python setup.py install 
然后,修改/user/local/bin/gitosis-三个文件的第一行,python后面加2.7
经过上面的修改,大环境中python版本仍为3.6,而gitosis会自行应用2.7

→环境搭建

本地公钥生成,做为管理的初始公钥
生成公钥命令:ssh-keygen -t rsa
注意生成后把
.pub的结尾,把@后面数字开头或者有_的都去掉,本人直接改成@localhost.
为此,我还去改造了命令提示符,但生成的公钥匙结果依然依赖hostname
https://www.cnblogs.com/xiaofeiIDO/p/8037331.html
并使用

  1. su - gitfarmer
  2. gitosis-init<~/new.pub
上面这条命令2,后台会执行一系列操作,比如生成一个gitosis-admin的仓库,把new.pub中的内容移至仓库的keydir目录中,同时公钥文件名称与仓库中的gitosis.conf里的memebers名一致。 最后,由于公钥匙是gitfarmer用户下生成的,所以,另建立了manage_instance目录,在里面
  1. git clone gitfarmer@127.0.0.1:repositories/gitosis-admin.git
此时,管理已经具备功能而且是在服务端本地来管理,安全分离。

客户端应用

→生成应用者的公钥

https://www.jianshu.com/p/ba6efe6bf60d 一般客户端为window且安装了git bash。下面就是在git bash中生成自己公钥匙的过程。 把id2cvm.pub上传到keydir中,然后,修改gitosis.conf增加你要管理的代码仓库。 然后,git commit. 事实上发现,通过命令行建立的好像并不被git bash接受,最后,还是用了git gui中的工具,生成了默认的id_rsa.pub才有效果。 ssh -Tv gitfarmer@hostname是很好的工具,但有时你发现没有反应这是因为你的服务端并未设置欢迎语录而已,需要看日志中是否22端口已经登录成功。并且要看最后的返回值是否为0来证明测试成功。

→在服务端建立裸仓库来对应客户端

原以为gitosis会代劳这个动作,实践发现需要自己来,有些帖子说的不对。

→客户建立仓库关联,推送代码

本人在git bash中操作系列命令:
mkdir BL_main

cd BL_main

git init

vim readme.md

git add .

git commit -m "first import"

git remote add origin gitfarmer@182.XXX.181.XXX:repositories/BL_YTF_prj.git

git push origin master
最后一条会跳出让你输入服务端登录ssh密码,并且此前在服务端~/respositories/已经建立了相应的裸仓库。

→在客户端多个公钥匙对应多个仓库的管理

在windows下,git bash会找到用户目录下.ssh/config文件来判断,如果你配置了分支,就会根据你请求的@后面值来查找config中的HostName来匹配
$ cat ~/.ssh/config 
HOST mycvm
HostName 182.XXX.181.XXX
User gitfarmerXXX
Port 22
#PreferredAuthentications publickey
IdentityFile C:\Users\user\.ssh\id_rsa

HOST github
HostName github.com
PreferredAuthentications publickey
IdentityFile C:\Users\user\.ssh\id2cvm
上面的mycvm就是你命令中要给出的
ssh -Tv gitfarmer@mycvm
 
如果测试成功,就说明分支判断了,支持多公钥管理

附录

https://blog.csdn.net/harry_haiwei/article/details/77714651 https://www.cnblogs.com/yshyee/p/4288465.html https://www.webyang.net/Html/web/article_257.html 原理指导
把用户gitfarmer加入到sudo组中: https://blog.csdn.net/qq_39290007/article/details/81125750 同一主机多个git ssh公钥配置: https://blog.csdn.net/yigehui12/article/details/89333264

VC权威剖析:MFC原理、机制与开发实例—-读后感

基础概念和消息映射

Image
窗口:
按级别分:
桌面窗口
     顶级窗口
          子窗口
     重叠或弹出窗口
CS_PARENTDC:
     有此属性(并不是窗口风格),它可以继承父窗口的显示设备上下文。edit,button都是如此的。
WS_CHILD:
     纯子窗口,只有客户区,并且客户区的显示界面要在WM_PAINT消息处理中进行绘制。edit,button都是如此的。
WS_OVERLAPPED:
     若不同时指定WS_CHILD那么它是顶级窗口,总有标题栏WS_CAPTION和边框,并且自动设置WS_CLIPSIBLINGS。创建重叠窗口时可以指定默认大小选项CW_USEDEFAULT。
WS_POPUP:
     弹出窗口创建时,也会自动设置WS_CLIPSIBLINGS。但其它风格必须专门指定,包括WS_CAPTION,也不能指定默认大小选项。
检索窗口:可以跨进程找到窗口的句柄,因为用的是CWnd的静态函数,如下:
FindWindow()
GetWindow()
以下相对来说是内部查找了。
用于找父窗口的:
CWnd::GetParent(),可以省略CWnd
但有可能父又是别人的子,所以
CWnd::GetParentOwner()
用于找子窗口的:
CWnd::GetTopWindow()
CWnd::GetDlgItem()
CWnd::GetDescendantWindow()——–通过ID号取得窗口指针
CWnd::GetWindowFromPoint(POINT)函数取得占用父窗口客户区指定点的子窗口。实参POINT是客户区坐标。
消息:
Image
窗口消息(区别于线程消息):
     窗口消息:除了WM_COMMAND外,所有WM_开关的消息。与某类窗口紧密相关。
1,系统自动生成的窗口消息映射
2,通过类向导来生成的消息映射
3,通过宏ON_MESSAGE(message,memberFxn)
主要讲解以下三类消息,原因是类向导不能自动帮助生成,也没有系统建立好,要手工添加。包括自定义消息。
     命令消息
          菜单(工具栏,加速键)、按钮向窗口发送,要求执行某个功能操作的消息,与程序动作相关。
          用宏ON_COMMAND(id,memberFxn)来建立消息映射。加入数组的第二参数为,CN_COMMAND(内容是0,而通知消息则是非零值)
     通知消息
          MFC为每个通知消息都定义了宏,如果控件的内容变化ON_EN_CHANGE,ON_EN_UPDATE,鼠标滚动等。
          通过ON_CONTROL(wNotifyCode,id,memberFxn)来生成消息映射。其实它是ON_COMAND的重载而己。新控件都使用专门的ON_NOTIFY来建立了。它能传递更多的附加信息。如:
         纯正,新式的通知消息使用如下:
          ON_NOTIFY(TVN_KEYDOWN,IDC_TREE,OnKeydown)
          注:在两层面变化了,通知代码和处理的函数原型上,后者有实参,并引入新的结构了。
          不通过ON_CONTROL来消息映射的特殊通知消息。WM_CTLCOLOR
     反射消息
          由主窗口通过CWnd::ReflectLastMsg()发给子窗口,此函数调用了子窗口的OnChildNotify()—-ReflectChildNotify()
          在其中,就是原始的switch了。
               对旧式通知消息的反射消息和通知消息的反射消息时
               —–OnCmdMsg()
Image
命令ID:
     [0x8000,0xF000)———–全局命令,可由不同对象处理。菜单项的的ID值都在此范围内。
     小于0x8000—————-局部命令,按钮
MFC应用程序角度—-CWndApp分析

接开发者地气的些设计。它的父和子,都是一个程序从生到死的维护者。在继承的应用类实例中,把这爷仨的属性都设置了,找到相应的归宿。
有三种主窗口:单选的。事实看看MFC应用程序向导即可。
单,多文档的主窗口都是CFrameWnd(后者派生的)。而基于对话框的就不用多说了。
Image
m_pszAppName
向导中填写的工程名称,可以在CWndApp构造时传参指定。如果没有指定,会使用字符串资源“AFX_IDS_APP_TITLE”,如果还没设置这个串,将由可执行文件名代替。
属于CWndApp类
m_pszExeName
属于CWndApp类
m_pszProfileName
应用程序的INI配置文件名,在继承应用类中设置自己的配置文件 。
GetProfileString()等系列函数来配合。
属于CWndApp类(默认是执行程序.ini)
m_hInstance
模块在进程中的装入地址
属于CWndApp类
m_pMainWnd
在CSingleDocTemplate或CMultiDocTemplate构造时,就把资源文件绑定和主窗口框架类,文档类,视图类全都实例化,同时设置了此指针。基于对话框的也按其方式会设置此指针。注:没有命令行参数时,默认执行ID_FILE_NEW
文档,视图,都是MFC管理的,实例在堆上,不用手动回收。
当设置好,别忘记
ShowWindow(SW_SHOW);
UpdateWindow();
SetWindowText(“XXX程序”);
这样这个主窗口的消息循环,在Run时触发。
属于CWinThread。设置了此指针的UI窗口,在销毁时,都是安全的。
用向导也好,自己个性化改造也好,反正重载的initInstance函数至少有有模有样了。
命令行参数功能,有时在不同进程启动的相互调用时很有用。

双系统搭建及ubuntu和CentOS下安装Qt5

把大象放冰箱里需要三步,同样,玩linux也需要。第一,制作USB启动盘,第二,安装系统,第三,安装Qt5。

第一篇,材料准备

有多种方式来制作USB启动盘。本人实验了两个,用vmware12和ultraISO.

虚机方式:

建立好空白虚机后,就是提示第一坑。
第一个坑,就是开启intel VT-x.从bios中设置。
重启,再来,可以了,不要装vmware-tool先,不然就在抢占CD-rom。
在我本机S1 yoga的bios上设置两处:
一,sercurity中的安全引导去掉
二,startup中的boot中选择both,即允许传统模式。
用烧录方式:
当然就是把ISO用ultraISO来烧录到USB中了。这个方式不用过多介绍。
当做好USB启用盘后,你F12引导从U盘进入系统,你会看到try和安装两个大按键的情况。我们即可进入第二篇章了。
第二篇章,系统安家
你是租房还是要买房?系统放到你的U盘上还是,想系统在你的硬盘上?这个问题赶快想,尤其是安装步骤到了分区时。但不管如何,选择安装到硬盘是入口。
如果是想在USB上玩linux,那当然安全,不会破环原来的系统。但是磁盘空间,硬件支持和使用体验必须是要慢被理解的。分区方法如下:(我的U盘就16G)
要在U盘上/dev/sdb建立新分支,一个主15G,一个交换分区9百M。
安装不必细说,当出现提示重启时,拔出U盘即可。
当你是个老司机,硬盘富余,且酷的话,来吧,装在硬盘上。并且让windows来当房东。这个意义深远了,因为,如果你想linux撤出,只要格式下那个分区即可。方便的代价就是要懂得原理并实现,还有找到利器,比如easybcd。
原理其实就是:
MBR—-grub2—-bootmgr(由grub来接管系统,在它的分支中选择windows还是linux)
现在:
MBR—-bootmgr—-grub(由windows提供的引导菜单,它当房东,grub就只管引导linux即可,不用去学习grub命令行,好主意)
那个利器就是编辑bootmgr的。所以,我用后面的引导模式了。
用windows的磁盘管理,压缩卷,把最后一个分区给缩小,然后就会多出一个空闲分区,这个就是给硬盘linux的“新房”。
然后,重启用U盘引导,这次同样选择安装到硬盘选项。在分区时,需要充分小心了。
先看看前人的指导:http://blog.csdn.net/pop_rain/article/details/70477085
在我的环境中最终分三个,/,/boot,/home分别为10G,200M,50G,注意引导要放在与/boot同映射的分区上。注意没有/swap区。
因为据说17.04后的版本不需要分交换分区了,而变成了交换文件的方式。
并且,如果你把引导装在了/boot对应的分区,grub2不会跑出来作怪,这是让windows来引导的前提。不然,得用工具修复MBR,所以,装完ubuntu,再重启应该是熟悉的wiondows不是grub。如果是后者,你分区错了。
当你再重启发现进入了熟悉的windows了,没有错,因为,房东管理着客户linux。此时,搬家已经完成,linux入住了,但房东没有给配好钥匙。进系统后,找那个利器吧。easybcd中加一个引导条目,分区选择为/boot那个系统分区。
再重启,windows给你选择权了,让你进linux去吧。不过,我碰到了问题。
最大的坑是:ext4 superblock checksum 。没错,这个是硬盘格式的错误。卡了我一下午。
一个国外帖子搞定了。
先用USB安装盘,启动进去,用root修复好挂载/的那个分区/dev/sda7.
然后,重启硬盘引导后发现可以有root的命令行,看来修复硬盘格式有戏。
然后,就是把其它的两个linux分区修复。之后,ubuntu17.04的用户登陆界面出现。
但最后,反朴归真了,发现在busybox的initramfs的命令提示符下,用 (sudo) fsck.ext4 /dev/sda7,8,9,三次命令后,reboot即可。
终于是躺在我硬盘里的,与win7同床的,让微软引导的小弟系统呀。
第一件事,开启root。
技巧把$变成#,sudo -s.或sudo su
此时安装东东已经够了,但如果你想用root来登陆系统。继续下面操作。
然后执行: vi /etc/lightdm/lightdm.conf.
增加 greeter-show-manual-login=true  allow-guest=false  . 修改完的整个配置文件是
[SetDefaults]
greeter-session=unity-greeter
user-session=ubuntu
greeter-show-manual-login=true #手工输入登陆系统的用户名和密码
allow-guest=false   #不允许guest登录
然后我们启动root帐号:
sudo passwd root
根据提示输入root帐号密码。
重启ubuntu,登录窗口会有“登录”选项,这时候我们就可以通过root登录了。
第三篇章 系统装修
与房东win7磨合得不错,但linux下没啥好玩的就有些寒酸了。装个Qt5来。
如果你是CentOS,这可以这么玩了。
{
一,编译器准备:
yum check-update
yum -y install gcc
yum -y install gcc-c++
—–解释
gcc: yum install gcc
g++: yum install gcc-c++
此外还有以下方法:
yum install make
— 或者
yum groupinstall “Development Tools”
— 或者(这个省事,把系列工具全搞定)
yum install gcc gcc-c++ kernel-devel
二,Qt5依赖库准备:
#yum install mesa-libGL-devel mesa-libGLU-devel
#yum install freeglut-devel

}//end CentOS

ubuntu:
{
首先不可或缺的就是编译器与基本的函式库,如果系统没有安装的话,依照下面的方式安装:
  $ sudo apt-get install build-essential
安装OpenGL Library
  $ sudo apt-get install libgl1-mesa-dev
安装OpenGL Utilities
  $ sudo apt-get install libglu1-mesa-dev
  OpenGL Utilities 是一组建构于 OpenGL Library 之上的工具组,提供许多很方便的函式,使 OpenGL 更强大且更容易使用。
安装OpenGL Utility Toolkit
如果不行就把,sudo apt-get install libglut-dev命令改成
$ sudo apt-get install freeglut3-dev
}//end ubuntu
三.直接运行安装包
#sh qt-opensource-linux-x64-5.5.1.run
四.安装好之后,需要添加环境变量
#vim /etc/profile
在最后一行,添加以下内容:
export PATH=”/opt/Qt5.5.1/5.5/gcc_64/bin:$PATH”
export PATH=”/opt/Qt5.5.1/Tools/QtCreator/bin:$PATH”
如果第四步没有搞好,编译好的测试项目不能运行执行文件。本人就碰到了xcb的插件要求报错。原来在5.5以上的高级Qt版本中,引用了platform的概念。所以,要使用LD_LIBRARY_PATH来找那些库。当然,你找那个qtcreator.sh执行,里面有自动配置好系统环境的处理。
until now,enjoy!

git局网实战

介绍个轻量级方案,让局网下使用git方便,抛砖引玉了。

第一步,首先在A机上,把代码的目录变成仓库。
用git init或者用GUI操作,这没啥新鲜的。
第二步,在A机某个共享文件夹中建立个裸仓库(基于第一步的仓库)
即使用命令:在第一步的目录中,而share则是本机的共享目录。
git clone –bare . /c/Users/Administrator/Downloads/share/bare-cad.git
但,此时,第一步的仓库并没有把第二步刚建立的仓库当成远程仓库。所以,还要手工建立联系。
git remote add origin /c/Users/Administrator/Downloads/share/bare-cad.git
再加上一个
git push –set-upstream origin master
可保万全,它设置了第一步仓库的上游或者说远端源是第二步仓库了。不信,你用git branch -a或git push来测试。
到此,A机内循环通道完毕。
第三步,在局网的其它机器B上,映射驱动器为A机的那个共享目录。
Y:/bare-cad.git就是那个第二步建立的仓库。
并同时克隆一个仓库在自己喜欢的目录下。
git clone /Y/bare-cad.git
上游或远程关系自动建立好,git pull/push都没问题了。
第四步,开始协同开发,推拉自如。好像装箱和开箱,而这个中转箱,则为bare-cad.git.

git学习笔记

基础概念:
合并(merge):一般在分支到主线
     快进:另一分支并没有更改过。
     合并:两分支各自变化了,需要解决冲突
比如,如果要将开发中的分支(develop),合并到稳定分支(master),
  首先切换的master分支:git checkout master。
  然后执行合并操作:git merge develop。
  如果有冲突,会提示你,调用git status查看冲突文件。
  解决冲突,然后调用git add或git rm将解决后的文件暂存。
  所有冲突解决后,git commit 提交更改。
分支衍合(rebase):一般在主线到分支
     最好的场景是把主线的修复推向需要的支线。
分支衍合和分支合并的差别在于,分支衍合不会保留合并的日志,不留痕迹,而 分支合并则会保留合并的日志。
  要将开发中的分支(develop),衍合到稳定分支(master)。
  首先切换的master分支:git checkout master。
  然后执行衍和操作:git rebase develop。
  如果有冲突,会提示你,调用git status查看冲突文件。
  解决冲突,然后调用git add或git rm将解决后的文件暂存。
  所有冲突解决后,git rebase –continue 提交更改
     一个对象名,是根据内容sha出来的40字符串。
     二个目录:git目录,工作目录
     三个:
          index,staging area,未入仓库的,由仓库管理的,暂存区
     四种对象:每个对象都包括三部分:类型,大小和内容。
          blob,git show
          tree,git ls-tree
          commit,git show -s –pretty=raw ,一个commit只指向一个tree,它用来标记某一个特定时间点的状态。包括时间戳,提交者,(parent)指向上次提交对象的指针,(tree)。
          tag,git cat-file tag v1.5.0 用来标识某个提交的方法,包括对象名,对象类型,标签名,,标签创建者名字。
以下转来的思路清楚的后台逻辑:
————————————-

设想你现在位于 alpha/ 目录下,这里有一个文本文件 number.txt,里面的内容只有一个词:“first”。

现在执行 git init 将这个 alpha 文件夹初始化为 Git 仓库。

执行 git add number.txt 会将 number.txt 添加到 Git 的索引(index)中。这个索引记录了所有 Git 保持追踪的文件,现在它有了一个映射记录 number.txt -> first,同时 add 命令还会把一个包含了 first 字符串的二进制对象加入 Git 的对象数据库里。

现在执行 git commit -m first。这条命令会做三件事情。首先在对象数据库内创建一个树对象,用以记录 alpha 目录下的文件列表,这个对象有一个指针指向前面 git add 命令创建的 first 二进制对象;第二,这条命令还会创建一个 commit 对象用以代表刚刚提交的版本,它包含一个指针指向刚刚的树对象;第三,master 分支也会指向这个新创建的 commit 对象。

现在执行 git clone . ../beta。它会创建一个新目录 beta 并将其初始化为 Git 仓库,然后把 alpha 仓库的对象数据库中所有对象拷贝给 beta 的对象数据库,将 beta 的 master 分支像 alpha 的 master 一样指向相应的对象。它还根据 first提交的内容配置索引,并根据索引更新目录下的文件——也就是 number.txt

现在切换到 beta 目录,修改 number.txt 的内容为“second”,执行 git add number.txt 和 git commit -m second,新创建的提交对象 second(译注:姑且称之为 second)会有一个指向父提交(first)的指针,表示 second 继承自 first,而 master 分支则指向 second 提交。

回到 alpha 目录,执行 git remote add beta ../beta,将 beta 仓库设为远程仓库。然后执行 git pull beta master

在这条命令背后,它其实会执行 git fetch beta master,从 beta 仓库中找到 second 提交的相关对象拷贝到 alpha 仓库;把 alpha 中关于 beta 的 master 分支记录指向这个 second 提交;更新 FETCH_HEAD 指向刚刚从 beta 仓库拉取的 master 分支,还是这个 second 提交。

此外,pull 命令还会执行 git merge FETCH_HEAD。从 FETCH_HEAD 得知最近拉取的分支是 beta 仓库的 master 分支,据此拿到相应的对象,也就是 second 提交对象。此时 alpha 的 master 分支指着 first 提交,正好是 second 的祖先提交,于是对于 merge 命令来说只需要将 master 分支指向 second 提交即可。接下来 merge 命令还会更新索引以匹配 second 提交的内容,并且相应更新工作目录中的文件。

现在执行 git branch red,创建一个名为“red”、指向 second 提交的新分支。

然后执行 git checkout red。在 checkout 之前,HEAD 指向 master 分支,执行命令之后它就指向了 red 分支,使得 red 成为当前分支。

接下来把 number.txt 的内容修改为 “third”,执行 git add numbers.txt 和 run git commit -m third

之后再执行 git push beta red,这条命令会把 alpha 仓库内跟 third 提交相关的对象拷贝至 beta 仓库,并且将(alpha 仓库内记录的)beta 仓库 red 分支指向 third 提交。就酱。

—————————-

事实上只有理解后台的动作,才能在命令中游刃有余。下面个人总结的,请大家抛砖。

后台的勤劳者
git clone
—后台把新仓库的同名分支和旧仓库的远程分支(相对于新仓库)做“自动追踪”映射了。
手工改的命令是:
git branch –set-upstream master origin/next
–set-upstream-to=origin/next master
在push后加下面的效果一致(关联阅读):注远程没有next也会生推过去,并设置了跟踪关系。
-u origin next
git pull <远程主机或仓库默认origin> <远程分支>:<本地分支>
—后台的动作包括fetch FETCH_HEAD(默认是远程的master并设置,在不加参数情况下,它也会全取来远程下面的所有分支)
—后台还有merge动作。前提是当前分支与远程分支存在追踪关系了。
git push<远程主机或仓库默认origin> <本地分支>:<远程分支>
—注意这是危险的,要先pull才好。它在后台只接受“快进”,并且要注意冒号前的分支所属
rebase
—后台有个删除动作的,为了让树看起来漂亮,他会像橡皮一样擦除本分支内的commit对象,然后做好搬运合并。所以,这一般都在非主分支上。
附个技巧:有点像“月光宝盒”哟
#保留你当前状态,包括未跟踪的垃圾文件,并最后再搞回来
git stash
git checkout fe9c4
#看代码等操作
git checkout master
git stash pop
注意pop是会删除stash对象的,而apply不会,要有多个stash时,用stash@{num}来指代。

git工作流设计

对于源码管理和产品线管理为了避免混乱,应该有个大致的管理方案:
项目名假如为:tj_dj
则产品管理线:(主机)
主分支–master
开发分支–develop-tj_dj
发布分支–release-tj_dj
特性分支(短生命线分支)–f-[特性名]-tj_dj
修复分支–hotfix-tj_dj

轻量级开发情况:(AB机间没有网络)
在各自本机建立环境,本地建立好bare仓库和本地开发仓库。
总体上要求,bare仓库是同名的,但在自己的本地开发仓库中把远程仓库命名个性化。Dell为例:
dell-前缀。
技巧:
bare仓库用来fetch和push的“箱子”,为远程仓库。
使用拷贝方式来和其它机共享bare仓库。
各机器为主工作时,则要使用很多分支技术来merge其它机的进度代码。

多人联合开发情况:
这里就仁者见仁,智者见智了。但是最典型的就是gitflow了。但不是起对了几个分支名就行了。要得其要领。
原则:
master和develop分支是稳定分支,一直存在。
master只允许release和hotfix分支来的merge
develop日常开发
feature上开发功能,功能成熟后合并到develop上
release是从develop上分出来,bug修复后,打上tag后,要同时合并回develop和master
很小的bug修复会则会在hotfix上进行。
1). 首先将远程代码拉取到本地
  git clone xxx
  git checkout -b develop origin/develop
2).新建feature分支
  git checkout -b feature
3).多人在feature上开发,如果中途需要将develop的变更合入feature,所有人需要将本地的代码变更提交到远程
  git fetch origin
  git rebase origin/feature
  git push origin feature
然后由feature负责人rebase develop分支,删除原来feature分支,重新新建feature分支;
  git fetch origin
  git rebase origin/feature
  git rebase develop
  git push origin :feature
  git push origin feature
这样可以保证feature保持线性变更;
4).feature开发完成后,所有人需要将本地的代码变更提交到远程
  git fetch origin
  git rebase origin/feature
  git push origin feature
然后由feature负责人rebase develop分支,然后将feature分支合入develop,删除feature;
  git fetch origin
  git rebase origin/feature
  git rebase develop
  git checkout develop
  git merge feature
  git push origin :feature
这样可以保证develop保持线性变更,各feature的变更完整可追溯;
5).合入feature后拉出对应的release/feature分支,后续bug修复在release/feature上
  git checkout develop
  git checkout -b release/feature
release/feature分支的同步合并与feature分支相同
6).release/feature分支bug修复完成后,拉取对应的tag推送远程进行发布
  git tag -a v1.0 -m ‘feature发布’
  git push origin v1.0
之后将release/feature合入develop分支,然后删除
  git rebase develop
  git checkout develop
  git merge release/feature
  git push origin :release/feature
7).发布完成后将release合入master分支,保证master为最新稳定版本(实际操作为发起merge request)

windows核心编程(第5版)读书笔记一

第一章节 错误处理
几乎所有的windows API返回值都是下列之一:
VOID——不会失败,失败了骚扰bill gates去,
BOOL——不用说了吧,
HANDLE—失败则是NULL,当然有时是-1,
PVOID—–失败是NULL,成功就是指针喽,
LONG/DWORD—-要看具体的上下文环境了。
当调用失败,返回值会先指出已经发生错误。所以要先判断返回值。然后,使用GetLastError()来得到详细的错误提示。返回值是dword类型的,要得到描述,加入WinError.h.
技巧一:在监视中,$err,hr,就会看到调用的API错误的内容。
技巧二:使用VS的IDE小工具,error lookup
只你自己开发的模块想返回不一样的error时,可以使用SetLastError(DWORD)来写入,当然,错误代码要像点样,即32位中的29位要必须为1.而0是给系统用的。
第二章节 字符和字符串的处理
VC6——ANSI,DBCS——-/Zc:wchar_t(这个选项就会有定义wchar_t这个数据类型)
VS201X———–ANSI,UNICODE(指的是UTF-16)
事实上,typedef unsigned short wchar_t;
WinNT.h中统一了类型的名称。
TEXT(param)在unicode宏定义下,在param前加了L前缀。
所以,TCHAR也是个宏,可以配合TEXT(),_T() 来一起变脸。
unicode阵营的后缀或关键字母:
w—wide
L—-
ansi阵营的后缀或关键字母:
a—ansi
中性函数:或会变脸的,应用在两种编码下都可以编译场景,加入TChar.h配合String.h
_tcslen()会变脸成wcslen或strlen
C库的新版本的安全系列函数
1)字符串函数:加入StrSafe.h
_tcs拼加后面的选项即可cpy/cat/再拼接_s后才是安全字符串函数。第二参数为要处理的字符长度,用_countof宏(stdlib.h) 来得出字符数最好,注意不是字节数哟.
StringCch为前缀的也是安全函数。
注意:
使用微软包装的安全函数代替C库函数,好处是即时发现内存操作的异常,但有时也可能会出现“Debug Assertion Failed”对话框。当然要是debug模式下,当然也有办法屏了它,用release或定义InvailidParameterHandler函数,然后注册它,再程序运行开头加入个宏:_CrtSetReportMode(_CRT_ASSERT,0);
判断返回值必须等于宏S_OK,当不是这个值时必须要检查字符串的操作。
2)安全缓冲区函数:加入CrtDefs.h
memcpy_s——–wmemcpy_s
memmove_s——-wmemmove_s
第三章节 内核对象
有SECURITY_ATTRIBUTES结构为参数的生成才是内核对象,区别于GDI和其它的对象。
所以这也揭露了内核对象的本质是—-结构。而句柄则是—–由系统管理着的内存地址
CloseHandle()函数详析:
工作步骤:
1,验证自己主调进程中的句柄表,是否有权访问此句柄。如果有效,则获得内核对象的数据结构地址。
2,把内核对象结构使用计数减1,如果是0了,则销毁。
注意:
如果参数是无效的句柄,CloseHandle返回false,GetLastError返回ERROR_INVALD_HANDLE。如果在调试,则出现0xC0000008的异常抛出。
当函数返回前,清除当前进程的句柄表,所以以后代码不能再使用此句柄了。
当用变量保存过句柄的话,应该设置为NULL。
任务管理器是可以查看程序中的进程句柄表。
跨进程边界共享内核对象—略

windows核心编程(第5版)读书笔记二

第四章节 进程
进程内核对象在创建的时候总会处于未激发,无信号状态,但当进程终止时,系统自动会让进程对象变成激发状态,并且会永远保持这种状态。即回不到未激发状态。
C库会根据三个维度选择入口点函数:
编码,运行模式,运行环境
_tWinMain(WinMain)
wmainCRTStartup
_tmain(wMain)
_tmain(Main)
mainCRTStartup
wWinMainCRTStartup
WinMainCRTStartup
_tWinMain(wWinMain)
编码
ANSI
UNICODE
UNICODE
ANSI
ANSI
UNICODE
ANSI
UNICODE
运行模式
GUI
CUI
CUI
CUI
CUI
GUI
GUI
GUI
运行环境
WIN16
WIN32
WIN16
WIN16
WIN32
WIN32
WIN32
WIN16
在VC自有的C运行库的源代码中,crtexe.c中可以找到以上win16四个函数的源代码。
这些启动函数或者说入口函数的作用是:
1)获取指向新进程的完整命令行的一个指针
2)获取指向新进程的环境变量的一个指针
3)初始化C运行库的全局变量。如果包括了StdLib.h,就可以访问这些全局变量了。
4)初始化内存分配和IO底层
5)调用所有全局和静态C++类对象的构造函数。
系统接管,加载exe,dll到进程的一个地址空间(与链接器有关了),把这个地址返回给第一个入口函数的参数,即实例句柄。
下面可以玩这个句柄了,GetModuleFileName().
如果,你忘记实例句柄了,或没没放到全局里,不过没关系,可以用GetModuleHandle(param).参数可以是一个路径,最好是程序里用到的某个dll,要么,param就是NULL,这样就会得到运行着的当前进程的实例句柄。
命令行和环境变量,最好不要用C运行库初始化后的内容,万一时机没对,还没初始化你就读了,会出问题,所以window有厚道的API。GetCommandLine(),C运行库都在用,你凭啥找事儿,对吧。
技巧一:配合CommandLineToArgvW(GetCommandLine(),&nNum),可以得到友好的命令行参数。
这个配置和系统—》高级系统设置—》系统变量的内容是一致的。
入口点函数完后,就是进程的后事了,包括:
1)C运行库接管,调用自己的exit
2)调用_onexit()此前注册的任何一函数,假如你注册了的话。
3)调用所有全局和静态C++类对象的析构函数
4)如果有DEBUG则可以生成内存泄漏报告,可以深入去研究下。
5)C运行库来调用操作系统的ExitProcess函数,把入口点返回值以参数传入,即退出代码。这样系统就会杀死进程了,此函数返回值是void,它通知OS了,就应该无声息的over了。
注意,有时入口点返回,而有时线程可以调用ExitProcess和TerminalPorcess。
入口函数中显示使用ExitThread的函数,会让主线程退出,但如果其它线程还在工作呢?进程就不会退出,造成僵尸进程的凶手。
入口函数中显示使用ExitProcess的函数,会让C运行库函数没有执行清理资源的机会。
所以,最保险就是永远不显示的调用ExitX之类的函数。
更NB和危险的函数还有,那就是TerminalProcess,它厉害在它可以在某线程里被用,去干掉自己和别人的进程。

进程当前目录
这里要注意,因为,进程下的线程是有能力改写进程的当前目录,这也包括子进程。所以,要注意。
线程会通过GetCurrentDirectory()和SetCurrentDirectory()来存取路径。
做为进程,可以使用GetFullPathName()来看看现在的路径或者根据驱动器去环境变量里找到某路径。