Git | Keeping Git Simple

Git Commands | For What You Need To Know and What You Need to Get Done

Before issuing Git commands you need to know where you stand. Your remote repo project, your branches, your local changes, the set and that hasn’t been pushed and the pushed branches that haven’t been merged.

You need the Git commands

  • that tell you what the state of play is?
  • that do what needs to get done.

When you need to know the state of play you come here to get the Git commands that tell you what you need to know.

Git | I’ve Done This, I Need to Do That

The key states and commands to run are broken down into the scope, the state of play, the question in your mind and the commands that will deliver the infformation (value) you need.

I’ve Done This I Need to Do That What you need to Know What to do – to get the job done
I’ve Sat Down What Branch Do I Checkout and Edit? What branch will I use? Commands initialize, checkout a remote branch
I’ve Edited Files and Folders How Do I Add Edits to a Commit Set? What branch will I use? Commands initialize, checkout a remote branch
I’ve Added Edits to a Commit Set How Do I Commit (Stage) a Commit Set? What branch will I use? Commands initialize, checkout a remote branch
Working Copy from/to Staged Changes I’ve made changes (add, edit, move and/or delete). How do I stage or (revert) changes in my working copy? Commands
Staged Changes to/from Commit Sets I have staged the changes I want to commit. How do I commit (or reset) my staged changes? Commands
Commit Sets to/from Remote Branch I’m ready to push, unpush, pull, unpull perhaps even purge commit sets to and from remote. What commit sets need to be pushed, purged and pulled? Commands
Remote Branch to/from Master Ready to merge (or unmerge) branches with master (and/or others). I need to merge this branch with master (or rebase)? Commands

Git | How do I Search For Strings, Files and Folders

These commands search the entire project in your working copy – that’s the simple way – but you can get funky and search all manner of corners using certain modifiers.

It doesn’t matter at which directory level you are – unlike the Linux grep command that searches the folder you are in (or recursively below with a -r switch).

  1. git ls-files *.html » to find all html files
  2. git grep simple » to search (project) for lines containing “simple”
  3. git grep -in simple » case insensitive search for “simple” (with line numbers printed)
  4. git grep simple -- *.html » search for “simple” in html files
  5. git grep -in "simple " -- *.java » simple followed by space in java files

get funky and search all manner of corners

You can search files that have been deleted, ignored, staged, not yet merged and even modified using switches like below.

–[cached|deleted|others|ignored|stage|unmerged|killed|modified]
-[c|d|o|i|s|u|k|m]

Simple Git

Git can be over-complicated so here are “simple as” listings command groups that deliver observable value.
Just because you can (handle complexity) does not mean you should.

You want your brain working on your domain – not fighting with abstract version control concepts. These 7 things are what you’ll do with Git 90% of the time.

Git – The 7 Simple Git Tasks

  1. create or connect to a Git repository
  2. branch the master line
  3. edit, add and delete files and folders
  4. commit (to the branch) frequently
  5. pull frequently (this makes the merge easier)
  6. push into the branch
  7. merge the branch back into the master

Don’t worry you are still doing 3 things – checking out repository files usually from a remote repository, changing your copy and checking your changes back into the repository. Git is still the copy modify merge model (as opposed to lock change unlock).

Git Configuration – Line Endings | Global or Local

For Linux Git clients use
git config --global core.autocrlf input

For Windows Git clients use

git config --global core.autocrlf true

You can configure using –local or –global (steer clear of –system). You need to tell git your full name and email address.
For scripts it is best to use --local and for human beings on a Windows client say it is best to use --global

Human Being

git config --global user.name "Apollo Akora"
git config --global user.email "apolloakora@gmail.com"

DevOps Software

git config --local user.name "DevOps Script"
git config --local user.email "devops@assets4u.co.uk"

0. The First Git Client Interaction with a Git Repository

This is the simple case – you can interact with a git repo via archive files, ssh, and so on.

Assume we have installed GitLab and we have a username and password to the repositories that we have setup within it. Cloning is easy.

  git clone http://www.assets4u.co.uk/commons/laundry4j.com.git/ mirror.laundry4j
  git checkout -b first/branch
  ... (make changes)
  git add .
  git commit -m "The first repository checkin"
  git push -u origin first/branch
  ... (enter username/password)

