Git

From HaFrWiki
Revision as of 08:55, 6 March 2019 by Hjmf (talk | contribs) (A new repo from an existing project)
Jump to: navigation, search

Git [1], is a distributed revision control and source code management (SCM) system with an emphasis on speed. Initially designed and developed by Linus Torvalds for Linux kernel development, Git has since been adopted by many other projects. Every Git working directory is a full-fledged repository with complete history and full revision tracking capabilities, not dependent on network access or a central server.

Introduction

Many people from traditional VCS systems have trouble learning and especially knowing Git. See the why at Why the heck is Git so hard?.
So if you are still struggling with Git, try to do it over and over. This webpage may help you in doing so.

Stages

Git Repo Stages

This is the main thing to remember about Git if you want the rest of your learning process to go smoothly.
Git has three main states that your files can reside in:

  • Committed
    Committed means that the data is safely stored in your local database or Local repository.
  • Modified
    Modified means that you have changed the file but have not committed it to your local database yet.
  • Staged
    Staged means that you have marked a modified file in its current version to go into your next commit snapshot.

This leads us to the three main sections and and two extra stages of a Git project:

  1. The Stash area,
  2. the Git directory, also known as Local Repository
  3. the Working directory, also known as Workspace
  4. the Staging area, also known as Index.
  5. the Upstream Repository
  • Stash area
    Stashing takes the dirty state of your working directory — that is, your modified tracked files and staged changes — and saves it on a stack of unfinished changes that you can reapply at any time.
  • Git directory
    The Git directory is where Git stores the metadata and object database for your project. This is the most important part of Git, and it is what is copied when you clone a repository from another computer.
    The directory named .git in the project directory of the local copy is the Local Git Repository.
  • Working directory
    The working directory is a single checkout of one version of the project. These files are pulled out of the compressed database in the Git directory and placed on disk for you to use or modify.
    The checkout directory (containing the .git directory) is the working directory.
  • Staging area
    The staging area is a simple file, generally contained in your Git directory, that stores information about what will go into your next commit. It’s sometimes referred to as the index, but it’s becoming standard to refer to it as the staging area.
    As said is located inside the .git directory.
  • Upstream Repository
    The area to put your work so it can be accessed by other co-workers.

Please take a close look at interactive Git-Cheat Sheet at NdpSoftware Git-CheatSheet. The example ScreenShot on the right is NOT interactive!

NpdSoftware-Git-Cheat-Sheet.png

Summerise

When your project is under the care of a VCS, you edit in your working directory and commit your changes to your repository for safekeeping.
Git works similarly but inserts another layer, the Index, between the working directory and the repository to stage, or collect, alterations.
When you manage your code with Git:

  • You edit in your working directory,
  • Accumulate changes in your index
  • Commit whatever has amassed in the index as a single change-set.

Basic Workflow

The basic Git workflow goes something like this:

  1. Modify files in your working directory.
  2. Stage the files, adding snapshots of them to your staging area. In fact telling the repo you will commit the files into the local repository.
  3. Commit, which takes the files as they are in the staging area and stores that snapshot permanently to your Git directory (Local Repository).
  4. Push, which takes the committed files into the remote repo.

Setup

To setup git [2] follow the steps below.

Username

First you need to tell git your name, so that it can properly label the commits you make.

 # Sets the default name for git to use when you commit.
 $ git config --global user.name "harm"

Email

Git saves your email address into the commits you make. We use the email address to associate your commits with your GitHub [3][4] account.

# Sets the default email account for git when you commit
$ git config --global user.email "h.frielink@<you-server-name>"

Cheat Sheet

Always handy are Cheat Sheets [5].

Information & Config

Information Tools
Status Repo git status Store away (stash) git stash
Shows git version git --version Configuration git config
Show files in index git ls-files -s

Creation, Addition & Removal

Create & Clone Add & Remove
Initialized empty Git repository in .git/ git init Add changes to INDEX git add <filename>
Clone local repo git clone /path Add all changes to INDEX git add *
Clone remote repo git clone username@host:/path/to/repo Remove / Delete git rm <filename>
Connect local repo to remote repo git remote add <remote-url> Remove staged files (unstage) git rm --cached <file>...

