Showing posts with label GIT SERVICES. Show all posts
Showing posts with label GIT SERVICES. Show all posts

Thursday, 25 October 2018

Re-basing Diverged Branches git rebase --onto

Rebasing Diverged Branches

git rebase --onto - The Simple One-Minute Explanation


git rebase --onto [the new HEAD base] [the old head base - check git log] [the-branch-to-rebase-from-one-base-to-another]
Bash
And my main motivation to putting it here is to easily find it again in the future as I always forget the syntax.
(This is a re-post from my old blog on drupalgardens, but it is still helpful.)

Mental model

To make all of this simpler think of:
You have:
  • Two red dishes on top of two blue dishes
  • One yellow dish
You want:
  • Those two red dishes on top of the one yellow dish
You do:
  • Carefully go with the finger down to the bottom of the two red dishes, which is the first blue dish
  • Take the two red dishes
  • Transfer them over to the one yellow dish
That is what rebase --onto does:
git rebase --onto [yellow dish] [from: first blue dish] [the two red dishes]
Bash
Note: The following is meant for an intermediate audience that is familiar with general rebasing in GIT

Longer explanation

It happened! A branch - you had based your work - on has diverged upstream, but you still have work in progress, which you want to preserve.
So it looks like this for you:
"Your Commit A" - "Your Commit B" - "Upstream Commit: This is the last upstream commit" - "Upstream Commit: This is another upstream commit"
But now the branch you based your work on squashed their work together or removed a file due to privacy concerns and now upstream has:
"Upstream Commit: This is the last upstream commit and this is another upstream commit together in one."
So all that you want is to move your two commits onto the new base.

The cherry-pick way

Lets assume your branch is called 'work' and you based your work upon 'upstream/develop'.
What you could do is to checkout the develop branch, reset it to the new version and cherry-pick your two commits:
# Reset the develop branch
git checkout develop
git reset --hard upstream/develop

# Checkout a new branch
git checkout -b work2
Bash
# Now find the two commit IDs
git log work

# Cherry-pick those
git cherry-pick 28d3fc5
git cherry-pick a67b2c

# And reset your work branch to the new work
git checkout work
git reset --hard work2
git branch -d work2
Bash
(Note: cherry-pick now also supports commit ranges, so this can be further simplified.)

The rebase way

Usually git knows - when you call rebase - how to rebase as it has a common history. It gets only problematic if the history diverges as happened above.
In that case you will need to tell git to rebase which on what.
So when you normally use:
git fetch upstream
git rebase upstream/develop
Bash
You would now use with the new base:
git fetch upstream
git rebase --onto upstream/develop [old base] work
Bash
and thats it.
To get the old base just use the commit ID of the first commit that does not contain changes you made.

A real drupal.org contribution example

This is super helpful when having to juggle several branches for e.g. the Drupal 8 core queue that depend on each other.
Lets say you worked on issue-X and issue-Y and issue-Y is built on top of issue-X.
Now you work mostly on issue-Y, but now you work more on issue-X and for your personal merit decide to make the history a little nicer, so now issue-X has diverted.
But a simple:
git checkout issue-Y
git rebase --onto issue-X [old base of X in issue-Y] issue-Y
Bash
can again save the day. The same is sometimes needed when the branches are based of of different core versions.

Tuesday, 25 September 2018

Delete a local and a remote GIT branch

Have you ever gone through a few sprints of work, created several local and remote branches and wondering how to get rid of them (both local and remote branches)?
Here some tips to do that:

Delete a Local GIT branch

To delete the local GIT branch we can try one of the following commands:
git branch -d branch_name
git branch -D branch_name
as you can see above, we have 2 different argument, one with ‘d’ and one with ‘D’.
The -d option stands for --delete, which would delete the local branch, only if you have already pushed and merged it with your remote branches.
The -D option stands for --delete --force, which deletes the branch regardless of its push and merge status, so be careful using this one!

Delete a remote GIT branch

To delete a remote branch you can use the following command:
git push <remote_name> --delete <branch_name>
Alternatively, there is this other following option too, which might be just a bit hard to remember:
$ git push <remote_name> :<branch_name>
These top options can also be used if you want to delete a “tag”.

