A DBAs introduction to Mercurial Working with files and changes

A DBAs introduction to Mercurial Working with files and changes

A DBAs introduction to Mercurial - Working with files and changes

SQLShack

SQL Server training Español

A DBAs introduction to Mercurial – Working with files and changes

January 28, 2016 by Joshua Feierman

Introduction

In my previous article, we went over the reasons why DBAs should use version control, as well as the benefits of Mercurial as a specific choice. We also gave three examples of instances where source control can come in handy (though to be honest they were picked from a much longer list). In this article, I’m going to go a step further and actually walk you through setting up your first repository (locally for now, we’ll go into setting up a remote one later), making your first commit, and making (and viewing) changes to your newly tracked files. Let’s get started!

Setting up a repository

Now that we have some ideas for things to actually put in version control, how do we actually go about getting it setup? The steps are not difficult, so we’ll go through them here one at a time. Note: I’m very much a command line guy, so I will tend to give examples using that as a method when possible.

Downloading TortoiseHG

First we need to download the Mercurial tools. I find the best way to get this is to go and grab TortoiseHG, an excellent variation on the popular TortoiseSVN Subversion client. Yes, I know I just said I love the command line, and yet I’m advocating downloading a GUI tool. I do this for two reasons: 1) it’s an easy way to grab everything you need in one shot, 2) there are still times when I find a GUI nice, such as looking at revision history. I’d also recommend that you download and install WinMerge, which at least in my opinion is the best visual comparison tool available. As we’ll see, viewing the differences between files is a huge part of using version control. When running the installation package, I recommend leaving the default options selected. Once the installation finishes we can go on to creating our first repository.

Creating the repository

Before we go on, it bears repeating that the concept of a “repository” is very different with a distributed version control system than with more tradition server-centric models. Remember, each and every user has their own complete copy of the repository kept locally, including all history. To create a new repository, simply open a command prompt, navigate to the folder where you want the repository created, and type “hg init”. This command initializes the repository, and if it works you’ll see a folder called “.hg” in your directory. Next, we’ll want to change a few settings. Mercurial stores its settings at three levels: computer wide, the current user, and the current repository. There’s a few settings that we’ll want to configure at the user level, so we’ll start there. Navigate to your user profile directory (powershell shortcut: “cd $env:userprofile”) and look for a file called “mercurial.ini”. If it’s not there, then simply create an empty file with that name and open it in your favorite text editor. Then, paste in the following lines: 12345678 [ui]username = Your Name And E-Mail Heremerge = winmergeu [extensions]mercurial_keyring = These settings tell Mercurial the following: The user name to record when changes are committed (you could use an e-mail address but I like an actual name). To use the aforementioned WinMerge utility for all visual merging activities. Activate the mercurial_keyring extension, which allows you to securely save credentials for remote repositories (believe me, this is worth its weight in gold, unless you like entering in user names and passwords over and over again). Now, we’re ready to try our first commit of a file.

Your first commit

