git


How to use git features on a local project without a Git server

Like many of you, sometimes we develop code that does not belong to a Git server.
Working as so, one would think that we would miss all the features of a Version Control System (VCS).
Fortunately, this assumption is wrong.
Using the already installed Git tools, we can create a new local repository in any system folder with no additional configuration.

To do so, and create a new repository from an existing project, we need to do the following using a terminal/shell:

  1. Navigate into the directory that contains the project e.g. cd /home/bytefreaks/Projects/Party/banana/
  2. Type git init
    This command will create an empty Git repository in that folder and it will produce a message as follows:
    Initialized empty Git repository in /home/bytefreaks/Projects/Party/banana/.git/
  3. In case you have files that should not be included in your repository, it is better that you create a .gitignore file and add them there.
    This way you will be able to indicate all of the files that you don’t want to the repository to track.
  4. Use git add . (please note that you need the dot . for this command)
    This command will stage all files that are not in .gitignore to be part of your next commit.
  5. Finally, type git commit or git commit -m "Initial Commit with status bla bla", to make your first commit to the repository
  6. Profit!

By now, you should have a fully functional local git repository without the assistance of an external server.


About restoring a deleted Git branch

Recently, a branch was deleted from the server without it being merged.
Luckily for us, we had a local copy.

We used used the command git reflog to get access to the reference logs of the branch.
The command returned results similar to the below:

271f0084 HEAD@{0}: pull: Merge made by the 'recursive' strategy.
 0e71c0b HEAD@{1}: commit: Minor change: Cracked NSA systems
 c81624b HEAD@{2}: pull: Fast-forward
 ef1f281 HEAD@{3}: commit (amend): Deployed satelite
 1ed1a5a HEAD@{4}: commit (amend): Deployed satelite
 a8682cb HEAD@{5}: commit (amend): Deployed satelite
 e4560c8 HEAD@{6}: commit (amend): Deployed satelite
 1679a90 HEAD@{7}: commit (amend): Deployed satelite
 d27d2c9 HEAD@{8}: commit: Deployed satelite
 aaf8261 HEAD@{9}: checkout: moving from master to crack-nsa-systems
 2500e11 HEAD@{10}: clone: from ssh://[email protected]:7999/secret/bananas.git

From this information we got the hash value in front of the commit which we wanted to use to restore, which was 271f0084.

Then, we checked out that version using

git checkout 271f0084;

When we tried to push the branch back to the server the Git pre commit hooks blocked the operation.
Based on the rsa key used, we could only submit changes that were committed by the owner of that key.
The option to disable temporarily the pre commit hooks was unfortunately out of the question.
So we had to replace all author names and emails with the name of the one holding the key.

To do so we used the following command before pushing to the server once more:

git filter-branch --commit-filter '
   if [ "$GIT_COMMITTER_NAME" = "Doe, John" ];
   then
     GIT_COMMITTER_NAME="Squarepants, Bob";
     GIT_AUTHOR_NAME="Squarepants, Bob";
     GIT_COMMITTER_EMAIL="[email protected]";
     GIT_AUTHOR_EMAIL="[email protected]";
     git commit-tree "$@";
   else
     git commit-tree "$@";
   fi' HEAD

git filter-branch lets you rewrite Git revision history by rewriting the branches mentioned, in our case it was HEAD, applying custom filters on each revision. Those filters can modify each tree (e.g. removing a file or running a perl rewrite on all files) or information about each commit. Otherwise, all information (including original commit times or merge information) will be preserved.

HEAD is a reference to the currently checked out commit. In normal states, it’s actually a symbolic reference to the branch you have checked out.
Looking at the contents of .git/HEAD you’ll see something similar to ref: refs/heads/master.
The branch itself is a reference to the commit at the tip of the branch.


Git: Create a branch on your local machine, switch to it and then push it on the server

Following are a couple of simple commands that we use daily to create a new branch on git and push it to the git server.

The following command will create locally a new branch called branch_name and switch to it.

git checkout -b branch_name;

The following command will push the local branch you are currently switched to on the git server.
It will be made available to the server using the name branch_name.

git push --set-upstream origin branch_name;

Script to clone all git repositories from all projects of a privately hosted Bitbucket server 1

The following script can download all git repositories from all of the projects that you have access to on a privately hosted Bitbucket server.

The execution work-flow of this script is as follows:

  1. It will ask for your username (the one you use to login on the Bitbucket server)
  2. Then it will ask for your password, the password will not be visible on screen as you type because we disabled the echo functionality for that step.
  3. Later, you will be prompted to provide the URL of the server, for this step be sure to define the protocol if it is http or https and the correct port number as well (e.g. https://bitbucket.bytefreaks.net:7990)
  4. Finally, you will be requested to give the location to where the repositories should be cloned to.
  5. Then the script will connect to the server, get the list of projects that you have access to and for each project retrieve the repositories of the project and clone them in the designated folder.

[download id=”2637″]


#!/bin/bash

echo -n "Username: ";
read username;
echo -n "Password: "; 
#Disabling echo, so that password will not be visible on screen
read -s password
#Enabling echo
echo

echo -n "Server (e.g https://repository.bytefreaks.net:7990): ";
read server;
echo -n "Location to clone repositories in: ";
read location;

mkdir -p "$location";
cd "$location";

#Getting all projects
curl --user "$username:$password" "$server/rest/api/1.0/projects/" | \
  grep -oP '"key":"\K\w+' | xargs -I {} -n 1 -I_project -- sh -c \
    "curl --user \"$username:$password\" \"$server/rest/api/1.0/projects/_project/repos\" | grep -o '\"ssh:[^ ,]\+' | xargs -L1 git clone";

exit 0;

[download id=”2637″]

 

Notes for the future:

  • Separate the cloned repositories per project
  • Support for people that have hundreds of projects and/or hundreds of repositories using the paging functionality