Commit & Branches

Commit & Synchronize Branches
Commit changes git commit -m "Message" Create new branch git checkout -b <branch>
i.e.: git checkout feature-x
Push changes to remote repo git push origin master Switch to master branch git checkout master
Connect local repo to remote repo git remote add origin <server> Delete branch git branch -d <branch>
Update local repo with remote changes git pull push branch to remote repo git push origin <branch>

Merging & Tagging

Merge Tagging
Merge changes from another branch git merge <branch> Create tag git tag <tag> <commit-ID>
View changes between 2 branches git diff <src-branch> <trg-branch> Get commit IDs git log

Beginner Documentation

The beginners documentation is taken from the cheat sheets of Atlassian [6].

Basics

Git Command Description
git init <directory> Creates an empty Git repository in specified directory <directory>.
Run without arguments to initialize the current directory as Git-Repository.
git clone <repo> Clones a repository located at <repo> onto the local machine.
Original repository can be located on the local filesystem or on the remote machine via HTTP or SSH.
git config user.name <name> Defines author name to be used for all commits in the current repo.
Developers commonly use --global flag to set config options for the current user.
git add <directory> Stages all changes in the <directory> for the next commit.
Replace <directory> with <file> to change a specific file.
git commit -m "<message>" Commits the staged snapshot with given text-message "<message>".
git status Lists which files are staged, unstaged and untracked.
git log Displays the entire commit history using the default format.
For customization see additional options.

Undoing Changes

Git Command Description
git revert <commit> Creates new commit that undoes all the changes made in commit then apply it to the current branch.
git reset <file> Removes <file> from the staging area, but leaves the working directory unchanged.
This unstages a file without any changes.
git clean -n Shows which files would be removed from the working directory.
Use the -f flag in place of -n flag to execute the clean.

Rewriting Git History

Git Command Description
git commit --amend Replaces the last commit with the staged changes and last commit combined.
Use with nothing staged to edit the last commit’s message.
git rebase <base> Rebases the current branch onto <base>.
<base> can be a commit ID, a branch name, a tag, or a relative reference to HEAD.
git reflog Shows a log of changes to the local repository’s HEAD.
Add --relative-date flag to show date info or --all to show all refs.

Git Branches

Git Command Description
git branch Lists all of the branches in your repo.
Add a <branch> argument to create a new branch with the name <branch>.
git checkout -b <branch> Creates and checks out a new branch named <branch>.
Drop the -b flag to checkout an existing branch.
git merge <branch> Merge <branch> into the current branch.

Remote Repositories

Git Command Description
git remote add <name> <branch> Creates a new connection to a remote repo.
After adding a remote, you can use <name> as a shortcut for <url> in other commands.
git fetch <remote> <branch> Fetches a specific <branch>, from the repo.
Leave off <branch> to fetch all remote refs.
git pull <remote> Fetches the specified remote’s copy of current branch and immediately merge it into the local copy.
git push <remote> <branch> Pushes the branch to <remote>, along with necessary commits and objects.
Creates named branch in the remote repo if it doesn’t exist.

Git difference

Git Command Description
git diff HEAD Shows difference between working directory and last commit.
git diff --cached Shows difference between staged changes and last commit

Git reset

Git Command Description
git reset Resets staging area to match most recent commit, but leaves the working directory unchanged.
git reset --hard Resets staging area and working directory to match most recent commit and overwrites all changes in the working directory.
git reset <commit> Moves the current branch tip backward to <commit>, resets the staging area to match, but leaves the working directory alone.
git reset --hard <commit> Same as previous, but resets both the staging area & working directory to match.
Deletes uncommitted changes, and all commits after <commit>.

Git rebase

Git Command Description
git rebase -i <base> Interactively rebases current branch onto <base>.
Launches editor to enter commands for how each commit will be transferred to the new base.

Scenarios's

New repo from scratch

Say you’ve just got some data from a collaborator and are about to start exploring it.

  • Create a directory to contain the project.
  • Go into the new directory.
    $ git init
  • Write some code.
    $ git add .
    to add the files (see the typical use page).
    $ git commit -m "Introduction"
    .