Push to remote branch and delete

If you ever want to push your local branch to remote and delete your local, you can use git push with the -d option as an alias for --delete.

Friday, 21 September 2018

Create a new Git Repository

In this tutorial we will learn How to create a new Git Repository. However, before you proceed with this tutorials it is very important that you have gone through the previous set of tutorials on GIT here:

What is a Git Repository?

The purpose of Git is to manage a project, or a set of files, as they change over time. Git stores this information in a data structure called a repository. In short Git Repository is a collection of all project files along with their historyIt is a virtual storage of your project where you keep all the resources/files of the project along with a special folder called .git. The .git folder in a git repository is used by GIT programs to store information about the repository like LogsPosition of Head and more.. It allows you to save versions of your code, which can be accessed, tracked and managed.
At this article we don’t know much about these terms and hence we will keep our discussion to minimum about the .gitfolder. For the time being just remember that every GIT repository will have a hidden .git folder to enable GIT programs to track changes in the repository.

Create a new Git Repository

We can create Git Repository using one of the three approaches enlisted below: 
  1. Create a bare repository
  2. Initialize repository in an existing project directory
  3. Clone a remote repository from Github
We’ll be using Git command line tool to create repositories and also for learning all the Git operations in this series of tutorials. Use of Git command line tool will help you get familiar with the GIT Commands. Using Git command line tool gives you more flexibility than Git Clients or Git GUIs because they provide only a subset of GIT Features. So, to harness the complete power of Git like a pro, Git command line tools are the recommended way to use GIT. 
So, let’s get started and see how we can create Git repository in the three ways mentioned above. The very first thing is to find the Git command line tool on system. I hope you have already gone through the Git installation process described in the tutorial here:

Create a Bare Git Repository

Creating a Bare Git Repository for new project is three set process:
  1. Create a New Project/Folder
  2. Browse to New Project
  3. Initialize Git Repository for the Project
Once you have Git installed, simply search of git cmd  in your system search bar. You will get the Command line tool listed as shown in the below image. 
Search for Git CMD
Note: that this is Windows 8 System search bar, you will have a different one based on the OS you have.

Open the Git command line tool, you will see a command line window open up as shown in the image below.
Navigate to folder for storing all local git repositories

Step 1: Create a New Project/Folder

Now that we have our command line tool open, let us create a project folder. Creating a project folder with a good name is very important. If you have a Good and Relevant name of your project it will become easier for you to identify and relate to the project when you comeback to it in the future. 
Note: Usally people create a Root Project folder with the company name like toolsqaamazon, flipkart etc and with in this root folder they keep all the different projects of the same company.
Command to create a folder on a Windows and Mac system is: mkdir <folderName>. Where folder name is the project name. Let us name our first project LocalGit. With this name the command becomes: mkdir LocalGit
Create a directory to store all local git repositories

Navigate to this folder by using the command cd LocalGit, both on Windows and Mac systems.
Navigating to directory created for storing git repositories
Now you are inside the repository folder where we’ll create our Git repositories using three approaches mentioned above. 
Bare Git repository means an empty directory with just a hidden .git folder. Let us name the project as BareGitRepo. Ensure that you’re in the LocalGit folder before proceeding with following steps. Enter command mkdir BareGitRepo
Create a directory to store bare repository
Note: So now you have your Root Folder (LocalGit) ready and with in that the Project (BareGitRepository)

Step 2: Browse to New Project

Navigate to the project created in the previous step using the command cd BareGitRepo
Navigate to directory created to initialize bare repo

Step 3: Initialize Bare Git Repository for the Project

Enter the command git init. Consequently, execution of this command creates a hidden .git folder therein. Or in other words, an empty Git Repository is initialized. You’ll notice a message stating that an empty Git repository is created.
Create a New Git Repository
Note: git init is a standard GIt command and it initializes the directory with a .git folder used for tracking versions of project artifacts. 

Let us view the contents of the newly initialized Git repository by executing the command dir /ah
View content of bare repository
After the execution of dir, you will see empty project folder as expected from a Bare Git repository. You can now add project files to this repository and they’ll be tracked by GIT. 
However, if you want to see the .git folder being reported in command line use the command dir /a:hdThis will show hidden folders in the directory and you will notice .git folder there.

