Working Locally with Git - aakash14goplani/FullStack GitHub Wiki

Overview In this module, we're going to look at working locally with Git. We're going to start by talking about how we can create a local repository, adding files, how we can commit those pending changes to the repository, view history of commits made, looking at differences between commits in the history, the difference between the working copy, the staging area, and repository itself, the leading files, as well as, updating files, and how we can clean the working copy of any extraneous files that shouldn't be there. And then we'll wrap up with we can ignore files using a gitignore for common things like log files or build artifacts that we don't want in a repository. ( Pause )

Creating a local repository, adding files, and committing changes I have an empty directory which I'd like to turn into a local Git repository. I can do this by running Git init. Git init has created a dot Git directory which contains the repository and all of its metadata. I can add a file to this repository by first echoing hello Git to a readme dot TXT file and running Git status. That tells me that the readme dot TXT file is an untracked file, Git does not have it in its repository yet. I can run a Git add and run status again and Git now notices that that file is a new file and is staged to be added to the repository which I can do by running Git commit. Git commit brings up the defaults text editor, in my case bin though it could be notepad, notepad to or any other text editor of your choice, and I can say I added readme dot TXT. If take a look at this history, I can see that I have one commit in my repository now. You can see the author information, data information, as well as, the comment I made. You can also see the commit SHA. Git identifies commits by a SHA1 hash of the commit. Often, you can deal with these commits by simply using the abbreviated 5 to 8 characters, first characters of that commit SHA rather than the full SHA. Now, if I actually update that readme dot TXT file by adding a second line and run Git status, Git knows a bit the readme dot TXT file and notes that it is modified. I can add all modified files by doing a dash U or updated, running Git status again. I've now staged that change to be committed. So I will do a get commit and I can use the dash M option which allows me to provide the message directly in line so I don't need to go to my text editor.

Viewing history and diffs If I do a log again, you can see I now have two Gits, two commits in my Git repository listed in reversed chronological order. So the most recent commit is at the top and later commits are at the bottom. Now, if I want to find what has changed between these commits, I can run a git diff. I can specify the initial commit, so that one, the very first commit to my repository, and the later commit, and that notes that the hello again has been added. It's also provides some context around it so that I can see what other source lines are close to the change lines. Now, always working with the SHA1 hash is can be difficult and so Git provides an easier way of specifying these things. The latest commit is known as Head. I can also go back from the head by using a tilde syntax, so tilde1 is one commit back from the Head so I can go from Head tilde1 to Head which provides with the same one. If I do not specify a commit then Git assumes that I mean Head so I can abbreviate this further to just Head tilde1 dot dot. Now, if I-- lets add a few file. Add file one, add file two, and if I look at status, both of these are untracked files. If I run a Git add dash U, that's going to add all updated files to my staging area. Git has this notion of a staging area which is files that are going to be added in the next commit or changes I'm going to be adding in the next commit. If I run a dash U and run status again, you'll notice that nothing has changed. It's because, the dash U option only adds updated files, files that have changed Git knows about. These could be either changes to files or it could also be deletions of files, dash U will noticed those as well. I can either add these explicitly by names so I can say file one dot TXT and file two dot TXT, or I can use the dash capital A option. Capital A adds all files including untracked ones. You have to be careful when you're using this option to make to sure that's you're not accidentally adding files you don't intend to running Git status. You can see that both files are staged and ready to be committed so I'm going to say Git commit dash M added cool new feature. If I looked at the log, you can see that I've got the new commit in their and if I do a diff on Head tilde1, I'm going-- remember I'm going back from the Head so this is between the updated readme dot TXT and the added cool new feature, you can see that I've added to new files. They're empty files, if I got file one dot TXT, it's empty that's why we're not seeing any content. But those files have been added to the repository.

Staging changes as multiple commits Now let's go ahead and I'm going to edit them-- I'm going to edit file one dot TXT. So, adding some code here and I'm also going to edit the readme, updating readme with new information. If do a Git status, I've got two pending changes in my working copy but they might completely different. I might have noticed-- I might having adding a feature or fixing a bug in my code and noticed a typo in the readme so I've done two things at once. So, I'd like to actually stage this as two different commits. Git allows me to do this easily. I can say Git add file one dot TXT, and if I look at the status, you can see that file one dot TXT changes have been staged but the readme dot TXT changes have not been, I can now Git commit and say fixed bug number 1, 2, 3, 4, and now I can say Git add readme, and say Git commit, and give a fixed typo and readme dot TXT, and added additional information about other features. So by having this staging area, I can pull in parts of my working copy at one time in order to break commits up into logical units. Now you do want to be careful about this because if I had multiple code changes, I haven't actually run all of those pieces together. So I-- I might not want to-- you want to be careful about what you're actually staging in. So you wouldn't want to only pull in-- accidentally pull in part of feature and then your commit doesn't make. It doesn't actually compile. So just be aware of that.