The first file to create (and add and commit) is probably a ReadMe file, either as plain text or with Markdown, describing the project.
Markdown allows you to add a bit of text markup, like hyperlinks, bold/italics, or to indicate code with a monospace font.
Markdown is easily converted to html for viewing in a web browser, and GitHub will do this for you automatically.

A new repo from an existing project

Say you’ve got an existing project that you want to start tracking with git on GitLab [7]

Main Additional Data
Assume:
  • The location is /Sources/AWK.
  • The name for the git-repo is awk.
  • The username is HaFr1954.

Steps:

  • For an existing project follow the steps
  • Goto GitLab
  • Create a new Blank Project let's say awk.git
    • Project Name: AWK
    • Project URL: https://gitlab.com/HaFr1954
    • Project slug: awk
    • Project description: <Give some description>
    • Visibility level: Private
    • Do not Initialize a README.md
    • Click on the button Create project.
  • In the projects directory:
    • Create a .gitignore.
    • Create a README.md.
  • In Terminal:
# Goto the directory containing the project (/Source/AWK)
$ cd /Sources/AWK
# It is very wise to create a .gitignore file and a README.md first!
# Also if made, add to the .svn ignore!
$ git init
$ git remote add origin git@gitlab.com:HaFr1954/awk.git 
$ git add .
$ git commit -m "Initial commit"
 xx files changed, xxxx insertions(*)
 ...
$ git push -u origin master
 Counting objects xx, done,
 ...
 Branch 'master' set up track remote branch 'master' from 'origin'
  • You’ll probably have made a .gitignore file earlier.
    But in case you forgot you can do it now.
    See the right section for an example. Then do:
$ git add .gitignore
$ git commit -m "Introducing gitignore"

Now open SourceTree. You need to add the project. Do:

  • Add existing local Repository

Explanation: The git-directory contains the remote URL! See: the config file in the git-directory!
Almost there, but if your repo also contains a Subversion repo' (and you forget to add that in the .igitignore), you'll need to remove that also but not from the workspace (therefor use the option --cached): [8]

$ git rm -r --cached .svn

And go to SourceTree to finalize by commit and push.

On other devices

To add the same repo on an already existing svn-repo on another device, the most simple way is:

  • Rename the existing directory into AWK-old using the Finder.
  • Clone the git-repo:
    • Open Terminal and
$ rmdir /Data/AWK
$ cd /Data/AWK
$ git clone <url> .
  • Check with BeyondCompare the new cloned folder with the old one.
  • Copy the .svn folder back into the repo. (Can be done in BeyondCompare).
  • Add the Repo to SourceTree using the Add Existing Local Repository.
  • Delete the old repo (after checking all works fine).
Examples Git .ignore file
# Compiled source #
###################
*.com
*.class
*.dll
*.exe
*.o
*.so

# Packages #
############
# it's better to unpack these files and commit the raw source
# git has its own built in compression methods
*.7z
*.dmg
*.gz
*.iso
*.jar
*.rar
*.tar
*.zip

# Version Control
#################
.svn
\#svn-prop.tmp#

# Logs and databases #
######################
*.log
*.sql
*.sqlite

# OS generated files #
######################
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
la

Template for README.md

# Introduction
Project _AWK_ contains ..
The website has always been under VCS Subversion.
It is my wish to migrate to Git, but for a while I want to use both Subversion and Git next to each other.
It does not contain the directories for Subversion and the Log-directory and files.

The main tools for the maintenance of the repository under Git are:
- Git CLI
- Atlassian Git Tool SourceTree.
- Gitlab Webtool

# Comments

# Issues

# Milestones

# Version
The current version is 0.1.0.1 - 24 Jan 2019 - Introduction

## Version History
- 0.1.0.1 - 24 Jan 2019 - Introducing VCS Git

# Explanation on Gitlab Markdown
GitLab uses “GitLab Flavored Markdown” (GFM).
It extends the CommonMark specification (which is based on standard Markdown) in a few significant ways to add additional useful functionality.
It was inspired by GitHub Flavored Markdown.
You can use GFM in the following areas:
- Comments
- Issues
- Merge requests
- Milestones
- Snippets (the snippet must be named with a .md extension)
- Wiki pages
- Markdown documents inside repositories
- Epics

