Skip to content

Instantly share code, notes, and snippets.

@flavius
Forked from sarvsav/git_intro.txt
Last active December 24, 2015 08:59
Show Gist options
  • Save flavius/6773815 to your computer and use it in GitHub Desktop.
Save flavius/6773815 to your computer and use it in GitHub Desktop.
Introduction to git
What is git?
- git is basically, a version control system where you can collaborate with
other and work on your projects. Developed by Linus.
Advantages of using git over other version system?
- git maintains snapshot of your projects, while other SVN store the diff for every change.
- git uses SHA1, so data loss is almost impossible (checks for data integrity).
- git maintains the local database, so the search is faster as compare to other.
git has mainly three areas:
- Working directory (This is the local directory where we code).
- Staging area (After making the changes in your local directory,
you must stage them, only staged files will get affected).
- git repository (Your git repo, server).
git uses 4 kinds of protocol for transfer:
- local file protocol.
- https.
- ssh (the problem with ssh protocol is, we have to create accounts for
everyone, anonymous read access is not possible).
- git.
Installation on Ubuntu:
- $ sudo apt-get install git
Configuration files and directories:
- /etc/gitconfig => for all users
- ~/.gitconfig => for particular user
- yourproject/.git/config => for particular project
git and github.com requirements:
- working internet connection
- ssh installed on your machine
- ssh-keygen, ssh-agent, ssh-add packages installed too (not necessary,
just to save you from lots of work)
---------- Have a cup of COFFEE -------------
Basic setup on your machine and at github:
- create an account at github.com (Free and Premium service, the difference
is we are able to create private repo with premium one).
- now it's time to create a git on github.com (for example - I have created
"flaviusLB")
- it will be created as sarvsav/flaviusLB.git
Set up on your machine:
- run ssh-keygen, it will create private and public keys (by default it
create rsa and dsa both, but you can specify the type by appending
-t option).
- $ ssh-keygen -t rsa
- it will ask for passphrase, use the one that is difficult to guess
and hard to crack.
- it will create two files in your ~/.ssh folder named id_rsa (private key file)
and id_rsa.pub (public key file).
- on server your public key is need to be added in ~/.ssh/authorative_keys file
but in case of github.com you just add them in your account
& save the settings.
- run ssh-agent and ssh-add, so that these keys are stored
and forwarded by authentication agent.
- you can anytime, list the key using ssh-add -l option.
- clone it to the machine
- $ git clone git@github.com:sarvsav/flaviusLB.git
as who are you ssh'ing into the github machine?
As to do ssh, you need an account, it is not possible to do ssh anonymously.
So there is git user for it, that contains all the public keys of the user &
give read access to all public repositories for cloning.
There are two ways, you can authorize the account on the server, one way is
to create the seprate accounts of all the user and give access to them. The
other way is to create a single account and add the public keys of the users
in ~/.ssh/authorized_keys file. Here I am accessing this as git user, and my
public key is already added in authorized_keys file (I added the key in my
github account). In case, the key is not added there, I will prompt with a
message (public key denied). When we have to use the "git push" command if we
have wite access to the directory, then we are able to successfully push the
content too.
- or you can do, is create a folder named flaviusLB on your local directory
- initialize the git using git init command
- create any file (README.md) would be preferred ($ touch README.md).
- marked it as staged by adding into staging area ($ git add README.md).
- commit the changes ($ git commit -m "First Commit).
- you can use the commit and in single step using the command
($ git commit -am "First Commit") a used for all files get staged, use i for
interactive.
- now its time to push on our github server.
- to use ssh , set your remote url as ssh (in case if its https)
- $ git remote set-url origin git@github.com:sarvsav/flaviusLB.git
- or you can use ($ git remote show origin) to see the set url
- now push it as origin
- $ git push -u origin master (it will prompt for your passphrase,
and if you used ssh-agent, you can bypass it but you need to enter it for
once, u for upstream )
- verify by entering the passphrase.
- to pull, you just need the command git pull.
gist snippets:
- the snippets you create are also the git repositories, you can fork them.
- used to share a piece of code with your friend.
- by forking any git snippet, the replica of snippet get created in your
account, where you can work on it, as you have read and write access.
- works directly by using : git@github.com:\d+\.git
How to fork a snippet:
- visit your favorite snippet.
- on right hand side, you will see the option to fork snippet.
Adding remote:
- for adding remote the syntax is (git remote add <name> <remote URI>).
it's a remote URI, not a branch
- $ git remote add flaviusLB git@github.com:6773815.git .
- verify it by entering ($ git branch -r).
- after adding you have two option either fetch or pull.
- in case of fetch, you have to pull data and merge it to your local one.
- in case of pull, data is pulled and merged in one statement.
- lets try to pull the flaviusLB/master branch.
- $ git pull flaviusLB master .
- fetched and merged the changes and renamed file First to git_intro.txt.
- run $ git status, to verify there is no pending files and untracked files.
- $ git branch -r , to check your head position.
- $ git log, to see the logs.
- $ git diff <branch name1> <branch name2>, to see the diff of two branches.
- $ git diff flaviusLB/master origin/master .
- $ git commit -am "fixed the mistakes"
try to avoid -a, it leads to bulky commits. Each commit must be self-
contained, with a commit message which describes it shortly but clearly.
Use for instance -pv (Okay, i will take remember this)
- $ git push origin master
git commit message:
- git commit messages are not only for you, its for all the contributors
working with you.
- commit messages are like the goals of your project, which you have achieved
- git commit messages must be self explanatory, a good commit message help
others to know what changes you have made in your project.
- main feature of git is that it works offline, and if you dont write good
commit messages, then you may loose the benefit. A good commit message will
help you to easily locate the things, what are you looking for.
- git commit messages are not related to your code, its about your targets.
How to write a good commit message:
- always try to make one commit for one change, its bad practice to make many
changes and write a big list of commit message.
- try to avoid mixing two unrelated functional changes.
- never assume that others know what changes you have made, try to use proper
heading and make it self explanatory.
- as git works offline, so never assume that others have working net connection
all the time, so better commit message would be very helpful.
- describe why the change is required.
- what changes you've made.
git message structure:
- brief description of the change (50 chars).
- insert a single blank line.
- description of the change and what it effected and why required (70 chars).
- put the external references at the bottom.
I like that you've tried to really figure out how it works.
Questions:
- Do you have to enter your password every time you want to push? Why/Why not?
- What's the username you authentify as to the github ssh server when you push?
- What is asymmetric cryptography? What is digital signing? How do they work?
Answers:
- no, we dont need to enter the password again and again, as we are using key
based authentication. However, if we had set the passphrase during
private public pair key generation, we need to enter that passphrase.
To avoid passphrase, we need ssh-add and ssh-agent.
Yes, it was wrongly updated by me. I faced this issue earlier I was using
Linux, with no GNOME/KDE environment as server. On server I had configured
X11 forwarding as yes in sshd_config file, and on my client I was using linux
with X11 environment. So i thought that it need X11 environment. Now, after
reading manual page of ssh-keygen I figured it out that it will work perfect
on terminal. "If the identity has a passphrase, ssh-add(1) asks for the pass
phrase on the terminal if it has one or from a small X11 program if running
under X11." pts and tty both will work (virtual terminal too).
ssh-agent dont have any keys by default, to add keys we need ssh-add.
to add where?
ssh-add stores it in memory and passes to ssh-agent.
ssh-add will add the keys, by default it will look into your ~/.ssh directory
ssh-agent is an authentication agent and it will manage the authentication
process.
Where is the passphrase stored once you enter it?
Once entering passphrase it unlocks the private key and the key is added made
available for the ssh-agent. Then it maintain the session using SSH_AUTH_SOCK
and SSH_AGENT_PID. ssh-agent creates a socket and listens,i.e. SSH_AUTH_SOCK
and listens for the incoming connection on it.
- $ git config --global user.name "sarvsav"
$ git config --global user.email sarvsav@gmail.com
the above 2 commands are used to set the default username and email,
& use this name,email for authentication during the process of pushing.
to check all the parameters, you will need to run
$ git config --list
- Asymmetric cryptography is the process, where a user generates 2 keys
private and public, and the one who wants to interact with user will obtain
the public key (it uses rsa algo for encryption), then they start exchanging
the data over network using public key (used for encryption), however the
data is decrypted only by using private key. In case, of symmetric
cryptography, the same key is used for both encryption and decryption, and
its less secure.
Digital signing, is the way to protect yout document from forgery. In the
process of digital signing, you create an MD5 hash first using hashing algo.
MD5 cannt be deoded back to its original text. Then by using the private key,
this hash is encrypted to signature and appended to the original doument.
Once someone, recieves the document, he uses the public key to decrypt the
signature to MD5 and verify that both of the MD5 are same. If they are same
means the document is generated by you.
References:
- help.github.com
- ubuntu manual pages
- http://git-scm.com/documentation
- https://kimmo.suominen.com/docs/ssh/
- https://wiki.openstack.org/wiki/GitCommitMessages
Thankful to Flavius.
/**
* The program must calculate the sum of n numbers, you don't
* know how big n is, but it's >=3.
*
* The stop condition is that the last entered number is the
* sum of the previous two numbers.
*/
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
//there must be only one define for LOG() and it must be variadic - allowing
//the same usage as printf-like functions, but writing to stderr.
//Additionally, a "call" to LOG() must automatically show the file path
//and the line number in code where it was used - for easier bug finding
//and fixing.
#define LOG_NOENT(x) fprintf(stderr,"File %s doesn't exist",x)
#define LOG_NOPERM(x) fprintf(stderr,"No permission to read file %s",x)
enum _file_error { E_SUCCESS = 0,
E_INVALID_CHARS = -1,
E_CNDTN_FAIL = -2 };
struct _output_detail {
int code;
int iTotal;//is it possible to have different values in the same output_detail
//variable for both integer and float results? If not, think about
//a mechanism to make this fact more expressive and "story-telling"
float fTotal;
int myType;//think about using other means of the C language to make the code
//more expressive, rather than writing in code cryptic numbers like "2"
//such numbers do not help to better express the idea behind the code, they
//only make the code harder to follow
//PS: you've already used that
};
typedef struct _output_detail output_detail;
/**
* A function that will check whether the file is of
* int stream or float stream
*/
int FSCheck(FILE *myFile) {
int check = 0; // 0 for int, 1 for float, 2 - unknown
int current;
while((current = fgetc(myFile)) != EOF) {
if (current == 46) {
check = 1;
}
if (((current < 48) || (current > 57)) && (current != 46) &&
(current != 13) && (current != 10) && (current != 9) && (current != 32)) {
check = 2;
return check;
}
}
return check;
}
float FloatDiv(FILE *myFile){
float fCurrent = 1;
int total;
int counter = 1;
while(fscanf(myFile,"%f",&fCurrent) == 1) {
if((counter >= 2) && (fCurrent == 0)) {
return total;
}
else {
if (counter == 1) {
total = fCurrent;
counter++;
}
else {
total /= fCurrent;
counter++;
}
}
}
return total;
}
//this function is not needed. you are allowed to read integers as floats,
//it's not a problem. The only problem was with casting while saving INTO
//output_detail, but you've found the proper solution by using a special
//"data type" field.
int IntDiv(FILE *myFile){
int iCurrent = 1;
int total;
int counter = 1;
while(fscanf(myFile,"%d",&iCurrent) == 1) {
if((counter >= 2) && (iCurrent == 0)) {
return total;
}
else {
if (counter == 1) {
total = iCurrent;
counter++;
}
else {
total /= iCurrent;
counter++;
}
}
}
return total;
}
/**
* Function to calculate the divison of all the numbers
* in series, the stopping condition is when 0 is encountered.
*/
output_detail DivCalculator(FILE *myFile) {
output_detail outputDiv;
outputDiv.fTotal = 0;
outputDiv.iTotal = 0;
outputDiv.myType = FSCheck(myFile);
if(outputDiv.myType == 2) {//you are doing twisted code again by moving such
//checks in a function which is supposed to do only the pure "number
//crunching"
//you are supposed to just read in values, calculate the result as
//a float, and tell the caller where to look inside output_detail for
//the result by setting the myType field. this function is the one
//setting that field, NOT the one reading from it and deciding what to do
// - what to do is already set in stone by the very name "DivCalculator"
outputDiv.code = E_INVALID_CHARS;
return outputDiv;
}
rewind(myFile);
if(outputDiv.myType == 1) {
outputDiv.fTotal = FloatDiv(myFile);
if(fgetc(myFile) == EOF) {
outputDiv.code = E_CNDTN_FAIL;
}
else {
outputDiv.code = E_SUCCESS;
}
}
if(outputDiv.myType == 0) {
outputDiv.iTotal = IntDiv(myFile);
if(fgetc(myFile) == EOF) {
outputDiv.code = E_CNDTN_FAIL;
}
else {
outputDiv.code = E_SUCCESS;
}
}
return outputDiv;
}
/**
* Function to calculate the sum of all the integers
* and checks for the stopping condition.
*/
output_detail SumCalculator(FILE *myFile) {
output_detail outputSum;
int prev1 = 0;
int prev2 = 0;
int current = 0;
int sum = 0;
int counter = 0; //check for prev1 and prev2 get assigned
outputSum.iTotal = 0;
while (fscanf(myFile,"%d",&current) == 1) {
sum += current;
if (((prev1 + prev2) == current) && (counter >= 2)) {
outputSum.code = E_SUCCESS;
outputSum.iTotal = sum;
return outputSum;
}
prev2 = prev1;
prev1 = current;
counter++;
}
if(fscanf(myFile,"%d",&current) == EOF) {
outputSum.code = E_CNDTN_FAIL;
return outputSum;
}
else {
outputSum.code = E_INVALID_CHARS;
return outputSum;
}
}
int main(int argc,
char *argv[]) {
output_detail sum;
output_detail div1;
FILE *myFile;
if (argc >= 2) {
myFile = fopen(argv[1],"r");
if(!(myFile)) {
if(errno == ENOENT) {
LOG_NOENT(argv[1]);
return EXIT_FAILURE;
}
if(errno == EACCES) {
LOG_NOPERM(argv[1]);
return EXIT_FAILURE;
}
}
}
else {
myFile = stdin;
}
//sum = SumCalculator(myFile);
div1 = DivCalculator(myFile);
//if(sum.code == E_SUCCESS) {
//fprintf(stdout, "Sum is %d\n", sum.iTotal);
//}
//else {
//fprintf(stderr,"Error Code: %d",sum.code);
//}
if(div1.code == E_SUCCESS) {
if(div1.myType == 0) {
fprintf(stdout,"Divison is %d",div1.iTotal);
}
else {
fprintf(stdout,"divison is %f",div1.fTotal);
}
}
else {
fprintf(stderr,"Error code: %d",div1.code);
}
fclose(myFile);
return EXIT_SUCCESS;
}
//please think about the names of the structure fields and the name of the
//data structure itself and rename them. Currently, the names are either
//ambiguos - for instance "my" - who is "me"??? or they are not named
//generally enough for what they could actually hold. Do not limit the names
//of those fields and data structure to your current use case - remember that
//you're designing with the FUTURE in mind!
//
//the naming is a very important step because it reflects how
//abstract/generalized you have thought as you were inventing the data
//structure and its fields.
After you've fixed the code, step back from it for a moment and analyze your
thoughts throughout the process of getting peer-review. How have your thoughts
changed?
Why have you structured the code the way it is? What are the implications?
Do not write this document as a programmer, do not talk about code snippets
or specifics about your code, talk about principles and try to gain a
deeper perspective by analyzing everything until now in detail.
Do not use phrases I've used, do not repeat what I've said, do not bootlick.
Challenge yourself and your own thoughts.
Think and write down all of your thoughts as you think. Spend at least one
full hour doing only this.
Do not only think, thoughts are fuzzy, actually write them down - thoughts
become clear only after you've verbalized them some way.
This document could get pretty long.
And remember, philosophize, do not talk about concrete code. The more general
the principles you manage to extract from this experience are, the better.
AFTER you've done this (meaning: after an hour of thinking and writing as
you think), go back over what you've written and think about your mistakes as
you read your own text, then polish the text.
The end result must be a really properly worded and formatted English text,
which really enlightens the reader, which gives insights into what you've
truly learned from this exercise, beyond the superficial technicalities like
using file pointers, POSIX, etc. (Try to avoid technicalities at all price,
this is a philosophy and self-reflection exercise - because I want you to
learn to become independent in your thoughts).
The things I've learned in my first exercise are:
- Code is not meant only for you, it's for everyone. The code you write must
be well documented and properly structured, so that anyone can easily
understand & read your code.
- Writing a Code is path oriented approach, not result oriented. Code is not
about what it does, its about how it does. Because there are so many ways to
complete a task, but choosing the best one is always a good practise. So,
always try to choose the best path to achieve your task.
- Code must be written in human language, not alien's one. It means, always try
to achieve your complex things, with simple ones by using basic functions.
Don't use complex structure that looks like alien language to others.
- Think first & then Code, not Code first then think. Think first what to do,
and how to do, then start working on your code. Don't try to start writing
your code first and changing it according to your need. It will create
trouble sooner or later.
- Code is a house, every room has a special meaning not a circus tent where all
things perform at single stage. It means, your code must be divided into
smaller structures that perform specific tasks (for eg. Kitchen is dedicated
for cooking purpose), don't try to achieve all the things at same place.
It will mess up all the things, and difficult to understand. You will loose
lots of features of your code.
- Code is one time process. It means, once you have written, it need not to be
restructure again and again as your requirement changes, rather, its easy to
embed and extend it.
- Writing a code, assuming that you're the genious is the foolest thing of all,
as it leads to complex structure, and may not be helpful for others.
The reason why we structured the code in above manner:
Let's take the analogy to make it more clear, every element in this world
constitue of smaller and simple elements. For Ex: Take the case of water,
it's made up of atoms & molecules, then atoms can be further classified into
electrons, protons and neutrons. So, In the same manner your code must be
combination of small and simple elements, which results in fully functional
program and having all the properties.
Like water has the property of easily mix up with the salt and other elements
(eg. sugar,honey) & results in new product. In the same manner, your code can
easily be extended and mix up with other codes, to provide different functional
structure and properties without making changes in core elements.
Like water, if you pour it in kind of jar, it will shape itself accordingly
doesn't matter the shape of jar, in the same manner your code must be able to
handle each kind of user input, doesn't matter what the user have entered and
works well for every situations in all kind of environments. As water don't
loose it's properties by pouring in different kind of containers. So, your
code is not environment specific.
By having such properties, your code can be:
- easy to understand
- easy to implement
- works with every kind of environment
- handles every kind of input
- easy to extend
- easy to embed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment