What are the good practices to collect/assemble package intially or on the further upgrades? (in order not to miss any components) Maybe there are automated options like pass package.xml and the package will be assembled based on this package.xml
A key factor in assembling a package is how components depend on each other.
In some cases the dependency is such that component A (e.g. a Visualforce page) can't work without component B (e.g. its controller class). For those cases, the platform's packaging tools automatically follow the dependency chain and include the necessary components which is good.
But there are also cases where component C (e.g. a custom object) can work perfectly well with or without component D (e.g. a trigger). For those cases, you have to make the decision and add the component. Components in this category that I find (for the types of package I develop) have to often be manually added are Apex tests, triggers, custom buttons, layouts, custom fields on standard objects.
My point is that this selection is not automatable in general. Perhaps tooling could be built to e.g. include "everything" in an org but then the risk would just flip from too little being packaged to too much being packaged. But the packaging is repeatable: your starting point for the next version is everything you included in the previous version.
If you are creating "Managed - Released" packages, the worst mistake to make is not to leave something out but to accidentally add something that shouldn't be there. This is because the version compatibility mechanism is very inflexible, requiring that later versions of packages are largely a superset of earlier versions.
(Depending on what your package does, you may find "Managed - Beta" packages helpful. These avoid the problem of not being able to change things in your package but at the cost of always requiring an uninstall/install that essentially throws away all your test data and configuration instead of just an upgrade where the data and configuration are preserved.)
So on good practices, have a checklist as you work and/or add the components to the package soon after you create them. Before creating a package or a new version of a package, select the various component types in the packaging UI and see if there are things in the org that you have missed and should be in the package. And when you have created a package install it and check that what you expect to be there is there.
Your question mentions package.xml that should certainly be used to synchronize your packaging org with a version control system. I remember (but can't find) a post on this site about extracting a copy of exactly what was packaged in the form of a package.xml; I don't think the idea there was to use the package.xml to nominate what was to go into the package though.
You can use package.xml to control what will wind up in your package. The trick is to specify only a fullName element in the package.xml which will cause the deployment to put the metadata into your org as members of the package.
We use this setup for deploying code to our DE orgs and our packaging org. It ensures that whatever a developer was working with in their DE org package also makes it into the package in the packaging org without ever needing to use the Add Components button or manually maintain a list of what new metadata is added to the package.
There are three gotchas to watch out for:
You must list every metadata type, including subtypes such as CustomField, in your package.xml file. If you already have a package, this is easy as you just need to retrieve the package's metadata via the API (more details here: Retrieve Setup>Create>Packages). Another option is to use the ant targets we've built for our package to dynamically construct a package.xml file (https://github.com/SalesforceFoundation/Cumulus)
You must manually create the package in the target org before deploying as there is no API available to create a package. Go to Setup -> Create -> Packages and create an unmanaged package. Use the name of the package as the value of the fullName element in your package.xml like My Package
If you use the Force IDE, you will need to delete the project from your workspace (but not the filesystem) then recreate the project. When recreating, you should be able to select to only load metadata from your package. Simply removing the Force.com nature from the project is not enough to trigger this change in behavior.
We also use a custom built ant job to compare what's in the package in the packaging org versus what's in the repository we're deploying. The macro then deletes any metadata from the packaging org which doesn't exist in our repository (i.e. stale metadata). With the combination of using fullName and the destroyStaleMetadata target, our managed package contents are entirely managed through our Github repository.