Unix-based systems carry a lot of useful tool. actually they made them to help us improve our productivity. patch
is one of useful tool that help programer update a existing codebase.
Note
A patch
is a file that contains the differences between two sets of code or files. It is used to update an existing codebase by applying changes without rewriting the entire code. The patch utility is a useful tool for programmers to apply updates to codebases.
When we work on a existing codebase we might update and do some change to it to fix a bug then we can use patch
utility to add update to codebase. I try to explain its advantage with an example like this :
suppose I recently I develop a library
in C++
. inside my library i have a file like object.h
. and inside this file I already defined a classe like this :
class Object {
public:
Object() {}
~Object() {}
void setfObject(int _f) { fObject = _f;}
void setbObject(int _b) { bObject = _b;}
int getfObject() {return fObject;}
int getbObject() {return bObject;}
private :
int fObject;
int bObject;
}
Now, suppose I'm working on another library that requires a class similar to Object but with a different name, GlobalObject. What should I do?
1.) I should declare a new GlobalObject class inside newLib with the same properties as the Object class (meaning I should rewrite the existing class with a new name).
2.) Alternatively, I could use the existing Object class, make the necessary changes, create a patch for it, and then generate a new class with the new name GlobalObject through the patch.
personally I prefer to choose item 2. but how ? we will learn how to make patch
through git diff
in the next section.
indeed to make a .pach
file and use it we could use git
and diff
. as you might familiar with git
and diff
I try to make a patch
file for class Object
and ready it to be GlobalObject
class whiout implement whole GlobalObject
class.
let look at this sample:
1.) I create a project and named it patchDemo
. also inside it I a create 2 directories and named them libA
and libB
:
if you want do with me you can use this bash
script to create directory structure.
#!/bin/sh
wDir=patchDemo
libADir=libA
libBDir=libB
mkdir $wDir && cd $wDir && mkdir $LibADir $libBDir
2.) inside libA
directory I created Object.h
file then added this simple class within it.
class Object {
public:
Object() {}
~Object() {}
void setfObject(int _f) { fObject = _f;}
void setbObject(int _b) { bObject = _b;}
int getfObject() {return fObject;}
int getbObject() {return bObject;}
private :
int fObject;
int bObject;
}
3.) after save save our class our libA
is ready. i just use git
to add it and commit a message to libA
:
you can also do it through below command in libA
directroy.
git init && git add . && git commit -m "init libA"
4.) now I want create libB
and my class GlobalObject.h
as we know. GlobalObject
class is really similar to Object
class for that reasone I try to use libA/Object.h
to create libB/GlobalObject.h
.
5.) I switch to libB
directory and try to make a clone from libA
through git clone
.
inside libB
directroy you can use this command :
git clone ../libA
6.) last command will create a clone from libA
inside libB
directory. now we can edit Object
class and add new feature to it to make our GlobalObject
.
you can with me :
# inside path/patchDemo/libB/libA
vim ./Object.h
7.) I edit Object
class and replace it with this snippet code for GlobalObject
class :
class GlobalObject {
public:
GlobalObject() {}
~GlobalObject() {}
void setfGlobalObject(int _f) { fObject = _f;}
void getfGlobalObject() {return fObject;}
void setbGlobalObjectName(std::string goName) { bGlobalObjectName = goName}
std::string getbGlobalObjectName() { return bGlobalObjectName; }
private :
int fGlobalObject;
std::string bGlobalObjectName;
}
as you can see properties and methods are similar to Object
class.
when I done with it we are ready to create patch from it. before we create our patch
file. I use git
to add changes to libB
for this purpose you can use this below command :
git add . && git commit -m "init libB"
now if check git log
I should see something like this :
commit 02c3b3f7d16c6384872efeb0f6f631af7ac09546 (HEAD -> master)
Author: vheidari <v**********[email protected]>
Date: Fri May 31 19:36:01 2024 -0400
init libB
commit e88f74b1d9646122487fe450f5c1fd75f9c126c3 (origin/master, origin/HEAD)
Author: vheidari <v**********[email protected]>
Date: Fri May 31 19:30:42 2024 -0400
init libA
as you can see we did change and update project and ready it for libB
.
8.) now we could create patch file through git diff
command
you can also use this below command :
# This command run under path/patchDemo/libB/libA
git diff e88f74b1d9646122487fe450f5c1fd75f9c126c3 > ../../libB.patch
9.) above command will create a patch file through commait id
. if I do change my directory to project root directory patchDemo
with this command cd ../../
we could find libB.patch
.
now we have patch file. but how we could use it. we will learn about it in the next section.
if you are curious about this file and you want see what git diff
made you can open it within vim ./libB.patch
:
diff --git a/Object.h b/Object.h
index 8a6b5e5..19d4ac4 100644
--- a/Object.h
+++ b/Object.h
@@ -1,14 +1,16 @@
-class Object {
- public:
-
- Object() {}
- ~Object() {}
+class GlobalObject {
+ public:
+
+ GlobalObject() {}
+ ~GlobalObject() {}
+
+ void setfGlobalObject(int _f) { fObject = _f;}
+ void getfGlobalObject() {return fObject;}
+ void setbGlobalObjectName(std::string goName) { bGlobalObjectName = goName}
+ std::string getbGlobalObjectName() { return bGlobalObjectName; }
+
+ private :
+ int fGlobalObject;
+ std::string bGlobalObjectName;
+};
- void setfObject(int _f) { fObject = _f;}
- void setbObject(int _b) { bObject = _b;}
- int getfObject() {return fObject;}
- int getbObject() {return bObject;}
- private :
- int fObject;
- int bObject;
-}
Ok we made libB.patch
file. now I want use it to create my libB
from libA
but how ?
before we do anything I will remove directory libB
then I try make GlobalObject.h
file from Object.h
with patch
and libB.patch
.
in patchDemo
directory I remove libB
and with this command :
rm -rf ./libB
Now we should create a new libB
directroy then clone libA
to it then patch Object.h
with patch
tool and libB.patch
.
below bash script show steps that we should do to create GlobalObject.h
from Object.h
.
#!bin/sh
# crete libB directory
mkdir libB
# change current directroy to libB
cd libB
# crete a clone from libA and put it in libB directroy
git clone ../libA
# switch to libA
cd ./libA
# copy libB.patch from root (patchDemo) to current directroy (path/patchDemo/libB/libA)
cp ../../libB.patch ./libB.patch
# patch Object.h through libB.patch
patch -p1 ./Objet.h ./libB.patch
# rename Object.h and move it from this directory to path/patchDemo/libB directroy
mv ./Object.h ../GlobalObject.h
# back to libB directory from pathDemo/libB/libA
cd ..
# remove libA directory
rm -rf ./libA
- https://docs.gitlab.com/omnibus/development/creating-patches.html
- Project to review :
- https://github.com/linusg/libjs-bindings/blob/master/patches/jsb.patch