First, we need something to commit, so create a text file and put some content in it. We can do this easily from the command line. Note that for ease of use I’m using some Powershell commands to add the text to the file, rather than through a text editor (I’m a command line guy, remember?). 123 PS C:\A_Workspace\repo> Add-Content .\helloworld.txt "Hello World!" Now we can check to see what the status of the file is. 12345 PS C:\A_Workspace\repo> hg status? helloworld.txtPS C:\A_Workspace\repo> The “hg status” command tells Mercurial we want to see the status of all the files in our repository working directory. The “?” tells us that Mercurial isn’t sure what to do about that file, because it’s not currently being tracked. By default Mercurial doesn’t track files in a folder until we ask it to, which we can do with the following command: 12345 PS C:\A_Workspace\repo> hg addadding helloworld.txtPS C:\A_Workspace\repo> Note that we could specify a specific file name with the “hg add” command, or even a path or pattern. If you want to know all the different combinations, all you need to do (as with any Mercurial command) is type “hg help add”. Now we’re ready to actually commit our change, meaning it will be stored in the repository. 123 PS C:\A_Workspace\repo> hg commit -m"My first commit!" This commits the change into Mercurial with the comment “My first commit!”. Don’t believe me though, let’s verify that it’s there. There’s two ways to do this: 1) via the command line or via TortoiseHg’s graphical interface. First, the command line: 1234567891011 PS C:\A_Workspace\repo> hg status -AC helloworld.txtPS C:\A_Workspace\repo> hg logchangeset: 0:5b776a994ea9tag: tipuser: Josh Feiermandate: Sun Oct 25 09:06:20 2015 -0400summary: My first commit!PS C:\A_Workspace\repo> The “status -A” command shows us all files in the working directory and their status (the “C” means “clean”, I.e. the file has not changed since its last committed state); the “log” command shows us the history of changes committed to the repository. If we’d rather see this in the graphical interface (and even a hard core command line guy like me does admit this is a case where a graphical interface is pretty nice), we can look in the folder in Windows Explorer, where we’ll see this. That little green “check” tells us the file is unchanged since its last commit. We can also right click in the directory and choose “Hg Workbench”: Then we’ll see this. Here you can see the complete history of the repository, including the files changed in each revision and (as we’ll later see) the differences between them.

Making modifications

Now let’s learn how to make modifications to a file, see the differences between what we’ve committed, and finally commit our changes back to the repository. First, let’s make some changes to the file. 123 PS C:\A_Workspace\repo> Add-Content .\helloworld.txt "Hello again!" We can then use the “hg status” command to see that the file has been modified. 1234 PS C:\A_Workspace\repo> hg statusM helloworld.txt We can also look at the file in Windows Explorer, where we will notice a change in its appearance. See that little red exclamation point? That tells us the file has been modified since the last commit. To see what changes have been made, we can right click on the file and choose “Visual Diff”. This will bring up a window showing the differences between the committed version of the file and the one currently in your working directory. Note that your window’s appearance may vary from the one you see below, depending upon what tool is configured for Mercurial to use for comparisons. For me, there is no better option than WinMerge. Now, let’s suppose that we’ve accidentally made changes to the file and wish to remove them. Again, this is exceptionally easy with Mercurial. All we need to do is issue a command from the command prompt in the repository folder. 123 PS C:\A_Workspace\repo> hg revert .\helloworld.txt Now if we run the “hg status” command, we will see that there are no differences. We can also see that the familiar green check mark has returned. Let’s say that we did in fact want to commit these changes. If that’s the case, the procedure is exactly the same as our first commit. 123 PS C:\A_Workspace\repo> hg commit -m"Committing change." .\helloworld.txt Note that I specified the file name here. If you have multiple modified files and only want to commit one, this is how to do it. The change has now been committed, and we can see the results in the history of the file.

Fixing history

