Sei sulla pagina 1di 15

Git Fundamentals

Three main states:


1. Committed data is safely stored in your local database
2. Modified f ile has been changed, but has not yet been committed to the database.
3. Staged modified file has been marked in its current version to go into your next commit
snapshot.

Git Projects:
1. Git directory (repository)
a. Git stores metadata and object database (compressed)
b. This is what is copied when you clone a repository from another computer
2. Working directory
a. A single check of one version of the project
3. Staging area
a. A simple file, usually in your git directory, that stores information on what will be
committed (aka as the index)

Basic Git Workflow:


1. Modify files in your working directory (modified state)
2. Stage files, by adding snapshots of them to your staging area (staged state)
3. You do a commit, which takes the snapshots from your staging area and stores them
permanently to your Git directory (committed state)

Config Files
1. The system wide config file
a. C:/Program Files/Git/etc/gitconfig
b. Use the system option with git config to set variables in this file
2. The user config file
a. ~/.gitconfig
b. Use the--global option with git config to set variable in this file
3. The repository config file
a. Config file local to the working directory, .git/config
it config without the
b. To set values in the config file for this simply execute g
--system or --global switches
4. Each level trumps the other levels, with the local config file being the highest trump
5. git config --list
a. lets you check your settings

Git heads
1. A head is simply a reference (or pointer) to a commit object
2. Each head has a name
3. By default, there is a head in every repo called m aster
4. A repo can contain any number of heads
5. At any g iven time one head is selected as the current head. This head is always aliased
to HEAD
a. HEAD~ is the parent of the current HEAD reference (i.e. the commit before the
current commit)
6. A head is typically synonymous with branch. However, branch can also mean its current
head and all of its ancestors. Where a head only points to a single commit.
7. it is possible to have a commit be the active (or checked out ) commit but has no branch
referencing it. This condition is called a detached head. Note HEAD of course will be
pointing to it, as it always points to the active commit, but the commit doesnt havent any
other named heads pointing to it.
a. reconciling a detached head
i. http://stackoverflow.com/questions/5772192/git-how-can-i-reconcile-detac
hed-head-with-master-origin

Creating a new repository


1. git init
a. this will create a new repository with a .git folder

Cloning a repository
1. git clone [source] [destination]
a. this will create a complete copy of the source repository
b. example(s)
i. git clone http://file2/K3150-utils.git /c/projects/K3150-utils
ii. git clone --recursive ssh://cphillips@10.8.8.22:/proj/git/N3.git
/f/Projects/N3
iii. git clone --recursive git@bitbucket.org:KetraLighting/_ketrapy_.git
/c/Projects/_ketrapy_
c. If the repo has submodules use
i. git clone --recursive [source] [destination]
ii. if the clone has already happened switch to the repo directory and use
1. git submodule update --init --recursive

The Repository
1. Each file in working directory is either
a. Tracked
i. Files that were in the last snapshot
ii. They can be unmodified, modified, or staged
b. Untracked
i. Files in the directory that are not tracked (ie all the other files)
2. If you edit a file that is tracked, it becomes modified
3. You can check status of files in the working directory by running:
a. git status
i. this will give you the status of tracked or untracked files
b. git status s
i. short version of the git status
ii. there are actually two columns before the file names, the first column
indicates staging status, the second column indicates modification status
1. ?? file is untracked
2. A- file is staged
3. -M file is modified (tracked, but not staged)
4. M- file is modified(tracked and staged)
5. MM file was modified again after it was modified and staged, so
there is a version of the file that was modified and staged, and
there is a version of the file that is modified, but that modification
has not yet been staged (using git add)
4. We can track untracked files by:
a. git add <filename>
i. this will move the file to the stage area (aka index area)
ii. the status will now show the file in the Changes to be commited:
heading of the status report, subheading newfile:
b. git add <directory>
i. this will move all files in the folder to the stage area
5. If we modify a tracked file and check the status:
a. This will move the file to the Changes not staged for commit: heading
6. We can move a modified, tracked file to the stage area by running:
a. git add <filename>
i. Note it will move to the Changes to be committed: heading of the status
report, but will be listed under a subheading modified:
7. In the case of submodules, if the submodule has commits that are advanced from the
commit currently tracked in our working repo, we can if we choose, add that submodule
to staged area and commit the submodule just like a regular file.
a. git add <submodule name>
8. When we checkout a branch of repo that uses submodules, we need to update the repo
to point at the correct commit of the submodule
a. git submodule update --recursive --init
i. the --recursive is necessary if the submodule itself has a submodule
ii. the --init clones any new submodules
b. git ls-tree <branch_name>
i. running this command in the super repo will show the SHA1 of the
submodule. Note the type of entry is commit
ii. you can also use the commit hash rather than a branch name
c. cat .gitmodules
i. this will show us the location of the submodule, if any
d. git submodule status --recursive
i. this will list any submodules, including nested
submodules