Deleting and renaming files Now let's say I realized that I don't need file two anymore. So file two is no longer used so I'll just remove file two dot TXT, just using an operating system command, and if run a Git status, Git notices that that file has been deleted. If I do a Git add dash U, and a status again, that stages that deletion into the next commit, into that staging area. ( Pause ) Now although I have that file deletion staged for the next commit, if I realized that there's additional changes that I want to make, I can still do so. So if I need to add file three, text for file three and do a git status, I can go ahead and add this as well. ( Pause ) If I realize that I need to move a file, I need to rename it, I can do that using normal operating system commands. For instance, I can rename file one to new filename and if I do a get status, it will look to get initially like there is a deletion of file one and a new untracked file. Now, I'm going to do a git add dash A which will add any deletions to these staging area as well as any new files and let's take a look if what happens. Now, git is going to examine the contents. See the contents of those two files are the same and realize that this was a rename operation. So, I can-- now that all these are in the staging area, I'll reorganize the feature, so there we go. And if I do and git status, all those changes have been committed to my repository. You also notice now that I do and git log that I've got more commits than will fit on the single screen and it's actually page forming.

Undoing changes to the working copy So let's take a look at what happens if I make an edit that I don't like. So let's go into read me and I'm going to just delete everything. So there, I do and git status, I've got a modified file. I realized-- oh, I didn't want to actually make that change. I can do or git checkout to pull that into the repository by defaulted grab of the head version by looking at it and git status, I've got nothing to commit, so I don't have no pending changes. And if I look at the contents of read me, it has all of its contents back then again. So, you can check out files from the repository in order to clean up or revert changes that you might have made by mistake or realized in hindsight was about idea. Now, let's say I go ahead and I'm going to edit the read me file. So I'm going to delete all of the contents and I'm also going to remove file one dot TXT. I'm also going to remove and we renamed it new file dot TXT, and if I go and git status, I have a bunch of changes, I could do individual checkouts on each of them. The other thing that I can do is to git reset. And here I'm going to do a hard reset and looking at the status, I've reset myself, my working copy back to the head so I've actually removed all of those changes.

Undoing/redoing changes in the repository Now, let's look out the log. That feature reorganization, I realized, hey, that didn't go quite as planned. I can actually do a git reset soft head tilde1. So let's take a look at what that actually did. If I look at the log, my head now has that reorganization of the feature omitted. I've basically taken that last commit out of my repository. If I look at my status, you can see that all of those changes that I made in the reorganization have been moved back into the staging area and they're also reflected in my working copies. So I can now go in and change that commit around, I can make corrections, I realized-- oh, I forgot to run may unit test and there's a broken one, I can rule that back out, make the fixes and recommit a working commit into my repository. So let's go ahead and commit that and I'm going to say, reorganized, so just to the same old messages before, git, commit, oops, dash M. Let's do a git commit dash M, reorganized file, files for feature. If I do a git status, my working copy is clean. If I do and git log that new commit is in there. Now, let's say that I decide that, that features just was-- there is something fundamentally broken that commit. If I do and get reset hard to the head tilde1 that is going to move my head back, the head commit back, it's going delete that last commit, reorganize files for feature and discard all the changes. So, those changes have gone if I do a git status, you can see I have nothing in my working copy, and if I do a git log, that commit has vanished entirely. There are ways to get it back which we'll look out in the later module, but this allows me to fix things in my local repository before I might push to a public repository.

Cleaning the working copy Now, let's say that I've created a bunch of temp files, so I've got temp 1, and temp 2 and I look at a git status. So, I've got these spare files kicking around. This could be the results of-- they could be build artifacts, they could be extraneous log files, it could be anything and I've liked to clear these out. There is a git clean command which me allows me to remove files. So if I run and git clean by it self by default, I have to specify a forced option. So I can specify an end which means, what would I do? So, the results of this would be removing the temp 1 and temp 2 dot TXT files and a dash F options actually performs the operation. So if I do a git status now, you can see that my working copy is once again clean. So it's a very easy way to clean up if you have stray files kicking around in your working copy, you can go a git clean to remove those.

Ignoring files with .gitignore Now, let's say I do have something like a log directory, so let's make directory logs and I'm going to add some logs in there, log dot TXT and I do git status. Logs are constantly changing as the application runs and so, I don't want to actually commit this to my repository. Git provides a gitignore file. So, I can add a gitignore to my root and this specifies files that I don't want to actually commit to my repository. I can do it relative. So if I say logs, that will be any log directory, anywhere very deep in my application or I can explicitly root it an absolute path and this is relative to the root of my repositories. It is not root to the file system, it's the root of the repository, so I can say, I'm going to omit everything, logs, and asterisk dot TXT or I might want to say logs slash asterisk dot log or I can even say just logs or anything in that log directory, it's you choice how you want to put it together. If I now do a git status, you'll notice that there is one changed file, it's the gitignore file. The gitignore file does get committed to the repository and then shared across the team, if you got multiple people working in this repository, but logs is a no longer being pulled in. So this is a great way to ignore build artifacts, binaries, log files, anything that you don't want actually committed to your repository. So I'm going ahead and add dot gitignore file and commit it, added dot gitignore. Looking at a status, you can see that my working copy is clean. Looking at the log, you can see I've got this nice history of everything that has been done in this repository up to this point, I can-- we'll look at in a future module, how we can actually search through this repository, find interesting commits, as well as, we will be looking at how we can branch so we can have a local features branch, do some development and merge back in. We'll also be looking at how we can share this repository with the world so that multiple developers can be working on the same code base at the same time and be able to merge their changes back together.

Summary In the screen cast, we have looked at how we can create a local repository, adding, updating, and deleting files from the repository. How we can commit set of changes and how we can break up larger sets of changes into individual commits, how we can view the history and the repository and depths of that repository history. We talked a bit the difference between the working copy, the staging area, and the repository itself, how we can clean up the working copy of any extraneous files, and lastly, wrapping up with ignoring files with the gitignore.