See: https://docs.gitlab.com/ee/user/markdown.html

Problems

Diacritic Filenames

If you have filenames with diacritic characters (i.e. éíóúàèìòùãõ) and you are on OS X, you might have problems. After cloning these files maybe marked as unknown in subversion. Special for MAC:

$ git config --global core.precomposeunicode true

As described in git config man page, the option is related to the particular decomposition of Unicode characters in Mac OS:
This option is only used by Mac OS implementation of git.
When core.precomposeunicode=true, git reverts the unicode decomposition of filenames done by Mac OS.
This is useful when sharing a repository between Mac OS and Linux or Windows. (Git for Windows 1.7.10 or higher is needed, or git under cygwin 1.7).
When false, file names are handled fully transparent by git, which is backward compatible with older versions of git.

Connect it to GitLab

You’ve now got a local git repository.
You can use git locally, like that, if you want. But if you want the thing to have a home on github, do the following.

  • Go to GitLab.
  • Log in to your account.
  • Click the wnew project button in the top-right.
    You’ll have an option there to initialize the repository with:
    • ProjectName (Mandatory)
    • Project Description (Optional)
    • Visibility Level choose private
    • Initialize with a README
    • Click on the create button
  • Click the “Create repository” button.

Now, follow the second set of instructions.

  • On the GitLab go to your project
  • Settings → Repository → Protected Branches"
  • Do the required changes to the unprotect!
  • Now perform
    $ git push gitlab master --force

And you have it done!

Inside .git folder

What's inside the Git-Local-Repository directory .git? [9]

