Skip to content

HOWTO dev git

steveoro edited this page Jan 15, 2021 · 1 revision

HOWTO: git usage and references

Index

References

We won't go through all the basics here. so, point your browsers to:

When in doubt...

...Take a look at the git manual with a simple:

$> man git <git_command>

...Where <git_command> is the command for which you're seeking more info. For instance, clone, remote, push, branch, merge or whatever.


BASICS: Clone a repo

This will create a local copy of the remote repo, already linked to the correct remote origin in <https_github_url>:

$> git clone <https_github_url>

BASICS: Pull a new, remote branch (non-existing locally)

To create a new local branch based upon an already existing remote branch, first get the updated list of branches from the origin, using fetch. Then list the branch names with branch -a and, finally, switch to the new local branch via checkout:

$> git fetch origin
$> git branch -v -a
$> git checkout -b <local_branch_name> origin/<remote_branch_name>

BASICS: Stage everything & commit

To add everything to staging area (before commit):

$> git add .
$> git commit -m <my_awesome_but_meaningful_message>

BASICS: create & push to remote tracking branches

Either the branch already exists (let's say, case B) or it has to be created by a push (case A).

Case A: creating a local branch & pushing to a new remote branch

1.1 Create a local branch to a non-yet existing remote branch:

$> git checkout -b <feature_or_branch_name>

[...​edits + commit​...]

1.2. Push using the upstream parameter, to set the default for the remote push location:

$> git push -u origin f_name

1.3. However when you push some branch for the first time. You need to associate between your local branch and the one at origin like this:

$> git branch --set-upstream my_branch origin/my_branch

Case B: pushing to an existing remote branch

  1. whenever a remote branch already exists, simply do a:
$> git branch --track f_name origin/f_name

BASICS: Push your commits to the correct origin

Assuming we have a remote origin origin, to push the master branch onto the remote server, simply do a:

$> git push -u origin master

BASICS: Changing branch during edits or during merge conflicts ("stashing" changes)

Unresolvable merge conflicts? Someone asked you to edit that file on another branch while you're in the middle of your work on the current branch and you simply cannot commit the current changes due to [insert whatever reason you got]? Just stash away your changes and restore (or delete them) later on!

For ref.: stashing your changes

To stash all the pending changes, just add them to the staging area and invoke stash:

$> git add .
$> git stash

When the changes are stashed away, you can change branch (via checkout), delete the messed-up branch with the stashed changes if it's the case, or do anything else on another branch.

The stash can be restored later on with a simple git stash apply.

To enlist all the stored stashes, use git stash list.

To erase just a single stash, use git stash drop <stash_id>.

To clear all the stash area, use git stash clear.


BASICS: Git Diff among different branches

Use git diff to compare differences from the current branch and another (e.g: "feature-whatever"):

$> git diff feature-whatever

To list the changes between 2 different branches (e.g.: "master" & "staging"):

$> git diff master..staging

To list only the file names that have changed between current branch and another one (e.g. "staging"):

$> git diff --name-status staging

BASICS: Restore files from different branches

To restore a specific file from another branch (e.g. "my-awesome-feature"):

$> git checkout my-awesome-feature -- <file_path_1> <file_path_2> <file_path_3> <...file_path_N>

Wildchars like * or ? are supported in file paths.


BASICS: Cherry-picking some commits from a remote "sandbox" repo

Retrieve all the latest updates first:

$> git pull

Assuming we have a remote origin origin/sandbox, if a local sandbox branch is missing, create it with:

$> git branch --track sandbox origin/sandbox

Display all existing branches (both local and remote):

$> git branch -a

Install the TIG Git front-end for Linux if missing ("TIG" stands for "Text-mode Interface for Git"), which provides also a convenient UI for cherry-picking of individual commits:

On OpenSuse:

$> sudo zypper install tig

On Ubuntu/Debian:

$> sudo apt-get i tig

Launch tig specifying the remote repo to be displayed:

$> tig origin/sandbox

The UI works similarly to less, support h for "help" and q for "quit". Select and highlight the desired commit and press "C" (capital C) to create a new cherry-picked commit on the current (local) branch. Exit with "q" and push the committed changes.


ADVANCED: overwrite master branch with another containing a new reference implementation

Assuming master and new_implementation are local branches already synchronized with their remote counterpart, that no pending changes are staged, and that a possible backup branch (with a remote counterpart) has already been created for master, proceed like this:

$> git checkout new_implementation
$> git merge --strategy=ours master    # keep the content of this branch, but record a merge
$> git checkout master
$> git merge new_implementation        # fast-forward master up to the merge

If you want your history to be a little clearer, I'd recommend adding some information to the merge commit message to make it clear what you've done. Change the second command line to:

$> git merge --strategy=ours --no-commit master
$> git commit                             # add information to the template merge message

Then push the changes to remote.


DANGEROUS: Delete a local or remote branch (DESTRUCTIVE!)

To delete a local branch

$> git branch -d the_local_branch

Use -D, instead of -d to force delete the local branch in case of errors.

To remove a remote branch (if you know what you are doing!): For git v. 1.5+

$> git push origin :remote_branch_name

For git v. 1.7+

$> git push origin --delete remote_branch_name

DANGEROUS: reset local changes in case of a wrong, unsuccessful merge or other mistakes

Do not use this in case of any "rightful" merge that has resulted in merge conflicts. Use this only when the remote origin has been rebased due to history editing.

    # Reset local changes:
$> git reset --hard

    # Force a rebase while pulling:
$> git pull --rebase

EXOTIC: Remove or cut-off git revision history (DESTRUCTIVE!)

This procedure is useful when creating external teams repo, based upon an existing branch of the main source tree.

Assuming we have this commit history tree:

A <-- B <-- C <-- D <-- E <-- F (HEAD)

Now, suppose we want to "rebase" the commit history to commit "D", setting it as new "root" of the commit tree, while completely pruning the rest. The best thing to do, is to create a temp, orphan branch with the contents of the commit, merging it to master, and then clean out everything.

   # Create a new branch with D's content:
   # (Checkout to the status of the git repo at commit <D-sha1>; creating a branch named "temp")
$> git checkout --orphan temp <D-sha1>

   # Create a new commit that is to be the new root commit
$> git commit -m "new root commit due to rebase and cleanup"

   # Rebase the part of history from <D-sha1> & everything else onto the temp branch:
$> git rebase --onto temp <D-sha1> master

   # Rebase will checkout automatically to "master" with the above command; we can clean up dead branch:
$> git branch -d temp

   # To keep up the repo in good shape:
$> git prune --progress       # delete all the objects w/o references
$> git gc --aggressive        # aggressively collect garbage; may take a lot of time on large repos

   # Force push the changes to the remote origin: (WARNING: this is destructive and will erase remote history)
$> git push -f

Alternatively to the previous prune and gc commands, to erase and clean-up the latests log entries, you can issue also the following

   # Remove PERMANENTLY from the log history everything up until now:
$> git reflog expire --expire=now --all
$> git gc --prune=now

Clone this wiki locally