Posts tagged with "github"

The Git Add Patch Command

When you’re using Git for your version control, each commit should be atomic and topical. That is, it should contain related changes and nothing but related changes.

You don’t commit something broad in scope like “changed all the necessary files to implement feature 712”. That’s what a branch is for. Instead, you commit something like “added fetch() method call to the orders page”. That’s likely just one small part of feature 712. A whole bunch of commits end up implementing the feature.

But what about when you’re working away like crazy on your code base and you end up changing a single file in two different places and these two changes relate to different commits? Most people just go ahead and roll the changes into the same commit. Not ideal.

The hard way to do this right is to delete one change, stage and commit, and then paste the change back in.

There’s an easier way though. It’s called a patch add, but I like to call it a partial add. git add -h will show you the -p argument and inform you that it allows you to “select hunks interactively”. As much as that sounds like an online dating service for women, its actually just a really easy way from the command line to stage portions of a file and not the entire file.

Let’s say we start with this file…

//foobar.js
function foo() {
console.log('foo');
}

function bar() {
console.log('bar');
}

Now let’s say I end up editing both of the functions in that file, but these changes are unrelated to one another. I simply changed foo to foo foo and bar to bar bar. Let’s look first at using the command line to take care of business here, and then we’ll try it with Visual Studio Code.

Here’s the changed file contents…

//foobar.js
function foo() {
console.log('foo foo');
}

function bar() {
console.log('bar bar');
}

Command Line

Type git diff

C:\scratch\foobar [master]> git diff
diff --git a/foobar.js b/foobar.js
index 10aef9d..4c282ce 100644
--- a/foobar.js
+++ b/foobar.js
@@ -1,8 +1,8 @@
function foo() {
- console.log('foo');
+ console.log('foo foo');
}

function bar() {
- console.log('bar');
+ console.log('bar bar');
}

Now to actually start the staging command, we type git add foobar.js -p and get the same diff along with these interactive options…

Stage this hunk [y,n,q,a,d,/,s,e,?]?

There are actually a few more options than what are listed there too. You can type ?<enter> to get help on what those mean, but to spare time they are…

Command Action
y stage this hunk
n do not stage this hunk
q quit; do not stage this hunk or any of the remaining ones
a stage this hunk and all later hunks in the file
d do not stage this hunk or any of the later hunks in the file
g select a hunk to go to
/ search for a hunk matching the given regex
j leave this hunk undecided, see next undecided hunk
J leave this hunk undecided, see next hunk
k leave this hunk undecided, see previous undecided hunk
K leave this hunk undecided, see previous hunk
s split the current hunk into smaller hunks
e manually edit the current hunk
? print help

Which to choose? Well, the diff that we see on the screen shows both changes. That’s too much. So we want to press s to split this hunk. That gives us…

Stage this hunk [y,n,q,a,d,/,s,e,?]? s
Split into 2 hunks.
@@ -1,5 +1,5 @@
function foo() {
- console.log('foo');
+ console.log('foo foo');
}

function bar() {
Stage this hunk [y,n,q,a,d,/,j,J,g,e,?]?

…where now only one of the changes remains and we have our same interactive prompt.

The change we’re looking at is entirely related and should be in a single commit (along with possibly some other files). So we press y to stage it and then q to quit and we’re finished.

Visual Studio Code

Now let’s do the same thing using Visual Studio Code. This and a few other git-enabled IDE’s are smart enough to let you do a patch add. VS Code doesn’t call it a patch add though. It calls it staging selected lines, which actually makes good sense.

Start with the same file and changes, and view the changed file in VS Code and you should see…

Now just put your cursor anywhere within the first change in the pane on the right and then find the little ellipse (...) on the top right corner of the window. From there choose Stage Selected Lines.

And then if you look in the Git panel, you’ll see that the foobar.js file has been staged but it also has changes that have not yet been staged.

Whether you used the command line or Visual Studio Code to stage that first change and commit, you can just go about staging and committing the rest of the file as you normally would.

The end.

Saving Your Code Settings and Snippets

I finally realized why I wasn’t investing a lot of thought or time on my Visual Studio Code snippet library. It’s transient.

I looked up where the user settings are being saved - C:\users\<me>\AppData\Roaming\Code\User.

Well, that’s a bit of a crock. It’s 2016. I want everything saved to my OneDrive folder so I can do a reload without considering the various settings files I’ll have to back up and restore. What, am I a caveman?

I searched VS Code and my registry and didn’t see an obvious (I only have about 2.5 minutes to spend on tasks like this) way to customize the path, so I did what any developer in this modern era would do. I posted a question on StackOverflow.

And in true SO form, I got an answer back very quickly. Well, it wasn’t exactly an answer, but close. DAXaholic responded that there is an extension for VS Code that may fit the bill.

It’s called Visual Studio Code Settings Sync by Shan Khan. You can install it in Visual Studio Code by going to your command palette (CTRL+P) and typing ext install code-settings-sync.

Now, I had to spend a few synapses on this strategy for saving settings. The way Shan set this up it saves your settings, snippets, launch, and keybindings to your GitHub account as gists. Creative, Shan. It’s not exactly the same as having my settings and snippets saved to my OneDrive, but I kinda like it. I do have to manually upload everything, and by manual I only mean that I have to execute the Sync: Update/Upload Settings command in Code. And then when I reload or slide over to a new work machine I have to Sync: Download Settings.

I sort of like, however, storing bits of code in my GitHub Gists repository.

One advantage is that I could easily share my settings with the world. By default, the extension creates the gist as secret. I don’t like secrets though, so I can just edit that gist on gist.github.com and hit the Make Public button.

And now I can share the link with you. Very cool. And that’s a live link too so that every time I add an awesome new snippet, you can see it. Now, I just have to remember not to put any secret keys in my settings or snippets :)

Anyway. I thought this was very cool. Kudos to Shan Khan on the cool extension.

Happy coding.