9. If we modify a file that already been moved to the stage area, but not yet committed, the
status will show that file in both the Changes to be committed: and Changes not
staged for commit: headings
a. If we commit at this point in time, the file that gets committed is the file as it was
when it was added to the stage area, not the file that is in the working directory
and unstaged. If we want the unstaged file to be committed we need to stage it,
by running the git add <filename> command. This will replace the version of the
file that was in the staged area with the one that is in the working directory.
10. We can unstage a file that is in the staged (indexed) area
a. Run:
i. git reset HEAD <filename>
11. We can make a modification to our most recent commit to fix a simple issue with our
most recent commit
a. fix the file that has the issue
b. Run:
i. git commit --amend -m type commit message here
1. we can also use this to simply update the commit message with
changing any of the files
12. We can revert to an earlier file in our commit chain
a. Run:
i. git checkout <short SHA1> --<filename>
1. This moves the copy of file to the working directory that was
stored in the commit referenced by the short SHA1
13. We can have git status ignore certain files that we dont want to even know are being
untracked because we will never track them
a. Use the file .gitignore
b. if git was already tracking a file(s) that you no longer want git to track you will
need to remove it from the tracking list
i. git rm --cached <filename>
14. We can get more details of changes.
a. To see what changes we have made to tracked files (modified file in the working
directory), but not yet staged, run:
1. git diff
b. To see what changes we have made between the files from our last commit
compared to the staged area, run:
i. git diff staged
ii. git diff cached
c. To see what changes we have made between the files from our last commit
compared to the commit area, run:
i. git diff HEAD
15. To move files from the staged area to the commit area
a. run:
i. git commit
1. This will launch vim so you can document your changes
ii. git commit m <message string in double or single quotes>
1. This will commit the files with string following the m flag
b. The commit lets you know what branch you committed to
c. The commit shows you the SHA-1 checksum that is unique for the commit (the
snapshot of your files)
d. The commit shows you how many files were changed
e. The commit shows you statistics on how many lines were add and removed
f. Git stores a commit object that contains:
i. a pointer to the snapshot of the content that was staged
ii. authors name and email
iii. the message for the commit
iv. a pointer to parent (or parents)
1. parents can happen if the commit is part of a merge of two or
more branches
16. To move all tracked files, even if they are not staged to the commit area, run:
a. git commit a m <message string in double or single quotes>
i. this skips the step of using git add to move files from the working
directory to the staged area
17. To remove a file from the commit area
a. Run:
i. git rm <filename>
1. This stages the file for removal. Running git commit at this point
will remove the file completely from the commit area and the
working directory
2.
b. just removing a file from the working directory does not remove the file from the
commit area
i. The removed file will show up when running git status under the
Changes not staged for commit: under the subheading deleted:
18. To show remote servers
a. Run:
i. git remote v
1. shows the short name and the URL
19. To get data from a remote project
a. Run:
i. git fetch [remote-name]
1. This will grab any updates that have been pushed into the remote
project. Note it doesnt merge any files, it simply gets them into
your local repository
20. To see the SHA1 for the master pointer
a. From within the .git folder Run:
i. cat refs/heads/master
21. To see a simple stacked view of the commits starting from the most recent
a. Run:
i. git log
1. if the git log results dont fit on the screen it will put the output into
an editor
a. use Shift + zz to quit the editor
b. To see a one line compact version of the log Run:
i. git log --oneline
22. To see only the commit logs of the current HEAD versus a remote branch commit run
a. git log HEAD..remote_short_name/remote_branch_name
i. for example
1. git log HEAD..origin/development
23. Work that is not ready to be committed can be stashed
a. git stash
i. pushes the uncommited files to a stash stack
b. git stash list
i. produces the stash list with information on each item as to the branch and
commit hash
c. git stash apply
i. this applies the most recent stash to your current work
d. git stash apply stash@{2}
i. this applies the stashed code from the third item in the list
e. git stash apply --index
i. this will cause any files that were in the staging area (indexed) to be
applied in the staging area, otherwise if you dont use the --index option
the files will just go in the WIP area
f. git stash drop stash@{2}
i. this will remove a stashed item. Just applying the stash does not remove
it from the stash list
g. git stash pop
i. applies the most recent stash and drops it from the list
24. To remove empty folders that git no longer needs to track run
a. git clean -fd
i. to verify what the clean will do first you can run
1. git clean -fdn
b. note that the clean will remove stuff that has not been committed to make sure all
the stuff you want in already committed.
Git Diff
1. To see differences between the working directory and the staged index (although if git
status is clean, it seems to me this compares the working directory to the current commit
pointed to by HEAD)
a. Run:
i. git diff
1. staged index = a file, working directory = b file
2. - in front means the line is in the staged file (or the a file) or you
can think of it as that line is not in (deleted from) the working file
(or the b file)
3. + means the line is in the working file (or the b file), or you can
think of it as that line was added to the working file (or the b file)
2. To see differences between the staged index and the current commit (HEAD)
a. Run:
i. git diff --staged or git diff --cached
ii. in this case, the a file is the file in the current commit (HEAD) and the b
file is the file in the staged area
3. To see differences between the working directory and the current commit (HEAD)
a. Run:
i. git diff HEAD
4. To see differences between the working directory and the commit just before the current
commit
a. Run:
i. git diff HEAD^
5. Deciphering diff results
a. diff works on the philosophy of changing the first file, a, to make it appear like the
second file, b
i. the - symbol is used as a marker for the a file
ii. the + symbol is used as a marker for the b file
b. differences are shown in chunks (or context of the difference)
i. The @@ signs enclose a header for the chunk
ii. The format between the @@
1. <marker symbol> <beginning line number>, < number of lines
extracted>
a. e.g. -34, 6 means file a, starting at line 34, 6 lines extracted
b. e.g. +34, 8 means file b, starting at line 34, 8 lines
extracted
iii. There may also be text following the second @@ symbol
1. This is an attempt to identify a function or method that the code
difference exists in
c. Following the chunk header there will be a list of changes within the chunk
i. the <marker symbol> identifies which text comes from which file
ii. for most cases we can think of the a file marker as the old content and
the b file marker as the new content
1. so + changes with no corresponding - changes means the b file
has added these lines as compared to a. In other words, you
would have to add these lines to the a file to make it look like the b
file in regard to this change
2. so - changes with no corresponding + changes means the a file
has lines that were removed from the b file. In other words, you
would have to delete these lines from the a file to make it look like
the b file in regard to this change
3. If the chunk has a series of - markers followed by an equivalent
set of + markers this means the line(s) has been modified
between the a and b files. In other words, you would delete the -
marked line from the a file, and then add the + marked line from
the b file into the a file to make the a file look like the b file in
regard to this change