Either in emacs or Git Bash or DOS prompt (do not use Tortoise Git) – Git will pop up a box asking for the username and password. Enter these and you are done.

First Git Workspace – Important Notes

The below are important and need careful attention.

  1. the forward slash after dot git is important .git/
  2. append .git/ in the above clone url to avoid pesky warnings
  3. append .git/ to url in workspace .git/config file if you forgot
  4. ensure in main git config (off home) » autocrlf = true

1. Create or Connect to a Git Repository

The most common use case is connecting to a ready-made remote repository which is readable by everyone.

  git clone http://www.assets4u.co.uk/docs/ mirror.documentation.git
  cd mirror.app.assets
  git show

Git Clone | Key Considerations

Keep two things in mind when you clone a repository.

  1. End the repository url with a forward slash.
  2. End (with .git) the name you choose for the git assets folder.

If you omit the final forward slash when cloning the repository you will get the below warning every time you do a git push origin ...

warning: redirecting to …

Lucky for you – the final forward slash omission is fixable.

Visit the .git/config file (off your local working directory) and add the final forward slash there.

Creating the Original Git Repository

To create the original (source) repository, you can

  1. create an account at GitHub, GitLab or BitBucket
  2. create a (local file accessible) git repository
  3. create a (remote ssh accessible) git repository
  4. instal GitLab and http/https wire it with nginx

The Git Front Ends

You manage Git (and all version control systems) from a local mirror called a “working directory” or “working copy” and a way to issue commands.

Front end client software talks to the Git API on your behalf. You can choose to use one (or more) of the below Git clients

  1. Tortoise Git – a high quality Windows based GUI. It has a great diff and conflict resolution interface.
  2. Git Bash – a command line (or GUI) shell which coincidentally rolls out (brings to Windows), most Linux shell commands as a tribute to its (Git’s) creatorLinus Torvalds).
  3. any SSH Client like Putty or MobaXTerm – they talk to a remote Git repository by issuing commands through SSH (TCP based) protocol (only for hardcore users).
  4. Emacs Generic Version Control Interface – emacs has a generic interface that talks to Git, Subversion, Mercurial, Perforce and more. Clearly the productivity boost is felt most keenly by emacs users.
  5. Every self-respecting IDE ships with a Git communicator as standard – this includes IntelliJ, Eclipse, Visual Studio, NetBeans and PyCharm.

The 4 Git Back Ends

GitHub, BitBucket (and the hosted GitLab) are free as long as everyone can read your intellectual property. If you can install GitLab, you get to choose who can read (fork) and/or write (merge) to it.

The 4th Git Backend – Your Filesystem. – Every git working directory is a repository all in itself carrying the full repository version history.

git clone http://www.assets4u.co.uk/ mirror.app.artifacts.git

The git clone command gives you a mirrored functional repository containing the full version history.

2. Branch the Master Line

You’ve cloned the repository (see above) to a directory called mirror.app.assets.

Your aim is to commit after every little successful change – once every 10 or 15 minutes. But you don’t want to hammer the main repository – aim to update (merge into) the main repository every time you finished and tested a feature, usually once or twice a day. Within the mirror.app.assets folder root

git status
git checkout -b ui-layer/bug-4214
git status

Checking out a branch you did not create

When checking out a branch you did not create the command git checkout ui/contact-form will fail because that branch does not exist in your .git folder (under remotes).

The solution is to use the -b switch to create the branch on your local machine as a copy from the remote one. But first it pays to update your repo remotes with a git fetch.

git fetch origin
git checkout -b ui/contact-form origin/ui/contact-form

Now you workspace will echo the changes in the remote branch – your remotes will be up to date and you are ready to continue working on this branch.

git status – after checking out a branch

The git status command the first time says “your branch is up-to-date with origin/master” and “nothing to commit”. That’s the simple way before branching. (If not then you get into stashing and other confusing matters).

The second time the git status command says “On branch ui-layer/bug-4214″

Branch Naming

Keep your branch (feature) names simple and informative. Like

  1. validate-emails
  2. process-clientxml
  3. feature-153.12
  4. reafactor/monolith/login.use.case
  5. mysql-to-mongo/drivers

