File Status life cycle in Git
UnTracked:
When a new file is created or added to the repository, Git will not track it
untill we include it in our repo by using the –add Command.
Once
‘added’, the state of the file becomes ‘UnModified’ and it is ready to be
modified or commited.
If modified, the file state becomes ‘Modified’ and it is
ready to be commited i.e it has reached the staging area also called as Index.
Staging
area or Index is a virtual place that collects all the files that we want to
include in the next commit.
-When
we modify a content and not committed it, then it is still in the working
directory and will show as modified in each and every branch of repository,
until we commit it to some specific branch.
-Files
in the working directory can be a)
Tracked or b) UnTracked
After
adding, the files becomes tracked.
The Tracked Files can be a) Modified or b) UnModified or c) Staged
To
make proper good of Git, just avoid
1.
working hard on the same file on different branches.
2.
Rarely merging the branches.
-
A Hash is a name, whereas a ref is a pointer
to a commit.
The
default shell that comes with GitHub for windows is PoshGit, which is windows
power shell environment for git.
Poshgit
will let you use windows and powershell commands with Git at the command line.
On the other hand, GitBash uses Bash Shell (Bourne Again Shell) which is part
of a Linux style environment and command line tools.
-
Common Rules for Rebasing in Git:
1.
Never Rebase after pushing a branch.
2.
Never rebase after commits use your branch.
3. Never rebase after pulling someone else’s branch.
Git
Personalization configuration and settings can be applied at
1. System configs : These are available for all
the users and repositories on the system .ie. TOP LEVEL
2. Global configs: These are available for all
the repos of current user.(MIDDEL LEVEL)
3. Repository Level configs : These are only
available for current Repo.(LOWEST LEVEL)
Every config parameter can
be set a every level and if the same parameter is set at different levels, then
the lowest level parameter hides the top level parameter.
For
System level config we use the --System flag.
For
user specific settings we use the --
global flag.
For
Repository level config we use the --local flag.
If
we don’t specify any of these options, then the config setting will take place
only in the current repository we are in now.
Global
settings are stored in ~/.gitconfig and local settings are stored in the file
.git/config for the repo we are working on.
>
to edit the .gitconfig in a text editor
>
vi ~/.gitignore {here “vi” is a text editor, press “I”
to go into editor mode and “wq” to save
n exit.}
1. Local Protocols – Cloning to the local system. Limited access.
2. Git Protocol- Only read-only so cant push. No security provided.
3. Http/https Protocols: connection is encrypted. If repo is public, we can clone/pull anonymously over https. For pushing, credentials verified. Https always works even if we are behind any firewall/proxy.
4. SSH Protocol: Git recommends using https over ssh.
-For
pushing over https, credentials are verified repeatedly , so to remember
credentials use below, default is 15 mins.
Git
config --global credential.helper cache
We
can also set Timeout in seconds eg. For one hour
git
config –global credential.helper ‘cache –timeout=3600’
GIT
PUSH
git
push origin master
origin:
it is our remote destination that we set by using remote add command.
Master:
it is our current active branch.
git
push simply pushes the code in the current branch to the remote origin branch
of the same name. Branch is created on the origin if not already present.
git push -u -- set-upstream origin – all
git
push remote_branch_name : pushes the code in the current branch to the named
branch on the remote.
git
push ‘origin_remote_branchname’
‘localbranchname’
Above
command pushes our code from the local ‘localbranchname’ (irrespective of our
current branch) to the remote branch of the same name on the remote. If the
remote branch not exists, then it will get created.
git
push remote_name local_branch :
remote_branch
Above
command pushes the local_branch from the local repository to the remote_branch
of the remote.
Above
command can also be used to delete a branch on the remote. eg.
git
push remote_name : remote_branch
Note
that we are sending an empty branch to the ‘remote_branch’ branch of remote,
which empties the remote_branch i.e deletes it on the remote.
git
push -u origin
mybranch
Here
we are uploading our ‘mybranch’ branch(with all the commits in it) to the
remote origin.
The
–u option is used to track a remote upstream branch i.e it will tie our local
branch with remote one. This process is not automatic. We have to set it
manually using –u flag. So that when we use git –fetch command, then we get
changes from all the tracked branches.
Use git config -- global
push.default nothing = to change the default push settings.
Now we have to mention the target branch everytime.
Use git config – global push.default simple
= Now git will push only when
there is remote branch with the same name as that of the local branch.
GIT
PULL
To
update local repos, we first download and then merge.
git
fetch remote_name (or ) git fetch
Following
a fetch, we have to merge eg.
To
update the local master branch with the remote master branch, we use
git
merge origin / master it will update the currently
active branch.
Git
Pull is essentially a Git Fetch followed by a get merge.
-
To update currently active branch.
git pull origin master
Like
merge, git pulls are fast-forward by default. but can be overridden by – no- ff
postfix.
Like
push, we can specify different local and remote branches for pull too.
git
pull or git pull remote_name by default, it pulls the code from the
master branch of the origin remote and merges into currently active branch, or
we can also give name of the remote branch.
git
pull remote_name branch_name
It
pulls code from the ‘branch_name’ branch of the ‘remote_name’ remote and then
merges to the currently active branch.
git
pull remote_name local_branch :
remote_branch
it
pulls code from the ‘remote_branch’ branch of the ‘remote_name’ remote and
merges with the ‘local_branch’ branch in the local repository.
GIT Commands
git add –a : Add changes from all tracked and untracked
files.
git add –u : Do not add new files. Only add changes to the
currently tracked files and removals to the next commit.
git add . : Do
not add removals. Add new or changed files to Staging.
git commit –a : We can skip (adding to staging) of a
modified file by postfixing –a to git commit which performs add operation. But
“-a” only adds tracked files hence we might lose any untracked files that we
wanted in the commit. Also “git commit
–a “ would add all the changed files in the same commit.
git branch ‘brach_name’
Base
creates a branch based on
existing one. eg. git branch
testbranch HEAD
git add -P
Shows the path and staging hunks. Partial commit.
-
To unstage a file after git add, we use
‘git reset HEAD
myfile’ or ‘git reset
myfile’ but changes will be retained in the working directory. and to undo the
changes in the working directory, use
‘git checkout myfile’
git reset – soft HEAD~1
To undo a commit. The soft
option undoes a commit but lets the changes we made in that commit remain
staged for us to review.
-To create a branch based on
certain commit
git checkout
-b mynewBranch cafdef
-To rename current branch
git branch
-m renamedBranchName
The ‘-m’
flag : move/rename a branch and its reflog.
The ‘-M’
flag : move/rename a branch even if the target already exists. ie.
overwrites it.
To delete a branch
git branch -D
branchname
git branch -d branchName
‘-d’ flag will delete the
branch only if it has been synched i.e it will only delete a fully merged
branch.
‘-D’ flag will delete the
branch even if it is not merged.
A branch is just a link
between different commits and HEAD of a branch points to the latest commit in
the branch. i.e. HEAD and the tip of the current branch points to the same
commit.
-
-- ff merge
: Only the branch path way is
changed and the HEAD of the branch is updated. It is default.
-
-- no - ff
: A new commit is created on the
base branch with the changes from the other (to-be-merged) branch. eg….
git merge -- no -ff
newFeatureBranch
If there is diverging
history, then there can’t be a --no -ff merge.
-
alias
gl = ’git log -- oneline -- all -- graph --decorate’
To unstage a file
git rm --
cached [file]
git diff : Without any flag it compares whats in the
staging area with whats in the working area. i.e difference of what is changed
but not staged.
git diff -- staged
To compare Staged and
Committed git repository. ie.
difference of what is staged
but not yet committed.
git diff (file_name) Show changes in single file compared to last
commit
To compare working directory
with the git repository ie. without taking into account staging area
diff HEAD <filename>
HEAD is actually a reference
to the last commit on the current branch.
git diff branchB -- branchA
Shows the difference of what
is in branchA that is not in branchB.
git diff <sourceBranch> <targetBranch>
CTM : Note that the
differences are shown from the point of view of the targetBranch.
git log : Shows the commit history for the currently
active branch.
git log branchB -- branchA Shows the commits on branchA that are not on branchB.
git log --follow [filename]
Shows the commits that
changed the file, even across renames.
git log --stat -m
Show all commit logs with
indication of any paths that moved.
git log --oneline
--graph -- all --decorate
git log --pretty = “%h, %cn,
%cr”
git log -all
Shows commits in all
branches including current branch.
To temporarily store
modified, tracked files in order to change branch.
git stash : save modified and staged
changes.
git stash list : list stack order of stashed file
changes.
git stash pop :
write working from top of stash stack.
git stash drop : discard the changes from top of stash
stack.
git stash apply : to apply changes that are stored in the
last stash.
To restore an old stash, we
mention the serial no. next to the stash in the list of stashes.
git stash apply stash@{1}
We can apply multiple
stashes too.
Stash commands stashes the
changes made to the Tracked files only. To add untracked files to the stash, we
have to add them.
To see few latest commits
git log -n 2 or git log -2
git log
--after=’2015-3-1’ or git log
--since=’2015-3-1’
git log
--before=’2015-3-1’ or git log
--untill=’2015-3-1’
git shortlog : shows the authors of commits and
messages.
git log --author = ‘vikas’
To
stage only a part of our changes to the same file use
git
add -p
Git
will club all the changes together into a hunk and give us options. A larger
hunk can be further splitted into smaller hunks by using the option ‘s’
CTM:
After staging a part of the modified file, never commit the changes by using
the ‘--a ’ option, as this would add the rest of the modified file too.
Cherry
Pick :
If we wanted to merge a single commit from one branch into another
branch, then merge or rebase wont suffice. In merge and rebase we join our
current branch with a different branch. ie. all the changes/commits that have
happened since it diverged from our branch, will appear in our final branch
after merge.
With
cherry pick we can pick a single commit from a different branch and make it
appear in our own branch eg.
git
cherry -pick abcdef [this is the commitid of the commit]
git
cherry -pick -- continue : continues the operation in progress.
git
cherry -pick -- abort :
cancel the operation and return to the pre-sequence state.
git
cherry -pick --quit : Forget the current operation in progress.
We
can even pick the commit sets by using the
<startcommit> --
<endcommit> syntax. eg.
git
cherry-pick mybranch~2 .. mybranch~0
By
this syntax, we are picking the last two commits from the ‘mybranch’ branch.
Git
enables searching in commit messages by using the --grep option.
git
log --grep = ‘redirect’ : searches for ‘redirect’ in the messages.
Tags
: The Tags are the labels for milestone commits in the repository. They can be
used to mark changes being made without creating an extra branch. Tags provide
an easy way to go back in history of branch.
git
tag : list the tags in alphabetical
order.
git
tag tagname : create a tag by the name of ‘tagname’
git
show mytagname : Show tag details
There
exists two types of Tags. Lightweight
and Annotated.
LightWeight
: only tagname and points to a commit.
Annotated
: contains tagName, info about tagger and a message.
To
create annotated tag
git
tag -a myTagName -m ‘my commit message’
We
can also checkout a Tag named ‘myTag’ by creating a new branch.
git
checkout -b myBranchName myTag
By
default, when we push our code to remote, our tags won’t get pushed.
To
push our tags to the remote origin, we use
git
push origin --tags
To
specifically push a named Tag
git
push origin mytag
A
Hash is a name whereas a ‘ref’ is a pointer to a commit. Refs are stored
internally in Git.
HEAD
is also a ref.
Some
special refs are ORIG_HEAD, MERGE_HEAD, FETCH_HEAD
reflog
is a ref of logs.
Any
change we make in the Git is recorded and accessible via the reflog command ie.
changes like commit, merge, checkout etc.
git reflog
reflog
command stores the records for each action we performed in our repository
locally.
reflog
can be used to review changes to our local repo and can also be used to recover
lost commits. i.e. If during hard reset we lose some of our commits, then by
using the reflog command we can find our lost commit hashes and by using these
commit hashes we can checkout a new branch based on that hash.
The
reflog command only track back changes for a certain time. Git automatically
clears reflog data periodically ie. by default it is of 90 days. but we can
also modify this time by using the ‘expire’ option of the command.
If
you want reflog never to forget any action, then use
git
reflog expire --expire = never
A
commit is lost when it is not part of any branch. The log command fails to
search and show lost commits.
Reasons
for lost commits : 1. Hard Reset 2.
Deleting branches without merge.
Lost
commits are those that are recorded by Git, but are not present anywhere in our
branches.
To
search lost commits that are not part of any branch, use fsck (file system
check) command.
git
fsck --lost -found
To
recover a lost commit c9067 from the
above list to your current branch, use
git
merge c9067 {this is the commitid hash of the commit.}
fsck
VS reflog : There is an advantage of fsck over reflog. for eg.
If
we have cloned a remote branch and deleted it. Then the commits present there
would never show up on the reflog, bcoz they were never done on our local
system. However, the fsck will list all
the lost commits from that branch.
Rebasing
is a way of rewriting the history of a branch by moving it to a new ‘base’
commit. It avoid loops in the project history.
If
you are rebasing a master into branch B1, the new commits in master are put
before the new commits in the branch B1 that are not common to master. To do
this, use this command from the branch B1 i.e
git
rebase master.
But
if you are working in a team, then you should first checkout to master, then
pull from the upstream branch to update your master with the latest commits and
then switch back to branch B1 before running the ‘git rebase master’ command.
This
above process can also be accomplished by using
git
merge -- rebase master
Similarly
we can also rebase with a pull by using
git
pull --rebase origin master
1. git rebase does not create any additional ‘commit’ objects.
2. When running git rebase [other-branch] from the current-branch, then the git will first checkout the [other-branch] before re-applying the commits of the [current-branch].
Practically, this means that the [other-branch] will stand for ORIG_HEAD and [current-branch] will stand for MERGE-HEAD.
3. git will drop a commit for which the computed diff is now empty.
Below
will set the user credentials for the commit transactions at the user level.
ie. all the repositories of the current user will use these credentials.
git
config --global user.name
git
config --global user.email
to
make mergetool not to keep backup files after merging
git
config --global mergetool.keepBackup false
Set
Kdiff3 as merge tool
git
config --global merge.tool kdiff3
Set
diffmerge as diff tool for GIT.
git
config --global diff.tool diffmerge
Configure
diffmerge command
git
config --global diff.tool
diffmerge.cmd/usr/bin/diffmerge
LOCAL REMOTE
Shows
the remote url
git
config --get remote.origin.url
Enables
colorization of command line output
git
config --global color.ui.auto
save
all uncommitted changes with messages.
git
stash save message
git
stash pop | list|drop|apply etc
git
init [project-name]
creates
a new local repo with the specified name
git
status -s Shows the git short
status
git ls-files --other --ignored --exclude-standard
Shows the list of all ignored files
git
gui blame [file-name]
Shows
the file’s last content change history line by line
git
bisect Find by binary
search, the change that introduced a
bug.
git
remote rm origin
Removes
origin ssh link. This name will be
deleted from the local git repo.
git
remote show origin
Shows
the url saved as origin.
git
remote add <Name> <url of
remote repo>
Name
= this is the name for remote repository link.
git
remote set-url origin url
Sets
remote url name as origin.
git
rebase -i
“i”
means ‘interactive’. For reordering, squashing and other purpose.
git
rebase -i HEAD~n
Reorder
commits
git
checkout
Total
number of local commits ahead of remote origin.
git
rebase -onto
Allows
us to change the base of a commit or rebase it in a non-interactive way.
git
checkout --
removes
all uncommitted changes.
git
clean -df
deletes
all untracked files.
git
difftool
open
difftool to view difference.
git
pull --rebase
To
fetch and merge to latest CL (commit log)
Pull
is equal to Fetch + merge.
git
revert SHA2 SHA1
Use
this when you have shared your codes. But you must revert your CL in reverse
order.
git
merge --squash ‘branchname’
This
command squashes all the commits of ‘branchname’ branch into one commit and
merges into current branch.
git
notes add [commit]
Add
a note to a specific commit
git
reset --hard
reset
= Revert, Rollback. Permanently go back to previous commit.
It
deletes all local commits. Use this only if we have not shared our code.
git
reset --hard [SHA of commit]
git
reset --soft HEAD^
moves
the mistakenly committed files back to the staging area from the previous
commit.
git
reset [filename]
unstages
the file but preserves its changes locally.
git
commit --dry -run
to
see what changes will be committed before actually running the git commit.
$ git
commit -a -m 'added new benchmarks'
git
commit -am “(message)”
Add all changes to staging and commit
them with message
you
don’t have to run git add on the changed file in this case before you
commit. That’s because the -a flag includes all changed files.
If you want to skip the staging area,
Git provides a simple shortcut. Adding the -a option to the git commit command
makes Git automatically stage every file that is already tracked before doing
the commit, letting you skip the git add part:
git rm
--cached [filename]
removes
the file from version control but preserves it locally.
git
rm [filename]
Deletes
the file from working directory and stages the deletion.
git
mv [original_filename] [new_filename]
Changes
the filename and prepares it for the commit.
git
rev -list HEAD -- count
Total
number of commits.
Fixing
a previous bad commit
git
checkout <badcommit>
git
commit --amend -v
git
rebase --onto HEAD [bad commit] [checked-out-branch]
git
rebase [branchname]
Apply
any commits of current branch ahead of the specified branch.
To
check which editor git will use
git
config --get core.editor
To
create alias
git
config --global alias.co checkout
git
config --global alias.cm “commit -m”
git
config --global alias.unstage ‘reset
HEAD --’ and then use like this >
git unstage myfile.txt
git
config --global alias.tree ‘log --graph
--decorate --pretty =oneline’
now
use this alias as
git
tree
To
remove alias
git
config --global --unset alias.cm
git
diff master..mybranch (to see the
changes)
git pull
--rebase origin
To
pull all remote changes but baseline them before your local changes, so your
local changes move on top of what everybody else has already committed.
git
clone --branch xyz
url
to
clone a specific Tag ‘xyz’ from a remote repo.
To
unstage a file
git
reset HEAD [filename]
It
will bring back the file in the unstaged state by removing it from
index/staging
git
reset --hard HEAD
It
will go back to initial state by losing all the changes in the working
directory.
Another
way to unstage a file is by using “git
rm ” command.
use “--cached” option with
“git rm” if want to preserve the file on our local folder.
--cached
option removes file from the index/staging area , and not from the file system
of the computer.
CTM:
Remember that “git rm “ is used to remove the file from index. So, if we use the git rm command on an already
committed file, then we are actually marking it for deletion next time. So the next commit will delete that file.
For
merging, First we have to checkout the branch into which we want to merge the
other branch.
To
checkout the previous branch we were in , we can simply use the
git
checkout --
ie.
we don’t have to type the branch’s name again. and after checking out to that
branch, we can use
git
merge [branchNameWhichWeWantToMerge]
Fork
is not a git feature, but a GitHub invention.
When
we fork a repo on GitHub, we get a server-side clone of repository on our
GitHub account. Now
If
you clone your forked repository on to your local computer, then in the remote
list of your local repository, you would find the ‘origin’ alias that points to
your github account’s forked repository,
Whereas, The original repository from which you have forked, will assume
the alias of ‘UPSTREAM’. But this upstream alias does not get set
automatically, we have to set it manually.
git remote
add upstream url
Now
our local repo can be in sync with the ’remote upstream’ and ‘origin’ aliases.
Simply
pull from the upstream and merge those changes in your local repository, and
then push them into your origin remote.
For
contribution to the upstream repo, we have to create a pull request bcoz we
cannot push directly to the upstream remote if we not a contributor of the
original project.
Tracing
changes in file : To view last modifications made in a file.
>
git blame [filename]
and
then use the commit hash to view the changes
>
git show <commithash>
or
>git
gui blame myfile.txt
Bare
repositories are repos that do not contain working copy files but contain only
the .git folder. A bare repository is
essentially for sharing.
To
setup a bare repo we use
>git
init --bare NewRepo.git
Here
we are using the .git extention in repository name which is not mandatory but
it a common way to identity bare
repositories.
A
regular repository can be converted to a bare repository by using
>git
clone --bare myrepo myrepo.git
By
this, we have a 1:1 copy of our repo, but in a bare version &
ready to be shared.
Backup
Repository : There exists two commands for this
1. Archive
It archives only the files without including the versioning information. It can also archive files including in a branch, or even in a single commit. eg.
1. Archive
It archives only the files without including the versioning information. It can also archive files including in a branch, or even in a single commit. eg.
git archieve
master --format=zip --output=../repobak.zip
And to archive only the last commit, we use
git archive HEAD --format=zip --output=../headbackup.zip
Archiving files in this way is useful if we have to share our code with people that don’t have Git installed.
2.
Bundle : It backups the entire repository
into a bundle including the versioning
information. With git bundle, we can export a snapshot from your repository ,
and we can then restore it. For eg. say,
we want to clone our repository on another computer and the network is down,
then in this case, we can create a bundle file of master branch of our
repository.
git bundle create
--/myrepo.bundle master
Now, we can restore this bundle in other computers like this
> cd /othercomputer/Folder
> git clone myrepo.bundle testreponame -b master
Now, we can restore this bundle in other computers like this
> cd /othercomputer/Folder
> git clone myrepo.bundle testreponame -b master
0 comments:
Post a Comment