Git Resets
1. Three kinds:
a. Soft
i. Run:
1. git reset --soft <short SHA1>
ii. moves the HEAD to the referenced commit
iii. moves the most recent commit into the staging area
b. Mixed
i. Run:
1. git reset --mixed <short SHA1> or
2. git reset <short SHA1>
ii. changes the HEAD to the referenced commit
iii. moves the referenced commit into the staging area
1. thus a git diff --staged wont show any differences
c. Hard
i. Run:
1. git reset --hard <short SHA1>
ii. reverts completely back to selected commit
1. changes the HEAD to the referenced commit
2. moves the referenced commit into the staging area
3. moves the referenced commit into the working directory ******This
means any files in the working directory will get over written*******
Git Objects
1. Four basic objects
a. Blobs
i. Contain data, typically file data
b. Trees
i. Contain pointers to other trees and blobs
ii. In the case of submodules, they can also have commits as entries
c. Commits
i. Contains a tree entry which is the working directory
ii. Holds a pointer (aka reference) to its parent (commit) or parents
(commits), no parent if it is the root commit
iii. Author entry
iv. Committer entry
v. Comment entry
vi. a set of files, reflecting the state of the project at a given point in time
(need to understand this better)
vii. SHA1 name
d. Tags

Git Branching
1. Default branch name is: master
a. This is simply the default name given when we run git init, it is like any other
branch
b. It is a pointer to a particular commit object
2. Note that when we commit, the created commit object points back to the previous
commit object (identified by its SHA-1)
a. This is in the parent field of the new commit object
b. Note also the that the HEAD pointer and the pointer to the current branch we are
on moves forward automatically when we make a commit
3. We can see what branch we are currently on
a. Run:
i. git branch
1. This lists all the local branches in the repo
2. The one with the star next to it is your current branch
4. To create a new branch
a. Run:
i. git branch [branch-name]
1. This creates a branch pointer to the current commit object
2. This does NOT change the HEAD pointer which holds the pointer
to the branch we are currently on, it simply creates a pointer to the
current commit object, referenced using the branch-name
5. To see which commits various branch pointers are pointing at
a. Run:
i. git log --oneline --decorate
1. n
a. Limit the number of commits reported to the number n,
starting with the most recent
2. p
a. Shows difference between commits
6. To move to a different branch
a. Run:
i. git checkout [branch-name]
1. This will cause the HEAD pointer to now point to the branch-name
pointer, which of course is pointing at some commit object
2. This will also cause the files in the working directory to be
changed to the state they had when that commit object was
created (assuming the branch-name is actually pointing to a
commit object that is different than the commit object before the
checkout command)
ii. If we make some changes and stage them and commit them, the HEAD
pointer will move forward to the created commit object, as will the
branch-name pointer that we switched to with the checkout command
7. To look at branch history
a. Run:
i. git log --oneline --decorate--graph --all
8. To create and move to a different branch in one command
a. Run:
i. git checkout b new_branch_name
9. Before switching branches commit all uncommitted changes in the working
directory and staging area
10. We can examine differences between branches
a. Run:
i. git diff branch_name_a..branch_name_b
11. We can rename a branch
a. Run:
i. git branch -m current_branch_name new_branch_name
12. We can delete a branch
a. Run:
i. git branch -d branch_name
1. if this branch has not been merged back into the branch it
originated from git wont let you delete it with -d, we have to use
a. git branch -D branch_name

