CONCEPTS
Take a clone of a remote repository and run git branch -a (to show all the branches git knows about). It will probably look something like this:
* master
remotes/origin/HEAD -> origin/master
remotes/origin/master
Here, master is a branch in the local repository. remotes/origin/master is a branch named master on the remote named origin. You can refer to this as either origin/master, as in:
git diff origin/master..master
You can also refer to it as remotes/origin/master:
git diff remotes/origin/master..master
These are just two different ways of referring to the same thing (incidentally, both of these commands mean "show me the changes between the remote master branch and my master branch").
remotes/origin/HEAD is the default branch for the remote named origin. This lets you simply say origin instead of origin/master.
Technically there aren't actually any "remote" things at all in your git repo, there are just local names that should correspond to the names on another, different repo. The ones named origin/whatever will initially match up with those on the repository you cloned-from:
git clone ssh://some.where.out.there/some/path/to/repository # or git://some.where...
makes a local copy of the other repo. Along the way it notes all the branches that were there, and the commits those refer-to, and sticks those into your local repository under the directory .git/refs/remotes/origin/.
Depending on how long you go before you git fetch or equivalent to update "my copy of what's some.where.out.there", they may change their branches around, create new ones, and delete some.
When you do your git fetch (or git pull which is really fetch plus merge), your repository will make copies of their new work and change all the refs/remotes/origin/<name> entries as needed.
It`s that moment of fetching that makes everything match up (well, that, and the initial clone, and some cases of pushing too?asically whenever git gets a chance to check).
Git normally has you refer to your own refs/heads/<name> as just <name>, and the remote ones as origin/<name>, and it all just works because it's obvious which one is which. It's sometimes possible to create your own branch names that make it not obvious, but don't worry about that until it happens.
Just give git the shortest name that makes it obvious, and it will go from there: origin/master is "where master was over there last time I checked", and master is "where master is over here based on what I have been doing".
Run git fetch to update git on "where master is over there" as needed.
WORKSPACE (a.k.a. work tree, working directory): red
INDEX/STAGING AREA: green
GIT REPOSITORY/DIRECTORY:
LOCAL REPOSITORY: a local copy of the remote since last pull
REMOTE REPOSITORY: a remote and updated copy of the directory on origin
origin/master: local master copy of HEAD on origin
Create SSH Key
ls -ltr ~/.ssh/ // go to the SSH key folder
ssh-keygen -t rsa -b 4096 -C "percyvega@gmail.com" // enter your email
Enter id_rsa
Enter your password
eval `ssh-agent -s` // verify the ssh agent is present
ssh-add ~/.ssh/id_rsa // add key to ssh agent
clip < ~/.ssh/id_rsa.pub // copy key contents
ssh -T git@github.com // authenticate
Verify that the [project]/.git/config file has something like https://percyvega@github.com... instead of https://github.com...
Manage your remote repo
List your existing remotes (fetch and push)
$ git remote -v (or $ git config -l | grep remote.origin.url)
Overwrite remote's URL
$ git remote set-url origin git@github.com:USERNAME/REPOSITORY2.git
Remove remote repo
git remote rm origin
Add remote repo
git remote add origin git@github…
Set upstream repo
git branch --set-upstream-to=origin/main [main]
INITIALIZE LOCALLY (immediately after a repository has been initialized remotely)
Create a project in GitHub.com:
{Go to GitHub.com and use web UI to create new repository}
Initialize the folder to make it a git repository
mkdir /path/to/your/project // if folder doesn't exist
cd /path/to/your/project
git init // will create the .git/ folder
Add your (red) local changes to the (green) INDEX/STAGING AREA:
git add .gitignore // git add --all .
Commit your (green) INDEXed/STAGEd/registered changes to (white) repo
git commit -m 'My initial commit'
Associate to its remote counterpart
Using ssh:
git remote add origin git@bitbucket.org:percyvega/project-name.git
Using https:
git remote add origin https://github.com/percyvega/project-name.git
Verify the remote URL
git remote -v
Pushes the (white) repository and its refs to (not shown) origin for the first time
git push -u origin master
BRANCHES
List branches:
git branch -l or git branch // list local
git branch -r // list remote
git branch -a // list all (local + remote)
Switch branch:
git checkout <branch_name> // checkout a branch
git checkout <hash> // checkout a hash
Create (based on current changes):
git checkout -b <new_branch_name> // create and switch to branch
then
git push --set-upstream origin <branch_name> // after creating the branch locally, persist remotely
git branch <new_branch_name>
then
git checkout <branch_name>
and
git push --set-upstream origin <new_branch_name> // push newly created branch to remote whether commits were made or not
or
git push origin/<new_branch_name> <new_branch_name> (or git push origin <new_branch_name> <new_branch_name>)
or
git branch -u upstream/<new_branch_name> [<new_branch_name>] // track remote branch from origin
of
git push origin [<new_branch_name>] // push newly created branch to remote when no commits yet made
Rename branch:
git branch -m [<old_branch_name>] <new_branch_name> // change local but not remote
git push origin --delete [old_branch_name] // delete remote
git push origin <new_branch_name> // re-create remote branch with new name
git branch -u origin/<new_branch_name> // rename remote/upstream tracking
Delete a local branch
git branch -D [branch_name]
Delete a remote branch
git push origin --delete [branch_name]
Remove an element just excluded in .gitignore, element must be untracked
git rm --cached [filename] // untrack a file
git rm -r --cached [directory] // untrack a folder structure
Exclude in [project_path]/.git/info/exclude
echo [file_path_relative_to_project] >> .git/info/exclude
git update-index --assume-unchanged [file_path_relative_to_project]
Merge branch_with_changes into destination_branch
git checkout <destination_branch>
git pull
git merge origin/<source_branch> // e.g. git merge origin/master
if conflicts found:
git mergetool
git push // don't forget to push after merging!
To pull changes from the origin remote, master branch and merge them to the local checked-out branch
git merge origin master
git push
To pull changes from the locally stored branch origin/master and merge that to the local checked-out branch. The origin/master branch is essentially a "cached copy" of what was last pulled from origin, which is why it's called a remote branch in git parlance. This might be somewhat confusing.
git pull origin/master
FILES
INCOMING
Update local repository branches with remote repository changes without modifying WORKSPACE files.
git fetch [remote]
e.g. git fetch origin main:main
Update local repository and WORKSPACE branches with remote repository changes, modifying WORKSPACE files.
git pull [remote] [branch]
OUTGOING
Add your local additions (in red) to the INDEX/STAGING AREA (in green):
git add .
Add your local changes (in red) to the INDEX/STAGING AREA (in green):
git add *.java
git add README
git add . // add to INDEX/STAGING AREA those created
git add . +
git add -u // remove from INDEX/STAGING AREA those deleted
git add --all . // add your local changes (+, - and ~)
Commit your INDEXed/STAGEd/registered changes (in green):
git commit -m <message> // specify message log here
git commit -a // specify message log in a window file
Push changes to origin:
git push
COMPARE
List local file changes and additions (except additions are inside folders not yet checked-in):
git status
List visually file changes:
git gui
List the commits of a branch or a of specific file:
git log [specific_file]
git log --raw
Shows the files that changed per commit
git log --oneline
Show one line per commit
git log --graph
git log --oneline --graph
git log --oneline --graph --all --decorate
List differences between local branch and remote (origin) version:
git fetch origin
then
git difftool --name-only master origin/master
List visually a tree of differences in branches or specific file:
gitk [specific_file] // uses git tool
git difftool [specific_file] // uses whatever difftool was defined
List local file differences:
git diff[tool] <file> // folder and branches too???
Show file's content differences between branches
git diff[tool] <branch1> [<branch2>] // if branch2 is not specified, local branch will be compared with branch1
git diff[tool] <branch1> [<branch2>] -- <file>
List differing files between the workspaces of branch1 and branch2 (use master..my_branch to see branch changes):
git diff --name-status [<branch1>]..[<branch2>] // specify at least one of the two branches
List the files changed at a specific commit (gotten from git log):
git diff-tree --no-commit-id --name-only -r 2437e0330494441a72f65e336f09a7b95e795ea1
Compare the committed changes of a branch against main
git difftool main..[branch_name]
Compare any difference between your local code and that of main
git difftool main
DISCARD
Discard NEW elements (files and directories):
git clean -fd
Discard NEW files (in ALREADY registered directories):
git clean -f [absolute_path]
Discard CHANGED elements (deletions and modifications):
git checkout <file_folder_path> // specific file or everything under folder
git reset --hard // restore to local repository (last commit)
REBASE
git rebase -i main
fixup with an f all following commits
If there are conflicts
You can either use
mergetool
git mergetool
Fix all conflicts
Or fix manually
For each file with conflicts
Using IntelliJ, resolve each of the conflicts.
End
Immediately after this
git add --all .
git rebase --continue
The file will open only with the commit of main. Don't touch anything. Save and close.
mcis
git push -f
STASH
Git stash stores the changes you made to the working directory locally (inside your project's .git directory; /.git/refs/stash, to be precise) and allows you to retrieve the changes when you need them.
$ git stash
Saves your changes
$ git stash save "Message that describes your changes"
Saves your changes and assigns a description to your stash
$ git stash pop
Apply the changes stashed in the latest stash (i.e. stash@{0}) and remove that stash
Optionally, you can specify a stash_id e.g. $ git stash pop stash@{2}
$ git stash apply
Apply the changes stashed in the latest stash (i.e. stash@{0}) but keep the stash
Optionally, you can specify a stash_id e.g. $ git stash apply stash@{2}
$ git stash -u (or $ git stash --include-untracked)
Stash untracked files
$ git stash -a (or $ git stash --all)
Stash untracked files and ignored files
$ git stash -p (or $ git stash –patch)
Stash specific hunks (file changes)
$ git stash list
List your stashes
$ git stash drop <stash_id>
Drops a specific stash from the list
$ git stash clear
Clears the stash list
$ git stash show
Show a diff of the latest stash
Optionally, you can specify a stash_id e.g. $ git stash show stash@{2}
Optionally, you can see the file changes e.g. $ git stash show stash@{2} --patch
PROBLEMS/SOLUTIONS
Problem
fatal: Authentication failed for
Solution
Go to the repo and run
1) git config --global credential.helper store
2) git push
3) Enter your percyv credentials
Problem
fatal: Not possible to fast-forward, aborting
Solution
git pull --rebase