It is possible to do this with workflow rules. Detecting whether a field value has been changed is easy enough to do with the formula editor's ISCHANGED(field)
function. Getting old field values isn't something that an email template would be able to do directly, but you could add another custom field to hold that value and update it with another workflow rule after the email is sent.
./package.xml
<?xml version="1.0" encoding="UTF-8"?>
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<types>
<members>Account.Group_ID_Updated__c</members>
<!-- <members>Account.Group_ID__c</members> -->
<members>Account.Old_Group_ID__c</members>
<name>CustomField</name>
</types>
<types>
<members>unfiled$public/AccountGroupIdChanged</members>
<name>EmailTemplate</name>
</types>
<types>
<members>Account.AccountGroupIdChanged</members>
<name>WorkflowAlert</name>
</types>
<types>
<members>Account.PutNewValueInOldGroupIdField</members>
<members>Account.SetGroupIdUpdated</members>
<members>Account.UnsetGroupIdUpdated</members>
<name>WorkflowFieldUpdate</name>
</types>
<types>
<members>Account.AccountGroupIdChanged</members>
<members>Account.GroupIdUpdatedSet</members>
<name>WorkflowRule</name>
</types>
<version>35.0</version>
</Package>
./objects/Account.object
<?xml version="1.0" encoding="UTF-8"?>
<CustomObject xmlns="http://soap.sforce.com/2006/04/metadata">
<fields>
<fullName>Group_ID_Updated__c</fullName>
<defaultValue>true</defaultValue>
<externalId>false</externalId>
<label>Group ID Updated</label>
<trackFeedHistory>false</trackFeedHistory>
<trackHistory>false</trackHistory>
<type>Checkbox</type>
</fields>
<!--<fields>
<fullName>Group_ID__c</fullName>
<externalId>false</externalId>
<label>Group ID</label>
<length>18</length>
<required>false</required>
<trackFeedHistory>false</trackFeedHistory>
<trackHistory>false</trackHistory>
<type>Text</type>
<unique>false</unique>
</fields> -->
<fields>
<fullName>Old_Group_ID__c</fullName>
<externalId>false</externalId>
<label>Old Group ID</label>
<length>18</length>
<required>false</required>
<trackFeedHistory>false</trackFeedHistory>
<trackHistory>false</trackHistory>
<type>Text</type>
<unique>false</unique>
</fields>
</CustomObject>
./email/unfiled$public/AccountGroupIdChanged.email
The Group ID of {!Account.Name} has changed from:
{!Account.Old_Group_ID__c}
to
{!Account.Group_ID__c}
./email/unfiled$public/AccountGroupIdChanged.email-meta.xml
<?xml version="1.0" encoding="UTF-8"?>
<EmailTemplate xmlns="http://soap.sforce.com/2006/04/metadata">
<available>true</available>
<description>Account Group Id Changed</description>
<encodingKey>UTF-8</encodingKey>
<name>AccountGroupIdChanged</name>
<style>none</style>
<subject>Group ID Changed: {!Account.Name}</subject>
<type>text</type>
</EmailTemplate>
./workflows/Account.workflow
<?xml version="1.0" encoding="UTF-8"?>
<Workflow xmlns="http://soap.sforce.com/2006/04/metadata">
<alerts>
<fullName>AccountGroupIdChanged</fullName>
<ccEmails>[email protected]</ccEmails>
<ccEmails>[email protected]</ccEmails>
<ccEmails>[email protected]</ccEmails>
<description>AccountGroupIdChanged</description>
<protected>false</protected>
<senderType>DefaultWorkflowUser</senderType>
<template>unfiled$public/AccountGroupIdChanged</template>
</alerts>
<fieldUpdates>
<fullName>PutNewValueInOldGroupIdField</fullName>
<field>Old_Group_ID__c</field>
<formula>Group_ID__c</formula>
<name>PutNewValueInOldGroupIdField</name>
<notifyAssignee>false</notifyAssignee>
<operation>Formula</operation>
<protected>false</protected>
</fieldUpdates>
<fieldUpdates>
<fullName>SetGroupIdUpdated</fullName>
<field>Group_ID_Updated__c</field>
<literalValue>1</literalValue>
<name>SetGroupIdUpdated</name>
<notifyAssignee>false</notifyAssignee>
<operation>Literal</operation>
<protected>false</protected>
<reevaluateOnChange>true</reevaluateOnChange>
</fieldUpdates>
<fieldUpdates>
<fullName>UnsetGroupIdUpdated</fullName>
<field>Group_ID_Updated__c</field>
<literalValue>0</literalValue>
<name>UnsetGroupIdUpdated</name>
<notifyAssignee>false</notifyAssignee>
<operation>Literal</operation>
<protected>false</protected>
</fieldUpdates>
<rules>
<fullName>AccountGroupIdChanged</fullName>
<actions>
<name>AccountGroupIdChanged</name>
<type>Alert</type>
</actions>
<actions>
<name>SetGroupIdUpdated</name>
<type>FieldUpdate</type>
</actions>
<active>true</active>
<formula>NOT ( ISNEW() ) && ISCHANGED( Group_ID__c )</formula>
<triggerType>onAllChanges</triggerType>
</rules>
<rules>
<fullName>GroupIdUpdatedSet</fullName>
<actions>
<name>PutNewValueInOldGroupIdField</name>
<type>FieldUpdate</type>
</actions>
<actions>
<name>UnsetGroupIdUpdated</name>
<type>FieldUpdate</type>
</actions>
<active>true</active>
<criteriaItems>
<field>Account.Group_ID_Updated__c</field>
<operation>equals</operation>
<value>True</value>
</criteriaItems>
<triggerType>onAllChanges</triggerType>
</rules>
</Workflow>