Git Merging
1. Merging back into the master (or production) branch
a. Run
i. git checkout master
1. this moves the HEAD pointer to point at the master commit
ii. git merge branch_name
1. if the branch_name is directly upstream ahead of the master
branch in commits, you will see the phrase fast-forward in the
merge results
2. if the merge was a fast-forward merge, by default we cant really
tell that the commit created by the merge was in fact from a
different branch. To record that fact:
a. Run:
i. git merge --no-ff branch_name
ii. record message about the merge
b. Once the merge is successful, you wont need that branch
anymore, so we can delete it
i. Run
1. git branch d branch_name
2. The fundamental merge process is
a. Check out the branch you want to receive the merger
b. Execute the merge command calling out the branch we want to merge into the
checked out branch
3. If the branch that is merging into the checked out branch is not a direct descendant of
that checked out branch git needs to do some more work
a. Simple three way merge
i. Find the common ancestor of both the checked out branch and the
branch to be merged into the checked out branch
ii. Git will attempt to merge these three commits (snapshots) together
iii. Git will automatically make a new commit (snapshot) that results from this
three way merge, moving the checked out branch pointer forward. This
new commit object will now point back to both the previous commit in the
checked out branch, and the commit object from branch merging into the
checked out branch, named in the merger command. This process is
referred to as a merge commit. This new commit object has two parents
iv. Note that Git actually determines which commit to use as its base for the
merge process
4. If the merge fails to complete successfully
a. You can check the status with
git status
i.
1. you will see a line stating You have unmerged paths
2. you will also see which files have conflicts that need to be
resolved manually
b. Within the file that needs resolution you will see standard resolution conflict
markers
i. <<<<<<<<<
1. Shows which branch the lines above the === come from
ii. =========
iii. >>>>>>>>>
1. Shows which branch the lines below the === come from
c. After the file has been manually fixed, and the conflict markers have been
removed
i. Use git add to mark those files resolved
d. Once all the merge conflicts have been resolved and have been added to the
staging area
i. Use git commit
5. Branch Management Tools
a. git branch
i. run with no arguments gives a simple listing of the current branches
1. * indicates the current branch that is checked out, i.e. HEAD is
pointing to this branch
b. git branch v
i. shows the last commit on each branch
c. git branch --merged
i. lists branch that have already been merged into the current/active branch
d. git branch --no-merged
i. lists branches that have NOT been merged into the current/active branch

Git Branching - Remote Branches