One of the neat things about Mercurial is that it enables you to go back in time and fix your mistakes. Those changes are then propagated to any downstream versions with minimal further intervention. This makes fixing bugs a lot less painful since there is less work to do. Let’s look at an example. 12345678910 PS C:\A_Workspace\repo> Add-Content .\helloworld.txt "Here's a change that introduces a bug."PS C:\A_Workspace\repo> hg statusM helloworld.txtPS C:\A_Workspace\repo> hg commit -m"Commit of bug"PS C:\A_Workspace\repo> Add-Content .\helloworld.txt "Here's another change."PS C:\A_Workspace\repo> hg statusM helloworld.txtPS C:\A_Workspace\repo> hg commit -m"Commit of another change." What we’ve done above is the following: 1) made and committed a change that introduced a bug, 2) made and committed another change. At some point in the future, we discover the bug. In this case we’re only one step ahead, but in many cases you might have committed many more changes before the bug was discovered. How would we go about solving this? First, we need to determine when the change that introduced the bug was committed. Mercurial has a great feature for this, aptly called “blame” (technically it is called “annotate”, but “blame” is a shortcut and besides, I like the name better). Blame lets you list out the file and see who last modified a particular line of code and in what revision it was modified. 1234567 PS C:\A_Workspace\repo> hg blame -u -d -l -c .\helloworld.txtJosh Feierman 8779c69e108f Mon Jan 25 06:28:31 2016 -0500:1: hello world!Josh Feierman 0daec33bfe0d Mon Jan 25 06:31:36 2016 -0500:2: Hello Again!Josh Feierman 1aa44aa5accf Mon Jan 25 06:37:27 2016 -0500:3: Here's a change that introduces a bug.Josh Feierman f8ddcc0802ff Mon Jan 25 06:37:45 2016 -0500:4: Here's another change. Curse that rascal Josh… Moving on, here’s the step by step process for actually fixing this bug. First, we need to “update” to the revision where the breaking change was made. In the list shown above, the revision is identified by that odd looking string of characters right after the user’s name. So in this case, the target revision is “1aa44aa5accf”. 1234 PS C:\A_Workspace\repo> hg update 1aa44aa5accf1 files updated, 0 files merged, 0 files removed, 0 files unresolved Next, we need to edit the line of code causing the bug to occur. We can use the “Visual Diff” feature to see our change. Then, we commit the change. 1234 PS C:\A_Workspace\repo> hg commit -m"Fixed the bug."created new head You’ll notice that Mercurial let us know that we “created a new head” when we issued the commit command. What this means is that we now have two paths of changes in the repository; one where our bug still exists and our final change (that line that says “Here’s another change”) was added, and one where the bug has been fixed but that last change doesn’t exist. To complete the process, we need to merge the two of them together. 123456 PS C:\A_Workspace\repo> hg mergemerging helloworld.txt0 files updated, 1 files merged, 0 files removed, 0 files unresolved(branch merge, don't forget to commit) When you issue the merge command, in general Mercurial is pretty good at merging the contents of two files together and will do so on its own. Sometimes it will need a nudge in the right direction however, such as cases where the edit conflicts with changes made later (such as editing the same line of code or adding on to the end of the file). When this happens, Mercurial will pop up a window of your chosen differential viewer, and let you choose the exact result. In our case, I had to copy and paste that last change into the merged file to get everything looking right. Finally, we need to issue the commit command to get everything back in order. You can then use the “hg log” command to see the complete list of changes. 12345678910111213141516171819202122 PS C:\A_Workspace\repo> hg commit -m"Merge of bug fix."PS C:\A_Workspace\repo> hg logchangeset: 5:d56d0cadaa51tag: tipparent: 4:681119c99a77parent: 3:f8ddcc0802ffuser: yardbirdsaxdate: Tue Jan 26 06:13:25 2016 -0500summary: Merge of bug fix. changeset: 4:681119c99a77parent: 2:1aa44aa5accfuser: yardbirdsaxdate: Tue Jan 26 06:04:42 2016 -0500summary: Fixed the bug. changeset: 3:f8ddcc0802ffuser: yardbirdsaxdate: Mon Jan 25 06:37:45 2016 -0500summary: Commit of another change. Notice how the second change listed (changeset 4:681119c99a77) lists the “parent” as not the one directly before it? This is because we essentially went back in time and created a new line of changes by fixing the bug. Then, we merged the two together for the final committed changeset (5:d56d0cadaa51), hence that one has two parents listed. If all this sounds a little confusing, don’t worry, it all becomes very natural with time and experience. The important thing to understand is how to go through the steps detailed above in order to fix problems introduced in our code. And if you ever find yourself in a situation where you’re not quite sure how to proceed, always review the documentation first and experiment. It’s a good idea to make a copy of your repository before trying anything new. Since each copy is a complete isolated repository in and of itself, this minimizes risk. (And yes, it’s true that you could just undo anything you accidentally did, but when playing around it’s often easier to just do it in a sandboxed copy rather than having to go through a long series of steps to back out mistakes.)

Conclusion and next steps

Congratulations, you’ve successfully configured and setup Mercurial, created a repository, and made your first commit! You are well on your way towards leveraging the remarkable power of version control to better standardize and maintain your tools and scripts as a DBA. In the next installment, we’ll dig deeper into Mercurial, looking at how to use branches to make experimental changes to our code without risk, and even create linked copies of existing files (something that will come in very handy as we’ll see). Finally, we’ll look in more depth at the specific cases mentioned earlier, and how we can leverage Mercurial to keep track of all the scripts in our DBA’s toolbox. Stay tuned!
Author Recent Posts Joshua FeiermanAfter completing a degree in neuro-psychology in college, Josh started his career in IT almost by accident.

In what was originally a temporary job creating reports for clients of a financial company, he decided we would rather write some VBA macro code than repeatedly push the same buttons on a keyboard .

After working in low level development and support roles, he transitioned to the role of a full time SQL Server DBA, supporting both production and development systems, and has never looked back.

He currently works as a senior DBA for Gateway Ticketing Systems, advising customers on maximizing SQL Server performance and availability. He also recently co-founded the independent software startup Do It Simply Software. He loves learning about what makes SQL Server tick, and how to make it go faster. For more information, follow him at sqljosh.com

View all posts by Joshua Feierman Latest posts by Joshua Feierman (see all) A DBAs Introduction to Mercurial – Branching and merging - February 19, 2016 A DBAs introduction to Mercurial – Working with files and changes - January 28, 2016 A DBA’s introduction to Mercurial – When and why we should use version control - December 18, 2015

Related posts

Revision history of an object change in a SQL database using Mercurial How to create a new Git repository on Bitbucket and review committed objects Source Control using Git in Azure Data Studio (ADS) SQL Server Linux installation for Amazon EC2 instance with Red Hat OS Introduction to SQL Server database continuous integration 1,525 Views

Follow us

Popular

SQL Convert Date functions and formats SQL Variables: Basics and usage SQL PARTITION BY Clause overview Different ways to SQL delete duplicate rows from a SQL Table How to UPDATE from a SELECT statement in SQL Server SQL Server functions for converting a String to a Date SELECT INTO TEMP TABLE statement in SQL Server SQL WHILE loop with simple examples How to backup and restore MySQL databases using the mysqldump command CASE statement in SQL Overview of SQL RANK functions Understanding the SQL MERGE statement INSERT INTO SELECT statement overview and examples SQL multiple joins for beginners with examples Understanding the SQL Decimal data type DELETE CASCADE and UPDATE CASCADE in SQL Server foreign key SQL Not Equal Operator introduction and examples SQL CROSS JOIN with examples The Table Variable in SQL Server SQL Server table hints – WITH (NOLOCK) best practices

Trending

SQL Server Transaction Log Backup, Truncate and Shrink Operations Six different methods to copy tables between databases in SQL Server How to implement error handling in SQL Server Working with the SQL Server command line (sqlcmd) Methods to avoid the SQL divide by zero error Query optimization techniques in SQL Server: tips and tricks How to create and configure a linked server in SQL Server Management Studio SQL replace: How to replace ASCII special characters in SQL Server How to identify slow running queries in SQL Server SQL varchar data type deep dive How to implement array-like functionality in SQL Server All about locking in SQL Server SQL Server stored procedures for beginners Database table partitioning in SQL Server How to drop temp tables in SQL Server How to determine free space and file size for SQL Server databases Using PowerShell to split a string into an array KILL SPID command in SQL Server How to install SQL Server Express edition SQL Union overview, usage and examples

Solutions

Read a SQL Server transaction logSQL Server database auditing techniquesHow to recover SQL Server data from accidental UPDATE and DELETE operationsHow to quickly search for SQL database data and objectsSynchronize SQL Server databases in different remote sourcesRecover SQL data from a dropped table without backupsHow to restore specific table(s) from a SQL Server database backupRecover deleted SQL data from transaction logsHow to recover SQL Server data from accidental updates without backupsAutomatically compare and synchronize SQL Server dataOpen LDF file and view LDF file contentQuickly convert SQL code to language-specific client codeHow to recover a single table from a SQL Server database backupRecover data lost due to a TRUNCATE operation without backupsHow to recover SQL Server data from accidental DELETE, TRUNCATE and DROP operationsReverting your SQL Server database back to a specific point in timeHow to create SSIS package documentationMigrate a SQL Server database to a newer version of SQL ServerHow to restore a SQL Server database backup to an older version of SQL Server

Categories and tips

►Auditing and compliance (50) Auditing (40) Data classification (1) Data masking (9) Azure (295) Azure Data Studio (46) Backup and restore (108) ►Business Intelligence (482) Analysis Services (SSAS) (47) Biml (10) Data Mining (14) Data Quality Services (4) Data Tools (SSDT) (13) Data Warehouse (16) Excel (20) General (39) Integration Services (SSIS) (125) Master Data Services (6) OLAP cube (15) PowerBI (95) Reporting Services (SSRS) (67) Data science (21) ►Database design (233) Clustering (16) Common Table Expressions (CTE) (11) Concurrency (1) Constraints (8) Data types (11) FILESTREAM (22) General database design (104) Partitioning (13) Relationships and dependencies (12) Temporal tables (12) Views (16) ▼Database development (418) Comparison (4) Continuous delivery (CD) (5) Continuous integration (CI) (11) Development (146) Functions (106) Hyper-V (1) Search (10) Source Control (15) SQL unit testing (23) Stored procedures (34) String Concatenation (2) Synonyms (1) Team Explorer (2) Testing (35) Visual Studio (14) DBAtools (35) DevOps (23) DevSecOps (2) Documentation (22) ETL (76) ►Features (213) Adaptive query processing (11) Bulk insert (16) Database mail (10) DBCC (7) Experimentation Assistant (DEA) (3) High Availability (36) Query store (10) Replication (40) Transaction log (59) Transparent Data Encryption (TDE) (21) Importing, exporting (51) Installation, setup and configuration (121) Jobs (42) ►Languages and coding (686) Cursors (9) DDL (9) DML (6) JSON (17) PowerShell (77) Python (37) R (16) SQL commands (196) SQLCMD (7) String functions (21) T-SQL (275) XML (15) Lists (12) Machine learning (37) Maintenance (99) Migration (50) Miscellaneous (1) ►Performance tuning (869) Alerting (8) Always On Availability Groups (82) Buffer Pool Extension (BPE) (9) Columnstore index (9) Deadlocks (16) Execution plans (125) In-Memory OLTP (22) Indexes (79) Latches (5) Locking (10) Monitoring (100) Performance (196) Performance counters (28) Performance Testing (9) Query analysis (121) Reports (20) SSAS monitoring (3) SSIS monitoring (10) SSRS monitoring (4) Wait types (11) ►Professional development (68) Professional development (27) Project management (9) SQL interview questions (32) Recovery (33) Security (84) Server management (24) SQL Azure (271) SQL Server Management Studio (SSMS) (90) SQL Server on Linux (21) ►SQL Server versions (177) SQL Server 2012 (6) SQL Server 2016 (63) SQL Server 2017 (49) SQL Server 2019 (57) SQL Server 2022 (2) ►Technologies (334) AWS (45) AWS RDS (56) Azure Cosmos DB (28) Containers (12) Docker (9) Graph database (13) Kerberos (2) Kubernetes (1) Linux (44) LocalDB (2) MySQL (49) Oracle (10) PolyBase (10) PostgreSQL (36) SharePoint (4) Ubuntu (13) Uncategorized (4) Utilities (21) Helpers and best practices BI performance counters SQL code smells rules SQL Server wait types © 2022 Quest Software Inc. ALL RIGHTS RESERVED. GDPR Terms of Use Privacy
Share:
0 comments

Comments (0)

Leave a Comment

Minimum 10 characters required

* All fields are required. Comments are moderated before appearing.

No comments yet. Be the first to comment!