Create Git Repository for an Existing Project

We’d also like to track an existing project by using Git. In this case, we’ll initialize a Git repository in an existing project directory. There is no rocket science in creating git Repository for existing project, it is as same as creating a git repository for a new project with the only difference of step 1 is not required:
  1. Create a New Project/Folder
  2. Browse to Existing Project
  3. Initialize Git Repository for the Project

Step 2: Browse to Existing Project

Navigate to the directory containing your project artifacts. In this case, let us consider that name of the project is SampleProject at the location C:\Users\admin1\LocalGit\SampleProjectmove to a similar location on your system. One can view the content of the directory by using the command dir.
.Content of existing project
Note: I already have few files in the SampleProject for a demo purpose, so it is not an empty folder.

Step 3: Initialize Git Repository for the Project

Initialize the git repository in this project by using the same command used while creating a bare repository i.e. git initGit init in existing project directory
View the content of the directory and note that a .git folder has been created therein. View Project Directory after Git Init command
After Git initializing, the project is tracked by GIT.

 

Cloning a Remote Repository from GitHub

When you want to contribute to an existing project hosted on GitHub or a similar online Git service provider, you’ve to Clone their repository from remote server like Github, GitLab etc. For example, remote repository of Apache POI (Java library to read from and write to Excel files) is hosted at https://github.com/apache/poi 
Definition of word Clone in context of Git is to create a local copy of the Remote repository. In this case remote Repository is hosted at https://github.com/apache/poi and we will Clone it on our local system.
Here are the steps to clone (download and track the changes) this repository. 

Step 1: Fetch and copy the URL, as mentioned in the image below, of the Apache POI repository at GitHub. That is, https://github.com/apache/poi.git
Remote Apache POI Repository
Step 2: In Git CMD, navigate to the folder for storing all the Git repositories locally. That is, C:\Users\admin1\LocalGit in this example. 
Step 3: Create a directory called RemoteCloneRepo to store the source code of Apache POI repository locally by using the command mkdir RemoteCloneRepo.
Navigate inside this newly created directory by using the command cd RemoteCloneRepo
Create a directory to clone remote repo
Step 4: To clone the repository, enter the command git clone https://github.com/apache/poi.git 
Execute git clone command
Note: git clone <repoURL> is a standard GIt command to clone an an existing remote repository. 

Step 5: Cloning a repository depends on size of the repository. Usually, it takes a while for a big repository. You’ll have to wait until all the files are checked out. Execute git clone command
Now you can make changes to the repository. Git will track all the changes.

In this tutorial we looked at the three ways to create a Git repository. In the next tutorial, we’ll learn about the typical Life-Cycle of files in a Git repository. We will also learn about different Git commands that will help us move our Git repositories into different stages of a typical Git life-cycle.

Git Life Cycle

Till now we have understood what Git is and how to create a Git repository. It will be great to take a quick look at the life cycle of files in a Git repository. It is important for us to have an abstract idea of the different stages of Git before going into more detailed understanding of Git. In this tutorial it is expected that you create a mental map of different stages in Git life cycle.
Before proceeding with this tutorial, it’d be helpful to go through following tutorials first: 

Stages in GIT Life Cycle

Files in a Git project have various stages like CreationModificationRefactoring, and Deletion and so on. Irrespective of whether this project is tracked by Git or not, these phases are still prevalent. However when a project is under Git version control system, they are present in three major Git states in addition to these basic ones. Here are the three Git states:
  • Working directory 
  • Staging area 
  • Git directory 
These stages are the essence of Git. You get great flexibility in tracking the files due to these stages that files can reside in under Git. Let’s understand each of these states one by one.

Working Directory

Consider a project residing in your local system. This project may or may not be tracked by Git. In either case, this project directory is called your Working directory. 
Working directory is the directory containing hidden .git folder. 
Git Init
Note: git init – Command to initialize a Git repository
For sake of further discussion, let’s assume that this directory is now tracked by Git. That is we’ve created a Git repository in this existing project directory. So, as discussed in the tutorial on Creation of Git Repository, a hidden .git folder is initialized therein. In this state, Git is just aware of the files in the project. It doesn’t track the files yet. To track the files, we’ve to commit these files by first adding the files to the staging area. This brings us to the next state in Git life-cycle.

