{"id":1293,"date":"2017-06-30T14:39:08","date_gmt":"2017-06-30T19:39:08","guid":{"rendered":"http:\/\/lisa.rushworth.us\/?p=1293"},"modified":"2019-07-30T08:25:05","modified_gmt":"2019-07-30T13:25:05","slug":"git","status":"publish","type":"post","link":"https:\/\/www.rushworth.us\/lisa\/?p=1293","title":{"rendered":"Git"},"content":{"rendered":"<p>I mentioned that I had inherited a Git implementation last week. Here is the documentation I created to teach my coworkers what Git is and how to use it. Some isn&#8217;t applicable outside of our environment (you won&#8217;t care about the AD groups that control access to the system), some is applicable for small non-dedicated development teams &#8230; but I figured I&#8217;d post the presentation and <a href=\"http:\/\/lisa.rushworth.us\/wp-content\/uploads\/2017\/06\/GitQuickReferenceGuide.pdf\" target=\"_blank\" rel=\"noopener noreferrer\">quick reference guide<\/a>\u00a0on the Internet in case it was useful to someone else.<\/p>\n<p><strong>Background:<\/strong><\/p>\n<p>Git is a system that provides version control for files \u2013 we\u2019re using it to control script\/program code versions (source control management), but I could put <em>this<\/em> document in Git and use the version control to manage edits to the document. You can use it to maintain configuration files \u2013 allowing config changes to be traceable. You could use it as a cookbook if you were so inclined \u2013 a chef tinkering with a recipe might be interested in going back a few versions and trying something else.<\/p>\n<p>Git provides some functionality that is redundant to other systems \u2013 you could, for instance, import our scripts to SharePoint and make code changes within SharePoint. The individual replacing the file is recorded. If a previous version is needed, SharePoint maintains previous versions that can be recovered. Why use Git instead of SharePoint? Git makes it easier to have multiple developers working on a program, including functions to \u201cmerge\u201d the edited files together. You can have different versions of the whole project \u2013 in SharePoint, I can see different versions of each file, but I have no way of correlating which version of file x.cs goes with y.h &#8230; which makes the versioning less useful. The inverse is also true &#8212; I&#8217;m speaking about git as a source code management platform, but we use it to maintain configuration files too. There are even <em>less<\/em> IT\/source control uses for git out there &#8212; anything where tracking who changed what when is valuable could leverage git.<\/p>\n<p>If you want the history, <a href=\"http:\/\/lmgtfy.com\/?q=git\">LMGTFY<\/a> \ud83d\ude42 Or, you know, read <a href=\"https:\/\/en.wikipedia.org\/wiki\/Git\">WikiPedia<\/a>. LT;DR: It\u2019s one of Torvalds&#8217;s projects, initially used for Linux kernel development and has since become a widely adopted source control management platform. If you have ever looked at a project on GitHub, you have seen a little bit of Git. GitHub is a massive, public Git repository. Because Git has significant adoption within the OpenSource community, there are a lot of good documents on its internal mechanisms (<a href=\"https:\/\/book.git-scm.com\/book\/en\/v2\/Git-Internals-Git-Objects\">https:\/\/book.git-scm.com\/book\/en\/v2\/Git-Internals-Git-Objects<\/a> for example, if you are interested in how data is stored), how it is used (Google \u201cgit cheatsheet\u201d and there are <em>thousands<\/em> of them, or full books like <a href=\"https:\/\/git-scm.com\/book\/en\/v2\">https:\/\/git-scm.com\/book\/en\/v2<\/a>), and oddball errors that might crop up.<\/p>\n<p><strong>Implementation<\/strong><\/p>\n<p>We have a Bobobo Git server using Active Directory for both authentication and authorization. The server source is available on GitHub (<a href=\"https:\/\/github.com\/jakubgarfield\/Bonobo-Git-Server\">https:\/\/github.com\/jakubgarfield\/Bonobo-Git-Server<\/a>) where you can see issues and be included in conversation about source updates (subscribing lets you know when new versions should be available for install).<\/p>\n<p>Questions and bugs regarding the program are maintained in the GitHub issues section. The Google forum that may come up in searches is not active and was retained for history.<\/p>\n<p>This brainshare is primarily to show client-side usage of the Git server. Server setup, configuration, and management is not the focus. One thing I will highlight on the server config: the groups used to provide authorization are not preexisting or nested groups. This means new team members will need to be added to the appropriate \u201cWindstream CSG Git \u2026\u201d group to use the server.<\/p>\n<p>&lt;add key=&#8221;ActiveDirectoryMemberGroupName&#8221; value=&#8221;Windstream CSG Git Users&#8221; \/&gt;<\/p>\n<p>&lt;add key=&#8221;ActiveDirectoryTeamMapping&#8221; value=&#8221;VDI=Windstream CSG Git VDI,SharePoint=Windstream CSG Git SharePoint, Directory Design=Windstream CSG Git Directory Design&#8221;\/&gt;<\/p>\n<p>&lt;add key=&#8221;ActiveDirectoryRoleMapping&#8221; value=&#8221;Administrator=Windstream CSG Git Admins&#8221; \/&gt;<\/p>\n<p>The above snippet is from the Web.config file located on the server at F:\\inetpub\\www\\CSG \u2013 if new groups need to be added to the Git server, that is where the magic happens.<\/p>\n<p><strong>Some Terminology: <\/strong><\/p>\n<p>A repository is a storage location. It can store one file, it could be a whole bunch of files that make up a single program (e.g. the CSOCheck Visual Studio project), it could be a bunch of independent programs that have similar purposes (e.g. \u2018Provisioning\u2019 that holds <em>all<\/em> our provisioning scripts). A repository <em>could<\/em> be all our code glommed into one place (don\u2019t do this \u2013 it makes maintaining an individual program more difficult).<\/p>\n<p>A branch is another server-hosted copy of the project. You don\u2019t want to directly edit the in-use production code (we <em>do<\/em> but this is certainly not a programming best practice!) \u2013 a branch is a copy on which development is done. Once development has been completed, the branch is merged back into the master copy. Looking at Git with small projects and a small number of developers, I wouldn\u2019t expect to see a lot of branches on a project. A large program with a lot of dedicated developers may have some break\/fix branches as well as longer term feature enhancement branches.<\/p>\n<p>A fork is a personal copy of a repository. In OpenSource development, forks avoid making changes in someone else\u2019s repository. You create your fork, work within your copy, then offer the changes in your fork for inclusion in the project. We don\u2019t have much need to create forks &#8212; we would create a branch within the project.<\/p>\n<p>Project \u2013 Bonobo does not seem to have projects, but other Git implementations do. A\u00a0 project includes the repository, an issues log, pull requests, and sometimes even a Wiki for the application. If you see someone referring to a project, <em>for us<\/em> that is just the repository.<\/p>\n<p>The project maintainer is the individual who \u201cowns\u201d the project \u2013 this isn\u2019t a project sponsor (a non-tech individual who owns a business relationship) but a technical supervisor for the development work who may also have project sponsor define-requirement type roles. The maintainer decides if changes and features are added. You can <em>suggest<\/em> changes or features \u2013 in OpenSource projects, review the existing issues to see if the feature was already requested (and make a new issue to request the feature if one does not exist) before spending a lot of time working on code that will not be accepted. Your idea may be something people are excited to see included in the project. Or it may be something they don\u2019t want (you can always make a fork and add the feature to <em>your<\/em> iteration of the project). Even a bugfix \u2013 your proposed solution <em>may<\/em> be accepted. Or there may be a reason the maintainer wants to use a different approach to the issue. We do not have project maintainers.<\/p>\n<p>Commit \u2013 this is basically making changes to the branch (add a file, delete a file, or modify a file). A commit should represent a single change. By that, I don\u2019t mean every time you change a line, make a commit. You may well have to update a hundred lines of code across five different files to resolve an issue or implement a feature. But it\u2019s just *one* issue or feature being implemented in the commit. You shouldn\u2019t have a commit that implements SSL encryption in LDAP authentication and allows individuals to approve requests for direct reports. These two things have <em>nothing<\/em> to do with each other, even if they happen to be the two cards you\u2019ve worked on today.<\/p>\n<p>Commit messages associated with commits where you can indicate what is being changed in the commit. A \u201cgood\u201d commit message is like well commented code \u2013 don\u2019t provide too much info like \u201cI added XYZ to line 81 on file abc.def, but don\u2019t write \u201cBug fixes\u201d either. A commit message should convey what has been changed without someone having to diff the versions (i.e. saves time). In more formal software development, commit messages also aid in the creation of release notes. Something like \u201cChanged new user template to include ourOrgPerson objectClass\u201d provides enough detail that we can tell what the commit <em>did<\/em> \u2013 if someone wants to find out what lines got edited, they can diff the files and tell. You can view the commit history in the web site or by using \u201cgit log\u201d.<\/p>\n<p>Push is the process of updating the server repository with changes you have made on your local repository.<\/p>\n<p>Pull Request is a term you may encounter when reading Git documentation or participating in GitHub. The request basically clue someone into the fact you\u2019ve got code to be reviewed or integrated into an upstream branch. The project maintainer would, once the changes had been reviewed and agreed upon, merge the feature into the repository and close the pull request. This is not a process we are following, nor are code-related discussions or issue lists tracked within the Git server.<\/p>\n<p>Deploy \u2013 once the pull request has been approved, you can deploy and test the changes. If the changes do not work, you roll back by re-deploying the existing master.<\/p>\n<p>Merge is used to combine an individual\u2019s local repository with a server-housed copy of the branch or to combine two branches.<\/p>\n<p>GitHub is an Internet based Git repository used by a\u00a0<em>lot<\/em> of people and a\u00a0<em>lot<\/em> of OpenSource projects. Projects are publicly readable (well, projects held in free accounts. There&#8217;s an add-on fee that allows you to maintain private projects). Yes, we could just get Git enterprise licenses and use the hosted service. We elected to deploy an internally hosted and maintained server.<\/p>\n<p><strong>Process Flow:<\/strong><\/p>\n<p>In a simple development environment like we have (we\u2019re not dedicated programmers working on enormous applications), branches are straightforward. We\u2019ve got a master for a project. When we encounter a problem, or wish to expand functionality, we make a working branch. Sort the issue or add the feature, commit. Deploy and test the code, then merge your working branch back into master.<\/p>\n<p>If there is only one person working on a project at a time, merge conflicts are not really a thing. We don\u2019t <em>have<\/em> ten different branches, we don\u2019t have branches from branches (e.g. a branch for implementing external authentication which then has a branch for LDAP, DB table, and external authentication providers. Then the external authentication provider branch has a branch for Facebook, .NET, and Google authentication providers.). When you have a tree full of branches, you need to resolve merge conflicts (pick which change makes it) before you can merge your pull request branch.<\/p>\n<p>A lot of \u201chow to use Git\u201d is process-related and not technical how-to stuff. Questions like \u201cwhat are your software development lifecycle management processes?\u201d and \u201cWhat are your criterion for creating a new branch?\u201d<\/p>\n<p>When I worked with full-time developers, we created an \u201cEmerStaging\u201d branch for development on critical incidents and a \u201cDevStaging\u201d branch for development on non-critical incidents. The EmerStaging branch was only intended to be around for a few days \u2013 the branch would start out identical to the master, whatever big deal issue would be sorted, then the branch merged back into the master. These changes would then be sync\u2019d down to all other branches (we don\u2019t want the bug to impact development or, worse, to be reintroduced as someone merges in their long-term development project). The DevStaging branch was always present \u2013 there\u2019s always a backlog of lower priority bug-fix type stuff to be done \u2013 and the project maintainer would ensure the downstream branches were updated when they processed pull requests. In addition to these break\/fix branches, a new branch existed for the long-term development work \u2013 next version application or specific new features that had not been assigned to a specific release iteration.<\/p>\n<p>Our environment is not so complex \u2013 we <em>should<\/em> be able to get by with one development branch when there is active development on a project and <em>only<\/em> the master branch when changes are not being made. Following this process, we avoid the challenges of synchronizing and merging multiple branches and sub-branches.<\/p>\n<p><strong>The Git Client<\/strong><\/p>\n<p>Simply put, a Git client puts files on the local disk and pushes those files back to the server. The first step is getting a git client installed. The examples I am showing today are using the CLI utilities from <a href=\"https:\/\/git-scm.com\/download\/win\">https:\/\/git-scm.com\/download\/win<\/a> simply because I already use them at home (it\u2019s the version . Yes, there are other git clients. Lots. If you have used a different client that you prefer, go for it. Different clients will not corrupt a repository.<\/p>\n<p>Some IDE\u2019s have Git integration \u2013 their own Git client \u2013 it may or may not work with our implementation (some are specific to GitHub \/ GitHub Enterprise which is <em>not<\/em> the same thing). If you are using an IDE, it may be convenient to research integrating your IDE directly with Git. There is no <em>need<\/em> \u2013 you can use the command line utilities to retrieve files, switch over to the IDE for your development work, and then use the command line utilities to add, commit, and merge your changes.<\/p>\n<p>To install the Git-SCM clients, download and run the installer. Selecting the defaults on the installation are sufficient \u2013 although if you do not have the Win32 port of the GNU utilities, you can select the third option to get grep and such in DOS.<\/p>\n<p>Once the installation completes, grab the two files from \\\\CWWAPP695\\c$\\Program Files\\Git\\mingw64\\ssl\\certs and put them into your install path\\git\\mingw64\\ssl\\certs folder (I renamed the existing ones, but there\u2019s no reason not to delete them). If you see the error \u201cSSL certificate problem: unable to get local issuer certificate\u201d, re-read the last sentence and try again.<\/p>\n<p>Identify a folder on your computer into which you want to clone projects. You can store different projects in distinct locations or you can have a top-level folder in which all your projects are housed.<\/p>\n<p><strong>Creating A New Repository<\/strong><\/p>\n<p>Log into <a href=\"https:\/\/csggit.windstream.com\">https:\/\/csggit.windstream.com<\/a> using your Active Directory username and password (no need to specify domain). Repositories are sorted into groups \u2013 a group <em>may<\/em> be a single application project. For example, \u201cAD Password Filter\u201d. A group may contain several different application projects \u2013 for example, \u201cAuth Samples\u201d.<\/p>\n<p>To create a new repository, click the big blue button in the upper right-hand corner that says exactly that. Provide a name for the repository \u2013 this cannot contain spaces, but should be descriptive enough that people do not need to actually read through the code to see what the program does. I am making a project called \u201cHelloWorld\u201d because \u2026 tradition.<\/p>\n<p>Supplying a group name will sort the repository into a group on that first page \u2013 please do this, even if your group is your program. Otherwise it\u2019s like creating all of your files in one folder \u2026 fine for a small number of files, but quickly difficult to look at. We may want to make a Misc group to hold oddball one-off programs.<\/p>\n<p>The description field provides a place for freeform text describing the purpose of the program. This doesn\u2019t have to be long, but it would be nice to have <em>something<\/em>. We can consider adding the server(s) to which the code is deployed \u2013 that would provide a quick way to list our scripts, what they do, and where they run.<\/p>\n<p>Contributors can clone, push, and pull a repository. Administrators are additionally able to edit the repository details (i.e. change the stuff we\u2019re putting in here now) and delete the repository.<\/p>\n<p>Select the team(s) which will need to access the repository. Disclaimer \u2013 most of my experience with Git is at home using a GitLab server. There are only two of us, so permissioning isn\u2019t really a concern. Not sure exactly how secure this is (i.e. if I don\u2019t select Directory Design, can they still <em>view<\/em> the source but cannot write to it? Do they not even see the repository? I\u2019d not interested enough to get another ID and add it into the security group, but if someone wants to test now \u2026 that would be cool.). Click \u2018Create\u2019 and the repository will be created.<\/p>\n<p>Look near the top of the page \u2013 there will be a hyperlink to go to the new repository. Click that.<\/p>\n<p>We will need the \u201cGeneral Url\u201d as we begin working with the repository (i.e. copy the link address now).<\/p>\n<p><strong>Working With Your Repository<\/strong><\/p>\n<p>Now that you have a project and URL, clone the project to your local repository \u2013 if this is a new project, ignore the warning. If this is a project you <em>expect<\/em> to have some existing content \u2026 well, don\u2019t ignore the error:<\/p>\n<p>D:\\tempCSG\\ljr\\Git&gt;<strong>git clone https:\/\/csggit.windstream.com\/CSG\/LJR.git<\/strong><\/p>\n<p>Cloning into &#8216;LJR&#8217;&#8230;<\/p>\n<p>warning: You appear to have cloned an empty repository.<\/p>\n<p>&nbsp;<\/p>\n<p>If you are using the Git credential manager, you will be asked to authenticate to the server the first time you clone a repository. You do not need to specify the domain. When you change your password, you can use the Windows Credential Manager to edit your stored credential.<\/p>\n<p>Once the connection has been authenticated, the client will clone the repository and volia, we have <em>stuff<\/em><\/p>\n<p>D:\\tempCSG\\ljr\\Git\\LJR&gt;<strong>dir<\/strong><\/p>\n<p>Volume in drive D is Data<\/p>\n<p>Volume Serial Number is FA7B-B3E4<\/p>\n<p>&nbsp;<\/p>\n<p>Directory of D:\\tempCSG\\ljr\\Git\\LJR<\/p>\n<p>&nbsp;<\/p>\n<p>06\/26\/2017\u00a0 02:33 PM\u00a0\u00a0\u00a0 &lt;DIR&gt;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 .<\/p>\n<p>06\/26\/2017\u00a0 02:33 PM\u00a0\u00a0\u00a0 &lt;DIR&gt;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ..<\/p>\n<p>0 File(s)\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0 bytes<\/p>\n<p>2 Dir(s)\u00a0\u00a0 9,644,441,600 bytes free<\/p>\n<p>&nbsp;<\/p>\n<p>OK, that wasn\u2019t a whole lot of stuff \u2013 it just created a folder for my application! Make some files in there \u2013 that may mean using the folder as your IDE project location. It may mean using notepad and making a new file. Whatever your approach, make a new file and add some code.<\/p>\n<p>D:\\tempCSG\\ljr\\Git\\LJR&gt;<strong>notepad helloworld.pl<\/strong><\/p>\n<p>Then add the new file(s) to the local git repository \u2013 important bit here, we are currently making changes to <em>our<\/em> copy. If you check the server, it is still an empty project.<\/p>\n<p>D:\\tempCSG\\ljr\\Git\\LJR&gt;<strong>git add *<\/strong><\/p>\n<p>The * is a wildcard \u2013 if you are working on a larger project, you can add just the files you are updating (i.e. I could use git add helloworld.pl here). I used the wildcard here because a lot of people like the convenience. Personally, I always recommend programmers add by name to ensure they are adding the proper \u2018stuff\u2019 to the project. There are other short-cut add options: git add . will stage new and modified files (not deletions), git add -u will stage modified and deleted files, and git add -A will stage all files.<\/p>\n<p>Then commit \u2013 since this is the first file, I am not using a great commit note. Generally I\u2019ve recommended making the first commit note a link to the requirements document \u2026 basically if I wanted to find out why we\u2019ve got this program and what it is meant to do, where do I go? In our case, this might be an INC # or a SharePoint URL. Or it might just be a freeform text like \u201cProvision DMZAD group memberships from acildsdb:OSR2.CWSODMZTable\u201d.<\/p>\n<p>D:\\tempCSG\\ljr\\Git\\LJR&gt;<strong>git commit -m &#8220;Created project&#8221;<\/strong><\/p>\n<p>[master (root-commit) 7a66c68] Created project<\/p>\n<p>1 file changed, 2 insertions(+)<\/p>\n<p>create mode 100644 helloworld.pl<\/p>\n<p>&nbsp;<\/p>\n<p>Check the web view to see what\u2019s in the project: nothing. Push the changes:<\/p>\n<p>D:\\tempCSG\\ljr\\Git\\LJR&gt;<strong>git push<\/strong><\/p>\n<p>Counting objects: 3, done.<\/p>\n<p>Writing objects: 100% (3\/3), 256 bytes | 0 bytes\/s, done.<\/p>\n<p>Total 3 (delta 0), reused 0 (delta 0)<\/p>\n<p>To https:\/\/csggit.windstream.com\/CSG\/LJR.git<\/p>\n<p>* [new branch]\u00a0\u00a0\u00a0\u00a0\u00a0 master -&gt; master<\/p>\n<p>I mentioned earlier that making updates in the master branch is not a best practice \u2026 the first time around is an exception \u2026 there\u2019s no production implementation that you\u2019re going to bugger up. Now that we\u2019ve got a project that\u2019s running in production (pretend), we\u2019ll make a branch when we want to make changes. Check out the branch \u2013 this changes your git \u2018context\u2019 to the new branch.<\/p>\n<p>D:\\tempCSG\\ljr\\Git\\LJR&gt;<strong>git branch newEdits<\/strong><\/p>\n<p>D:\\tempCSG\\ljr\\Git\\LJR&gt;<strong>git checkout newEdits<\/strong><\/p>\n<p>Switched to a new branch &#8216;newEdits&#8217;<\/p>\n<p>Yes there is a shortcut to doing this \u2013 \u201cgit checkout -b newBranchName\u201d. Push the new branch<\/p>\n<p>D:\\tempCSG\\ljr\\Git\\LJR&gt;<strong>git push origin newEdits<\/strong><\/p>\n<p>Total 0 (delta 0), reused 0 (delta 0)<\/p>\n<p>To https:\/\/csggit.windstream.com\/CSG\/LJR.git<\/p>\n<p>* [new branch]\u00a0\u00a0\u00a0\u00a0\u00a0 newEdits -&gt; newEdits<\/p>\n<p>&nbsp;<\/p>\n<p>Make some more changes and add the changed file(s) to the local repo<\/p>\n<p>D:\\tempCSG\\ljr\\Git\\LJR&gt;<strong>notepad helloworld.pl<\/strong><\/p>\n<p>D:\\tempCSG\\ljr\\Git\\LJR&gt;<strong>git add helloworld.pl<\/strong><\/p>\n<p>Commit the changes and push to the server:<\/p>\n<p>D:\\tempCSG\\ljr\\Git\\LJR&gt;<strong>git commit -m &#8220;Added international support&#8221;<\/strong><\/p>\n<p>[newEdits 28365d9] Added international support<\/p>\n<p>1 file changed, 8 insertions(+), 1 deletion(-)<\/p>\n<p>D:\\tempCSG\\ljr\\Git\\LJR&gt;<strong>git push origin newEdits<\/strong><\/p>\n<p>Counting objects: 3, done.<\/p>\n<p>Delta compression using up to 2 threads.<\/p>\n<p>Compressing objects: 100% (2\/2), done.<\/p>\n<p>Writing objects: 100% (3\/3), 335 bytes | 0 bytes\/s, done.<\/p>\n<p>Total 3 (delta 0), reused 0 (delta 0)<\/p>\n<p>To https:\/\/csggit.windstream.com\/CSG\/LJR.git<\/p>\n<p>7a66c68..28365d9\u00a0 newEdits -&gt; newEdits<\/p>\n<p>&nbsp;<\/p>\n<p>Now if you look @ the repository browser on the web site, <a href=\"https:\/\/csggit.windstream.com\/CSG\/Repository\/LJR\/newEdits\/Blob\/helloworld.pl\">https:\/\/csggit.windstream.com\/CSG\/Repository\/LJR\/newEdits\/Blob\/helloworld.pl<\/a>, you will see the additions we\u2019ve made. Add some more and repeat the process.<\/p>\n<p>D:\\tempCSG\\ljr\\Git\\LJR&gt;<strong>notepad helloworld.pl<\/strong><\/p>\n<p>D:\\tempCSG\\ljr\\Git\\LJR&gt;<strong>git commit -m &#8220;Added Swedish and Hungarian greetings&#8221;<\/strong><\/p>\n<p>[newEdits b2cbedd] Added Swedish and Hungarian greetings<\/p>\n<p>1 file changed, 2 insertions(+)<\/p>\n<p>&nbsp;<\/p>\n<p>D:\\tempCSG\\ljr\\Git\\LJR&gt;<strong>git push origin newEdits<\/strong><\/p>\n<p>Counting objects: 3, done.<\/p>\n<p>Delta compression using up to 2 threads.<\/p>\n<p>Compressing objects: 100% (2\/2), done.<\/p>\n<p>Writing objects: 100% (3\/3), 340 bytes | 0 bytes\/s, done.<\/p>\n<p>Total 3 (delta 1), reused 0 (delta 0)<\/p>\n<p>To https:\/\/csggit.windstream.com\/CSG\/LJR.git<\/p>\n<p>28365d9..b2cbedd\u00a0 newEdits -&gt; newEdits<\/p>\n<p>Now look at repository explorer and see how the history is tracked \u2013 look @ each commit (notice the commit messages and who made the changes). Click into previous version and see how the differences are tracked.<\/p>\n<p><strong>Fast Forward Merging:<\/strong><\/p>\n<p>This is possible for simple projects like we\u2019re using \u2013 there is a master, a branch for changes, then that branch gets collapsed back into the master when the changes have been finished.<\/p>\n<p>D:\\tempCSG\\ljr\\Git\\LJR&gt;<strong>git checkout master<\/strong><\/p>\n<p>Switched to branch &#8216;master&#8217;<\/p>\n<p>Your branch is up-to-date with &#8216;origin\/master&#8217;.<\/p>\n<p>&nbsp;<\/p>\n<p>D:\\tempCSG\\ljr\\Git\\LJR&gt;<strong>git merge newEdits<\/strong><\/p>\n<p>Updating 7a66c68..08931d5<\/p>\n<p>Fast-forward<\/p>\n<p>helloworld.pl | 12 +++++++++++-<\/p>\n<p>1 file changed, 11 insertions(+), 1 deletion(-)<\/p>\n<p>&nbsp;<\/p>\n<p>D:\\tempCSG\\ljr\\Git\\LJR&gt;<strong>git push origin master<br \/>\n<\/strong><\/p>\n<p>Total 0 (delta 0), reused 0 (delta 0)<\/p>\n<p>To https:\/\/csggit.windstream.com\/CSG\/LJR.git<\/p>\n<p>7a66c68..08931d5\u00a0 master -&gt; master<\/p>\n<p>&nbsp;<\/p>\n<p>Check web site \u2013 you\u2019ll see your changes in master. But newEdits branch is still there.<\/p>\n<p>D:\\tempCSG\\ljr\\Git\\LJR&gt;<strong>git branch<\/strong><\/p>\n<p>* master<\/p>\n<p>newEdits<\/p>\n<p>My recommendation is to collapse the branch (delete it) when you have completed your changes. Otherwise you need to manage branches and merges. If there\u2019s a <em>need<\/em> for multiple branches of sustained development \u2026 that\u2019s beyond the scope of a quick brain share. You can find information on more complex merging operations, including conflict resolution (<a href=\"https:\/\/git-scm.com\/book\/en\/v2\/Git-Branching-Basic-Branching-and-Merging#_basic_merging\">https:\/\/git-scm.com\/book\/en\/v2\/Git-Branching-Basic-Branching-and-Merging#_basic_merging<\/a>) and rebasing (<a href=\"https:\/\/git-scm.com\/book\/en\/v2\/Git-Branching-Rebasing\">https:\/\/git-scm.com\/book\/en\/v2\/Git-Branching-Rebasing<\/a>). Google can also tell you the ongoing debate about etiquette around creating new branches, merging, and rebasing.<\/p>\n<p>To delete a branch once development has been completed and the changes have been merged into master:<\/p>\n<p>D:\\tempCSG\\ljr\\Git\\LJR&gt;<strong>git push origin &#8211;delete newEdits<\/strong><\/p>\n<p>To https:\/\/csggit.windstream.com\/CSG\/LJR.git<\/p>\n<p>&#8211; [deleted]\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 newEdits<\/p>\n<p>&nbsp;<\/p>\n<p>D:\\tempCSG\\ljr\\Git\\LJR&gt;<strong>git branch -d newEdits<\/strong><\/p>\n<p>Deleted branch newEdits (was 08931d5).<\/p>\n<p>Notice the commit history \/ notes were copied from the newEdits branch into the master, so we haven\u2019t lost anything by merging our branch into the master.<\/p>\n<p>Your local repository is not automatically updated with changes <em>other<\/em> people commit to the project. A pull retrieves changes pushed by others to the Git server. Alternately , fetch and merge operations to download the changes and play those changes into your local repository.<\/p>\n<p>Since we are not full-time developers, we might opt <em>not<\/em> to persistently store projects locally (i.e. we have a specific program that needs to be updated, clone the repository locally, perform the edits, push and merge these edits, then destroy the local copy). Provided two people are not simultaneously working on the same project, the newly cloned project is up-to-date each time you start working on a program.<\/p>\n<p><strong>Stashing Changes<\/strong><\/p>\n<p>If you are working on a particular branch but not yet ready to commit your changes \u2013 and you have a need to work on some <em>else<\/em> in the previous commit \u2013 use \u201c<strong>git stash save<\/strong>\u201d to table the changes you\u2019ve currently made. Make whatever changes you need to make, add those changes, commit them, and then use \u201c<strong>git stash pop<\/strong>\u201d to return the tabled changes.<\/p>\n<p><strong>Getting Rid Of Stuff<\/strong><\/p>\n<p>The first question is <em>should<\/em> you remove something? We often keep old code around for future reference (you want to do something similar, instead of re-writing the whole thing \u2026 copy this old program and tweak it for the current need). But leaving <em>every<\/em> old bit of code in the repository is a bit like never deleting an e-mail message or document on disk \u2026 eventually you\u2019ll have a big mess of useless stuff that you\u2019re looking through and backing up.<\/p>\n<p>You could change the repository group to \u201cArchive\u201d (or \u201czzArchive\u201d so it sorts to the bottom of the web view) \u2013 this would retain the code but sort it out into a different logical container to identify it as no longer used code.<\/p>\n<p>Some companies will set up a second Git server dedicated to archive \u2013 lower I\/O requirements on hardware, not frequently backed up, etc. Old code is pushed up to the archive server and <em>then<\/em> deleted from the active code server. As we don\u2019t currently have an archive Git server, this isn\u2019t an option. But it <em>is<\/em> a possibility if inactive code that we want to keep becomes burdensome. Other companies archive the code outside of Git and delete the project from the repository.<\/p>\n<p>To remove a file from the repository, use \u201c<strong>git rm filename.xtn<\/strong>\u201d. To remove a repository, you can click the little rubbish can next to the project on the web site.<\/p>\n<p>There is no such thing as removing a group \u2013 as soon as no repositories exist in the group, it will disappear from the web view.<\/p>\n<p><strong>A Note On Binary Files<\/strong><\/p>\n<p>The typical solution to storing large binary files in Git is to implement LFS \u2013 this feature \u00a0is <a href=\"https:\/\/github.com\/jakubgarfield\/Bonobo-Git-Server\/issues\/342\">not yet supported in Bonobo<\/a>. As such, avoid storing binary files in Git (media, compiled binaries, compressed data).<\/p>\n<p>Binary files tend to be large. Because of the distributed nature of Git, large files are transmitted and stored a lot of places. Frequently changing binary files bloat the server database too. This isn\u2019t to say you <em>cannot<\/em> store binary files \u2013 just that it is a judgement call. Smaller and more static files, great. Three gig files that get updated daily \u2026 find another solution.<\/p>\n<p>Many types of binary files do not compress well \u2013 especially already compressed files. You can disable delta compression in .gitattributes (*.mp4 binary -delta) to avoid the I\/O of attempting to compress already-compressed data.<\/p>\n<p>When merging binary files, diff just tells you they are different. Not particularly illuminating information if you are manually resolving merge conflicts. For non-text files, there may be a filter that allows changes to be represented in a readable format (e.g. Microsoft Word documents) by setting an appropriate filter in .gitattributes (*.docx diff=word). The diff would not include format changes (i.e. if I bolded a specific sentence, that would not be apparent in the diff), but it will display text content that has been updated.<\/p>\n<p><strong>Remote Repositories<\/strong><\/p>\n<p>The whole point of Git is distributing copies of the repository elsewhere. It <em>is<\/em> possible to use Git locally \u2013 this would allow a single developer to track and revert changes \u2013 but typical implementations have multiple developers pulling from and pushing to a remote repository.<\/p>\n<p>You <em>can<\/em> have more than one remote repository.<\/p>\n<p>D:\\tempCSG\\ljr\\Git\\PKIWeb&gt;<strong>git remote -v<\/strong><\/p>\n<p>origin\u00a0 https:\/\/csggit.windstream.com\/CSG\/PKIWeb.git (fetch)<\/p>\n<p>origin\u00a0 https:\/\/csggit.windstream.com\/CSG\/PKIWeb.git (push)<\/p>\n<p>You may notice that we have the word origin in some of the commands \u2013 this is a default repository created when we clone the branch. You can add additional remote repositories (the example I am using is silly since they are the same location). This could be done to transfer a project to a different repository (moving an out-of-support product to an archive Git server or an acquired company moving repositories into the new company\u2019s repository) or to pull a project from an alternate location (other users who maintain their own project for the same application).<\/p>\n<p>D:\\tempCSG\\ljr\\Git\\PKIWeb&gt;<strong>git remote add ljr https:\/\/csggit.windstream.com\/CSG\/P<\/strong><strong>KIWeb.git<\/strong><\/p>\n<p>D:\\tempCSG\\ljr\\Git\\PKIWeb&gt;<strong>git remote -v<\/strong><\/p>\n<p>ljr\u00a0\u00a0\u00a0\u00a0 https:\/\/csggit.windstream.com\/CSG\/PKIWeb.git (fetch)<\/p>\n<p>ljr\u00a0\u00a0\u00a0\u00a0 https:\/\/csggit.windstream.com\/CSG\/PKIWeb.git (push)<\/p>\n<p>origin\u00a0 https:\/\/csggit.windstream.com\/CSG\/PKIWeb.git (fetch)<\/p>\n<p>origin\u00a0 https:\/\/csggit.windstream.com\/CSG\/PKIWeb.git (push)<\/p>\n<p>Normally there\u2019s no need for us to do this (i.e. don\u2019t maintain your own copy of a project, create a branch in the existing one!), <em>except<\/em> if our project is derivative work of an opensource project that we need to publish externally. You could have both the internal Git server and GitHub registered as repositories. Make your changes and do \u201cpush origin\u201d as well as \u201cpush whateverYouCallGitHub\u201d.<\/p>\n<p>You can also \u201cfetch origin\u201d and \u201cfetch whateverYouCallGitHub\u201d, but to avoid confusion, I would use the internal Git server as the authoritative repository (anyone else in the group may be editing the code) and <em>only<\/em> push to GitHub.<\/p>\n<p>When you no longer need a remote repository, you can remove it.<\/p>\n<p>D:\\tempCSG\\ljr\\Git\\PKIWeb&gt;<strong>git remote rm ljr<\/strong><\/p>\n<p>&nbsp;<\/p>\n<p>D:\\tempCSG\\ljr\\Git\\PKIWeb&gt;<strong>git remote -v<\/strong><\/p>\n<p>origin\u00a0 https:\/\/csggit.windstream.com\/CSG\/PKIWeb.git (fetch)<\/p>\n<p>origin\u00a0 https:\/\/csggit.windstream.com\/CSG\/PKIWeb.git (push)<\/p>\n<p><strong>README<\/strong><\/p>\n<p>If you participate in GitHub projects, you will notice a README.md file at the root of projects. This is a standard place to include documentation (hence the name), but it is also rendered out in the Git server web site. For an example, see the AD Password Filter project (<a href=\"https:\/\/csggit.windstream.com\/CSG\/Repository\/ADPasswordFilter\/master\/Tree\">https:\/\/csggit.windstream.com\/CSG\/Repository\/ADPasswordFilter\/master\/Tree<\/a>). If there is not a convenient external reference for the initial commit notes, you may want to consider including program documentation in the README.md file.<\/p>\n<p><strong>What if the changes <em>don\u2019t<\/em> work?<\/strong><\/p>\n<p>One nice Git feature is undoing changes. The first thing you need to know is that commits have ID numbers (often called a SHA in documentation). You can find that using \u201c<strong>git log<\/strong>\u201d or by looking at the web site.<\/p>\n<p>If the changes are local but haven\u2019t been committed to the server, just reset your local copy: <strong>git reset &#8211;hard ID#<\/strong><\/p>\n<p>If the changes haven\u2019t been merged into the master branch yet (i.e. you clone your dev branch to the script server, test it \u2026 then realize that won\u2019t work), use the git revert functions. First find the commit ID. Then use \u201c<strong>git revert ID#<\/strong>\u201d and git will create a commit that is the inverse of the commit specified (it undoes whatever the commit does). Don\u2019t forget to push this revert back to the server.<\/p>\n<p>If the problem is just the commit message, you can modify the message (i.e. remove a typo): <strong>git commit &#8211;amend -m \u201cThis is my new commit message\u201d<\/strong><\/p>\n<p>You can temporarily revert to a specific commit version (say, to see if the problem you are having was introduced in this version) using \u201c<strong>git checkout ID#<\/strong>\u201d. If you intend to make changes from the old state, use &#8220;<strong>git checkout -b previousState ID#<\/strong> &#8221; to create a new branch from that point.<\/p>\n<p><strong>Ingesting Existing Code<\/strong><\/p>\n<p>Create the repository. In the directory with your existing code, initialize the directory as a git repository. Add all files to the local repository and commit the initial file load.<\/p>\n<p>D:\\Scripts\\ljl\\wincare-oud&gt;<strong>git init<\/strong><\/p>\n<p>Initialized empty Git repository in D:\/Scripts\/ljl\/wincare-oud\/.git\/<\/p>\n<p>&nbsp;<\/p>\n<p>D:\\Scripts\\ljl\\wincare-oud&gt;<strong>git add *<\/strong><\/p>\n<p>&nbsp;<\/p>\n<p>D:\\Scripts\\ljl\\wincare-oud&gt;<strong>git commit -m &#8220;Uploading existing code to project&#8221;<\/strong><\/p>\n<p>[master (root-commit) 231bafa] Uploading existing code to project<\/p>\n<p>2 files changed, 76 insertions(+)<\/p>\n<p>create mode 100644 _simulateWincare.pl<\/p>\n<p>create mode 100644 res.txt<\/p>\n<p>&nbsp;<\/p>\n<p>Add a remote location repository (you can use \u201cgit remote -v\u201d to confirm the repository has been added) and push the local repository to the remote<\/p>\n<p>D:\\Scripts\\ljl\\wincare-oud&gt;<strong>git remote add origin https:\/\/csggit.windstream.com\/C<\/strong><strong>SG\/WinCareOUDTesting.git<\/strong><\/p>\n<p>D:\\Scripts\\ljl\\wincare-oud&gt;<strong>git push origin master<\/strong><\/p>\n<p>Counting objects: 4, done.<\/p>\n<p>Delta compression using up to 2 threads.<\/p>\n<p>Compressing objects: 100% (3\/3), done.<\/p>\n<p>Writing objects: 100% (4\/4), 1.06 KiB | 0 bytes\/s, done.<\/p>\n<p>Total 4 (delta 0), reused 0 (delta 0)<\/p>\n<p>To https:\/\/csggit.windstream.com\/CSG\/WinCareOUDTesting.git<\/p>\n<p>* [new branch]\u00a0\u00a0\u00a0\u00a0\u00a0 master -&gt; master<\/p>\n<p><strong>But wait \u2026<\/strong><\/p>\n<p>We\u2019ve got a whole bunch of code written and stashed somewhere \u2026 but how does that deploy it? It doesn\u2019t. For compiled code, there would be a build process that follows the commits. Someone like a build manager (or an automated process) takes the updated source code, compiles it, hands it off for testing (may be manual testing by QA people or may be an automated test program), then supplies the compiled binaries for release or deployment.<\/p>\n<p>With our interpreted code, using Git is a process change. Instead of going to the task server, copying the script file to something-ljr.xtn, editing my copy, testing, then moving my copy back to something.xnt \u2013 we would branch the master for development, clone the development branch to our workstation or elsewhere on the terminal server, make changes, test, commit and push those changes, then merge the development branch back into master.<\/p>\n<p>Once the branch has been merged into master, use git on the task server to integrate changes. (The shortcut below can also be done as \u201cgit fetch origin master\u201d and \u201cgit merge master\u201d). I am assuming that fast-forward merges can be done.<\/p>\n<p>D:\\Scripts\\ljl\\wincare-oud&gt;<strong>git pull origin master<\/strong><\/p>\n<p>From https:\/\/csggit.windstream.com\/CSG\/WinCareOUDTesting<\/p>\n<p>* branch\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 master\u00a0\u00a0\u00a0\u00a0 -&gt; FETCH_HEAD<\/p>\n<p>Updating 231bafa..202da14<\/p>\n<p>Fast-forward<\/p>\n<p>_simulateWincare.pl | 10 +++++++++-<\/p>\n<p>1 file changed, 9 insertions(+), 1 deletion(-)<\/p>\n<p>On next script execution, the updated code will be used.<\/p>\n<p><strong>Etiquette<\/strong><\/p>\n<p>There are guidelines to contributing to OpenSource projects (<a href=\"https:\/\/opensource.guide\/how-to-contribute\/\">https:\/\/opensource.guide\/how-to-contribute\/<\/a>) \u2013 if you will be working on public projects, read the guidelines and engage with the other developers. Individual projects may have their own guidelines \u2013 Git <em>itself<\/em> is an OpenSource project on GitHub, but pull requests with the obvious repository (named Git) are ignored.<\/p>\n<p>Here, we all know each other \u2026 if you see a ticket that requests a new column in a report or a different format for an export, make a development branch, sort the issue, test it, and merge the development branch back into master.<\/p>\n<p>There is one part of the OpenSource guidelines that produce more readable code when multiple individuals are contributing: coding standards. Software development teams have formal documents that define all manner of <em>form<\/em> within their coding. How to name variables. Are spaces or newlines used before braces? Are spaces used before parenthesis? How are functions named? What does a program or function comment block look like? How are variable and function names cased? When looking at OpenSource projects \u2013 or our internal team code \u2013 there isn\u2019t a single coding standard. In the absence of a company-supplied standard, most individuals have one of their own. From a class, from a previous job \u2026 <em>something<\/em>.<\/p>\n<p>Some people prefix variable names with type indicators (in statically cast language, you\u2019ve got to search up to the variable declaration otherwise). Some people appreciate concise code and write if(x == y){ doWhatever; } all on one line, others would consider that hopelessly unreadable. Some people use switch statements, some <em>hate<\/em> them and would rather long-form the if\/elseif\/else version. If you are making a quick change (+2 needs to be +4 or some word was misspelt), you don\u2019t need to review the code to see how it is written. Anything beyond a quick edit, it is polite to look at how the project maintainer (or original author in our case) has written the code and follow their form.<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I mentioned that I had inherited a Git implementation last week. Here is the documentation I created to teach my coworkers what Git is and how to use it. Some isn&#8217;t applicable outside of our environment (you won&#8217;t care about the AD groups that control access to the system), some is applicable for small non-dedicated &hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[33,30],"tags":[237,233,238],"class_list":["post-1293","post","type-post","status-publish","format-standard","hentry","category-coding","category-system-administration","tag-bonobo","tag-git","tag-scm"],"_links":{"self":[{"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=\/wp\/v2\/posts\/1293","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1293"}],"version-history":[{"count":6,"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=\/wp\/v2\/posts\/1293\/revisions"}],"predecessor-version":[{"id":5481,"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=\/wp\/v2\/posts\/1293\/revisions\/5481"}],"wp:attachment":[{"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1293"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1293"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.rushworth.us\/lisa\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1293"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}