Starting a git repository?

Git Concepts - Local only repository

Basic Concepts and Workflow

Basic Concepts

  1. Git is a snapshot based system - each commit is a snapshot not a delta, so this may take more space, but it is usually negligible in today's world of large disks.

  2. Nearly every operation is local - It is possible to do everything local if you are working alone.
    1. This means that all the history of the project at the time you copied it is local and you can view it without talking to a server system like Git Lab or some other system (Git Hub).
    2. You can work offline (provided you cloned your repository (repo) from a server.
  3. Everything is check-summed before it is stored and Git uses that checksum to refer to the files and commits.
  4. Snapshot data is stored in a special directory named .git (hidden on Linux based systems), and once you have committed (made a snapshot), it is actually hard to loose it, provided you don't delete the directory. This directory named .git is your repository!

  5. The working directory is where you checkout code from the repository to work on. If you have a folder named MyWebSite that you are working on, it will contain a .git folder that contains all of the git repository information. The rest of the files in MyWebSite is the working directory. That is, it is the current version that you have checked out of the repository to work on.

  6. The next concept is that of the staging area. It is conceptual in that we don't move files to a physical area. Instead it is just a list of files that we have marked as ready to be committed in the next snapshot.

  7. Git has three main states that the data can be in.
    1. Modified - means that you have changed the file but have not committed it to your database yet.
    2. Staged - means that you have marked a modified file in its current version to go into your next commit snapshot.
    3. Committed means that the data is safely stored in your local database.

There are always files that don't need to be included in a git repository. Add a plain text file in the working directory called .gitignore. Put the files or folders that you want to ignore in it, then stage it and commit it. Git will now ignore those files and won't list them as untracked or unstaged etc.

That is the concepts for basic git. Let's put it into action so that you can see a concrete example.

Workflow

Setup the repository:

  1. If you need to create a repository in the current working directory, type: git init

  2. If you haven't created a .gitignore, do so now through your VS environment if possible (see the video below) and commit this change.

Normal Development work:

  1. Make changes in your working directory (e.g. with Visual Studio [code]).
  2. Stage the changes either inside your editor if its VS or VSCode, or at the commandline at the root of the directory git add .

  3. Commit the changes either inside your editor if its VS or VSCode or at the commandline at the root of the directory git commit -m "message"

Git Branching

In the philosophy of Git, the master or main branch should always be ready to deploy/publish.

That means that it should have all files committed, and hence no staged and no un-tracked files that are not in the .gitignore file. So how do we work on a fix or a feature. The answer is branching!

Branches allow you to create a separate working tree that you can play with that does not affect the main or master branch! If someone else comes in to make a change to the master/main branch, it will not affect what you are doing. Every time you start working on a feature or fix, you should create a branch. Often times when you are working on a minor project and you are doing it all on your own, you don't want to deal with branches. And in the privacy of your own computer, working with no-one else, that is OK. But if you are working in any kind of business where files need to be ready to re-deploy at a moments notice, you really should (read must) use branches. Ideally in a small shop, if you have a DEVOPS environment with CI/CD, it may look like this:

DEVOPS Environment.drawio.png

Here in the blue oval are all the critical git activities.

Workflow

  1. Create a branch git checkout -b newbranch

  2. Work on your branch to implement the changes ultimately committing those changes to your branch.
  3. Test your branch to make sure that it works as expected.
  4. Merge your branch back into master. This can be the tricky bit, but for now let's assume that you are the only one working on it.
    1. git checkout master

    2. git merge newbranch

The last step will be, in git parlance, is called a fast forward merge. All this assumes that you have no changes made to the master/main repo.

WHY DO WE BOTHER WITH BRANCHES IF NOTHING CHANGES ON master/main??? Because at any point you have a working program on the master/main branch and that in academia or in business is critical.

One last thing that has confused more individuals new to git and github in particular. Why is a request to merge your code into a project called a pull request? Well the answer is that you are requesting the maintainers of the main code base to pull your feature branch code into their software. If that seems a little backwards to you, just remember that a pull request is just a fancy merge request. Interestingly in git a pull request (i.e. git pull master) is just shorthand for git fetch master followed by a get merge master. To see this just type git help pull. And what does that do? Gets the latest updates in master into your local copy of the repository (assuming you have a remote origin setup). Merges the fetched changes into your branch so that you will be ready to merge your feature branch back into the master/main branch. Then, it merges your updated feature branch back into master/main. HOWEVER, in GitHub, and the like, making a pull request is a bit more involved (including permission and discussion etc. on GitHub). See examples below for more information.

Git Examples

First setup the remote repository:

ssh git@brain2.scotnpatti.com
cd /home/git/repos               # you shouldn't use the base user directory for good reasons -- See SshGen page
mkdir my_project.git
cd my_project.git
git init --bare
git update-server-info # If planning to serve via HTTP
exit

On your local machine:

cd [your project directory]
git init
git add * # or "." if you want to add all the files in the hierarchy
git commit -m "My initial commit message"
git remote add origin http://gitlab.scotnpatti.com/username/my_project
git push -u origin master

Others can now clone track the remote repository:

git clone git@example.com:repos/my_project.git
cd my_project

Adapted from: http://thelucid.com/2008/12/02/git-setting-up-a-remote-repository-and-doing-an-initial-push/

Standard workflow for private project (you only)

edit/stage/commit

git status # View the state of the repo
git add <some-file> # stage a file
git commit -m "message" # commits changes 

You can also add and commit in one statement

git commit -a -m "message"

Publish

git push origin master

GitHub Workflow

You found a project you want to contribute to.

  1. Fork the project (on git hub - now you should have a copy in your repository that is separate from the original)
  2. Clone it to your local file system. (i.e. git clone [url])
  3. Create a branch (i.e. git checkout -b [branchname])
  4. Edit files as needed
  5. Add/commit changes (i.e. Commit -a -m "Message")
  6. push to your forked git repository on github: git push origin [branchname]
  7. Check github for a link to a pull request. (Pull request link should be on code page see end of video).

See the video here

Dealing with Errors

If you are working with multiple people You may get an error when you commit or when you are merging your branch. In the first case it might look like this:

Updates were rejected because the tip of your current branch is behind its remote counterpart. Merge the remote changes (e.g. 'git pull') before pushing again.

So you may need to pull by doing the following:

git fetch origin master 
git merge origin master
git pull origin master

If you have changes, go edit the file to remove the conflicts (Visual Studio [Code] works great for this).

You may then get a CONFLICT (content): Merge conflict in <some-file> which you will need to resolve by type git status. Looking at the git status is a good idea before you do anything.

Branches

So you started working on a program and realized that you should probably have started a branch. So,

git checkout -b [branchname]

... will create and checkout the new branch using the exiting code while leaving the old branch as is.

To switch to an existing branch leave off the -b. To switch to the previous branch do:

git checkout -

Viewing history

git log

Merging a Branch

Suppose you checkout a new branch

git checkout -b scot-bugfix

If you did this locally and not on gitlab, you will need to push it to getlab with the --set-upstream origin [name_of_branch] in our case it would look like:

git push --set-upstream origin scot-bugfix

Now, when you go look at gitlab, there will be a new branch called scot-bugfix.

Before you get to far on the bugfix, your boss comes in and gives you a hotfix that must be completed post haste. So, you create another branch off of main

git checkout -b scot-hotfix main

You immediately create the hotfix and commit it

git commit -m "Finished hotfix"

Then you switch back to main

git checkout main

and complete a git pull

git pull

This ensures that you have the latest. Let's assume for the moment that there were no updates on main since you branched. In this case you will be merging using a fast forward merge. Once done, you can push it up to main (assuming you aren't working with gitlab or github and can't).

git merge scot-hotfix
git push

This will complete with no errors, warnings etc. because no one changed anything. You are now free to delete the hotfix branch and continue working on your scot-bugfix branch.

git branch -d scot-hotfix
git checkout scot-bugfix

Once you are done with your bugfix, you can commit it, switch to the main branch and check to see if there have been any changes since you last looked.

git commit -m "bug fixed"
git checkout main
git status

Now, we have made and pushed changes since the scot-bugfix branch was created. So we know that this merge will not be a fast forward merge. That does not mean that git status will return a state indicating that we are behind commits from origin/main. If we are, we must do a pull, then we can do our merge.*

git pull
git merge scot-bugfix

This may tell us that there are conflicts. Go ahead and edit them in vscode using the resolve conflicts option (or in your editor of choice resolve the conflicts in the file indicated). Once the conflicts are resolved, commit and push.

git commit -m "resolved conflicts in merge..."
git push


*If you happen to be working in gitlab or github, you will have to go to the website and create a merge/pull request. See below for that.

Strategies

Condition 1: There have been no commits to the main branch since you checked out your code and you can merge using a fast-forward merge. This is the easiest!

Condition 2: There have been commits to the main branch since you checked out your code and commit history has diverged and you need to use one of the following methods:

  1. 3-way merge - run the merge and deal with conflicts as above.
  2. rebase - Beginners shouldn't rebase, but if you need to know more about it, see merging vs rebassing

Notes about Gitlab

  1. Its much easier if you create your branch in gitlab, do a fetch from your repo and then you can checkout the new branch. But if you didn't do that, you can push your new branch with --set-upstream ans shown above.
  2. It is absolutely imperative that you wait for gitlab to finish before you do anything else after you push the merge button - go to the merge requests page and check its status if it says complete in 1 minute (or x second), wait a minute and then refresh. When it says that it is done, then you can start interacting with the system again via git. But not before!!!

    1. If you did manage to interrupt gitlab, go to the files and finish the merge by hand. You will see <<<<<<<< ============ and >>>>>>>>>> stuff in there. Edit it and commit it.

  3. Always read the README.md and any .gitlab-yml type files. Some CI/CD stuff is setup by default and it may fail if you don't have any runners.

ProjectManagementTools/StartingGitRepository (last edited 2023-06-06 19:32:34 by scot)