Staging Area

While we’re in the working directory, we select the files that have to be tracked by Git. Why do we need to this? Why don’t we track everything in the project? That’s because some files in the project like class files, log files, result files and temporary data files are dynamically generated. It doesn’t make sense to track the versions of these files. Whereas the source code files, data files, configuration files and other project artifacts contain the business logic of the application. These files are to be tracked by Git are thus needs to be added to the staging area.
In other words, staging area is the playground where you group, add and organize the files to be committed to Git for tracking their versions. 
It’s important to make a quick note of the term called indexing here. Indexing is the process of adding files to the staging area. In other words, index constitutes of files added to the staging areaThis term will be explained again in the coming tutorial on Git terminologies
Git Add
Note: git add – Command to add files to staging area.

Git Directory

Now that the files to be committed are grouped and ready in the staging area, we can commit these files. So, we commit this group of files along with a commit message explaining what is the commit about. Apart from commit message, this step also records the author and time of the commit. Now, a snapshot of the files in the commit is recorded by Git. The information related to this commit (names of files committed, date and time of commit, author of commit, commit message) is stored in the Git directory. 
Thus, Git directory is the database where metadata about project files’ history will be tracked. 
Git Commit
Note: git commit -m”your message” – Command to commit files to Git repository with message.


Additional Lifecycle Stage with Github

Now mind that we’re learning the lifecycle in Git exclusively.  That is, it’s important to note that the three stages discussed above are only for Git and not Github. Why? Because as explained in the tutorial on What is Git and Github? you can track versions of your files by using only Git. That is, Github is needed when you want to collaborate and publish your code to a team or community. Thus, it helps to remember that the Git cycle doesn’t conventionally involve Github.
However, we work in teams and collaborate with multiple people on a given project. This makes it imperative to understand the additional stage related to Github. While dealing with Github, there’s a concept of Remote repositoryand a related process called Pushing the files.
Git Life Cycle
As seen in the image above, after committing the code to the local Git repository, it has to be pushed to remote repository. Here, Remote repository means mirror or clone of the local Git repository in Github. And pushing means uploading the commits from local Git repository to remote repository hosted in Github. This will allow other collaborators to view the code. Thus, whatever changes you make in the local Git repository will be visible to other collaborators when you push your code to the remote repository. Command to push the code to remote repository in Github is git push.
Note: git push – Command to push commits from local Git repository to remote Git repository hosted in Github. 

Need of Staging Area

After learning about these stages, one might naturally ask – Why is staging area required? Why can’t we directly commit the code instead of first adding it to the staging area? Let’s understand the reason behind this with help of following points:
  • Faster Git operations – Staging files regularly yields in very fast Git operations. A commit is essentially a resource-expensive interaction with the Git database. For those with background of SVN (a Client-Server model based VCS) know that every commit requires considerable time. This is because it has to first traverse the SVN commit tree to check if there have been any commits made by other users before the last commit made by us. Consequently, commit operations tend to be slow. However, in case of Git, staging the files doesn’t need interaction with the Git database. It’s only when the files have to be committed that Git check for presence of commits made by other users. Thus, staging helps in recording the changes even before committing them to Git database. 
  • Visualizing the commit before actual commit – As discussed earlier, staging area is the state in which the files reside before they’re committed. That is, staging area actually lets you visualize the group of changes that will be recorded by Git. Essentially this gives you fine-grained control over what gets committed to Git and what does not. 
  • Splitting work into separate related commits – Apart from the first commit when all the project files are committed at once, you should record (take snapshot of the project) at regular intervals. That is, suppose you’re working on a new feature whose timeline of development runs into several days. So, while you’re working on the feature you are required to refactor a small part of the code. In this case, you can quickly make the required changes, stage the required file and resume work on the feature. All of the changes i.e. feature changes and refactor code can be committed at once from the staging area. 
With this background in mind, let’s now proceed towards learning some crucial terminologies related to Git in the next tutorial.