Software Downloading Repository Assets from a Branch

Frequently operational and provisioning ( iaas – infrastructure as a service) software will download and use repository assets. If you want that software to read from your branch and not the master line use the below command.

  git clone -b ui-layer/bug-4214 http://www.assets4u.co.uk/vcs/know.how mirror.app.assets

3. Edit, Add, Delete, Rename Files and Folders

$ git add puts a file or folder into the commit set

git add | Adding to the Commit Set

Just go ahead and create files and folders, edit them and even delete them. It’s all good.

Run this command after you either create or change a file that you want to commit.

git add path/to/new-file.txt

git add | When do I use it?

In Subversion you add the file just once (after it is newly created). In Git you have to add the file every time you want to commit the changes. If you don’t add it, it won’t get committed. There is a shortcut in the next section by employing the -a switch to git commit.

You do need to use git add when

  1. you have created a new file
  2. you have edited a file and you want to version your changes
  3. you remove an already committed file
  4. you have renamed a file without using git rename

But you do not need to use git add when

  1. you use git rm to remove a file or folder
  2. you use git mv to move a file or folder
  3. you plan to use the a switch in git commit -a -m “Commit Message.”

Using git add (Period)

Tip | Using git add (period)

Did you know you can use git add (period).

git add .

Running this at the folder root of your working copy will add every single changed file to the commit set. It doesn’t add new files but it can be really handy if your IDE does a massive refactor and changes 200 files here there and everywhere.

Be careful not to delete files or folders that have been committed. The simple way is to sync (commit) them first.

Also renaming or deleting files changed in the repository (since you cloned it) – can cause stress. So it pays to refresh (“pull” or “checkout”) before the rename or delete.

It is best to use git mv because your version history will be preserved and viewable against the renamed file.

Finally note that Git can maintain version history when files and folders are renamed. Other repository managers treated renaming as “deleting” and then “adding” thereby banishing the history. Git does it better so you Git rename.

Empty Folders are Ignored

git by name becomes git by nature and ignores you

You will be ignored if you create an empty folder and try a git add or git status. Git by name really does become a git by nature.

Mind Change? | Rolling Back a File in Git

You’ve changed your mind about the changes in a file and you want to revert. What you do depends on these situations

  1. the local file is identical to the one in the repository branch but different to the one in master.
  2. the local file is identical to the one in the commit set but different to the one in the repository branch.
  3. the local file is not in the commit set and is different to the one in the repository branch.

[a] Identical to Branch | Different from Master

Your Intent

You want to roll back and make the file contents match the one on the master branch.

Your Situation

Your local file is not in the commit set. Furthermore it is identical to the file in the repository branch that you are working on.

Your Saviour

git checkout origin/master path/to/file

Assert that git status lists your file in the index (commit set). Your file is listed as “modified”.

Once you commit and push to the branch – the contents of the file in the repository branch will have been rolled back and are identifical to the contents of the file in master.

[b] Identical to Commit Set | Different from Branch

Your Intent

Actually you want to see two things.

  1. your local file identical to the file in the repository branch and
  2. the file removed from the commit set

Your Situation