.
|-- COMMIT_EDITMSG
|-- FETCH_HEAD
|-- HEAD
|-- ORIG_HEAD
|-- branches
|-- config
|-- description
|-- hooks
|   |-- applypatch-msg
|   |-- commit-msg
|   |-- post-commit
|   |-- post-receive
|   |-- post-update
|   |-- pre-applypatch
|   |-- pre-commit
|   |-- pre-rebase
|   |-- prepare-commit-msg
|   `-- update
|-- index
|-- info
|   `-- exclude
|-- logs
|   |-- HEAD
|   `-- refs
|-- objects
`-- refs
    |-- heads
    |-- remotes
    |-- stash
    `-- tags
  • COMMIT_EDITMSG (file): The last commit’s message. Not actually used by Git at all, but for your reference after you made a commit.
  • FETCH_HEAD (file): The SHAs [10] of branch/remote heads that were updated during the last git fetch.
  • HEAD (file): The current ref that you’re looking at. In most cases it’s probably refs/heads/master. HEAD always refers to the most recent commit on the current branch. When you change branches, HEAD is updated to refer to the new branch’s latest commit.
  • ORIG_HEAD (file): When doing a merge, this is the SHA of the branch you’re merging into. Certain operations, such as merge and reset, record the previous version of HEAD in ORIG_HEAD just prior to adjusting it to a new value. You can use ORIG_HEAD to recover or revert to the previous state or to make a comparison.
  • MERGE_HEAD (file): (Optional) When doing a merge, this is the SHA of the branch you’re merging from. When a merge is in progress, the tip of the other branch is temporarily recorded in the symref MERGE_HEAD. In other words, MERGE_HEAD is the commit that is being merged into HEAD.
  • MERGE_MODE (file): (Optional) Used to communicate constraints that were originally given to git merge to git commit when a merge conflicts, and a separate git commit is needed to conclude it. Currently --no-ff is the only constraints passed this way.
  • MERGE_MSG (file): (Optional) Enumerates conflicts that happen during your current merge.
  • RENAMED-REF (file): Still trying to track this one down. From a basic grep through the source, it seems like this file is related to errors when saving refs.
  • branches (folder): Contains the branching information??
  • config (file): Contains settings for this repository. Specific configuration variables can be dumped in here (and even aliases!) What this file is most used for is defining where remotes live and some core settings, such as if your repository is bare or not.
  • description (file): If you’re using Gitweb or firing up git instaweb, this will show up when you view your repository or the list of all versioned repositories. Is an old setting.
  • hooks (folder): Git comes with a set of script that you can automatically run at every meaningful git phase. Those scripts, called hooks, can be run before/after a commit/rebase/pull… The name of the script dictate when to execute it. An example of a useful pre-push hook would be to test that all the styling rules are respected to keep consistency in the remote (the distant repository).
  • index (file): The index is a temporary and dynamic binary file that describes the directory structure of the entire repository. More specifically, the index captures a version of the project’s overall structure at some moment in time.
  • info (file): Relatively uninteresting except for the exclude file that lives inside of it. We’ve seen this before in the ignoring files article, but as a reminder, you can use this file to ignore files for this project, but beware! It’s not versioned like a .gitignore file would be.
  • logs (folder): Contains history for different branches. Seems to be used mostly with the reflog command.
  • objects (folder): Git’s internal warehouse of blobs, all indexed by SHAs.
  • packed-refs (folder): Packs away dormant refs, this is not the definitive list of refs in your repository (the refs folder has the real ones!) Take a look at gitster’s comment to see more information on this.
  • refs (folder): The master copy of all refs that live in your repository, be they for stashes, tags, remote tracking branches, or local branches.

Git Tags

Although Git implements only one kind of tag object, there are two basic tag types, usually called

  • Lightweight tags are simply references to a commit object and are usually considered private to a repository.
  • Annotated tag is more substantial and creates an object. It contains a message, supplied by you.

Branches

A branch is the fundamental means of launching a separate line of development within a software project.
A branch is a split from a kind of unified, primal state, allowing development to continue in multiple directions simultaneously and, potentially, to produce different versions of the project.
Often, a branch is reconciled and merged with other branches to reunite disparate efforts.

Merge

The most difficult part of Git is merging, because it is complex and not very intuitive.
The process is complex because it has so many features / strategies.

Replace the master branch with another branch

If you checkout your current branch and merge the master into it with the ‘ours’ strategy, it has the effect of absorbing the master into your current branch but not using anything of the master.
This way, when you checkout the master and do an ordinary fast forward merge of your feature branch, the merge commit will be exactly like your feature branch, effectively making it seem like you replaced the master with your feature branch.

$ git checkout feature_branch
$ git merge -s ours --no-commit master
$ git commit      # Add a message regarding the replacement that you just did
$ git checkout master
$ git merge feature_branch

1. Makes sure you have the correct version
2. The 'ours' strategy resolves any number of heads, but the resulting tree of the merge is always that of the current branch head, effectively ignoring all changes from all other branches. Keeps the content of this branch, but record a merge
3. Merging ours and does nothing with the master.
4. Checking out the new master
5. Fast-Forward master up to the merge

But the best answer is quite simple:

# Makes sure everything is pushed up to your remote repository 
$ git checkout master      

# Overwrites "master" with "better_branch"
$ git reset --hard better_branch

# Forces the push to your remote repository
$ git push -f origin master

Please note to perform the command

$ git reset --hard origin/master

On every other local copy of the repository.

Gui Sourcetree

Atlassian Sourcetree is a GUI Git Client implementing the following git-commands to make your life easier.

Git Commit

git -c diff.mnemonicprefix=false 
     -c core.quotepath=false 
     -c credential.helper=sourcetree commit 
     -q 
     -F /var/folders/.../SourceTreeTemp.d2GNL8 
     -a 
Git CLI Parameter Description
-c name=value Pass a configuration parameter to the command. The value given will override values from configuration files.
The <name> is expected in the same format as listed by git config (subkeys separated by dots).
-q
--quiet
Suppress commit summary message.
-F <file-name> Take the commit message from the given file. Use - to read the message from the standard input.
-a Tell the command to automatically stage files that have been modified and deleted, but new files you have not told Git about are not affected.

Git push

git -c diff.mnemonicprefix=false 
     -c core.quotepath=false 
     -c credential.helper=sourcetree push 
     -v 
     --tags 
     origin refs/heads/master:refs/heads/master 
Git CLI Parameter Description
-c name=value Pass a configuration parameter to the command. The value given will override values from configuration files.
The <name> is expected in the same format as listed by git config (subkeys separated by dots).
-v
--verbose
Run verbosely.
--tags All refs under refs/tags are pushed, in addition to refspecs explicitly listed on the command line.

Git pull

Sourcetree has implemented the pull in a 2-step operation:

  1. fetch
  2. pull.

Explanation: See the discussion on StackOverflow difference origin and master.

git -c diff.mnemonicprefix=false 
      -c core.quotepath=false 
      -c credential.helper=sourcetree 
      fetch origin 
Git CLI Parameter Description
-c name=value Pass a configuration parameter to the command. The value given will override values from configuration files.
The <name> is expected in the same format as listed by git config (subkeys separated by dots).
fetch <repository> Download objects and refs from another repository. It does not merge them! Please note that origin is the repository.


The second operation is the pull command.

git -c diff.mnemonicprefix=false 
     -c core.quotepath=false 
     -c credential.helper=sourcetree 
     pull origin master 
Git CLI Parameter Description
-c name=value Pass a configuration parameter to the command. The value given will override values from configuration files.
The <name> is expected in the same format as listed by git config (subkeys separated by dots).
pull <repository> <branch> Fetches from and integrates with another repository or a local branch. Please note that origin refers to the repository and master to the local branch.

Git tag

To mark a release or create a new release use the git -tagging option.

git -c diff.mnemonicprefix=false 
     -c core.quotepath=false 
     -c credential.helper=sourcetree 
     tag 
     -a 
     -m  Beta-3-Bootgrid-3-Release 

After the tagging the command needs to be pushed.

Git CLI Parameter Description
-c name=value Pass a configuration parameter to the command. The value given will override values from configuration files.
The <name> is expected in the same format as listed by git config (subkeys separated by dots).
tag Creates, lists, deletes or verifies a tag object signed with GPG.
-a Makes an unsigned, annotated tag object. You may also use -s which makes a GPG-signed tag, using the default e-mail address’s key.
-m Uses the given tag message (instead of prompting).
git -c diff.mnemonicprefix=false 
     -c core.quotepath=false 
     -c credential.helper=sourcetree 
     push 
     -v 
    origin refs/tags/Beta-3-Bootgrid-3-Release 

See Push above.

Retrieving a specific tagged version

To retrieve a tagged version, do

# Retrieving the whole cloned local repository
$ git clone
# Retrieving the whole cloned remote repository
$  git clone git@gitlab.com:<username>/<repo-name>.git

# After the clone, list the tags:
$ git tag -l 

# Checkout a specific tag:
$ git checkout tags/<tag_name> -b <branch_name>

Git create Branch

$ git -c diff.mnemonicprefix=false -c core.quotepath=false -c credential.helper=sourcetree branch Bootgrid-4 

$ git -c diff.mnemonicprefix=false -c core.quotepath=false -c credential.helper=sourcetree checkout Bootgrid-4 
Switched to branch 'Bootgrid-4'

$ git -c diff.mnemonicprefix=false -c core.quotepath=false -c credential.helper=sourcetree submodule update --init 

See also

top

External

  • GitHub is the best place to share code with friends, co-workers, classmates, and complete strangers. Over eight million people use GitHub to build amazing things together.
    • Guides GitHub, Basic Information (Guides) to Git and the implementation of Git on GitHub.
    • Help GitHub, The best place to look with a massive number of categories and help. A must if you are looking for something.
  • Cloudforge, Free Git repository Website for all your code.

Internal

Tutorials

Tutorial Git

Reference

top

  1. Wikipedia Git-description, Git Software
  2. help-github, Setup.
  3. GitHub.com, Git-Repository Website for Open Source Projects
  4. GitHub, Help, Guides and more on using GitHub.
  5. Roger Dudler, Sheet Cheat
  6. Atlassian Git, Cheat Sheets.
  7. Co-Existence Subversion & Git, is an indept analysis of the coexistence of Subversion and Git and may also explain strange differences using to 2 together.
  8. StackOverflow, Remove a file/folder from a git repo without deleting it from the local filesystem.
  9. GitReady.com, What's inside your git-directory
  10. SHA: Git uses a common cryptographic hash function, called Secure Hash Function (SHA1), to name and identify objects within its database. Though perhaps not absolute, in practice it has proven to be solid enough to ensure integrity and trust for all Git’s distributed repositories. Git users speak of SHA1, hash code, and sometimes object ID interchangeably.