1. There are pointers to remote branches that are moved automatically during network
communication. They are not changed by the local repository.
2. They take the form (remote)/(branch)
3. When we clone a repository
a. git automatically names the remote, origin, and creates a pointer to its master
branch, origin/master (this is called a remote-tracking branch)
i. note it is possible to change the name of the remote when we clone it
using the -o switch
1. git clone -o name_not_origin
2. it would create a pointer called name_not_origin/master
b. git also makes a local pointer to master branch starting at the same place called,
master
c. If they are other branches in the git repo we just cloned and we want to view
them, run:
i. git branch -a
d. If we want to work on one of those branches in the remote repo we need to
create a local branch that tracks that branch. To do this we run:
i. git checkout -b local_branch_name
remote_short_name/remote_branch_name
1. for example:
a. git checkout -b development origin/development
4. If we dont keep up with the remote repository (i.e using the fetch command), the
origin/master pointer doesnt update
a. We can sync up with the remote server by running
i. git fetch origin
1. this will put the origin/master pointer pointing to a commit that is
up-to-date with the remote repository
2. note this does not change the working directory or tracking
branches, it only updates the remote-tracking branch pointer, for
example origin/master
5. We can add remote repositories by running
a. git remote add [shortname] [url]
b. adding remotes can be useful it we are collaborating on a project from several
remote servers
6. We can get the information from that remote repository by running
a. git fetch [remote_shortname]
i. note this only gives us the data for that remote repository, it doesnt
merge the files. We need to run the merge command if we want the files
from out there to be part of our current branch
1. instead of merging the branch, we could make our own local
branch
a. git checkout -b local_branch_name
remote_name/remote_branch_name
i. this creates a local branch called
local_branch_name that starts where the
remote_branch_pointer points, only it is local
7. We can push to a remote repository
a. git push <remote_name> <branch_name>
i. we can also use the syntax,
branch_name:different_remote_branch_name if we want the remote to
use a different name for the branch than our local branch name
b. git push -u <remote_name> <branch_name>
i. this will create the branch on the remote if it doesnt already exist
8. When we checkout a remote branch, git automatically creates a tracking branch
a. When we clone a repository, git normally makes a master branch which tracks
the remote, origin/master
b. if a local branch is tracking a remote branch, a git pull will automatically do a
fetch and merge from the remote branch to your local branch
c. to checkout a remote branch naming the local branch with the same name run:
i. git checkout --track remote_name/remote_branch_name
ii. need to do a git fetch first to make the local repo aware of the remote
branch
d. to checkout a remote branch with a new local branch name run:
i. git checkout -b new_local_branch_name
remote_name/remote_branch_name
9. To view tracking branches that are setup up, run
a. git branch -vv
i. this gives us more branch information, including a remote tracking branch
in [] if there is one, if it is tracking whether our branch is ahead or behind
(or up-to-date if neither ahead or behind is indicated)
1. this information is only relative to the last fetch from the remote, to
update all branches we could run
a. git fetch --all
10. We can inspect a remote to see information about it
a. git remote show remote_shortname
i. lists things like
1. URL for the remote
2. tracking branch information, including those that are new to the
local repository
3. which branches have been removed from the server
4. which remote branch(es) will automatically merge to which local
branch(es) with a git pull
5. which remote branch(es) are configured for the git push
11. While it is possible to run git pull in the current branch, it seems that git fetch, and then
git merge is preferred due to possible merge confusion if done all at once

Distributed Git Distributed Workflows


1. Centralized Workflow
a. One central hub (or repository)
b. Developers are nodes (consumers of that hub)
i. Each developer needs push access
c. Work is synchronize to that hub
2. Integration-Manager Workflow
a. Typically there is a canonical repository
b. Each developer creates their own public clone of the project
i. Their changes are pushed to their local repository
c. There is a maintainer (aka integration manager) that pulls in your changes
i. The maintainer can add the developers repository as a remote and test
changes locally
ii. Once tested okay, the maintainer can merge the changes into his branch
and push back to the public repository (such as github)
3. Dictator and Lieutenants Workflow
a. Lieutenants are maintainers of certain parts of large project
b. The project has a dictator over all the lieutenants, whose repository is the
reference repo

Distributed Git Contributing to a Project


1. Before committing run
a. git diff --check
i. look for possible whitespace errors
2. Try to make each commit a logically separate changeset
3. Create quality commit messages
a. Start with single no more than 50 characters that described the changeset
concisely
b. Follow short description by a blank line
c. Add more detail description next that includes:
i. Motivation for the change
ii. Contrast its implementation to previous behavior
d. Use the imperative present tense
i. Add tests for.
1. Rather than added or adding
4.

Potrebbero piacerti anche