You change your mind after editing the file and putting it into the commit set (with a git add path/to/file.

You want to undo two things. You want to undo your edits and you want to undo putting the file into the index (commit set).

Your Saviour

git reset HEAD path/to/file
git checkout path/to/file

Now do git status and your file should no longer be in the index (commit set).

Also your local file has been rolled back and is identical to the file in the repository branch.

[c] File Not in Commit Set (Index) | Different to Repository Branch

Your Intent

You want to roll back the edits you made to a file. You want the file contents to be identical to the file in the repository branch.

Your Situation

Your local file is not in the commit set. You edited it but you did not do a git add path/to/file. However, the contents of your file differ fron the contents of the file in the repository branch you are working on.

Your Saviour

git checkout path/to/file

Assert that git status still does not list your file in the index (commit set).

Check that your local edits have vanished (been rolled back). The local file is now identical to the file in the repository branch.

4. Commit to the Branch Frequently

You should commit every time a small change works – so every 10 to 15 minutes if you are adding and editing familiar code. This git command commits to our branch. It commits the files we have created, edited, removed and/or renamed and explicitly added with the git add command.

Go to our mirror.app.assets repository root.

  git status
  git commit -m "fixed validation of email addresses lacking periods"

Shortcut | Adding to the Commit Set During the Commit

If you are editing many files (or your IDE does a massive cascading refactor for you) – it makes no sense to add each and every file to the commit set individually. Lucky for us, git commit has a -a switch which assumes you want to add all new and edited files to the commit set.

  git commit -a -m "fixed validation of email addresses lacking periods"
  git status

Git Commit Name / Address Warning + Line Endings Protocol

Your name and email address were configured automatically based
on your username and hostname. Please check that they are accurate.

To avoid the above warning and to have the correct Windows/Linux line endings add the below snippet to the .gitconfig file in your home directory.
For emacs projects you add the below to the mirror.app.assets/.git/config file. Beware not to duplicate the [core] block as it may already exist.

[user]
name = Apollo Akora
email = apolloakora@gmail.com
[credential]
helper = manager
[core]
autocrlf = true

Once done, you should see the more succinct text below after git commit.

git commit -a -m “Committing a wee change.”
[ui-layer/bug-4214 2b0ee8e] Committing a wee change.
1 file changed, 1 insertion(+), 1 deletion(-)

5. Pull Frequently From the Master Branch

If the team is pushing changes into the master branch (see step 7) – it pays for us to pull those changes (twice a day) into our branch. When the time comes to merge our branch back into the master – you will be glad you pulled frequently. If others are working on the same branch as yourself then employ the second command.

  git pull origin master
  git pull origin ui-layer/bug-4214

If no files or folders clash your branch will be updated with the current contents of the master branch making our lives significantly simpler when we come to merge our branch back into master (see step 7).

6. Push Into the Branch

Once you have a gaggle of commits and you want to test your entire branch – the time has come to push up all your commits into the branch. This does not change the master branch – but it will allow you to see the up-to-date difference between your branch and the master.

  git push origin ui-layer/bug-4214

7. Merge branch back into the master

Finally we are ready for the team to see our bug fix. Aim to merge back into master once, twice or three times a day. It depends on how fast you develop a distinct feature or how fast you fix a bug, or how fast you perform a refactoring.

Three (3) common ways to merge our branch into the master exist

  1. the quick way
  2. the careful way
  3. the conflicts way

1. Git Branch Merging (The Fast Way)

Below is the fast (one-command) way to achieve merging our branch into master.

  git push origin ui-layer/bug-4214:master
  git branch -d ui-layer/bug-4214

Note the 2nd command deleted the branch on our local machine (the repository still has it).

This method cannot be used when an integration bug exists. An integration bug is when both branches work separately but not together.

2. Git Branch Merging (The Careful Way)

With the fast way you cannot forage and finger out integration bugs because master gets the branch changes immediately (in a conflict-free scenario).

We can forego changing the master branch after the merge.

With the careful way you can run exploratory and integration tests on the merged entity. If you aren’t happy abort changing the master.

The procedure is to

  1. pull master into a local folder
  2. perform the merge locally
  3. run integration and exploratory tests on the merged entity
  4. abort the merge if necessary
  5. push to the master branch if happy

As we are merging the two branches locally, we can resolve clashes and conflicts locally. You can now change your local repository in-place.

  git checkout master
  git pull origin master
  git merge ui-layer/bug-4214

The merge is done locally so do your integration and exploratory tests now. Skip the next step if you decide not to proceed.

To update the remote master (effectively merging the branch into it) – you issue this single command.

  git push origin master

In order to use git push you must have already run the command git push -u origin master in the session.

3. Git Branch Merging (The Conflict Way)

If there are conflicts between the branch and master – we need to step with even more care. Let’s assume the branch we are merging is called eco/cli.

First check out the branch that is to be merged.

  git fetch origin
  git checkout -b eco/cli origin/eco/cli

Then review the changes locally and when you are ready to proceed with the merge you do the following

  git checkout master
  git merge --no-ff eco/cli

Now is the time to resolve the conflicts. Simplest way is to go to the conflict locations and remove the line of left and right arrows and set the code in between them the way you want. Save and you are done – finally you push back to master.

  git push origin master

Leave a Reply

Your email address will not be published. Required fields are marked *